lint: run ktlintFormat

This commit is contained in:
Jarne Demeulemeester 2023-06-19 23:44:42 +02:00
parent 07efae6f4c
commit b426a920c3
No known key found for this signature in database
GPG key ID: 1E5C6AFBD622E9F5
116 changed files with 783 additions and 702 deletions

View file

@ -11,8 +11,8 @@ import coil.disk.DiskCache
import coil.request.CachePolicy import coil.request.CachePolicy
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import javax.inject.Inject
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
@HiltAndroidApp @HiltAndroidApp
class BaseApplication : Application(), Configuration.Provider, ImageLoaderFactory { class BaseApplication : Application(), Configuration.Provider, ImageLoaderFactory {

View file

@ -59,7 +59,7 @@ abstract class BasePlayerActivity : AppCompatActivity() {
protected fun isRendererType( protected fun isRendererType(
mappedTrackInfo: MappingTrackSelector.MappedTrackInfo, mappedTrackInfo: MappingTrackSelector.MappedTrackInfo,
rendererIndex: Int, rendererIndex: Int,
type: Int type: Int,
): Boolean { ): Boolean {
val trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex) val trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex)
if (trackGroupArray.length == 0) { if (trackGroupArray.length == 0) {

View file

@ -10,17 +10,17 @@ import dev.jdtech.jellyfin.adapters.HomeEpisodeListAdapter
import dev.jdtech.jellyfin.adapters.ServerGridAdapter import dev.jdtech.jellyfin.adapters.ServerGridAdapter
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
import dev.jdtech.jellyfin.api.JellyfinApi import dev.jdtech.jellyfin.api.JellyfinApi
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.models.FindroidEpisode import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
import dev.jdtech.jellyfin.models.FindroidMovie import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.Server import dev.jdtech.jellyfin.models.Server
import dev.jdtech.jellyfin.models.User import dev.jdtech.jellyfin.models.User
import java.util.UUID
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.BaseItemPerson import org.jellyfin.sdk.model.api.BaseItemPerson
import org.jellyfin.sdk.model.api.ImageType import org.jellyfin.sdk.model.api.ImageType
import java.util.UUID
import dev.jdtech.jellyfin.core.R as CoreR
@BindingAdapter("servers") @BindingAdapter("servers")
fun bindServers(recyclerView: RecyclerView, data: List<Server>?) { fun bindServers(recyclerView: RecyclerView, data: List<Server>?) {
@ -109,7 +109,7 @@ fun bindUserImage(imageView: ImageView, user: User) {
private fun ImageView.loadImage( private fun ImageView.loadImage(
url: String, url: String,
@DrawableRes placeholderId: Int = CoreR.color.neutral_800 @DrawableRes placeholderId: Int = CoreR.color.neutral_800,
): View { ): View {
val api = JellyfinApi.getInstance(context.applicationContext) val api = JellyfinApi.getInstance(context.applicationContext)

View file

@ -20,13 +20,13 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import com.google.android.material.navigation.NavigationBarView import com.google.android.material.navigation.NavigationBarView
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.databinding.ActivityMainBinding import dev.jdtech.jellyfin.databinding.ActivityMainBinding
import dev.jdtech.jellyfin.viewmodels.MainViewModel import dev.jdtech.jellyfin.viewmodels.MainViewModel
import dev.jdtech.jellyfin.work.SyncWorker import dev.jdtech.jellyfin.work.SyncWorker
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
@ -53,9 +53,9 @@ class MainActivity : AppCompatActivity() {
.setConstraints( .setConstraints(
Constraints.Builder() Constraints.Builder()
.setRequiredNetworkType( .setRequiredNetworkType(
NetworkType.CONNECTED NetworkType.CONNECTED,
) )
.build() .build(),
) )
.build() .build()
@ -105,7 +105,7 @@ class MainActivity : AppCompatActivity() {
R.id.mediaFragment, R.id.mediaFragment,
R.id.favoriteFragment, R.id.favoriteFragment,
R.id.downloadsFragment, R.id.downloadsFragment,
) ),
) )
setupActionBarWithNavController(navController, appBarConfiguration) setupActionBarWithNavController(navController, appBarConfiguration)
@ -118,8 +118,10 @@ class MainActivity : AppCompatActivity() {
R.id.twoPaneSettingsFragment, R.id.serverSelectFragment, R.id.addServerFragment, R.id.loginFragment, com.mikepenz.aboutlibraries.R.id.about_libraries_dest, R.id.usersFragment, R.id.serverAddressesFragment -> View.GONE R.id.twoPaneSettingsFragment, R.id.serverSelectFragment, R.id.addServerFragment, R.id.loginFragment, com.mikepenz.aboutlibraries.R.id.about_libraries_dest, R.id.usersFragment, R.id.serverAddressesFragment -> View.GONE
else -> View.VISIBLE else -> View.VISIBLE
} }
if (destination.id == com.mikepenz.aboutlibraries.R.id.about_libraries_dest) binding.mainToolbar.title = if (destination.id == com.mikepenz.aboutlibraries.R.id.about_libraries_dest) {
getString(CoreR.string.app_info) binding.mainToolbar.title =
getString(CoreR.string.app_info)
}
} }
} }

View file

@ -24,12 +24,12 @@ import dev.jdtech.jellyfin.dialogs.SpeedSelectionDialogFragment
import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment
import dev.jdtech.jellyfin.mpv.MPVPlayer import dev.jdtech.jellyfin.mpv.MPVPlayer
import dev.jdtech.jellyfin.mpv.TrackType import dev.jdtech.jellyfin.mpv.TrackType
import dev.jdtech.jellyfin.player.video.R as PlayerVideoR
import dev.jdtech.jellyfin.utils.PlayerGestureHelper import dev.jdtech.jellyfin.utils.PlayerGestureHelper
import dev.jdtech.jellyfin.utils.PreviewScrubListener import dev.jdtech.jellyfin.utils.PreviewScrubListener
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
import javax.inject.Inject
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
import dev.jdtech.jellyfin.player.video.R as PlayerVideoR
var isControlsLocked: Boolean = false var isControlsLocked: Boolean = false
@ -63,7 +63,7 @@ class PlayerActivity : BasePlayerActivity() {
appPreferences, appPreferences,
this, this,
binding.playerView, binding.playerView,
getSystemService(Context.AUDIO_SERVICE) as AudioManager getSystemService(Context.AUDIO_SERVICE) as AudioManager,
) )
} }
@ -106,7 +106,7 @@ class PlayerActivity : BasePlayerActivity() {
is MPVPlayer -> { is MPVPlayer -> {
TrackSelectionDialogFragment(TrackType.AUDIO, viewModel).show( TrackSelectionDialogFragment(TrackType.AUDIO, viewModel).show(
supportFragmentManager, supportFragmentManager,
"trackselectiondialog" "trackselectiondialog",
) )
} }
is ExoPlayer -> { is ExoPlayer -> {
@ -126,7 +126,7 @@ class PlayerActivity : BasePlayerActivity() {
this, this,
resources.getString(PlayerVideoR.string.select_audio_track), resources.getString(PlayerVideoR.string.select_audio_track),
viewModel.player, viewModel.player,
C.TRACK_TYPE_AUDIO C.TRACK_TYPE_AUDIO,
) )
val trackSelectionDialog = trackSelectionDialogBuilder.build() val trackSelectionDialog = trackSelectionDialogBuilder.build()
trackSelectionDialog.show() trackSelectionDialog.show()
@ -156,7 +156,7 @@ class PlayerActivity : BasePlayerActivity() {
is MPVPlayer -> { is MPVPlayer -> {
TrackSelectionDialogFragment(TrackType.SUBTITLE, viewModel).show( TrackSelectionDialogFragment(TrackType.SUBTITLE, viewModel).show(
supportFragmentManager, supportFragmentManager,
"trackselectiondialog" "trackselectiondialog",
) )
} }
is ExoPlayer -> { is ExoPlayer -> {
@ -176,7 +176,7 @@ class PlayerActivity : BasePlayerActivity() {
this, this,
resources.getString(PlayerVideoR.string.select_subtile_track), resources.getString(PlayerVideoR.string.select_subtile_track),
viewModel.player, viewModel.player,
C.TRACK_TYPE_TEXT C.TRACK_TYPE_TEXT,
) )
trackSelectionDialogBuilder.setShowDisableOption(true) trackSelectionDialogBuilder.setShowDisableOption(true)
@ -189,7 +189,7 @@ class PlayerActivity : BasePlayerActivity() {
speedButton.setOnClickListener { speedButton.setOnClickListener {
SpeedSelectionDialogFragment(viewModel).show( SpeedSelectionDialogFragment(viewModel).show(
supportFragmentManager, supportFragmentManager,
"speedselectiondialog" "speedselectiondialog",
) )
} }
@ -210,7 +210,7 @@ class PlayerActivity : BasePlayerActivity() {
imagePreview, imagePreview,
timeBar, timeBar,
viewModel.player, viewModel.player,
viewModel.currentTrickPlay viewModel.currentTrickPlay,
) )
timeBar.addListener(previewScrubListener) timeBar.addListener(previewScrubListener)

View file

@ -9,7 +9,7 @@ import dev.jdtech.jellyfin.databinding.CollectionItemBinding
import dev.jdtech.jellyfin.models.FindroidCollection import dev.jdtech.jellyfin.models.FindroidCollection
class CollectionListAdapter( class CollectionListAdapter(
private val onClickListener: OnClickListener private val onClickListener: OnClickListener,
) : ListAdapter<FindroidCollection, CollectionListAdapter.CollectionViewHolder>(DiffCallback) { ) : ListAdapter<FindroidCollection, CollectionListAdapter.CollectionViewHolder>(DiffCallback) {
class CollectionViewHolder(private var binding: CollectionItemBinding) : class CollectionViewHolder(private var binding: CollectionItemBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -34,8 +34,8 @@ class CollectionListAdapter(
CollectionItemBinding.inflate( CollectionItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }

View file

@ -9,10 +9,10 @@ import dev.jdtech.jellyfin.databinding.DiscoveredServerItemBinding
import dev.jdtech.jellyfin.models.DiscoveredServer import dev.jdtech.jellyfin.models.DiscoveredServer
class DiscoveredServerListAdapter( class DiscoveredServerListAdapter(
private val clickListener: (server: DiscoveredServer) -> Unit private val clickListener: (server: DiscoveredServer) -> Unit,
) : ) :
ListAdapter<DiscoveredServer, DiscoveredServerListAdapter.DiscoveredServerViewHolder>( ListAdapter<DiscoveredServer, DiscoveredServerListAdapter.DiscoveredServerViewHolder>(
DiffCallback DiffCallback,
) { ) {
class DiscoveredServerViewHolder(private var binding: DiscoveredServerItemBinding) : class DiscoveredServerViewHolder(private var binding: DiscoveredServerItemBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -25,14 +25,14 @@ class DiscoveredServerListAdapter(
companion object DiffCallback : DiffUtil.ItemCallback<DiscoveredServer>() { companion object DiffCallback : DiffUtil.ItemCallback<DiscoveredServer>() {
override fun areItemsTheSame( override fun areItemsTheSame(
oldItem: DiscoveredServer, oldItem: DiscoveredServer,
newItem: DiscoveredServer newItem: DiscoveredServer,
): Boolean { ): Boolean {
return oldItem.id == newItem.id return oldItem.id == newItem.id
} }
override fun areContentsTheSame( override fun areContentsTheSame(
oldItem: DiscoveredServer, oldItem: DiscoveredServer,
newItem: DiscoveredServer newItem: DiscoveredServer,
): Boolean { ): Boolean {
return oldItem == newItem return oldItem == newItem
} }
@ -40,14 +40,14 @@ class DiscoveredServerListAdapter(
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int,
): DiscoveredServerViewHolder { ): DiscoveredServerViewHolder {
return DiscoveredServerViewHolder( return DiscoveredServerViewHolder(
DiscoveredServerItemBinding.inflate( DiscoveredServerItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }

View file

@ -8,12 +8,12 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.EpisodeItemBinding import dev.jdtech.jellyfin.databinding.EpisodeItemBinding
import dev.jdtech.jellyfin.databinding.SeasonHeaderBinding import dev.jdtech.jellyfin.databinding.SeasonHeaderBinding
import dev.jdtech.jellyfin.models.EpisodeItem import dev.jdtech.jellyfin.models.EpisodeItem
import dev.jdtech.jellyfin.models.FindroidEpisode import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.isDownloaded import dev.jdtech.jellyfin.models.isDownloaded
import dev.jdtech.jellyfin.core.R as CoreR
private const val ITEM_VIEW_TYPE_HEADER = 0 private const val ITEM_VIEW_TYPE_HEADER = 0
private const val ITEM_VIEW_TYPE_EPISODE = 1 private const val ITEM_VIEW_TYPE_EPISODE = 1
@ -49,7 +49,7 @@ class EpisodeListAdapter(
binding.progressBar.layoutParams.width = TypedValue.applyDimension( binding.progressBar.layoutParams.width = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TypedValue.COMPLEX_UNIT_DIP,
(episode.playbackPositionTicks.div(episode.runtimeTicks.toFloat()).times(84)), (episode.playbackPositionTicks.div(episode.runtimeTicks.toFloat()).times(84)),
binding.progressBar.context.resources.displayMetrics binding.progressBar.context.resources.displayMetrics,
).toInt() ).toInt()
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
} else { } else {
@ -79,8 +79,8 @@ class EpisodeListAdapter(
SeasonHeaderBinding.inflate( SeasonHeaderBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }
ITEM_VIEW_TYPE_EPISODE -> { ITEM_VIEW_TYPE_EPISODE -> {
@ -88,8 +88,8 @@ class EpisodeListAdapter(
EpisodeItemBinding.inflate( EpisodeItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }
else -> throw ClassCastException("Unknown viewType $viewType") else -> throw ClassCastException("Unknown viewType $viewType")

View file

@ -11,14 +11,14 @@ import dev.jdtech.jellyfin.models.FavoriteSection
class FavoritesListAdapter( class FavoritesListAdapter(
private val onClickListener: ViewItemListAdapter.OnClickListener, private val onClickListener: ViewItemListAdapter.OnClickListener,
private val onEpisodeClickListener: HomeEpisodeListAdapter.OnClickListener private val onEpisodeClickListener: HomeEpisodeListAdapter.OnClickListener,
) : ListAdapter<FavoriteSection, FavoritesListAdapter.SectionViewHolder>(DiffCallback) { ) : ListAdapter<FavoriteSection, FavoritesListAdapter.SectionViewHolder>(DiffCallback) {
class SectionViewHolder(private var binding: FavoriteSectionBinding) : class SectionViewHolder(private var binding: FavoriteSectionBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun bind( fun bind(
section: FavoriteSection, section: FavoriteSection,
onClickListener: ViewItemListAdapter.OnClickListener, onClickListener: ViewItemListAdapter.OnClickListener,
onEpisodeClickListener: HomeEpisodeListAdapter.OnClickListener onEpisodeClickListener: HomeEpisodeListAdapter.OnClickListener,
) { ) {
binding.section = section binding.section = section
if (section.id == Constants.FAVORITE_TYPE_MOVIES || section.id == Constants.FAVORITE_TYPE_SHOWS) { if (section.id == Constants.FAVORITE_TYPE_MOVIES || section.id == Constants.FAVORITE_TYPE_SHOWS) {
@ -42,7 +42,7 @@ class FavoritesListAdapter(
override fun areContentsTheSame( override fun areContentsTheSame(
oldItem: FavoriteSection, oldItem: FavoriteSection,
newItem: FavoriteSection newItem: FavoriteSection,
): Boolean { ): Boolean {
return oldItem == newItem return oldItem == newItem
} }
@ -53,8 +53,8 @@ class FavoritesListAdapter(
FavoriteSectionBinding.inflate( FavoriteSectionBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }

View file

@ -8,17 +8,17 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.HomeEpisodeItemBinding import dev.jdtech.jellyfin.databinding.HomeEpisodeItemBinding
import dev.jdtech.jellyfin.models.FindroidEpisode import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
import dev.jdtech.jellyfin.models.FindroidMovie import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.isDownloaded import dev.jdtech.jellyfin.models.isDownloaded
import dev.jdtech.jellyfin.core.R as CoreR
class HomeEpisodeListAdapter(private val onClickListener: OnClickListener) : ListAdapter<FindroidItem, HomeEpisodeListAdapter.EpisodeViewHolder>(DiffCallback) { class HomeEpisodeListAdapter(private val onClickListener: OnClickListener) : ListAdapter<FindroidItem, HomeEpisodeListAdapter.EpisodeViewHolder>(DiffCallback) {
class EpisodeViewHolder( class EpisodeViewHolder(
private var binding: HomeEpisodeItemBinding, private var binding: HomeEpisodeItemBinding,
private val parent: ViewGroup private val parent: ViewGroup,
) : ) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
fun bind(item: FindroidItem) { fun bind(item: FindroidItem) {
@ -26,7 +26,8 @@ class HomeEpisodeListAdapter(private val onClickListener: OnClickListener) : Lis
if (item.playbackPositionTicks > 0) { if (item.playbackPositionTicks > 0) {
binding.progressBar.layoutParams.width = TypedValue.applyDimension( binding.progressBar.layoutParams.width = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TypedValue.COMPLEX_UNIT_DIP,
(item.playbackPositionTicks.div(item.runtimeTicks.toFloat()).times(224)), binding.progressBar.context.resources.displayMetrics (item.playbackPositionTicks.div(item.runtimeTicks.toFloat()).times(224)),
binding.progressBar.context.resources.displayMetrics,
).toInt() ).toInt()
binding.progressBar.visibility = View.VISIBLE binding.progressBar.visibility = View.VISIBLE
} }
@ -67,9 +68,9 @@ class HomeEpisodeListAdapter(private val onClickListener: OnClickListener) : Lis
HomeEpisodeItemBinding.inflate( HomeEpisodeItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
), ),
parent parent,
) )
} }

View file

@ -33,8 +33,8 @@ class PersonListAdapter(private val clickListener: (item: BaseItemPerson) -> Uni
PersonItemBinding.inflate( PersonItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }

View file

@ -10,7 +10,7 @@ import dev.jdtech.jellyfin.models.ServerAddress
class ServerAddressAdapter( class ServerAddressAdapter(
private val clickListener: (address: ServerAddress) -> Unit, private val clickListener: (address: ServerAddress) -> Unit,
private val longClickListener: (address: ServerAddress) -> Boolean private val longClickListener: (address: ServerAddress) -> Boolean,
) : ListAdapter<ServerAddress, ServerAddressAdapter.ServerAddressViewHolder>(DiffCallback) { ) : ListAdapter<ServerAddress, ServerAddressAdapter.ServerAddressViewHolder>(DiffCallback) {
class ServerAddressViewHolder(private var binding: ServerAddressListItemBinding) : class ServerAddressViewHolder(private var binding: ServerAddressListItemBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -32,14 +32,14 @@ class ServerAddressAdapter(
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int,
): ServerAddressViewHolder { ): ServerAddressViewHolder {
return ServerAddressViewHolder( return ServerAddressViewHolder(
ServerAddressListItemBinding.inflate( ServerAddressListItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }

View file

@ -10,7 +10,7 @@ import dev.jdtech.jellyfin.models.Server
class ServerGridAdapter( class ServerGridAdapter(
private val onClickListener: OnClickListener, private val onClickListener: OnClickListener,
private val onLongClickListener: OnLongClickListener private val onLongClickListener: OnLongClickListener,
) : ListAdapter<Server, ServerGridAdapter.ServerViewHolder>(DiffCallback) { ) : ListAdapter<Server, ServerGridAdapter.ServerViewHolder>(DiffCallback) {
class ServerViewHolder(private var binding: ServerItemBinding) : class ServerViewHolder(private var binding: ServerItemBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -32,7 +32,7 @@ class ServerGridAdapter(
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int,
): ServerViewHolder { ): ServerViewHolder {
return ServerViewHolder(ServerItemBinding.inflate(LayoutInflater.from(parent.context))) return ServerViewHolder(ServerItemBinding.inflate(LayoutInflater.from(parent.context)))
} }

View file

@ -10,7 +10,7 @@ import dev.jdtech.jellyfin.models.User
class UserListAdapter( class UserListAdapter(
private val clickListener: (user: User) -> Unit, private val clickListener: (user: User) -> Unit,
private val longClickListener: (user: User) -> Boolean private val longClickListener: (user: User) -> Boolean,
) : ListAdapter<User, UserListAdapter.UserViewHolder>(DiffCallback) { ) : ListAdapter<User, UserListAdapter.UserViewHolder>(DiffCallback) {
class UserViewHolder(private var binding: UserListItemBinding) : class UserViewHolder(private var binding: UserListItemBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -32,14 +32,14 @@ class UserListAdapter(
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int,
): UserViewHolder { ): UserViewHolder {
return UserViewHolder( return UserViewHolder(
UserListItemBinding.inflate( UserListItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }

View file

@ -9,7 +9,7 @@ import dev.jdtech.jellyfin.databinding.UserItemBinding
import dev.jdtech.jellyfin.models.User import dev.jdtech.jellyfin.models.User
class UserLoginListAdapter( class UserLoginListAdapter(
private val clickListener: (user: User) -> Unit private val clickListener: (user: User) -> Unit,
) : ListAdapter<User, UserLoginListAdapter.UserLoginViewHolder>(DiffCallback) { ) : ListAdapter<User, UserLoginListAdapter.UserLoginViewHolder>(DiffCallback) {
class UserLoginViewHolder(private var binding: UserItemBinding) : class UserLoginViewHolder(private var binding: UserItemBinding) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -31,14 +31,14 @@ class UserLoginListAdapter(
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
viewType: Int viewType: Int,
): UserLoginViewHolder { ): UserLoginViewHolder {
return UserLoginViewHolder( return UserLoginViewHolder(
UserItemBinding.inflate( UserItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }

View file

@ -7,11 +7,11 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.BaseItemBinding import dev.jdtech.jellyfin.databinding.BaseItemBinding
import dev.jdtech.jellyfin.models.FindroidEpisode import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
import dev.jdtech.jellyfin.models.isDownloaded import dev.jdtech.jellyfin.models.isDownloaded
import dev.jdtech.jellyfin.core.R as CoreR
class ViewItemListAdapter( class ViewItemListAdapter(
private val onClickListener: OnClickListener, private val onClickListener: OnClickListener,
@ -52,9 +52,9 @@ class ViewItemListAdapter(
BaseItemBinding.inflate( BaseItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
), ),
parent parent,
) )
} }

View file

@ -7,11 +7,11 @@ import androidx.core.view.isVisible
import androidx.paging.PagingDataAdapter import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.BaseItemBinding import dev.jdtech.jellyfin.databinding.BaseItemBinding
import dev.jdtech.jellyfin.models.FindroidEpisode import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
import dev.jdtech.jellyfin.models.isDownloaded import dev.jdtech.jellyfin.models.isDownloaded
import dev.jdtech.jellyfin.core.R as CoreR
class ViewItemPagingAdapter( class ViewItemPagingAdapter(
private val onClickListener: OnClickListener, private val onClickListener: OnClickListener,
@ -53,9 +53,9 @@ class ViewItemPagingAdapter(
BaseItemBinding.inflate( BaseItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
), ),
parent parent,
) )
} }

View file

@ -5,12 +5,12 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.CardOfflineBinding import dev.jdtech.jellyfin.databinding.CardOfflineBinding
import dev.jdtech.jellyfin.databinding.NextUpSectionBinding import dev.jdtech.jellyfin.databinding.NextUpSectionBinding
import dev.jdtech.jellyfin.databinding.ViewItemBinding import dev.jdtech.jellyfin.databinding.ViewItemBinding
import dev.jdtech.jellyfin.models.HomeItem import dev.jdtech.jellyfin.models.HomeItem
import dev.jdtech.jellyfin.models.View import dev.jdtech.jellyfin.models.View
import dev.jdtech.jellyfin.core.R as CoreR
private const val ITEM_VIEW_TYPE_NEXT_UP = 0 private const val ITEM_VIEW_TYPE_NEXT_UP = 0
private const val ITEM_VIEW_TYPE_VIEW = 1 private const val ITEM_VIEW_TYPE_VIEW = 1
@ -20,7 +20,7 @@ class ViewListAdapter(
private val onClickListener: OnClickListener, private val onClickListener: OnClickListener,
private val onItemClickListener: ViewItemListAdapter.OnClickListener, private val onItemClickListener: ViewItemListAdapter.OnClickListener,
private val onNextUpClickListener: HomeEpisodeListAdapter.OnClickListener, private val onNextUpClickListener: HomeEpisodeListAdapter.OnClickListener,
private val onOnlineClickListener: OnClickListenerOfflineCard private val onOnlineClickListener: OnClickListenerOfflineCard,
) : ListAdapter<HomeItem, RecyclerView.ViewHolder>(DiffCallback) { ) : ListAdapter<HomeItem, RecyclerView.ViewHolder>(DiffCallback) {
class ViewViewHolder(private var binding: ViewItemBinding) : class ViewViewHolder(private var binding: ViewItemBinding) :
@ -28,7 +28,7 @@ class ViewListAdapter(
fun bind( fun bind(
dataItem: HomeItem.ViewItem, dataItem: HomeItem.ViewItem,
onClickListener: OnClickListener, onClickListener: OnClickListener,
onItemClickListener: ViewItemListAdapter.OnClickListener onItemClickListener: ViewItemListAdapter.OnClickListener,
) { ) {
val view = dataItem.view val view = dataItem.view
binding.view = view binding.view = view
@ -75,25 +75,26 @@ class ViewListAdapter(
ITEM_VIEW_TYPE_NEXT_UP -> NextUpViewHolder( ITEM_VIEW_TYPE_NEXT_UP -> NextUpViewHolder(
NextUpSectionBinding.inflate( NextUpSectionBinding.inflate(
LayoutInflater.from( LayoutInflater.from(
parent.context parent.context,
), ),
parent, false parent,
) false,
),
) )
ITEM_VIEW_TYPE_VIEW -> ViewViewHolder( ITEM_VIEW_TYPE_VIEW -> ViewViewHolder(
ViewItemBinding.inflate( ViewItemBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
ITEM_VIEW_TYPE_OFFLINE_CARD -> { ITEM_VIEW_TYPE_OFFLINE_CARD -> {
OfflineCardViewHolder( OfflineCardViewHolder(
CardOfflineBinding.inflate( CardOfflineBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
false false,
) ),
) )
} }
else -> throw ClassCastException("Unknown viewType $viewType") else -> throw ClassCastException("Unknown viewType $viewType")

View file

@ -30,7 +30,7 @@ class AddServerFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentAddServerBinding.inflate(inflater) binding = FragmentAddServerBinding.inflate(inflater)
@ -117,7 +117,7 @@ class AddServerFragment : Fragment() {
} }
private fun bindDiscoveredServersStateServers( private fun bindDiscoveredServersStateServers(
serversState: AddServerViewModel.DiscoveredServersState.Servers serversState: AddServerViewModel.DiscoveredServersState.Servers,
) { ) {
val servers = serversState.servers val servers = serversState.servers
if (servers.isEmpty()) { if (servers.isEmpty()) {

View file

@ -38,7 +38,7 @@ class CollectionFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentFavoriteBinding.inflate(inflater, container, false) binding = FragmentFavoriteBinding.inflate(inflater, container, false)
@ -48,7 +48,7 @@ class CollectionFragment : Fragment() {
}, },
HomeEpisodeListAdapter.OnClickListener { item -> HomeEpisodeListAdapter.OnClickListener { item ->
navigateToMediaItem(item) navigateToMediaItem(item)
} },
) )
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
@ -112,23 +112,23 @@ class CollectionFragment : Fragment() {
findNavController().navigate( findNavController().navigate(
CollectionFragmentDirections.actionCollectionFragmentToMovieFragment( CollectionFragmentDirections.actionCollectionFragmentToMovieFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidShow -> { is FindroidShow -> {
findNavController().navigate( findNavController().navigate(
CollectionFragmentDirections.actionCollectionFragmentToShowFragment( CollectionFragmentDirections.actionCollectionFragmentToShowFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidEpisode -> { is FindroidEpisode -> {
findNavController().navigate( findNavController().navigate(
CollectionFragmentDirections.actionCollectionFragmentToEpisodeBottomSheetFragment( CollectionFragmentDirections.actionCollectionFragmentToEpisodeBottomSheetFragment(
item.id item.id,
) ),
) )
} }
} }

View file

@ -18,16 +18,16 @@ import dev.jdtech.jellyfin.R
import dev.jdtech.jellyfin.adapters.FavoritesListAdapter import dev.jdtech.jellyfin.adapters.FavoritesListAdapter
import dev.jdtech.jellyfin.adapters.HomeEpisodeListAdapter import dev.jdtech.jellyfin.adapters.HomeEpisodeListAdapter
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.FragmentDownloadsBinding import dev.jdtech.jellyfin.databinding.FragmentDownloadsBinding
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
import dev.jdtech.jellyfin.models.FindroidMovie import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.FindroidShow import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.utils.restart import dev.jdtech.jellyfin.utils.restart
import dev.jdtech.jellyfin.viewmodels.DownloadsViewModel import dev.jdtech.jellyfin.viewmodels.DownloadsViewModel
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class DownloadsFragment : Fragment() { class DownloadsFragment : Fragment() {
@ -40,7 +40,7 @@ class DownloadsFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentDownloadsBinding.inflate(inflater, container, false) binding = FragmentDownloadsBinding.inflate(inflater, container, false)
@ -50,7 +50,7 @@ class DownloadsFragment : Fragment() {
}, },
HomeEpisodeListAdapter.OnClickListener { item -> HomeEpisodeListAdapter.OnClickListener { item ->
navigateToMediaItem(item) navigateToMediaItem(item)
} },
) )
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
@ -108,8 +108,8 @@ class DownloadsFragment : Fragment() {
findNavController().navigate( findNavController().navigate(
DownloadsFragmentDirections.actionDownloadsFragmentToMovieFragment( DownloadsFragmentDirections.actionDownloadsFragmentToMovieFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidShow -> { is FindroidShow -> {
@ -117,8 +117,8 @@ class DownloadsFragment : Fragment() {
DownloadsFragmentDirections.actionDownloadsFragmentToShowFragment( DownloadsFragmentDirections.actionDownloadsFragmentToShowFragment(
item.id, item.id,
item.name, item.name,
true true,
) ),
) )
} }
} }

View file

@ -1,6 +1,5 @@
package dev.jdtech.jellyfin.fragments package dev.jdtech.jellyfin.fragments
import android.R as AndroidR
import android.app.DownloadManager import android.app.DownloadManager
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue import android.util.TypedValue
@ -15,7 +14,6 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import com.google.android.material.R as MaterialR
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
@ -23,7 +21,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.R import dev.jdtech.jellyfin.R
import dev.jdtech.jellyfin.bindCardItemImage import dev.jdtech.jellyfin.bindCardItemImage
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.EpisodeBottomSheetBinding import dev.jdtech.jellyfin.databinding.EpisodeBottomSheetBinding
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
import dev.jdtech.jellyfin.dialogs.getStorageSelectionDialog import dev.jdtech.jellyfin.dialogs.getStorageSelectionDialog
@ -36,13 +33,16 @@ import dev.jdtech.jellyfin.models.isDownloading
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetViewModel import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetViewModel
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.DateTime
import timber.log.Timber
import java.text.DateFormat import java.text.DateFormat
import java.time.ZoneOffset import java.time.ZoneOffset
import java.util.Date import java.util.Date
import java.util.UUID import java.util.UUID
import kotlinx.coroutines.launch import android.R as AndroidR
import org.jellyfin.sdk.model.DateTime import com.google.android.material.R as MaterialR
import timber.log.Timber import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class EpisodeBottomSheetFragment : BottomSheetDialogFragment() { class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
@ -57,7 +57,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = EpisodeBottomSheetBinding.inflate(inflater, container, false) binding = EpisodeBottomSheetBinding.inflate(inflater, container, false)
@ -175,7 +175,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} },
) )
dialog.show() dialog.show()
return@getStorageSelectionDialog return@getStorageSelectionDialog
@ -186,7 +186,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} },
) )
storageDialog.show() storageDialog.show()
return@setOnClickListener return@setOnClickListener
@ -202,7 +202,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} },
) )
dialog.show() dialog.show()
return@setOnClickListener return@setOnClickListener
@ -237,7 +237,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
binding.progressBar.layoutParams.width = TypedValue.applyDimension( binding.progressBar.layoutParams.width = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, TypedValue.COMPLEX_UNIT_DIP,
(episode.playbackPositionTicks.div(episode.runtimeTicks).times(1.26)).toFloat(), (episode.playbackPositionTicks.div(episode.runtimeTicks).times(1.26)).toFloat(),
context?.resources?.displayMetrics context?.resources?.displayMetrics,
).toInt() ).toInt()
binding.progressBar.isVisible = true binding.progressBar.isVisible = true
} }
@ -264,7 +264,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
CoreR.string.episode_name_extended, CoreR.string.episode_name_extended,
episode.parentIndexNumber, episode.parentIndexNumber,
episode.indexNumber, episode.indexNumber,
episode.name episode.name,
) )
} else { } else {
getString( getString(
@ -272,7 +272,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
episode.parentIndexNumber, episode.parentIndexNumber,
episode.indexNumber, episode.indexNumber,
episode.indexNumberEnd, episode.indexNumberEnd,
episode.name episode.name,
) )
} }
@ -307,12 +307,12 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
private fun bindCheckButtonState(played: Boolean) { private fun bindCheckButtonState(played: Boolean) {
when (played) { when (played) {
true -> binding.itemActions.checkButton.setIconTintResource( true -> binding.itemActions.checkButton.setIconTintResource(
CoreR.color.red CoreR.color.red,
) )
false -> binding.itemActions.checkButton.setIconTintColorAttribute( false -> binding.itemActions.checkButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, MaterialR.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme,
) )
} }
} }
@ -325,12 +325,12 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
binding.itemActions.favoriteButton.setIconResource(favoriteDrawable) binding.itemActions.favoriteButton.setIconResource(favoriteDrawable)
when (favorite) { when (favorite) {
true -> binding.itemActions.favoriteButton.setIconTintResource( true -> binding.itemActions.favoriteButton.setIconTintResource(
CoreR.color.red CoreR.color.red,
) )
false -> binding.itemActions.favoriteButton.setIconTintColorAttribute( false -> binding.itemActions.favoriteButton.setIconTintColorAttribute(
MaterialR.attr.colorOnSecondaryContainer, MaterialR.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme,
) )
} }
} }
@ -392,7 +392,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
findNavController().navigate( findNavController().navigate(
EpisodeBottomSheetFragmentDirections.actionEpisodeBottomSheetFragmentToPlayerActivity( EpisodeBottomSheetFragmentDirections.actionEpisodeBottomSheetFragmentToPlayerActivity(
playerItems, playerItems,
) ),
) )
} }
@ -400,8 +400,8 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
findNavController().navigate( findNavController().navigate(
EpisodeBottomSheetFragmentDirections.actionEpisodeBottomSheetFragmentToShowFragment( EpisodeBottomSheetFragmentDirections.actionEpisodeBottomSheetFragmentToShowFragment(
itemId = id, itemId = id,
itemName = name itemName = name,
) ),
) )
} }

View file

@ -37,7 +37,7 @@ class FavoriteFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentFavoriteBinding.inflate(inflater, container, false) binding = FragmentFavoriteBinding.inflate(inflater, container, false)
@ -47,7 +47,7 @@ class FavoriteFragment : Fragment() {
}, },
HomeEpisodeListAdapter.OnClickListener { item -> HomeEpisodeListAdapter.OnClickListener { item ->
navigateToMediaItem(item) navigateToMediaItem(item)
} },
) )
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
@ -105,23 +105,23 @@ class FavoriteFragment : Fragment() {
findNavController().navigate( findNavController().navigate(
FavoriteFragmentDirections.actionFavoriteFragmentToMovieFragment( FavoriteFragmentDirections.actionFavoriteFragmentToMovieFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidShow -> { is FindroidShow -> {
findNavController().navigate( findNavController().navigate(
FavoriteFragmentDirections.actionFavoriteFragmentToShowFragment( FavoriteFragmentDirections.actionFavoriteFragmentToShowFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidEpisode -> { is FindroidEpisode -> {
findNavController().navigate( findNavController().navigate(
FavoriteFragmentDirections.actionFavoriteFragmentToEpisodeBottomSheetFragment( FavoriteFragmentDirections.actionFavoriteFragmentToEpisodeBottomSheetFragment(
item.id item.id,
) ),
) )
} }
} }

View file

@ -23,7 +23,6 @@ import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.adapters.HomeEpisodeListAdapter import dev.jdtech.jellyfin.adapters.HomeEpisodeListAdapter
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
import dev.jdtech.jellyfin.adapters.ViewListAdapter import dev.jdtech.jellyfin.adapters.ViewListAdapter
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.FragmentHomeBinding import dev.jdtech.jellyfin.databinding.FragmentHomeBinding
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
import dev.jdtech.jellyfin.models.FindroidEpisode import dev.jdtech.jellyfin.models.FindroidEpisode
@ -33,9 +32,10 @@ import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.utils.checkIfLoginRequired import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.utils.restart import dev.jdtech.jellyfin.utils.restart
import dev.jdtech.jellyfin.viewmodels.HomeViewModel import dev.jdtech.jellyfin.viewmodels.HomeViewModel
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class HomeFragment : Fragment() { class HomeFragment : Fragment() {
@ -53,7 +53,7 @@ class HomeFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentHomeBinding.inflate(inflater, container, false) binding = FragmentHomeBinding.inflate(inflater, container, false)
@ -87,7 +87,7 @@ class HomeFragment : Fragment() {
settings.isVisible = true settings.isVisible = true
return true return true
} }
} },
) )
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
@ -114,7 +114,8 @@ class HomeFragment : Fragment() {
} }
} }
}, },
viewLifecycleOwner, Lifecycle.State.RESUMED viewLifecycleOwner,
Lifecycle.State.RESUMED,
) )
} }
@ -155,7 +156,7 @@ class HomeFragment : Fragment() {
onOnlineClickListener = ViewListAdapter.OnClickListenerOfflineCard { onOnlineClickListener = ViewListAdapter.OnClickListenerOfflineCard {
appPreferences.offlineMode = false appPreferences.offlineMode = false
activity?.restart() activity?.restart()
} },
) )
binding.errorLayout.errorRetryButton.setOnClickListener { binding.errorLayout.errorRetryButton.setOnClickListener {
@ -211,8 +212,8 @@ class HomeFragment : Fragment() {
HomeFragmentDirections.actionNavigationHomeToLibraryFragment( HomeFragmentDirections.actionNavigationHomeToLibraryFragment(
libraryId = view.id, libraryId = view.id,
libraryName = view.name, libraryName = view.name,
libraryType = view.type libraryType = view.type,
) ),
) )
} }
@ -222,23 +223,23 @@ class HomeFragment : Fragment() {
findNavController().navigate( findNavController().navigate(
HomeFragmentDirections.actionNavigationHomeToMovieFragment( HomeFragmentDirections.actionNavigationHomeToMovieFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidShow -> { is FindroidShow -> {
findNavController().navigate( findNavController().navigate(
HomeFragmentDirections.actionNavigationHomeToShowFragment( HomeFragmentDirections.actionNavigationHomeToShowFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidEpisode -> { is FindroidEpisode -> {
findNavController().navigate( findNavController().navigate(
HomeFragmentDirections.actionNavigationHomeToEpisodeBottomSheetFragment( HomeFragmentDirections.actionNavigationHomeToEpisodeBottomSheetFragment(
item.id item.id,
) ),
) )
} }
} }
@ -246,13 +247,13 @@ class HomeFragment : Fragment() {
private fun navigateToSettingsFragment() { private fun navigateToSettingsFragment() {
findNavController().navigate( findNavController().navigate(
HomeFragmentDirections.actionHomeFragmentToSettingsFragment() HomeFragmentDirections.actionHomeFragmentToSettingsFragment(),
) )
} }
private fun navigateToSearchResultFragment(query: String) { private fun navigateToSearchResultFragment(query: String) {
findNavController().navigate( findNavController().navigate(
HomeFragmentDirections.actionHomeFragmentToSearchResultFragment(query) HomeFragmentDirections.actionHomeFragmentToSearchResultFragment(query),
) )
} }
} }

View file

@ -21,7 +21,6 @@ import androidx.paging.LoadState
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.AppPreferences import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.adapters.ViewItemPagingAdapter import dev.jdtech.jellyfin.adapters.ViewItemPagingAdapter
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.FragmentLibraryBinding import dev.jdtech.jellyfin.databinding.FragmentLibraryBinding
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
import dev.jdtech.jellyfin.dialogs.SortDialogFragment import dev.jdtech.jellyfin.dialogs.SortDialogFragment
@ -32,10 +31,11 @@ import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.models.SortBy import dev.jdtech.jellyfin.models.SortBy
import dev.jdtech.jellyfin.utils.checkIfLoginRequired import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.viewmodels.LibraryViewModel import dev.jdtech.jellyfin.viewmodels.LibraryViewModel
import java.lang.IllegalArgumentException
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.SortOrder import org.jellyfin.sdk.model.api.SortOrder
import java.lang.IllegalArgumentException
import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class LibraryFragment : Fragment() { class LibraryFragment : Fragment() {
@ -52,7 +52,7 @@ class LibraryFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentLibraryBinding.inflate(inflater, container, false) binding = FragmentLibraryBinding.inflate(inflater, container, false)
return binding.root return binding.root
@ -75,10 +75,10 @@ class LibraryFragment : Fragment() {
args.libraryId, args.libraryId,
args.libraryType, args.libraryType,
viewModel, viewModel,
"sortBy" "sortBy",
).show( ).show(
parentFragmentManager, parentFragmentManager,
"sortdialog" "sortdialog",
) )
true true
} }
@ -87,10 +87,10 @@ class LibraryFragment : Fragment() {
args.libraryId, args.libraryId,
args.libraryType, args.libraryType,
viewModel, viewModel,
"sortOrder" "sortOrder",
).show( ).show(
parentFragmentManager, parentFragmentManager,
"sortdialog" "sortdialog",
) )
true true
} }
@ -98,7 +98,8 @@ class LibraryFragment : Fragment() {
} }
} }
}, },
viewLifecycleOwner, Lifecycle.State.RESUMED viewLifecycleOwner,
Lifecycle.State.RESUMED,
) )
binding.errorLayout.errorRetryButton.setOnClickListener { binding.errorLayout.errorRetryButton.setOnClickListener {
@ -108,7 +109,7 @@ class LibraryFragment : Fragment() {
binding.errorLayout.errorDetailsButton.setOnClickListener { binding.errorLayout.errorDetailsButton.setOnClickListener {
errorDialog.show( errorDialog.show(
parentFragmentManager, parentFragmentManager,
ErrorDialogFragment.TAG ErrorDialogFragment.TAG,
) )
} }
@ -116,7 +117,7 @@ class LibraryFragment : Fragment() {
ViewItemPagingAdapter( ViewItemPagingAdapter(
ViewItemPagingAdapter.OnClickListener { item -> ViewItemPagingAdapter.OnClickListener { item ->
navigateToItem(item) navigateToItem(item)
} },
) )
(binding.itemsRecyclerView.adapter as ViewItemPagingAdapter).addLoadStateListener { (binding.itemsRecyclerView.adapter as ViewItemPagingAdapter).addLoadStateListener {
@ -162,7 +163,7 @@ class LibraryFragment : Fragment() {
args.libraryId, args.libraryId,
args.libraryType, args.libraryType,
sortBy = sortBy, sortBy = sortBy,
sortOrder = sortOrder sortOrder = sortOrder,
) )
} }
} }
@ -201,24 +202,24 @@ class LibraryFragment : Fragment() {
findNavController().navigate( findNavController().navigate(
LibraryFragmentDirections.actionLibraryFragmentToMovieFragment( LibraryFragmentDirections.actionLibraryFragmentToMovieFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidShow -> { is FindroidShow -> {
findNavController().navigate( findNavController().navigate(
LibraryFragmentDirections.actionLibraryFragmentToShowFragment( LibraryFragmentDirections.actionLibraryFragmentToShowFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidBoxSet -> { is FindroidBoxSet -> {
findNavController().navigate( findNavController().navigate(
LibraryFragmentDirections.actionLibraryFragmentToCollectionFragment( LibraryFragmentDirections.actionLibraryFragmentToCollectionFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
} }

View file

@ -17,13 +17,13 @@ import androidx.navigation.fragment.navArgs
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.AppPreferences import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.adapters.UserLoginListAdapter import dev.jdtech.jellyfin.adapters.UserLoginListAdapter
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.databinding.FragmentLoginBinding import dev.jdtech.jellyfin.databinding.FragmentLoginBinding
import dev.jdtech.jellyfin.viewmodels.LoginViewModel import dev.jdtech.jellyfin.viewmodels.LoginViewModel
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class LoginFragment : Fragment() { class LoginFragment : Fragment() {
@ -41,7 +41,7 @@ class LoginFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentLoginBinding.inflate(inflater) binding = FragmentLoginBinding.inflate(inflater)

View file

@ -20,7 +20,6 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.adapters.CollectionListAdapter import dev.jdtech.jellyfin.adapters.CollectionListAdapter
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.FragmentMediaBinding import dev.jdtech.jellyfin.databinding.FragmentMediaBinding
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
import dev.jdtech.jellyfin.models.FindroidCollection import dev.jdtech.jellyfin.models.FindroidCollection
@ -28,6 +27,7 @@ import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.viewmodels.MediaViewModel import dev.jdtech.jellyfin.viewmodels.MediaViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class MediaFragment : Fragment() { class MediaFragment : Fragment() {
@ -42,7 +42,7 @@ class MediaFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentMediaBinding.inflate(inflater, container, false) binding = FragmentMediaBinding.inflate(inflater, container, false)
@ -50,7 +50,7 @@ class MediaFragment : Fragment() {
CollectionListAdapter( CollectionListAdapter(
CollectionListAdapter.OnClickListener { library -> CollectionListAdapter.OnClickListener { library ->
navigateToLibraryFragment(library) navigateToLibraryFragment(library)
} },
) )
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
@ -108,7 +108,8 @@ class MediaFragment : Fragment() {
return true return true
} }
}, },
viewLifecycleOwner, Lifecycle.State.RESUMED viewLifecycleOwner,
Lifecycle.State.RESUMED,
) )
} }
@ -152,13 +153,13 @@ class MediaFragment : Fragment() {
libraryId = library.id, libraryId = library.id,
libraryName = library.name, libraryName = library.name,
libraryType = library.type, libraryType = library.type,
) ),
) )
} }
private fun navigateToSearchResultFragment(query: String) { private fun navigateToSearchResultFragment(query: String) {
findNavController().navigate( findNavController().navigate(
MediaFragmentDirections.actionNavigationMediaToSearchResultFragment(query) MediaFragmentDirections.actionNavigationMediaToSearchResultFragment(query),
) )
} }
} }

View file

@ -24,7 +24,6 @@ import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.R import dev.jdtech.jellyfin.R
import dev.jdtech.jellyfin.adapters.PersonListAdapter import dev.jdtech.jellyfin.adapters.PersonListAdapter
import dev.jdtech.jellyfin.bindItemBackdropImage import dev.jdtech.jellyfin.bindItemBackdropImage
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.FragmentMovieBinding import dev.jdtech.jellyfin.databinding.FragmentMovieBinding
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
import dev.jdtech.jellyfin.dialogs.getStorageSelectionDialog import dev.jdtech.jellyfin.dialogs.getStorageSelectionDialog
@ -40,10 +39,11 @@ import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
import dev.jdtech.jellyfin.viewmodels.MovieViewModel import dev.jdtech.jellyfin.viewmodels.MovieViewModel
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import java.util.UUID
import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class MovieFragment : Fragment() { class MovieFragment : Fragment() {
@ -61,7 +61,7 @@ class MovieFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentMovieBinding.inflate(inflater, container, false) binding = FragmentMovieBinding.inflate(inflater, container, false)
@ -152,13 +152,14 @@ class MovieFragment : Fragment() {
binding.itemActions.progressPlay.isVisible = true binding.itemActions.progressPlay.isVisible = true
if (viewModel.item.sources.filter { it.type == FindroidSourceType.REMOTE }.size > 1) { if (viewModel.item.sources.filter { it.type == FindroidSourceType.REMOTE }.size > 1) {
val dialog = getVideoVersionDialog( val dialog = getVideoVersionDialog(
requireContext(), viewModel.item, requireContext(),
viewModel.item,
onItemSelected = { onItemSelected = {
playerViewModel.loadPlayerItems(viewModel.item, it) playerViewModel.loadPlayerItems(viewModel.item, it)
}, },
onCancel = { onCancel = {
playButtonNormal() playButtonNormal()
} },
) )
dialog.show() dialog.show()
return@setOnClickListener return@setOnClickListener
@ -170,7 +171,7 @@ class MovieFragment : Fragment() {
viewModel.item.trailer.let { trailerUri -> viewModel.item.trailer.let { trailerUri ->
val intent = Intent( val intent = Intent(
Intent.ACTION_VIEW, Intent.ACTION_VIEW,
Uri.parse(trailerUri) Uri.parse(trailerUri),
) )
try { try {
startActivity(intent) startActivity(intent)
@ -215,7 +216,7 @@ class MovieFragment : Fragment() {
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} },
) )
dialog.show() dialog.show()
return@getStorageSelectionDialog return@getStorageSelectionDialog
@ -226,7 +227,7 @@ class MovieFragment : Fragment() {
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} },
) )
storageDialog.show() storageDialog.show()
return@setOnClickListener return@setOnClickListener
@ -242,7 +243,7 @@ class MovieFragment : Fragment() {
onCancel = { onCancel = {
binding.itemActions.progressDownload.isVisible = false binding.itemActions.progressDownload.isVisible = false
binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download) binding.itemActions.downloadButton.setIconResource(CoreR.drawable.ic_download)
} },
) )
dialog.show() dialog.show()
return@setOnClickListener return@setOnClickListener
@ -324,7 +325,8 @@ class MovieFragment : Fragment() {
videoProfileChip.isVisible = when (this) { videoProfileChip.isVisible = when (this) {
DisplayProfile.HDR, DisplayProfile.HDR,
DisplayProfile.HDR10, DisplayProfile.HDR10,
DisplayProfile.HLG -> { DisplayProfile.HLG,
-> {
videoProfileChip.chipStartPadding = .0f videoProfileChip.chipStartPadding = .0f
true true
} }
@ -411,7 +413,7 @@ class MovieFragment : Fragment() {
true -> binding.itemActions.checkButton.setIconTintResource(CoreR.color.red) true -> binding.itemActions.checkButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.checkButton.setIconTintColorAttribute( false -> binding.itemActions.checkButton.setIconTintColorAttribute(
com.google.android.material.R.attr.colorOnSecondaryContainer, com.google.android.material.R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme,
) )
} }
} }
@ -426,7 +428,7 @@ class MovieFragment : Fragment() {
true -> binding.itemActions.favoriteButton.setIconTintResource(CoreR.color.red) true -> binding.itemActions.favoriteButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.favoriteButton.setIconTintColorAttribute( false -> binding.itemActions.favoriteButton.setIconTintColorAttribute(
com.google.android.material.R.attr.colorOnSecondaryContainer, com.google.android.material.R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme,
) )
} }
} }
@ -494,14 +496,14 @@ class MovieFragment : Fragment() {
) { ) {
findNavController().navigate( findNavController().navigate(
MovieFragmentDirections.actionMovieFragmentToPlayerActivity( MovieFragmentDirections.actionMovieFragmentToPlayerActivity(
playerItems playerItems,
) ),
) )
} }
private fun navigateToPersonDetail(personId: UUID) { private fun navigateToPersonDetail(personId: UUID) {
findNavController().navigate( findNavController().navigate(
MovieFragmentDirections.actionMovieFragmentToPersonDetailFragment(personId) MovieFragmentDirections.actionMovieFragmentToPersonDetailFragment(personId),
) )
} }
} }

View file

@ -17,7 +17,6 @@ import androidx.navigation.fragment.navArgs
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
import dev.jdtech.jellyfin.bindItemImage import dev.jdtech.jellyfin.bindItemImage
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.FragmentPersonDetailBinding import dev.jdtech.jellyfin.databinding.FragmentPersonDetailBinding
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
@ -27,6 +26,7 @@ import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.viewmodels.PersonDetailViewModel import dev.jdtech.jellyfin.viewmodels.PersonDetailViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
internal class PersonDetailFragment : Fragment() { internal class PersonDetailFragment : Fragment() {
@ -41,7 +41,7 @@ internal class PersonDetailFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentPersonDetailBinding.inflate(inflater, container, false) binding = FragmentPersonDetailBinding.inflate(inflater, container, false)
return binding.root return binding.root
@ -120,7 +120,7 @@ internal class PersonDetailFragment : Fragment() {
private fun adapter() = ViewItemListAdapter( private fun adapter() = ViewItemListAdapter(
fixedWidth = true, fixedWidth = true,
onClickListener = ViewItemListAdapter.OnClickListener { navigateToMediaItem(it) } onClickListener = ViewItemListAdapter.OnClickListener { navigateToMediaItem(it) },
) )
private fun setupOverviewExpansion() = binding.overview.post { private fun setupOverviewExpansion() = binding.overview.post {
@ -145,16 +145,16 @@ internal class PersonDetailFragment : Fragment() {
findNavController().navigate( findNavController().navigate(
PersonDetailFragmentDirections.actionPersonDetailFragmentToMovieFragment( PersonDetailFragmentDirections.actionPersonDetailFragmentToMovieFragment(
itemId = item.id, itemId = item.id,
itemName = item.name itemName = item.name,
) ),
) )
} }
is FindroidShow -> { is FindroidShow -> {
findNavController().navigate( findNavController().navigate(
PersonDetailFragmentDirections.actionPersonDetailFragmentToShowFragment( PersonDetailFragmentDirections.actionPersonDetailFragmentToShowFragment(
itemId = item.id, itemId = item.id,
itemName = item.name itemName = item.name,
) ),
) )
} }
} }

View file

@ -39,7 +39,7 @@ class SearchResultFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentSearchResultBinding.inflate(inflater, container, false) binding = FragmentSearchResultBinding.inflate(inflater, container, false)
@ -49,7 +49,7 @@ class SearchResultFragment : Fragment() {
}, },
HomeEpisodeListAdapter.OnClickListener { item -> HomeEpisodeListAdapter.OnClickListener { item ->
navigateToMediaItem(item) navigateToMediaItem(item)
} },
) )
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
@ -113,23 +113,23 @@ class SearchResultFragment : Fragment() {
findNavController().navigate( findNavController().navigate(
SearchResultFragmentDirections.actionSearchResultFragmentToMovieFragment( SearchResultFragmentDirections.actionSearchResultFragmentToMovieFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidShow -> { is FindroidShow -> {
findNavController().navigate( findNavController().navigate(
SearchResultFragmentDirections.actionSearchResultFragmentToShowFragment( SearchResultFragmentDirections.actionSearchResultFragmentToShowFragment(
item.id, item.id,
item.name item.name,
) ),
) )
} }
is FindroidEpisode -> { is FindroidEpisode -> {
findNavController().navigate( findNavController().navigate(
SearchResultFragmentDirections.actionSearchResultFragmentToEpisodeBottomSheetFragment( SearchResultFragmentDirections.actionSearchResultFragmentToEpisodeBottomSheetFragment(
item.id item.id,
) ),
) )
} }
} }

View file

@ -37,7 +37,7 @@ class SeasonFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentSeasonBinding.inflate(inflater, container, false) binding = FragmentSeasonBinding.inflate(inflater, container, false)
return binding.root return binding.root
@ -124,8 +124,8 @@ class SeasonFragment : Fragment() {
private fun navigateToEpisodeBottomSheetFragment(episode: FindroidEpisode) { private fun navigateToEpisodeBottomSheetFragment(episode: FindroidEpisode) {
findNavController().navigate( findNavController().navigate(
SeasonFragmentDirections.actionSeasonFragmentToEpisodeBottomSheetFragment( SeasonFragmentDirections.actionSeasonFragmentToEpisodeBottomSheetFragment(
episode.id episode.id,
) ),
) )
} }
@ -134,8 +134,8 @@ class SeasonFragment : Fragment() {
) { ) {
findNavController().navigate( findNavController().navigate(
SeasonFragmentDirections.actionSeasonFragmentToPlayerActivity( SeasonFragmentDirections.actionSeasonFragmentToPlayerActivity(
playerItems playerItems,
) ),
) )
} }
} }

View file

@ -30,7 +30,7 @@ class ServerAddressesFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentServerAddressesBinding.inflate(inflater) binding = FragmentServerAddressesBinding.inflate(inflater)
@ -42,16 +42,16 @@ class ServerAddressesFragment : Fragment() {
{ address -> { address ->
DeleteServerAddressDialog(viewModel, address).show( DeleteServerAddressDialog(viewModel, address).show(
parentFragmentManager, parentFragmentManager,
"deleteServerAddress" "deleteServerAddress",
) )
true true
} },
) )
binding.buttonAddAddress.setOnClickListener { binding.buttonAddAddress.setOnClickListener {
AddServerAddressDialog(viewModel).show( AddServerAddressDialog(viewModel).show(
parentFragmentManager, parentFragmentManager,
"addServerAddress" "addServerAddress",
) )
} }

View file

@ -26,7 +26,7 @@ class ServerSelectFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentServerSelectBinding.inflate(inflater) binding = FragmentServerSelectBinding.inflate(inflater)
@ -42,10 +42,10 @@ class ServerSelectFragment : Fragment() {
ServerGridAdapter.OnLongClickListener { server -> ServerGridAdapter.OnLongClickListener { server ->
DeleteServerDialogFragment(viewModel, server).show( DeleteServerDialogFragment(viewModel, server).show(
parentFragmentManager, parentFragmentManager,
"deleteServer" "deleteServer",
) )
true true
} },
) )
binding.buttonAddServer.setOnClickListener { binding.buttonAddServer.setOnClickListener {
@ -67,7 +67,7 @@ class ServerSelectFragment : Fragment() {
private fun navigateToAddServerFragment() { private fun navigateToAddServerFragment() {
findNavController().navigate( findNavController().navigate(
ServerSelectFragmentDirections.actionServerSelectFragmentToAddServerFragment() ServerSelectFragmentDirections.actionServerSelectFragmentToAddServerFragment(),
) )
} }

View file

@ -5,8 +5,8 @@ import androidx.fragment.app.viewModels
import androidx.preference.EditTextPreference import androidx.preference.EditTextPreference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.viewmodels.SettingsDeviceViewModel import dev.jdtech.jellyfin.viewmodels.SettingsDeviceViewModel
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
@Suppress("unused") @Suppress("unused")

View file

@ -8,9 +8,9 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dev.jdtech.jellyfin.AppPreferences import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.utils.restart import dev.jdtech.jellyfin.utils.restart
import javax.inject.Inject import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class SettingsFragment : PreferenceFragmentCompat() { class SettingsFragment : PreferenceFragmentCompat() {
@ -45,7 +45,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
findPreference<Preference>("privacyPolicy")?.setOnPreferenceClickListener { findPreference<Preference>("privacyPolicy")?.setOnPreferenceClickListener {
val intent = Intent( val intent = Intent(
Intent.ACTION_VIEW, Intent.ACTION_VIEW,
Uri.parse("https://github.com/jarnedemeulemeester/findroid/blob/main/PRIVACY") Uri.parse("https://github.com/jarnedemeulemeester/findroid/blob/main/PRIVACY"),
) )
startActivity(intent) startActivity(intent)
true true

View file

@ -20,8 +20,8 @@ class SettingsLanguageFragment : PreferenceFragmentCompat() {
startActivity( startActivity(
Intent( Intent(
Settings.ACTION_APP_LOCALE_SETTINGS, Settings.ACTION_APP_LOCALE_SETTINGS,
Uri.parse("package:${requireContext().packageName}") Uri.parse("package:${requireContext().packageName}"),
) ),
) )
true true
} }

View file

@ -22,7 +22,6 @@ import dev.jdtech.jellyfin.adapters.PersonListAdapter
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
import dev.jdtech.jellyfin.bindCardItemImage import dev.jdtech.jellyfin.bindCardItemImage
import dev.jdtech.jellyfin.bindItemBackdropImage import dev.jdtech.jellyfin.bindItemBackdropImage
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.databinding.FragmentShowBinding import dev.jdtech.jellyfin.databinding.FragmentShowBinding
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
@ -34,10 +33,11 @@ import dev.jdtech.jellyfin.utils.checkIfLoginRequired
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
import dev.jdtech.jellyfin.viewmodels.ShowViewModel import dev.jdtech.jellyfin.viewmodels.ShowViewModel
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import java.util.UUID
import javax.inject.Inject
import dev.jdtech.jellyfin.core.R as CoreR
@AndroidEntryPoint @AndroidEntryPoint
class ShowFragment : Fragment() { class ShowFragment : Fragment() {
@ -55,7 +55,7 @@ class ShowFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentShowBinding.inflate(inflater, container, false) binding = FragmentShowBinding.inflate(inflater, container, false)
@ -104,7 +104,7 @@ class ShowFragment : Fragment() {
viewModel.item.trailer.let { trailerUri -> viewModel.item.trailer.let { trailerUri ->
val intent = Intent( val intent = Intent(
Intent.ACTION_VIEW, Intent.ACTION_VIEW,
Uri.parse(trailerUri) Uri.parse(trailerUri),
) )
try { try {
startActivity(intent) startActivity(intent)
@ -123,7 +123,7 @@ class ShowFragment : Fragment() {
ViewItemListAdapter.OnClickListener { season -> ViewItemListAdapter.OnClickListener { season ->
if (season is FindroidSeason) navigateToSeasonFragment(season) if (season is FindroidSeason) navigateToSeasonFragment(season)
}, },
fixedWidth = true fixedWidth = true,
) )
binding.peopleRecyclerView.adapter = PersonListAdapter { person -> binding.peopleRecyclerView.adapter = PersonListAdapter { person ->
navigateToPersonDetail(person.id) navigateToPersonDetail(person.id)
@ -183,9 +183,11 @@ class ShowFragment : Fragment() {
binding.itemActions.downloadButton.isVisible = true binding.itemActions.downloadButton.isVisible = true
binding.itemActions.downloadButton.isEnabled = !downloaded binding.itemActions.downloadButton.isEnabled = !downloaded
if (downloaded) binding.itemActions.downloadButton.setIconTintResource( if (downloaded) {
CoreR.color.red binding.itemActions.downloadButton.setIconTintResource(
) CoreR.color.red,
)
}
} }
false -> { false -> {
@ -222,7 +224,7 @@ class ShowFragment : Fragment() {
CoreR.string.episode_name_extended, CoreR.string.episode_name_extended,
nextUp?.parentIndexNumber, nextUp?.parentIndexNumber,
nextUp?.indexNumber, nextUp?.indexNumber,
nextUp?.name nextUp?.name,
) )
} else { } else {
binding.nextUpName.text = getString( binding.nextUpName.text = getString(
@ -230,7 +232,7 @@ class ShowFragment : Fragment() {
nextUp?.parentIndexNumber, nextUp?.parentIndexNumber,
nextUp?.indexNumber, nextUp?.indexNumber,
nextUp?.indexNumberEnd, nextUp?.indexNumberEnd,
nextUp?.name nextUp?.name,
) )
} }
@ -265,7 +267,7 @@ class ShowFragment : Fragment() {
true -> binding.itemActions.checkButton.setIconTintResource(CoreR.color.red) true -> binding.itemActions.checkButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.checkButton.setIconTintColorAttribute( false -> binding.itemActions.checkButton.setIconTintColorAttribute(
R.attr.colorOnSecondaryContainer, R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme,
) )
} }
} }
@ -280,7 +282,7 @@ class ShowFragment : Fragment() {
true -> binding.itemActions.favoriteButton.setIconTintResource(CoreR.color.red) true -> binding.itemActions.favoriteButton.setIconTintResource(CoreR.color.red)
false -> binding.itemActions.favoriteButton.setIconTintColorAttribute( false -> binding.itemActions.favoriteButton.setIconTintColorAttribute(
R.attr.colorOnSecondaryContainer, R.attr.colorOnSecondaryContainer,
requireActivity().theme requireActivity().theme,
) )
} }
} }
@ -310,8 +312,8 @@ class ShowFragment : Fragment() {
private fun navigateToEpisodeBottomSheetFragment(episode: FindroidItem) { private fun navigateToEpisodeBottomSheetFragment(episode: FindroidItem) {
findNavController().navigate( findNavController().navigate(
ShowFragmentDirections.actionShowFragmentToEpisodeBottomSheetFragment( ShowFragmentDirections.actionShowFragmentToEpisodeBottomSheetFragment(
episode.id episode.id,
) ),
) )
} }
@ -322,8 +324,8 @@ class ShowFragment : Fragment() {
season.id, season.id,
season.seriesName, season.seriesName,
season.name, season.name,
args.offline args.offline,
) ),
) )
} }
@ -332,14 +334,14 @@ class ShowFragment : Fragment() {
) { ) {
findNavController().navigate( findNavController().navigate(
ShowFragmentDirections.actionShowFragmentToPlayerActivity( ShowFragmentDirections.actionShowFragmentToPlayerActivity(
playerItems playerItems,
) ),
) )
} }
private fun navigateToPersonDetail(personId: UUID) { private fun navigateToPersonDetail(personId: UUID) {
findNavController().navigate( findNavController().navigate(
ShowFragmentDirections.actionShowFragmentToPersonDetailFragment(personId) ShowFragmentDirections.actionShowFragmentToPersonDetailFragment(personId),
) )
} }
} }

View file

@ -30,7 +30,7 @@ class UsersFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?,
): View { ): View {
binding = FragmentUsersBinding.inflate(inflater) binding = FragmentUsersBinding.inflate(inflater)
@ -42,10 +42,10 @@ class UsersFragment : Fragment() {
{ user -> { user ->
DeleteUserDialogFragment(viewModel, user).show( DeleteUserDialogFragment(viewModel, user).show(
parentFragmentManager, parentFragmentManager,
"deleteUser" "deleteUser",
) )
true true
} },
) )
binding.buttonAddUser.setOnClickListener { binding.buttonAddUser.setOnClickListener {
@ -90,7 +90,7 @@ class UsersFragment : Fragment() {
private fun navigateToLoginFragment() { private fun navigateToLoginFragment() {
findNavController().navigate( findNavController().navigate(
AppNavigationDirections.actionGlobalLoginFragment() AppNavigationDirections.actionGlobalLoginFragment(),
) )
} }

View file

@ -20,14 +20,14 @@ import dev.jdtech.jellyfin.Constants
import dev.jdtech.jellyfin.PlayerActivity import dev.jdtech.jellyfin.PlayerActivity
import dev.jdtech.jellyfin.isControlsLocked import dev.jdtech.jellyfin.isControlsLocked
import dev.jdtech.jellyfin.mpv.MPVPlayer import dev.jdtech.jellyfin.mpv.MPVPlayer
import kotlin.math.abs
import timber.log.Timber import timber.log.Timber
import kotlin.math.abs
class PlayerGestureHelper( class PlayerGestureHelper(
private val appPreferences: AppPreferences, private val appPreferences: AppPreferences,
private val activity: PlayerActivity, private val activity: PlayerActivity,
private val playerView: PlayerView, private val playerView: PlayerView,
private val audioManager: AudioManager private val audioManager: AudioManager,
) { ) {
/** /**
* Tracks whether video content should fill the screen, cutting off unwanted content on the sides. * Tracks whether video content should fill the screen, cutting off unwanted content on the sides.
@ -78,7 +78,7 @@ class PlayerGestureHelper(
} }
return true return true
} }
} },
) )
private val seekGestureDetector = GestureDetector( private val seekGestureDetector = GestureDetector(
@ -89,7 +89,7 @@ class PlayerGestureHelper(
firstEvent: MotionEvent, firstEvent: MotionEvent,
currentEvent: MotionEvent, currentEvent: MotionEvent,
distanceX: Float, distanceX: Float,
distanceY: Float distanceY: Float,
): Boolean { ): Boolean {
// Excludes area where app gestures conflicting with system gestures // Excludes area where app gestures conflicting with system gestures
if (inExclusionArea(firstEvent)) return false if (inExclusionArea(firstEvent)) return false
@ -114,11 +114,13 @@ class PlayerGestureHelper(
swipeGestureValueTrackerProgress = newPos swipeGestureValueTrackerProgress = newPos
swipeGestureProgressOpen = true swipeGestureProgressOpen = true
true true
} else false } else {
false
}
} }
return true return true
} }
} },
) )
private val vbGestureDetector = GestureDetector( private val vbGestureDetector = GestureDetector(
@ -129,7 +131,7 @@ class PlayerGestureHelper(
firstEvent: MotionEvent, firstEvent: MotionEvent,
currentEvent: MotionEvent, currentEvent: MotionEvent,
distanceX: Float, distanceX: Float,
distanceY: Float distanceY: Float,
): Boolean { ): Boolean {
// Excludes area where app gestures conflicting with system gestures // Excludes area where app gestures conflicting with system gestures
if (inExclusionArea(firstEvent)) return false if (inExclusionArea(firstEvent)) return false
@ -138,8 +140,9 @@ class PlayerGestureHelper(
if (abs(distanceY / distanceX) < 2) return false if (abs(distanceY / distanceX) < 2) return false
if (swipeGestureValueTrackerProgress > -1 || swipeGestureProgressOpen) if (swipeGestureValueTrackerProgress > -1 || swipeGestureProgressOpen) {
return false return false
}
val viewCenterX = playerView.measuredWidth / 2 val viewCenterX = playerView.measuredWidth / 2
@ -197,7 +200,7 @@ class PlayerGestureHelper(
} }
return true return true
} }
} },
) )
private val hideGestureVolumeIndicatorOverlayAction = Runnable { private val hideGestureVolumeIndicatorOverlayAction = Runnable {
@ -236,7 +239,7 @@ class PlayerGestureHelper(
} }
override fun onScaleEnd(detector: ScaleGestureDetector) = Unit override fun onScaleEnd(detector: ScaleGestureDetector) = Unit
} },
).apply { isQuickScaleEnabled = false } ).apply { isQuickScaleEnabled = false }
private fun updateZoomMode(enabled: Boolean) { private fun updateZoomMode(enabled: Boolean) {
@ -294,14 +297,16 @@ class PlayerGestureHelper(
if ((firstEvent.x < insets.left) || (firstEvent.x > (screenWidth - insets.right)) || if ((firstEvent.x < insets.left) || (firstEvent.x > (screenWidth - insets.right)) ||
(firstEvent.y < insets.top) || (firstEvent.y > (screenHeight - insets.bottom)) (firstEvent.y < insets.top) || (firstEvent.y > (screenHeight - insets.bottom))
) ) {
return true return true
}
} else if (firstEvent.y < playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_VERTICAL) || } else if (firstEvent.y < playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_VERTICAL) ||
firstEvent.y > screenHeight - playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_VERTICAL) || firstEvent.y > screenHeight - playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_VERTICAL) ||
firstEvent.x < playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_HORIZONTAL) || firstEvent.x < playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_HORIZONTAL) ||
firstEvent.x > screenWidth - playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_HORIZONTAL) firstEvent.x > screenWidth - playerView.resources.dip(Constants.GESTURE_EXCLUSION_AREA_HORIZONTAL)
) ) {
return true return true
}
return false return false
} }

View file

@ -17,7 +17,7 @@ class PreviewScrubListener(
private val scrubbingPreview: ImageView, private val scrubbingPreview: ImageView,
private val timeBarView: View, private val timeBarView: View,
private val player: Player, private val player: Player,
private val currentTrickPlay: StateFlow<BifData?> private val currentTrickPlay: StateFlow<BifData?>,
) : TimeBar.OnScrubListener { ) : TimeBar.OnScrubListener {
private val roundedCorners = RoundedCornersTransformation(10f) private val roundedCorners = RoundedCornersTransformation(10f)
@ -26,8 +26,9 @@ class PreviewScrubListener(
override fun onScrubStart(timeBar: TimeBar, position: Long) { override fun onScrubStart(timeBar: TimeBar, position: Long) {
Timber.d("Scrubbing started at $position") Timber.d("Scrubbing started at $position")
if (currentTrickPlay.value == null) if (currentTrickPlay.value == null) {
return return
}
scrubbingPreview.visibility = View.VISIBLE scrubbingPreview.visibility = View.VISIBLE
onScrubMove(timeBar, position) onScrubMove(timeBar, position)

View file

@ -19,13 +19,13 @@ object ApiModule {
fun provideJellyfinApi( fun provideJellyfinApi(
@ApplicationContext application: Context, @ApplicationContext application: Context,
appPreferences: AppPreferences, appPreferences: AppPreferences,
serverDatabase: ServerDatabaseDao serverDatabase: ServerDatabaseDao,
): JellyfinApi { ): JellyfinApi {
val jellyfinApi = JellyfinApi.getInstance( val jellyfinApi = JellyfinApi.getInstance(
context = application, context = application,
requestTimeout = appPreferences.requestTimeout, requestTimeout = appPreferences.requestTimeout,
connectTimeout = appPreferences.connectTimeout, connectTimeout = appPreferences.connectTimeout,
socketTimeout = appPreferences.socketTimeout socketTimeout = appPreferences.socketTimeout,
) )
val serverId = appPreferences.currentServer ?: return jellyfinApi val serverId = appPreferences.currentServer ?: return jellyfinApi

View file

@ -20,7 +20,7 @@ object DatabaseModule {
return Room.databaseBuilder( return Room.databaseBuilder(
app.applicationContext, app.applicationContext,
ServerDatabase::class.java, ServerDatabase::class.java,
"servers" "servers",
) )
.fallbackToDestructiveMigration() .fallbackToDestructiveMigration()
.allowMainThreadQueries() .allowMainThreadQueries()

View file

@ -10,7 +10,7 @@ import dev.jdtech.jellyfin.viewmodels.ServerAddressesViewModel
import java.lang.IllegalStateException import java.lang.IllegalStateException
class AddServerAddressDialog( class AddServerAddressDialog(
private val viewModel: ServerAddressesViewModel private val viewModel: ServerAddressesViewModel,
) : DialogFragment() { ) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val editText = EditText(this.context) val editText = EditText(this.context)

View file

@ -11,7 +11,7 @@ import java.lang.IllegalStateException
class DeleteServerAddressDialog( class DeleteServerAddressDialog(
private val viewModel: ServerAddressesViewModel, private val viewModel: ServerAddressesViewModel,
val address: ServerAddress val address: ServerAddress,
) : DialogFragment() { ) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let { return activity?.let {

View file

@ -10,17 +10,17 @@ import dev.jdtech.jellyfin.core.R
import dev.jdtech.jellyfin.models.CollectionType import dev.jdtech.jellyfin.models.CollectionType
import dev.jdtech.jellyfin.models.SortBy import dev.jdtech.jellyfin.models.SortBy
import dev.jdtech.jellyfin.viewmodels.LibraryViewModel import dev.jdtech.jellyfin.viewmodels.LibraryViewModel
import org.jellyfin.sdk.model.api.SortOrder
import java.lang.IllegalStateException import java.lang.IllegalStateException
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
import org.jellyfin.sdk.model.api.SortOrder
@AndroidEntryPoint @AndroidEntryPoint
class SortDialogFragment( class SortDialogFragment(
private val parentId: UUID, private val parentId: UUID,
private val libraryType: CollectionType, private val libraryType: CollectionType,
private val viewModel: LibraryViewModel, private val viewModel: LibraryViewModel,
private val sortType: String private val sortType: String,
) : DialogFragment() { ) : DialogFragment() {
@Inject @Inject
lateinit var appPreferences: AppPreferences lateinit var appPreferences: AppPreferences
@ -48,7 +48,8 @@ class SortDialogFragment(
builder builder
.setTitle(getString(R.string.sort_by)) .setTitle(getString(R.string.sort_by))
.setSingleChoiceItems( .setSingleChoiceItems(
sortByOptions, currentSortBy.ordinal sortByOptions,
currentSortBy.ordinal,
) { dialog, which -> ) { dialog, which ->
val sortBy = sortByValues[which] val sortBy = sortByValues[which]
appPreferences.sortBy = sortBy.name appPreferences.sortBy = sortBy.name
@ -56,7 +57,7 @@ class SortDialogFragment(
parentId, parentId,
libraryType, libraryType,
sortBy = sortBy, sortBy = sortBy,
sortOrder = currentSortOrder sortOrder = currentSortOrder,
) )
dialog.dismiss() dialog.dismiss()
} }
@ -68,7 +69,8 @@ class SortDialogFragment(
builder builder
.setTitle(getString(R.string.sort_order)) .setTitle(getString(R.string.sort_order))
.setSingleChoiceItems( .setSingleChoiceItems(
sortByOptions, currentSortOrder.ordinal sortByOptions,
currentSortOrder.ordinal,
) { dialog, which -> ) { dialog, which ->
val sortOrder = try { val sortOrder = try {
sortOrderValues[which] sortOrderValues[which]
@ -82,7 +84,7 @@ class SortDialogFragment(
parentId, parentId,
libraryType, libraryType,
sortBy = currentSortBy, sortBy = currentSortBy,
sortOrder = sortOrder sortOrder = sortOrder,
) )
dialog.dismiss() dialog.dismiss()
} }

View file

@ -3,5 +3,5 @@ package dev.jdtech.jellyfin.models
data class DiscoveredServer( data class DiscoveredServer(
val id: String, val id: String,
val name: String, val name: String,
val address: String val address: String,
) )

View file

@ -6,5 +6,5 @@ data class DownloadSection(
val id: UUID, val id: UUID,
val name: String, val name: String,
val items: List<PlayerItem>? = null, val items: List<PlayerItem>? = null,
val series: List<DownloadSeriesMetadata>? = null val series: List<DownloadSeriesMetadata>? = null,
) )

View file

@ -1,9 +1,9 @@
package dev.jdtech.jellyfin.models package dev.jdtech.jellyfin.models
data class ExceptionUiText( data class ExceptionUiText(
val uiText: UiText val uiText: UiText,
) : Exception() ) : Exception()
data class ExceptionUiTexts( data class ExceptionUiTexts(
val uiTexts: Collection<UiText> val uiTexts: Collection<UiText>,
) : Exception() ) : Exception()

View file

@ -3,5 +3,5 @@ package dev.jdtech.jellyfin.models
data class FavoriteSection( data class FavoriteSection(
val id: Int, val id: Int,
val name: UiText, val name: UiText,
var items: List<FindroidItem> var items: List<FindroidItem>,
) )

View file

@ -5,5 +5,5 @@ import java.util.UUID
data class HomeSection( data class HomeSection(
val id: UUID, val id: UUID,
val name: UiText, val name: UiText,
var items: List<FindroidItem> var items: List<FindroidItem>,
) )

View file

@ -7,7 +7,7 @@ sealed class UiText {
data class DynamicString(val value: String) : UiText() data class DynamicString(val value: String) : UiText()
class StringResource( class StringResource(
@StringRes val resId: Int, @StringRes val resId: Int,
vararg val args: Any? vararg val args: Any?,
) : UiText() ) : UiText()
fun asString(resources: Resources): String { fun asString(resources: Resources): String {

View file

@ -6,5 +6,5 @@ data class View(
val id: UUID, val id: UUID,
val name: String, val name: String,
var items: List<FindroidItem>? = null, var items: List<FindroidItem>? = null,
val type: CollectionType val type: CollectionType,
) )

View file

@ -11,14 +11,14 @@ import androidx.annotation.AttrRes
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import dev.jdtech.jellyfin.models.CollectionType import dev.jdtech.jellyfin.models.CollectionType
import dev.jdtech.jellyfin.models.View import dev.jdtech.jellyfin.models.View
import java.io.Serializable
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import java.io.Serializable
fun BaseItemDto.toView(): View { fun BaseItemDto.toView(): View {
return View( return View(
id = id, id = id,
name = name ?: "", name = name ?: "",
type = valueOf(collectionType, CollectionType.Movies) type = valueOf(collectionType, CollectionType.Movies),
) )
} }
@ -30,14 +30,17 @@ fun MaterialButton.setIconTintColorAttribute(@AttrRes attributeId: Int, theme: R
this.iconTint = ColorStateList.valueOf( this.iconTint = ColorStateList.valueOf(
resources.getColor( resources.getColor(
typedValue.resourceId, typedValue.resourceId,
theme theme,
) ),
) )
} }
inline fun <reified T : Serializable> Bundle.serializable(key: String): T? = when { inline fun <reified T : Serializable> Bundle.serializable(key: String): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializable(key, T::class.java) Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializable(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializable(key) as? T else ->
@Suppress("DEPRECATION")
getSerializable(key)
as? T
} }
fun Activity.restart() { fun Activity.restart() {

View file

@ -13,11 +13,11 @@ import dev.jdtech.jellyfin.models.toFindroidSeason
import dev.jdtech.jellyfin.models.toFindroidShow import dev.jdtech.jellyfin.models.toFindroidShow
import dev.jdtech.jellyfin.models.toFindroidSource import dev.jdtech.jellyfin.models.toFindroidSource
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.io.File
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class DownloadReceiver : BroadcastReceiver() { class DownloadReceiver : BroadcastReceiver() {
@ -44,16 +44,16 @@ class DownloadReceiver : BroadcastReceiver() {
} else { } else {
val items = mutableListOf<FindroidItem>() val items = mutableListOf<FindroidItem>()
items.addAll( items.addAll(
database.getMovies().map { it.toFindroidMovie(database, repository.getUserId()) } database.getMovies().map { it.toFindroidMovie(database, repository.getUserId()) },
) )
items.addAll( items.addAll(
database.getShows().map { it.toFindroidShow(database, repository.getUserId()) } database.getShows().map { it.toFindroidShow(database, repository.getUserId()) },
) )
items.addAll( items.addAll(
database.getSeasons().map { it.toFindroidSeason(database, repository.getUserId()) } database.getSeasons().map { it.toFindroidSeason(database, repository.getUserId()) },
) )
items.addAll( items.addAll(
database.getEpisodes().map { it.toFindroidEpisode(database, repository.getUserId()) } database.getEpisodes().map { it.toFindroidEpisode(database, repository.getUserId()) },
) )
items.firstOrNull { it.id == source.itemId }?.let { items.firstOrNull { it.id == source.itemId }?.let {

View file

@ -8,7 +8,6 @@ import android.os.StatFs
import android.text.format.Formatter import android.text.format.Formatter
import androidx.core.net.toUri import androidx.core.net.toUri
import dev.jdtech.jellyfin.AppPreferences import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.core.R as CoreR
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.models.FindroidEpisode import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
@ -29,6 +28,7 @@ import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.io.File import java.io.File
import java.util.UUID import java.util.UUID
import kotlin.Exception import kotlin.Exception
import dev.jdtech.jellyfin.core.R as CoreR
class DownloaderImpl( class DownloaderImpl(
private val context: Context, private val context: Context,
@ -50,7 +50,7 @@ class DownloaderImpl(
val trickPlayData = if (trickPlayManifest != null) { val trickPlayData = if (trickPlayManifest != null) {
jellyfinRepository.getTrickPlayData( jellyfinRepository.getTrickPlayData(
item.id, item.id,
trickPlayManifest.widthResolutions.max() trickPlayManifest.widthResolutions.max(),
) )
} else { } else {
null null
@ -68,8 +68,8 @@ class DownloaderImpl(
UiText.StringResource( UiText.StringResource(
CoreR.string.not_enough_storage, CoreR.string.not_enough_storage,
Formatter.formatFileSize(context, source.size), Formatter.formatFileSize(context, source.size),
Formatter.formatFileSize(context, stats.availableBytes) Formatter.formatFileSize(context, stats.availableBytes),
) ),
) )
} }
when (item) { when (item) {
@ -98,10 +98,10 @@ class DownloaderImpl(
is FindroidEpisode -> { is FindroidEpisode -> {
database.insertShow( database.insertShow(
jellyfinRepository.getShow(item.seriesId) jellyfinRepository.getShow(item.seriesId)
.toFindroidShowDto(appPreferences.currentServer!!) .toFindroidShowDto(appPreferences.currentServer!!),
) )
database.insertSeason( database.insertSeason(
jellyfinRepository.getSeason(item.seasonId).toFindroidSeasonDto() jellyfinRepository.getSeason(item.seasonId).toFindroidSeasonDto(),
) )
database.insertEpisode(item.toFindroidEpisodeDto(appPreferences.currentServer!!)) database.insertEpisode(item.toFindroidEpisodeDto(appPreferences.currentServer!!))
database.insertSource(source.toFindroidSourceDto(item.id, path.path.orEmpty())) database.insertSource(source.toFindroidSourceDto(item.id, path.path.orEmpty()))
@ -189,8 +189,8 @@ class DownloaderImpl(
if (cursor.moveToFirst()) { if (cursor.moveToFirst()) {
downloadStatus = cursor.getInt( downloadStatus = cursor.getInt(
cursor.getColumnIndexOrThrow( cursor.getColumnIndexOrThrow(
DownloadManager.COLUMN_STATUS DownloadManager.COLUMN_STATUS,
) ),
) )
when (downloadStatus) { when (downloadStatus) {
DownloadManager.STATUS_RUNNING -> { DownloadManager.STATUS_RUNNING -> {
@ -233,7 +233,7 @@ class DownloaderImpl(
private fun downloadTrickPlay( private fun downloadTrickPlay(
item: FindroidItem, item: FindroidItem,
trickPlayManifest: TrickPlayManifest, trickPlayManifest: TrickPlayManifest,
byteArray: ByteArray byteArray: ByteArray,
) { ) {
database.insertTrickPlayManifest(trickPlayManifest.toTrickPlayManifestDto(item.id)) database.insertTrickPlayManifest(trickPlayManifest.toTrickPlayManifestDto(item.id))
File(context.filesDir, "trickplay").mkdirs() File(context.filesDir, "trickplay").mkdirs()

View file

@ -13,8 +13,6 @@ import dev.jdtech.jellyfin.models.ExceptionUiTexts
import dev.jdtech.jellyfin.models.Server import dev.jdtech.jellyfin.models.Server
import dev.jdtech.jellyfin.models.ServerAddress import dev.jdtech.jellyfin.models.ServerAddress
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
@ -27,6 +25,8 @@ import org.jellyfin.sdk.discovery.RecommendedServerInfo
import org.jellyfin.sdk.discovery.RecommendedServerInfoScore import org.jellyfin.sdk.discovery.RecommendedServerInfoScore
import org.jellyfin.sdk.discovery.RecommendedServerIssue import org.jellyfin.sdk.discovery.RecommendedServerIssue
import timber.log.Timber import timber.log.Timber
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class AddServerViewModel class AddServerViewModel
@ -34,7 +34,7 @@ class AddServerViewModel
constructor( constructor(
private val appPreferences: AppPreferences, private val appPreferences: AppPreferences,
private val jellyfinApi: JellyfinApi, private val jellyfinApi: JellyfinApi,
private val database: ServerDatabaseDao private val database: ServerDatabaseDao,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Normal) private val _uiState = MutableStateFlow<UiState>(UiState.Normal)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -65,11 +65,11 @@ constructor(
DiscoveredServer( DiscoveredServer(
serverDiscoveryInfo.id, serverDiscoveryInfo.id,
serverDiscoveryInfo.name, serverDiscoveryInfo.name,
serverDiscoveryInfo.address serverDiscoveryInfo.address,
) ),
) )
_discoveredServersState.emit( _discoveredServersState.emit(
DiscoveredServersState.Servers(ArrayList(discoveredServers)) DiscoveredServersState.Servers(ArrayList(discoveredServers)),
) )
} }
} }
@ -96,7 +96,7 @@ constructor(
val candidates = jellyfinApi.jellyfin.discovery.getAddressCandidates(inputValue) val candidates = jellyfinApi.jellyfin.discovery.getAddressCandidates(inputValue)
val recommended = jellyfinApi.jellyfin.discovery.getRecommendedServers( val recommended = jellyfinApi.jellyfin.discovery.getRecommendedServers(
candidates, candidates,
RecommendedServerInfoScore.OK RecommendedServerInfoScore.OK,
) )
val goodServers = mutableListOf<RecommendedServerInfo>() val goodServers = mutableListOf<RecommendedServerInfo>()
@ -139,17 +139,17 @@ constructor(
} catch (_: CancellationException) { } catch (_: CancellationException) {
} catch (e: ExceptionUiText) { } catch (e: ExceptionUiText) {
_uiState.emit( _uiState.emit(
UiState.Error(listOf(e.uiText)) UiState.Error(listOf(e.uiText)),
) )
} catch (e: ExceptionUiTexts) { } catch (e: ExceptionUiTexts) {
_uiState.emit( _uiState.emit(
UiState.Error(e.uiTexts) UiState.Error(e.uiTexts),
) )
} catch (e: Exception) { } catch (e: Exception) {
_uiState.emit( _uiState.emit(
UiState.Error( UiState.Error(
listOf(if (e.message != null) UiText.DynamicString(e.message!!) else UiText.StringResource(R.string.unknown_error)) listOf(if (e.message != null) UiText.DynamicString(e.message!!) else UiText.StringResource(R.string.unknown_error)),
) ),
) )
} }
} }
@ -173,7 +173,7 @@ constructor(
val serverAddress = ServerAddress( val serverAddress = ServerAddress(
id = UUID.randomUUID(), id = UUID.randomUUID(),
serverId = serverInDatabase.id, serverId = serverInDatabase.id,
address = recommendedServerInfo.address address = recommendedServerInfo.address,
) )
insertServerAddress(serverAddress) insertServerAddress(serverAddress)
@ -183,7 +183,7 @@ constructor(
val serverAddress = ServerAddress( val serverAddress = ServerAddress(
id = UUID.randomUUID(), id = UUID.randomUUID(),
serverId = serverInfo.id!!, serverId = serverInfo.id!!,
address = recommendedServerInfo.address address = recommendedServerInfo.address,
) )
val server = Server( val server = Server(

View file

@ -11,19 +11,19 @@ import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.FindroidShow import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class CollectionViewModel class CollectionViewModel
@Inject @Inject
constructor( constructor(
private val jellyfinRepository: JellyfinRepository private val jellyfinRepository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -52,29 +52,35 @@ constructor(
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_MOVIES, Constants.FAVORITE_TYPE_MOVIES,
UiText.StringResource(R.string.movies_label), UiText.StringResource(R.string.movies_label),
items.filterIsInstance<FindroidMovie>() items.filterIsInstance<FindroidMovie>(),
).let { ).let {
if (it.items.isNotEmpty()) favoriteSections.add( if (it.items.isNotEmpty()) {
it favoriteSections.add(
) it,
)
}
} }
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_SHOWS, Constants.FAVORITE_TYPE_SHOWS,
UiText.StringResource(R.string.shows_label), UiText.StringResource(R.string.shows_label),
items.filterIsInstance<FindroidShow>() items.filterIsInstance<FindroidShow>(),
).let { ).let {
if (it.items.isNotEmpty()) favoriteSections.add( if (it.items.isNotEmpty()) {
it favoriteSections.add(
) it,
)
}
} }
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_EPISODES, Constants.FAVORITE_TYPE_EPISODES,
UiText.StringResource(R.string.episodes_label), UiText.StringResource(R.string.episodes_label),
items.filterIsInstance<FindroidEpisode>() items.filterIsInstance<FindroidEpisode>(),
).let { ).let {
if (it.items.isNotEmpty()) favoriteSections.add( if (it.items.isNotEmpty()) {
it favoriteSections.add(
) it,
)
}
} }
} }

View file

@ -11,20 +11,20 @@ import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.FindroidShow import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import javax.inject.Inject
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class DownloadsViewModel class DownloadsViewModel
@Inject @Inject
constructor( constructor(
private val appPreferences: AppPreferences, private val appPreferences: AppPreferences,
private val repository: JellyfinRepository private val repository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -65,20 +65,24 @@ constructor(
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_MOVIES, Constants.FAVORITE_TYPE_MOVIES,
UiText.StringResource(R.string.movies_label), UiText.StringResource(R.string.movies_label),
items.filterIsInstance<FindroidMovie>() items.filterIsInstance<FindroidMovie>(),
).let { ).let {
if (it.items.isNotEmpty()) sections.add( if (it.items.isNotEmpty()) {
it sections.add(
) it,
)
}
} }
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_SHOWS, Constants.FAVORITE_TYPE_SHOWS,
UiText.StringResource(R.string.shows_label), UiText.StringResource(R.string.shows_label),
items.filterIsInstance<FindroidShow>() items.filterIsInstance<FindroidShow>(),
).let { ).let {
if (it.items.isNotEmpty()) sections.add( if (it.items.isNotEmpty()) {
it sections.add(
) it,
)
}
} }
_uiState.emit(UiState.Normal(sections)) _uiState.emit(UiState.Normal(sections))
} }

View file

@ -13,15 +13,15 @@ import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.models.isDownloading import dev.jdtech.jellyfin.models.isDownloading
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import dev.jdtech.jellyfin.utils.Downloader import dev.jdtech.jellyfin.utils.Downloader
import java.io.File
import java.util.UUID
import javax.inject.Inject
import kotlin.random.Random
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File
import java.util.UUID
import javax.inject.Inject
import kotlin.random.Random
@HiltViewModel @HiltViewModel
class EpisodeBottomSheetViewModel class EpisodeBottomSheetViewModel
@ -71,7 +71,7 @@ constructor(
_uiState.emit( _uiState.emit(
UiState.Normal( UiState.Normal(
item, item,
) ),
) )
} catch (_: NullPointerException) { } catch (_: NullPointerException) {
// Navigate back because item does not exist (probably because it's been deleted) // Navigate back because item does not exist (probably because it's been deleted)

View file

@ -11,18 +11,18 @@ import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.FindroidShow import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class FavoriteViewModel class FavoriteViewModel
@Inject @Inject
constructor( constructor(
private val jellyfinRepository: JellyfinRepository private val jellyfinRepository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -49,29 +49,35 @@ constructor(
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_MOVIES, Constants.FAVORITE_TYPE_MOVIES,
UiText.StringResource(R.string.movies_label), UiText.StringResource(R.string.movies_label),
items.filterIsInstance<FindroidMovie>() items.filterIsInstance<FindroidMovie>(),
).let { ).let {
if (it.items.isNotEmpty()) favoriteSections.add( if (it.items.isNotEmpty()) {
it favoriteSections.add(
) it,
)
}
} }
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_SHOWS, Constants.FAVORITE_TYPE_SHOWS,
UiText.StringResource(R.string.shows_label), UiText.StringResource(R.string.shows_label),
items.filterIsInstance<FindroidShow>() items.filterIsInstance<FindroidShow>(),
).let { ).let {
if (it.items.isNotEmpty()) favoriteSections.add( if (it.items.isNotEmpty()) {
it favoriteSections.add(
) it,
)
}
} }
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_EPISODES, Constants.FAVORITE_TYPE_EPISODES,
UiText.StringResource(R.string.episodes_label), UiText.StringResource(R.string.episodes_label),
items.filterIsInstance<FindroidEpisode>() items.filterIsInstance<FindroidEpisode>(),
).let { ).let {
if (it.items.isNotEmpty()) favoriteSections.add( if (it.items.isNotEmpty()) {
it favoriteSections.add(
) it,
)
}
} }
} }

View file

@ -11,11 +11,11 @@ import dev.jdtech.jellyfin.models.HomeSection
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import dev.jdtech.jellyfin.utils.toView import dev.jdtech.jellyfin.utils.toView
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class HomeViewModel @Inject internal constructor( class HomeViewModel @Inject internal constructor(
@ -77,8 +77,8 @@ class HomeViewModel @Inject internal constructor(
HomeSection( HomeSection(
uuidLibraries, uuidLibraries,
uiTextLibraries, uiTextLibraries,
collections collections,
) ),
) )
} }
@ -92,8 +92,8 @@ class HomeViewModel @Inject internal constructor(
HomeSection( HomeSection(
uuidContinueWatching, uuidContinueWatching,
uiTextContinueWatching, uiTextContinueWatching,
resumeItems resumeItems,
) ),
) )
} }
@ -102,8 +102,8 @@ class HomeViewModel @Inject internal constructor(
HomeSection( HomeSection(
uuidNextUp, uuidNextUp,
uiTextNextUp, uiTextNextUp,
nextUpItems nextUpItems,
) ),
) )
} }

View file

@ -9,8 +9,6 @@ import dev.jdtech.jellyfin.models.CollectionType
import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidItem
import dev.jdtech.jellyfin.models.SortBy import dev.jdtech.jellyfin.models.SortBy
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@ -18,12 +16,14 @@ import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.SortOrder import org.jellyfin.sdk.model.api.SortOrder
import timber.log.Timber import timber.log.Timber
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class LibraryViewModel class LibraryViewModel
@Inject @Inject
constructor( constructor(
private val jellyfinRepository: JellyfinRepository private val jellyfinRepository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -40,7 +40,7 @@ constructor(
parentId: UUID, parentId: UUID,
libraryType: CollectionType, libraryType: CollectionType,
sortBy: SortBy = SortBy.defaultValue, sortBy: SortBy = SortBy.defaultValue,
sortOrder: SortOrder = SortOrder.ASCENDING sortOrder: SortOrder = SortOrder.ASCENDING,
) { ) {
itemsloaded = true itemsloaded = true
Timber.d("$libraryType") Timber.d("$libraryType")
@ -58,7 +58,7 @@ constructor(
includeTypes = itemType, includeTypes = itemType,
recursive = true, recursive = true,
sortBy = sortBy, sortBy = sortBy,
sortOrder = sortOrder sortOrder = sortOrder,
).cachedIn(viewModelScope) ).cachedIn(viewModelScope)
_uiState.emit(UiState.Normal(items)) _uiState.emit(UiState.Normal(items))
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -9,8 +9,6 @@ import dev.jdtech.jellyfin.core.R
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.models.User import dev.jdtech.jellyfin.models.User
import javax.inject.Inject
import kotlin.Exception
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -23,6 +21,8 @@ import kotlinx.coroutines.withContext
import org.jellyfin.sdk.api.client.extensions.authenticateWithQuickConnect import org.jellyfin.sdk.api.client.extensions.authenticateWithQuickConnect
import org.jellyfin.sdk.model.api.AuthenticateUserByName import org.jellyfin.sdk.model.api.AuthenticateUserByName
import org.jellyfin.sdk.model.api.AuthenticationResult import org.jellyfin.sdk.model.api.AuthenticationResult
import javax.inject.Inject
import kotlin.Exception
@HiltViewModel @HiltViewModel
class LoginViewModel class LoginViewModel
@ -30,7 +30,7 @@ class LoginViewModel
constructor( constructor(
private val appPreferences: AppPreferences, private val appPreferences: AppPreferences,
private val jellyfinApi: JellyfinApi, private val jellyfinApi: JellyfinApi,
private val database: ServerDatabaseDao private val database: ServerDatabaseDao,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Normal) private val _uiState = MutableStateFlow<UiState>(UiState.Normal)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -114,8 +114,8 @@ constructor(
val authenticationResult by jellyfinApi.userApi.authenticateUserByName( val authenticationResult by jellyfinApi.userApi.authenticateUserByName(
data = AuthenticateUserByName( data = AuthenticateUserByName(
username = username, username = username,
pw = password pw = password,
) ),
) )
saveAuthenticationResult(authenticationResult) saveAuthenticationResult(authenticationResult)
@ -124,8 +124,10 @@ constructor(
_navigateToMain.emit(true) _navigateToMain.emit(true)
} catch (e: Exception) { } catch (e: Exception) {
val message = val message =
if (e.message?.contains("401") == true) UiText.StringResource(R.string.login_error_wrong_username_password) else UiText.StringResource( if (e.message?.contains("401") == true) {
R.string.unknown_error UiText.StringResource(R.string.login_error_wrong_username_password)
} else UiText.StringResource(
R.string.unknown_error,
) )
_uiState.emit(UiState.Error(message)) _uiState.emit(UiState.Error(message))
} }
@ -147,7 +149,7 @@ constructor(
delay(5000L) delay(5000L)
} }
val authenticationResult by jellyfinApi.userApi.authenticateWithQuickConnect( val authenticationResult by jellyfinApi.userApi.authenticateWithQuickConnect(
secret = quickConnectState.secret secret = quickConnectState.secret,
) )
saveAuthenticationResult(authenticationResult) saveAuthenticationResult(authenticationResult)
@ -167,7 +169,7 @@ constructor(
id = authenticationResult.user!!.id, id = authenticationResult.user!!.id,
name = authenticationResult.user!!.name!!, name = authenticationResult.user!!.name!!,
serverId = serverInfo.id!!, serverId = serverInfo.id!!,
accessToken = authenticationResult.accessToken!! accessToken = authenticationResult.accessToken!!,
) )
insertUser(appPreferences.currentServer!!, user) insertUser(appPreferences.currentServer!!, user)

View file

@ -6,16 +6,16 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.models.CollectionType import dev.jdtech.jellyfin.models.CollectionType
import dev.jdtech.jellyfin.models.FindroidCollection import dev.jdtech.jellyfin.models.FindroidCollection
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class MediaViewModel class MediaViewModel
@Inject @Inject
constructor( constructor(
private val jellyfinRepository: JellyfinRepository private val jellyfinRepository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
@ -41,7 +41,7 @@ constructor(
_uiState.emit(UiState.Normal(collections)) _uiState.emit(UiState.Normal(collections))
} catch (e: Exception) { } catch (e: Exception) {
_uiState.emit( _uiState.emit(
UiState.Error(e) UiState.Error(e),
) )
} }
} }

View file

@ -19,10 +19,6 @@ import dev.jdtech.jellyfin.models.VideoMetadata
import dev.jdtech.jellyfin.models.isDownloading import dev.jdtech.jellyfin.models.isDownloading
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import dev.jdtech.jellyfin.utils.Downloader import dev.jdtech.jellyfin.utils.Downloader
import java.io.File
import java.util.UUID
import javax.inject.Inject
import kotlin.random.Random
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Runnable import kotlinx.coroutines.Runnable
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
@ -34,6 +30,10 @@ import kotlinx.coroutines.withContext
import org.jellyfin.sdk.model.api.BaseItemPerson import org.jellyfin.sdk.model.api.BaseItemPerson
import org.jellyfin.sdk.model.api.MediaStream import org.jellyfin.sdk.model.api.MediaStream
import org.jellyfin.sdk.model.api.MediaStreamType import org.jellyfin.sdk.model.api.MediaStreamType
import java.io.File
import java.util.UUID
import javax.inject.Inject
import kotlin.random.Random
@HiltViewModel @HiltViewModel
class MovieViewModel class MovieViewModel
@ -41,7 +41,7 @@ class MovieViewModel
constructor( constructor(
private val repository: JellyfinRepository, private val repository: JellyfinRepository,
private val database: ServerDatabaseDao, private val database: ServerDatabaseDao,
private val downloader: Downloader private val downloader: Downloader,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -111,7 +111,7 @@ constructor(
getMediaString(item, MediaStreamType.SUBTITLE), getMediaString(item, MediaStreamType.SUBTITLE),
runTime, runTime,
getDateString(item), getDateString(item),
) ),
) )
} catch (_: NullPointerException) { } catch (_: NullPointerException) {
// Navigate back because item does not exist (probably because it's been deleted) // Navigate back because item does not exist (probably because it's been deleted)
@ -175,7 +175,7 @@ constructor(
AudioChannel.CH_5_1.raw -> AudioChannel.CH_5_1 AudioChannel.CH_5_1.raw -> AudioChannel.CH_5_1
AudioChannel.CH_7_1.raw -> AudioChannel.CH_7_1 AudioChannel.CH_7_1.raw -> AudioChannel.CH_7_1
else -> AudioChannel.CH_2_0 else -> AudioChannel.CH_2_0
} },
) )
/** /**
@ -199,7 +199,7 @@ constructor(
AudioCodec.TRUEHD.toString() -> AudioCodec.TRUEHD AudioCodec.TRUEHD.toString() -> AudioCodec.TRUEHD
AudioCodec.DTS.toString() -> AudioCodec.DTS AudioCodec.DTS.toString() -> AudioCodec.DTS
else -> AudioCodec.MP3 else -> AudioCodec.MP3
} },
) )
true true
} }
@ -217,12 +217,14 @@ constructor(
*/ */
if (stream.videoDoViTitle != null) { if (stream.videoDoViTitle != null) {
DisplayProfile.DOLBY_VISION DisplayProfile.DOLBY_VISION
} else when (videoRangeType) { } else {
DisplayProfile.HDR.raw -> DisplayProfile.HDR when (videoRangeType) {
DisplayProfile.HDR10.raw -> DisplayProfile.HDR10 DisplayProfile.HDR.raw -> DisplayProfile.HDR
DisplayProfile.HLG.raw -> DisplayProfile.HLG DisplayProfile.HDR10.raw -> DisplayProfile.HDR10
else -> DisplayProfile.SDR DisplayProfile.HLG.raw -> DisplayProfile.HLG
} else -> DisplayProfile.SDR
}
},
) )
/** /**
@ -240,7 +242,7 @@ constructor(
} }
else -> Resolution.SD else -> Resolution.SD
} },
) )
} }
true true
@ -256,7 +258,7 @@ constructor(
displayProfile.toSet().toList(), displayProfile.toSet().toList(),
audioChannels.toSet().toList(), audioChannels.toSet().toList(),
audioCodecs.toSet().toList(), audioCodecs.toSet().toList(),
isAtmosAudio isAtmosAudio,
) )
} }

View file

@ -6,17 +6,17 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.models.FindroidMovie import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.FindroidShow import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class PersonDetailViewModel @Inject internal constructor( class PersonDetailViewModel @Inject internal constructor(
private val jellyfinRepository: JellyfinRepository private val jellyfinRepository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
@ -37,13 +37,13 @@ class PersonDetailViewModel @Inject internal constructor(
val data = PersonOverview( val data = PersonOverview(
name = personDetail.name.orEmpty(), name = personDetail.name.orEmpty(),
overview = personDetail.overview.orEmpty(), overview = personDetail.overview.orEmpty(),
dto = personDetail dto = personDetail,
) )
val items = jellyfinRepository.getPersonItems( val items = jellyfinRepository.getPersonItems(
personIds = listOf(personId), personIds = listOf(personId),
includeTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.SERIES), includeTypes = listOf(BaseItemKind.MOVIE, BaseItemKind.SERIES),
recursive = true recursive = true,
) )
val movies = items.filterIsInstance<FindroidMovie>() val movies = items.filterIsInstance<FindroidMovie>()
@ -61,11 +61,11 @@ class PersonDetailViewModel @Inject internal constructor(
data class PersonOverview( data class PersonOverview(
val name: String, val name: String,
val overview: String, val overview: String,
val dto: BaseItemDto val dto: BaseItemDto,
) )
data class StarredIn( data class StarredIn(
val movies: List<FindroidMovie>, val movies: List<FindroidMovie>,
val shows: List<FindroidShow> val shows: List<FindroidShow>,
) )
} }

View file

@ -11,18 +11,18 @@ import dev.jdtech.jellyfin.models.FindroidMovie
import dev.jdtech.jellyfin.models.FindroidShow import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.models.UiText import dev.jdtech.jellyfin.models.UiText
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class SearchResultViewModel class SearchResultViewModel
@Inject @Inject
constructor( constructor(
private val jellyfinRepository: JellyfinRepository private val jellyfinRepository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()
@ -50,29 +50,35 @@ constructor(
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_MOVIES, Constants.FAVORITE_TYPE_MOVIES,
UiText.StringResource(R.string.movies_label), UiText.StringResource(R.string.movies_label),
items.filterIsInstance<FindroidMovie>() items.filterIsInstance<FindroidMovie>(),
).let { ).let {
if (it.items.isNotEmpty()) sections.add( if (it.items.isNotEmpty()) {
it sections.add(
) it,
)
}
} }
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_SHOWS, Constants.FAVORITE_TYPE_SHOWS,
UiText.StringResource(R.string.shows_label), UiText.StringResource(R.string.shows_label),
items.filterIsInstance<FindroidShow>() items.filterIsInstance<FindroidShow>(),
).let { ).let {
if (it.items.isNotEmpty()) sections.add( if (it.items.isNotEmpty()) {
it sections.add(
) it,
)
}
} }
FavoriteSection( FavoriteSection(
Constants.FAVORITE_TYPE_EPISODES, Constants.FAVORITE_TYPE_EPISODES,
UiText.StringResource(R.string.episodes_label), UiText.StringResource(R.string.episodes_label),
items.filterIsInstance<FindroidEpisode>() items.filterIsInstance<FindroidEpisode>(),
).let { ).let {
if (it.items.isNotEmpty()) sections.add( if (it.items.isNotEmpty()) {
it sections.add(
) it,
)
}
} }
} }

View file

@ -6,20 +6,20 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.models.EpisodeItem import dev.jdtech.jellyfin.models.EpisodeItem
import dev.jdtech.jellyfin.models.FindroidSeason import dev.jdtech.jellyfin.models.FindroidSeason
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.ItemFields import org.jellyfin.sdk.model.api.ItemFields
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class SeasonViewModel class SeasonViewModel
@Inject @Inject
constructor( constructor(
private val jellyfinRepository: JellyfinRepository private val jellyfinRepository: JellyfinRepository,
) : ViewModel() { ) : ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading) private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState = _uiState.asStateFlow() val uiState = _uiState.asStateFlow()

View file

@ -6,8 +6,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.api.JellyfinApi import dev.jdtech.jellyfin.api.JellyfinApi
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.models.ServerAddress import dev.jdtech.jellyfin.models.ServerAddress
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -15,6 +13,8 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class ServerAddressesViewModel class ServerAddressesViewModel

View file

@ -7,11 +7,11 @@ import dev.jdtech.jellyfin.AppPreferences
import dev.jdtech.jellyfin.api.JellyfinApi import dev.jdtech.jellyfin.api.JellyfinApi
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.models.Server import dev.jdtech.jellyfin.models.Server
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class ServerSelectViewModel class ServerSelectViewModel
@ -19,7 +19,7 @@ class ServerSelectViewModel
constructor( constructor(
private val jellyfinApi: JellyfinApi, private val jellyfinApi: JellyfinApi,
private val database: ServerDatabaseDao, private val database: ServerDatabaseDao,
private val appPreferences: AppPreferences private val appPreferences: AppPreferences,
) : ViewModel() { ) : ViewModel() {
val servers = database.getAllServers() val servers = database.getAllServers()

View file

@ -4,9 +4,9 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class SettingsDeviceViewModel class SettingsDeviceViewModel

View file

@ -7,8 +7,6 @@ import dev.jdtech.jellyfin.models.FindroidEpisode
import dev.jdtech.jellyfin.models.FindroidSeason import dev.jdtech.jellyfin.models.FindroidSeason
import dev.jdtech.jellyfin.models.FindroidShow import dev.jdtech.jellyfin.models.FindroidShow
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -17,6 +15,8 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jellyfin.sdk.model.api.BaseItemPerson import org.jellyfin.sdk.model.api.BaseItemPerson
import java.util.UUID
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class ShowViewModel class ShowViewModel
@ -89,7 +89,7 @@ constructor(
dateString, dateString,
nextUp, nextUp,
seasons, seasons,
) ),
) )
} catch (_: NullPointerException) { } catch (_: NullPointerException) {
// Navigate back because item does not exist (probably because it's been deleted) // Navigate back because item does not exist (probably because it's been deleted)

View file

@ -6,7 +6,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dev.jdtech.jellyfin.api.JellyfinApi import dev.jdtech.jellyfin.api.JellyfinApi
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.models.User import dev.jdtech.jellyfin.models.User
import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -14,6 +13,7 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject
@HiltViewModel @HiltViewModel
class UsersViewModel class UsersViewModel

View file

@ -29,7 +29,7 @@ class SyncWorker @AssistedInject constructor(
androidContext = context.applicationContext, androidContext = context.applicationContext,
requestTimeout = appPreferences.requestTimeout, requestTimeout = appPreferences.requestTimeout,
connectTimeout = appPreferences.connectTimeout, connectTimeout = appPreferences.connectTimeout,
socketTimeout = appPreferences.socketTimeout socketTimeout = appPreferences.socketTimeout,
) )
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
@ -59,7 +59,7 @@ class SyncWorker @AssistedInject constructor(
private suspend fun syncUserData( private suspend fun syncUserData(
jellyfinApi: JellyfinApi, jellyfinApi: JellyfinApi,
user: User, user: User,
items: List<FindroidItem> items: List<FindroidItem>,
) { ) {
for (item in items) { for (item in items) {
val userData = database.getUserDataToBeSynced(user.id, item.id) ?: continue val userData = database.getUserDataToBeSynced(user.id, item.id) ?: continue

View file

@ -3,7 +3,6 @@ package dev.jdtech.jellyfin.api
import android.content.Context import android.content.Context
import dev.jdtech.jellyfin.Constants import dev.jdtech.jellyfin.Constants
import dev.jdtech.jellyfin.data.BuildConfig import dev.jdtech.jellyfin.data.BuildConfig
import java.util.UUID
import org.jellyfin.sdk.api.client.HttpClientOptions import org.jellyfin.sdk.api.client.HttpClientOptions
import org.jellyfin.sdk.api.client.extensions.devicesApi import org.jellyfin.sdk.api.client.extensions.devicesApi
import org.jellyfin.sdk.api.client.extensions.itemsApi import org.jellyfin.sdk.api.client.extensions.itemsApi
@ -19,6 +18,7 @@ import org.jellyfin.sdk.api.client.extensions.userViewsApi
import org.jellyfin.sdk.api.client.extensions.videosApi import org.jellyfin.sdk.api.client.extensions.videosApi
import org.jellyfin.sdk.createJellyfin import org.jellyfin.sdk.createJellyfin
import org.jellyfin.sdk.model.ClientInfo import org.jellyfin.sdk.model.ClientInfo
import java.util.UUID
/** /**
* Jellyfin API class using org.jellyfin.sdk:jellyfin-platform-android * Jellyfin API class using org.jellyfin.sdk:jellyfin-platform-android
@ -31,7 +31,7 @@ class JellyfinApi(
androidContext: Context, androidContext: Context,
requestTimeout: Long = Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT, requestTimeout: Long = Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT,
connectTimeout: Long = Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT, connectTimeout: Long = Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT,
socketTimeout: Long = Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT socketTimeout: Long = Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT,
) { ) {
val jellyfin = createJellyfin { val jellyfin = createJellyfin {
clientInfo = clientInfo =
@ -42,8 +42,8 @@ class JellyfinApi(
httpClientOptions = HttpClientOptions( httpClientOptions = HttpClientOptions(
requestTimeout = requestTimeout, requestTimeout = requestTimeout,
connectTimeout = connectTimeout, connectTimeout = connectTimeout,
socketTimeout = socketTimeout socketTimeout = socketTimeout,
) ),
) )
var userId: UUID? = null var userId: UUID? = null
@ -68,7 +68,7 @@ class JellyfinApi(
context: Context, context: Context,
requestTimeout: Long = Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT, requestTimeout: Long = Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT,
connectTimeout: Long = Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT, connectTimeout: Long = Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT,
socketTimeout: Long = Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT socketTimeout: Long = Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT,
): JellyfinApi { ): JellyfinApi {
synchronized(this) { synchronized(this) {
var instance = INSTANCE var instance = INSTANCE
@ -77,7 +77,7 @@ class JellyfinApi(
androidContext = context.applicationContext, androidContext = context.applicationContext,
requestTimeout = requestTimeout, requestTimeout = requestTimeout,
connectTimeout = connectTimeout, connectTimeout = connectTimeout,
socketTimeout = socketTimeout socketTimeout = socketTimeout,
) )
INSTANCE = instance INSTANCE = instance
} }

View file

@ -1,9 +1,9 @@
package dev.jdtech.jellyfin.database package dev.jdtech.jellyfin.database
import androidx.room.TypeConverter import androidx.room.TypeConverter
import org.jellyfin.sdk.model.DateTime
import java.time.ZoneOffset import java.time.ZoneOffset
import java.util.UUID import java.util.UUID
import org.jellyfin.sdk.model.DateTime
class Converters { class Converters {
@TypeConverter @TypeConverter

View file

@ -21,8 +21,8 @@ import dev.jdtech.jellyfin.models.User
entities = [Server::class, ServerAddress::class, User::class, FindroidMovieDto::class, FindroidShowDto::class, FindroidSeasonDto::class, FindroidEpisodeDto::class, FindroidSourceDto::class, FindroidMediaStreamDto::class, TrickPlayManifestDto::class, IntroDto::class, FindroidUserDataDto::class], entities = [Server::class, ServerAddress::class, User::class, FindroidMovieDto::class, FindroidShowDto::class, FindroidSeasonDto::class, FindroidEpisodeDto::class, FindroidSourceDto::class, FindroidMediaStreamDto::class, TrickPlayManifestDto::class, IntroDto::class, FindroidUserDataDto::class],
version = 3, version = 3,
autoMigrations = [ autoMigrations = [
AutoMigration(from = 2, to = 3) AutoMigration(from = 2, to = 3),
] ],
) )
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class ServerDatabase : RoomDatabase() { abstract class ServerDatabase : RoomDatabase() {

View file

@ -241,7 +241,7 @@ abstract class ServerDatabaseDao {
itemId = itemId, itemId = itemId,
played = false, played = false,
favorite = false, favorite = false,
playbackPositionTicks = 0L playbackPositionTicks = 0L,
) )
insertUserData(userData) insertUserData(userData)
} }

View file

@ -8,11 +8,16 @@ enum class CollectionType(val type: String) {
Playlists("playlists"), Playlists("playlists"),
Books("books"), Books("books"),
LiveTv("livetv"), LiveTv("livetv"),
BoxSets("boxsets"); BoxSets("boxsets"),
;
companion object { companion object {
val unsupportedCollections = listOf( val unsupportedCollections = listOf(
HomeVideos, Music, Playlists, Books, LiveTv HomeVideos,
Music,
Playlists,
Books,
LiveTv,
) )
} }
} }

View file

@ -1,7 +1,7 @@
package dev.jdtech.jellyfin.models package dev.jdtech.jellyfin.models
import java.util.UUID
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import java.util.UUID
data class FindroidBoxSet( data class FindroidBoxSet(
override val id: UUID, override val id: UUID,

View file

@ -1,7 +1,7 @@
package dev.jdtech.jellyfin.models package dev.jdtech.jellyfin.models
import java.util.UUID
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import java.util.UUID
data class FindroidCollection( data class FindroidCollection(
override val id: UUID, override val id: UUID,
@ -16,7 +16,7 @@ data class FindroidCollection(
override val runtimeTicks: Long = 0L, override val runtimeTicks: Long = 0L,
override val playbackPositionTicks: Long = 0L, override val playbackPositionTicks: Long = 0L,
override val unplayedItemCount: Int? = null, override val unplayedItemCount: Int? = null,
val type: CollectionType val type: CollectionType,
) : FindroidItem ) : FindroidItem
fun BaseItemDto.toFindroidCollection(): FindroidCollection? { fun BaseItemDto.toFindroidCollection(): FindroidCollection? {

View file

@ -2,11 +2,11 @@ package dev.jdtech.jellyfin.models
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import org.jellyfin.sdk.model.DateTime import org.jellyfin.sdk.model.DateTime
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.LocationType import org.jellyfin.sdk.model.api.LocationType
import org.jellyfin.sdk.model.api.PlayAccess import org.jellyfin.sdk.model.api.PlayAccess
import java.util.UUID
data class FindroidEpisode( data class FindroidEpisode(
override val id: UUID, override val id: UUID,
@ -34,7 +34,7 @@ data class FindroidEpisode(
suspend fun BaseItemDto.toFindroidEpisode( suspend fun BaseItemDto.toFindroidEpisode(
jellyfinRepository: JellyfinRepository, jellyfinRepository: JellyfinRepository,
database: ServerDatabaseDao? = null database: ServerDatabaseDao? = null,
): FindroidEpisode? { ): FindroidEpisode? {
val sources = mutableListOf<FindroidSource>() val sources = mutableListOf<FindroidSource>()
sources.addAll(mediaSources?.map { it.toFindroidSource(jellyfinRepository, id) } ?: emptyList()) sources.addAll(mediaSources?.map { it.toFindroidSource(jellyfinRepository, id) } ?: emptyList())

View file

@ -14,19 +14,19 @@ import java.util.UUID
entity = FindroidSeasonDto::class, entity = FindroidSeasonDto::class,
parentColumns = arrayOf("id"), parentColumns = arrayOf("id"),
childColumns = arrayOf("seasonId"), childColumns = arrayOf("seasonId"),
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE,
), ),
ForeignKey( ForeignKey(
entity = FindroidShowDto::class, entity = FindroidShowDto::class,
parentColumns = arrayOf("id"), parentColumns = arrayOf("id"),
childColumns = arrayOf("seriesId"), childColumns = arrayOf("seriesId"),
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE,
) ),
], ],
indices = [ indices = [
Index("seasonId"), Index("seasonId"),
Index("seriesId"), Index("seriesId"),
] ],
) )
data class FindroidEpisodeDto( data class FindroidEpisodeDto(
@PrimaryKey @PrimaryKey

View file

@ -2,9 +2,9 @@ package dev.jdtech.jellyfin.models
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
import java.util.UUID
interface FindroidItem { interface FindroidItem {
val id: UUID val id: UUID
@ -23,7 +23,7 @@ interface FindroidItem {
suspend fun BaseItemDto.toFindroidItem( suspend fun BaseItemDto.toFindroidItem(
jellyfinRepository: JellyfinRepository, jellyfinRepository: JellyfinRepository,
serverDatabase: ServerDatabaseDao? = null serverDatabase: ServerDatabaseDao? = null,
): FindroidItem? { ): FindroidItem? {
return when (type) { return when (type) {
BaseItemKind.MOVIE -> toFindroidMovie(jellyfinRepository, serverDatabase) BaseItemKind.MOVIE -> toFindroidMovie(jellyfinRepository, serverDatabase)

View file

@ -2,11 +2,11 @@ package dev.jdtech.jellyfin.models
import androidx.room.Entity import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import java.util.UUID
import org.jellyfin.sdk.model.api.MediaStreamType import org.jellyfin.sdk.model.api.MediaStreamType
import java.util.UUID
@Entity( @Entity(
tableName = "mediastreams" tableName = "mediastreams",
) )
data class FindroidMediaStreamDto( data class FindroidMediaStreamDto(
@PrimaryKey @PrimaryKey

View file

@ -2,11 +2,11 @@ package dev.jdtech.jellyfin.models
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.util.UUID
import org.jellyfin.sdk.model.DateTime import org.jellyfin.sdk.model.DateTime
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemPerson import org.jellyfin.sdk.model.api.BaseItemPerson
import org.jellyfin.sdk.model.api.PlayAccess import org.jellyfin.sdk.model.api.PlayAccess
import java.util.UUID
data class FindroidMovie( data class FindroidMovie(
override val id: UUID, override val id: UUID,
@ -34,7 +34,7 @@ data class FindroidMovie(
suspend fun BaseItemDto.toFindroidMovie( suspend fun BaseItemDto.toFindroidMovie(
jellyfinRepository: JellyfinRepository, jellyfinRepository: JellyfinRepository,
serverDatabase: ServerDatabaseDao? = null serverDatabase: ServerDatabaseDao? = null,
): FindroidMovie { ): FindroidMovie {
val sources = mutableListOf<FindroidSource>() val sources = mutableListOf<FindroidSource>()
sources.addAll(mediaSources?.map { it.toFindroidSource(jellyfinRepository, id) } ?: emptyList()) sources.addAll(mediaSources?.map { it.toFindroidSource(jellyfinRepository, id) } ?: emptyList())

View file

@ -1,9 +1,9 @@
package dev.jdtech.jellyfin.models package dev.jdtech.jellyfin.models
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import java.util.UUID
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.PlayAccess import org.jellyfin.sdk.model.api.PlayAccess
import java.util.UUID
data class FindroidSeason( data class FindroidSeason(
override val id: UUID, override val id: UUID,

View file

@ -13,12 +13,12 @@ import java.util.UUID
entity = FindroidShowDto::class, entity = FindroidShowDto::class,
parentColumns = arrayOf("id"), parentColumns = arrayOf("id"),
childColumns = arrayOf("seriesId"), childColumns = arrayOf("seriesId"),
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE,
) ),
], ],
indices = [ indices = [
Index("seriesId"), Index("seriesId"),
] ],
) )
data class FindroidSeasonDto( data class FindroidSeasonDto(
@PrimaryKey @PrimaryKey

View file

@ -1,11 +1,11 @@
package dev.jdtech.jellyfin.models package dev.jdtech.jellyfin.models
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import java.util.UUID
import org.jellyfin.sdk.model.DateTime import org.jellyfin.sdk.model.DateTime
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemPerson import org.jellyfin.sdk.model.api.BaseItemPerson
import org.jellyfin.sdk.model.api.PlayAccess import org.jellyfin.sdk.model.api.PlayAccess
import java.util.UUID
data class FindroidShow( data class FindroidShow(
override val id: UUID, override val id: UUID,

View file

@ -2,10 +2,10 @@ package dev.jdtech.jellyfin.models
import dev.jdtech.jellyfin.database.ServerDatabaseDao import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.repository.JellyfinRepository import dev.jdtech.jellyfin.repository.JellyfinRepository
import java.io.File
import java.util.UUID
import org.jellyfin.sdk.model.api.MediaProtocol import org.jellyfin.sdk.model.api.MediaProtocol
import org.jellyfin.sdk.model.api.MediaSourceInfo import org.jellyfin.sdk.model.api.MediaSourceInfo
import java.io.File
import java.util.UUID
data class FindroidSource( data class FindroidSource(
val id: String, val id: String,
@ -14,7 +14,7 @@ data class FindroidSource(
val path: String, val path: String,
val size: Long, val size: Long,
val mediaStreams: List<FindroidMediaStream>, val mediaStreams: List<FindroidMediaStream>,
val downloadId: Long? = null val downloadId: Long? = null,
) )
suspend fun MediaSourceInfo.toFindroidSource( suspend fun MediaSourceInfo.toFindroidSource(
@ -39,7 +39,7 @@ suspend fun MediaSourceInfo.toFindroidSource(
type = FindroidSourceType.REMOTE, type = FindroidSourceType.REMOTE,
path = path, path = path,
size = size ?: 0, size = size ?: 0,
mediaStreams = mediaStreams?.map { it.toFindroidMediaStream(jellyfinRepository) } ?: emptyList() mediaStreams = mediaStreams?.map { it.toFindroidMediaStream(jellyfinRepository) } ?: emptyList(),
) )
} }

View file

@ -5,7 +5,7 @@ import androidx.room.PrimaryKey
import java.util.UUID import java.util.UUID
@Entity( @Entity(
tableName = "sources" tableName = "sources",
) )
data class FindroidSourceDto( data class FindroidSourceDto(
@PrimaryKey @PrimaryKey

View file

@ -5,7 +5,7 @@ import java.util.UUID
@Entity( @Entity(
tableName = "userdata", tableName = "userdata",
primaryKeys = ["userId", "itemId"] primaryKeys = ["userId", "itemId"],
) )
data class FindroidUserDataDto( data class FindroidUserDataDto(
val userId: UUID, val userId: UUID,

View file

@ -12,7 +12,7 @@ data class Intro(
@SerialName("ShowSkipPromptAt") @SerialName("ShowSkipPromptAt")
val showSkipPromptAt: Double, val showSkipPromptAt: Double,
@SerialName("HideSkipPromptAt") @SerialName("HideSkipPromptAt")
val hideSkipPromptAt: Double val hideSkipPromptAt: Double,
) )
fun IntroDto.toIntro(): Intro { fun IntroDto.toIntro(): Intro {

View file

@ -13,14 +13,14 @@ import java.util.UUID
entity = Server::class, entity = Server::class,
parentColumns = arrayOf("id"), parentColumns = arrayOf("id"),
childColumns = arrayOf("serverId"), childColumns = arrayOf("serverId"),
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE,
) ),
] ],
) )
data class ServerAddress( data class ServerAddress(
@PrimaryKey @PrimaryKey
val id: UUID, val id: UUID,
@ColumnInfo(index = true) @ColumnInfo(index = true)
val serverId: String, val serverId: String,
val address: String val address: String,
) )

View file

@ -8,12 +8,12 @@ data class ServerWithAddresses(
val server: Server, val server: Server,
@Relation( @Relation(
parentColumn = "id", parentColumn = "id",
entityColumn = "serverId" entityColumn = "serverId",
) )
val addresses: List<ServerAddress>, val addresses: List<ServerAddress>,
@Relation( @Relation(
parentColumn = "currentUserId", parentColumn = "currentUserId",
entityColumn = "id" entityColumn = "id",
) )
val user: User? val user: User?,
) )

View file

@ -8,12 +8,12 @@ data class ServerWithAddressesAndUsers(
val server: Server, val server: Server,
@Relation( @Relation(
parentColumn = "id", parentColumn = "id",
entityColumn = "serverId" entityColumn = "serverId",
) )
val addresses: List<ServerAddress>, val addresses: List<ServerAddress>,
@Relation( @Relation(
parentColumn = "id", parentColumn = "id",
entityColumn = "serverId" entityColumn = "serverId",
) )
val users: List<User> val users: List<User>,
) )

View file

@ -8,7 +8,7 @@ data class ServerWithUsers(
val server: Server, val server: Server,
@Relation( @Relation(
parentColumn = "id", parentColumn = "id",
entityColumn = "serverId" entityColumn = "serverId",
) )
val users: List<User> val users: List<User>,
) )

View file

@ -6,7 +6,8 @@ enum class SortBy(val SortString: String) {
PARENTAL_RATING("CriticRating"), PARENTAL_RATING("CriticRating"),
DATE_ADDED("DateCreated"), DATE_ADDED("DateCreated"),
DATE_PLAYED("DatePlayed"), DATE_PLAYED("DatePlayed"),
RELEASE_DATE("PremiereDate"); RELEASE_DATE("PremiereDate"),
;
companion object { companion object {
val defaultValue = NAME val defaultValue = NAME

View file

@ -8,7 +8,7 @@ data class TrickPlayManifest(
@SerialName("Version") @SerialName("Version")
val version: String, val version: String,
@SerialName("WidthResolutions") @SerialName("WidthResolutions")
val widthResolutions: List<Int> val widthResolutions: List<Int>,
) )
fun TrickPlayManifestDto.toTrickPlayManifest(): TrickPlayManifest { fun TrickPlayManifestDto.toTrickPlayManifest(): TrickPlayManifest {

View file

@ -13,9 +13,9 @@ import java.util.UUID
entity = Server::class, entity = Server::class,
parentColumns = arrayOf("id"), parentColumns = arrayOf("id"),
childColumns = arrayOf("serverId"), childColumns = arrayOf("serverId"),
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE,
) ),
] ],
) )
data class User( data class User(
@PrimaryKey @PrimaryKey
@ -23,5 +23,5 @@ data class User(
val name: String, val name: String,
@ColumnInfo(index = true) @ColumnInfo(index = true)
val serverId: String, val serverId: String,
val accessToken: String? = null val accessToken: String? = null,
) )

Some files were not shown because too many files have changed in this diff Show more