Provide better error messages with stacktrace (#119)
* Provide better error messages with stacktrace + clean up + fix error details popup in MediaInfoFragment * Simplify exception passing by sending complete exception to the dialog * Use viewLifecycleOwner with repeatOnLifecycle
This commit is contained in:
parent
741083da40
commit
751ee75c3e
31 changed files with 74 additions and 99 deletions
|
@ -8,18 +8,21 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dev.jdtech.jellyfin.R
|
import dev.jdtech.jellyfin.R
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
|
|
||||||
class ErrorDialogFragment(private val errorMessage: String) : DialogFragment() {
|
class ErrorDialogFragment(
|
||||||
|
private val error: Exception
|
||||||
|
) : DialogFragment() {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
return activity?.let {
|
return activity?.let {
|
||||||
val builder = MaterialAlertDialogBuilder(it, R.style.ErrorDialogStyle)
|
val builder = MaterialAlertDialogBuilder(it, R.style.ErrorDialogStyle)
|
||||||
builder
|
builder
|
||||||
.setMessage(errorMessage)
|
.setTitle(error.message ?: getString(R.string.unknown_error))
|
||||||
|
.setMessage(error.stackTraceToString())
|
||||||
.setPositiveButton(getString(R.string.close)) { _, _ ->
|
.setPositiveButton(getString(R.string.close)) { _, _ ->
|
||||||
}
|
}
|
||||||
.setNeutralButton(getString(R.string.share)) { _, _ ->
|
.setNeutralButton(getString(R.string.share)) { _, _ ->
|
||||||
val sendIntent: Intent = Intent().apply {
|
val sendIntent: Intent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
putExtra(Intent.EXTRA_TEXT, errorMessage)
|
putExtra(Intent.EXTRA_TEXT, "${error.message}\n ${error.stackTraceToString()}")
|
||||||
type = "text/plain"
|
type = "text/plain"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
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.R
|
|
||||||
import dev.jdtech.jellyfin.adapters.*
|
import dev.jdtech.jellyfin.adapters.*
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentDownloadBinding
|
import dev.jdtech.jellyfin.databinding.FragmentDownloadBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
||||||
|
@ -86,12 +85,11 @@ class DownloadFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: DownloadViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: DownloadViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: resources.getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.downloadsRecyclerView.isVisible = false
|
binding.downloadsRecyclerView.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToMediaInfoFragment(item: PlayerItem) {
|
private fun navigateToMediaInfoFragment(item: PlayerItem) {
|
||||||
|
|
|
@ -207,7 +207,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: EpisodeBottomSheetViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: EpisodeBottomSheetViewModel.UiState.Error) {
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.overview.text = uiState.message
|
binding.overview.text = uiState.error.message
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) {
|
private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) {
|
||||||
|
@ -222,7 +222,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) {
|
private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) {
|
||||||
Timber.e(error.message)
|
Timber.e(error.error.message)
|
||||||
|
|
||||||
binding.playerItemsError.isVisible = true
|
binding.playerItemsError.isVisible = true
|
||||||
binding.playButton.setImageDrawable(
|
binding.playButton.setImageDrawable(
|
||||||
|
@ -233,7 +233,7 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
|
||||||
)
|
)
|
||||||
binding.progressCircular.visibility = View.INVISIBLE
|
binding.progressCircular.visibility = View.INVISIBLE
|
||||||
binding.playerItemsErrorDetails.setOnClickListener {
|
binding.playerItemsErrorDetails.setOnClickListener {
|
||||||
ErrorDialogFragment(error.message).show(parentFragmentManager, "errordialog")
|
ErrorDialogFragment(error.error).show(parentFragmentManager, "errordialog")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
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.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
|
||||||
|
@ -87,12 +86,11 @@ class FavoriteFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: FavoriteViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: FavoriteViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: resources.getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.favoritesRecyclerView.isVisible = false
|
binding.favoritesRecyclerView.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToMediaInfoFragment(item: BaseItemDto) {
|
private fun navigateToMediaInfoFragment(item: BaseItemDto) {
|
||||||
|
|
|
@ -139,13 +139,12 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: HomeViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: HomeViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.refreshLayout.isRefreshing = false
|
binding.refreshLayout.isRefreshing = false
|
||||||
binding.viewsRecyclerView.isVisible = false
|
binding.viewsRecyclerView.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToLibraryFragment(view: dev.jdtech.jellyfin.models.View) {
|
private fun navigateToLibraryFragment(view: dev.jdtech.jellyfin.models.View) {
|
||||||
|
|
|
@ -132,12 +132,11 @@ class LibraryFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: LibraryViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: LibraryViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.itemsRecyclerView.isVisible = false
|
binding.itemsRecyclerView.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToMediaInfoFragment(item: BaseItemDto) {
|
private fun navigateToMediaInfoFragment(item: BaseItemDto) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ class LoginFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
viewModel.onUiState(viewLifecycleOwner.lifecycleScope) { uiState ->
|
viewModel.onUiState(viewLifecycleOwner.lifecycleScope) { uiState ->
|
||||||
Timber.d("$uiState")
|
Timber.d("$uiState")
|
||||||
when(uiState) {
|
when(uiState) {
|
||||||
|
|
|
@ -120,12 +120,11 @@ class MediaFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: MediaViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: MediaViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: resources.getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.viewsRecyclerView.isVisible = false
|
binding.viewsRecyclerView.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,6 +145,10 @@ class MediaInfoFragment : Fragment() {
|
||||||
viewModel.loadData(args.itemId, args.itemType)
|
viewModel.loadData(args.itemId, args.itemType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.errorLayout.errorDetailsButton.setOnClickListener {
|
||||||
|
errorDialog.show(parentFragmentManager, "errordialog")
|
||||||
|
}
|
||||||
|
|
||||||
binding.checkButton.setOnClickListener {
|
binding.checkButton.setOnClickListener {
|
||||||
when (viewModel.played) {
|
when (viewModel.played) {
|
||||||
true -> {
|
true -> {
|
||||||
|
@ -286,11 +290,11 @@ class MediaInfoFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: MediaInfoViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: MediaInfoViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.mediaInfoScrollview.isVisible = false
|
binding.mediaInfoScrollview.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) {
|
private fun bindPlayerItems(items: PlayerViewModel.PlayerItems) {
|
||||||
|
@ -305,7 +309,7 @@ class MediaInfoFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) {
|
private fun bindPlayerItemsError(error: PlayerViewModel.PlayerItemError) {
|
||||||
Timber.e(error.message)
|
Timber.e(error.error.message)
|
||||||
binding.playerItemsError.visibility = View.VISIBLE
|
binding.playerItemsError.visibility = View.VISIBLE
|
||||||
binding.playButton.setImageDrawable(
|
binding.playButton.setImageDrawable(
|
||||||
ContextCompat.getDrawable(
|
ContextCompat.getDrawable(
|
||||||
|
@ -315,7 +319,7 @@ class MediaInfoFragment : Fragment() {
|
||||||
)
|
)
|
||||||
binding.progressCircular.visibility = View.INVISIBLE
|
binding.progressCircular.visibility = View.INVISIBLE
|
||||||
binding.playerItemsErrorDetails.setOnClickListener {
|
binding.playerItemsErrorDetails.setOnClickListener {
|
||||||
ErrorDialogFragment(error.message).show(parentFragmentManager, "errordialog")
|
ErrorDialogFragment(error.error).show(parentFragmentManager, "errordialog")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,12 +104,11 @@ internal class PersonDetailFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: PersonDetailViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: PersonDetailViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: resources.getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.fragmentContent.isVisible = false
|
binding.fragmentContent.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun adapter() = ViewItemListAdapter(
|
private fun adapter() = ViewItemListAdapter(
|
||||||
|
|
|
@ -13,7 +13,6 @@ 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 dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
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
|
||||||
|
@ -91,12 +90,11 @@ class SearchResultFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: SearchResultViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: SearchResultViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.searchResultsRecyclerView.isVisible = false
|
binding.searchResultsRecyclerView.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToMediaInfoFragment(item: BaseItemDto) {
|
private fun navigateToMediaInfoFragment(item: BaseItemDto) {
|
||||||
|
|
|
@ -13,7 +13,6 @@ 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 dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.R
|
|
||||||
import dev.jdtech.jellyfin.adapters.EpisodeListAdapter
|
import dev.jdtech.jellyfin.adapters.EpisodeListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentSeasonBinding
|
import dev.jdtech.jellyfin.databinding.FragmentSeasonBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
||||||
|
@ -88,12 +87,11 @@ class SeasonFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: SeasonViewModel.UiState.Error) {
|
private fun bindUiStateError(uiState: SeasonViewModel.UiState.Error) {
|
||||||
val error = uiState.message ?: getString(R.string.unknown_error)
|
errorDialog = ErrorDialogFragment(uiState.error)
|
||||||
errorDialog = ErrorDialogFragment(error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
binding.loadingIndicator.isVisible = false
|
||||||
binding.episodesRecyclerView.isVisible = false
|
binding.episodesRecyclerView.isVisible = false
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
checkIfLoginRequired(error)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToEpisodeBottomSheetFragment(episode: BaseItemDto) {
|
private fun navigateToEpisodeBottomSheetFragment(episode: BaseItemDto) {
|
||||||
|
|
|
@ -49,7 +49,7 @@ class ServerSelectFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
viewModel.onNavigateToMain(viewLifecycleOwner.lifecycleScope) {
|
viewModel.onNavigateToMain(viewLifecycleOwner.lifecycleScope) {
|
||||||
if (it) {
|
if (it) {
|
||||||
navigateToMainActivity()
|
navigateToMainActivity()
|
||||||
|
|
|
@ -248,7 +248,7 @@ internal class MediaDetailFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindPlayerItemsError(error: PlayerItemError) {
|
private fun bindPlayerItemsError(error: PlayerItemError) {
|
||||||
Timber.e(error.message)
|
Timber.e(error.error.message)
|
||||||
|
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
binding.playButton.setImageDrawable(
|
binding.playButton.setImageDrawable(
|
||||||
|
|
|
@ -40,7 +40,7 @@ class TvLoginFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
viewModel.onUiState(viewLifecycleOwner.lifecycleScope) { uiState ->
|
viewModel.onUiState(viewLifecycleOwner.lifecycleScope) { uiState ->
|
||||||
Timber.d("$uiState")
|
Timber.d("$uiState")
|
||||||
when(uiState) {
|
when(uiState) {
|
||||||
|
|
|
@ -32,10 +32,12 @@ fun BaseItemDto.contentType() = when (type) {
|
||||||
else -> ContentType.UNKNOWN
|
else -> ContentType.UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Fragment.checkIfLoginRequired(error: String) {
|
fun Fragment.checkIfLoginRequired(error: String?) {
|
||||||
if (error.contains("401")) {
|
if (error != null) {
|
||||||
Timber.d("Login required!")
|
if (error.contains("401")) {
|
||||||
findNavController().navigate(AppNavigationDirections.actionGlobalLoginFragment())
|
Timber.d("Login required!")
|
||||||
|
findNavController().navigate(AppNavigationDirections.actionGlobalLoginFragment())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,8 +95,7 @@ constructor(
|
||||||
}
|
}
|
||||||
okServers.isNotEmpty() -> {
|
okServers.isNotEmpty() -> {
|
||||||
val okServer = okServers.first()
|
val okServer = okServers.first()
|
||||||
val issuesString = createIssuesString(okServer)
|
throw Exception(createIssuesString(okServer))
|
||||||
throw Exception(issuesString)
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw Exception(resources.getString(R.string.add_server_error_not_found))
|
throw Exception(resources.getString(R.string.add_server_error_not_found))
|
||||||
|
|
|
@ -8,7 +8,6 @@ import dev.jdtech.jellyfin.models.DownloadSection
|
||||||
import dev.jdtech.jellyfin.utils.loadDownloadedEpisodes
|
import dev.jdtech.jellyfin.utils.loadDownloadedEpisodes
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -24,7 +23,7 @@ constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val downloadSections: List<DownloadSection>) : UiState()
|
data class Normal(val downloadSections: List<DownloadSection>) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -40,10 +39,6 @@ constructor(
|
||||||
uiState.emit(UiState.Loading)
|
uiState.emit(UiState.Loading)
|
||||||
try {
|
try {
|
||||||
val items = loadDownloadedEpisodes(downloadDatabase)
|
val items = loadDownloadedEpisodes(downloadDatabase)
|
||||||
if (items.isEmpty()) {
|
|
||||||
uiState.emit(UiState.Normal(emptyList()))
|
|
||||||
//return@launch
|
|
||||||
}
|
|
||||||
val downloadSections = mutableListOf<DownloadSection>()
|
val downloadSections = mutableListOf<DownloadSection>()
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
DownloadSection(
|
DownloadSection(
|
||||||
|
@ -65,7 +60,7 @@ constructor(
|
||||||
}
|
}
|
||||||
uiState.emit(UiState.Normal(downloadSections))
|
uiState.emit(UiState.Normal(downloadSections))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ constructor(
|
||||||
) : UiState()
|
) : UiState()
|
||||||
|
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -91,7 +91,7 @@ constructor(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,12 @@ constructor(
|
||||||
val metadata = baseItemDtoToDownloadMetadata(episode)
|
val metadata = baseItemDtoToDownloadMetadata(episode)
|
||||||
downloadRequestItem = DownloadRequestItem(uri, itemId, metadata)
|
downloadRequestItem = DownloadRequestItem(uri, itemId, metadata)
|
||||||
downloadEpisode = true
|
downloadEpisode = true
|
||||||
requestDownload(downloadDatabase, Uri.parse(downloadRequestItem.uri), downloadRequestItem, application)
|
requestDownload(
|
||||||
|
downloadDatabase,
|
||||||
|
Uri.parse(downloadRequestItem.uri),
|
||||||
|
downloadRequestItem,
|
||||||
|
application
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ import dev.jdtech.jellyfin.models.FavoriteSection
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -25,7 +24,7 @@ constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val favoriteSections: List<FavoriteSection>) : UiState()
|
data class Normal(val favoriteSections: List<FavoriteSection>) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -78,7 +77,7 @@ constructor(
|
||||||
|
|
||||||
uiState.emit(UiState.Normal(favoriteSections))
|
uiState.emit(UiState.Normal(favoriteSections))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import dev.jdtech.jellyfin.utils.syncPlaybackProgress
|
||||||
import dev.jdtech.jellyfin.utils.toView
|
import dev.jdtech.jellyfin.utils.toView
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -34,7 +33,7 @@ class HomeViewModel @Inject internal constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val homeItems: List<HomeItem>) : UiState()
|
data class Normal(val homeItems: List<HomeItem>) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -60,7 +59,7 @@ class HomeViewModel @Inject internal constructor(
|
||||||
}
|
}
|
||||||
uiState.emit(UiState.Normal(updated))
|
uiState.emit(UiState.Normal(updated))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import dev.jdtech.jellyfin.utils.SortBy
|
import dev.jdtech.jellyfin.utils.SortBy
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
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.SortOrder
|
import org.jellyfin.sdk.model.api.SortOrder
|
||||||
|
@ -24,7 +23,7 @@ constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val items: List<BaseItemDto>) : UiState()
|
data class Normal(val items: List<BaseItemDto>) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -55,7 +54,7 @@ constructor(
|
||||||
)
|
)
|
||||||
uiState.emit(UiState.Normal(items))
|
uiState.emit(UiState.Normal(items))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
||||||
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
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jellyfin.sdk.model.api.AuthenticateUserByName
|
import org.jellyfin.sdk.model.api.AuthenticateUserByName
|
||||||
|
|
|
@ -19,10 +19,6 @@ class MainViewModel
|
||||||
constructor(
|
constructor(
|
||||||
private val database: ServerDatabaseDao,
|
private val database: ServerDatabaseDao,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _doneLoading = MutableLiveData<Boolean>()
|
|
||||||
val doneLoading: LiveData<Boolean> = _doneLoading
|
|
||||||
|
|
||||||
private val _navigateToAddServer = MutableLiveData<Boolean>()
|
private val _navigateToAddServer = MutableLiveData<Boolean>()
|
||||||
val navigateToAddServer: LiveData<Boolean> = _navigateToAddServer
|
val navigateToAddServer: LiveData<Boolean> = _navigateToAddServer
|
||||||
|
|
||||||
|
@ -36,9 +32,7 @@ constructor(
|
||||||
if (servers.isEmpty()) {
|
if (servers.isEmpty()) {
|
||||||
_navigateToAddServer.value = true
|
_navigateToAddServer.value = true
|
||||||
}
|
}
|
||||||
_doneLoading.value = true
|
|
||||||
}
|
}
|
||||||
_doneLoading.value = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doneNavigateToAddServer() {
|
fun doneNavigateToAddServer() {
|
||||||
|
|
|
@ -52,7 +52,7 @@ constructor(
|
||||||
) : UiState()
|
) : UiState()
|
||||||
|
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -121,9 +121,7 @@ constructor(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.d(e)
|
uiState.emit(UiState.Error(e))
|
||||||
Timber.d(itemId.toString())
|
|
||||||
uiState.emit(UiState.Error(e.message))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dev.jdtech.jellyfin.models.CollectionType
|
import dev.jdtech.jellyfin.models.CollectionType
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -22,7 +21,7 @@ constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val collections: List<BaseItemDto>) : UiState()
|
data class Normal(val collections: List<BaseItemDto>) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -43,7 +42,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.message)
|
UiState.Error(e)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,8 @@ import dev.jdtech.jellyfin.models.ContentType.TVSHOW
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import dev.jdtech.jellyfin.utils.contentType
|
import dev.jdtech.jellyfin.utils.contentType
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||||
import java.lang.Exception
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -26,7 +24,7 @@ internal class PersonDetailViewModel @Inject internal constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val data: PersonOverview, val starredIn: StarredIn) : UiState()
|
data class Normal(val data: PersonOverview, val starredIn: StarredIn) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -58,7 +56,7 @@ internal class PersonDetailViewModel @Inject internal constructor(
|
||||||
|
|
||||||
uiState.emit(UiState.Normal(data, starredIn))
|
uiState.emit(UiState.Normal(data, starredIn))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ class PlayerViewModel @Inject internal constructor(
|
||||||
createItems(item, playbackPosition, mediaSourceIndex).let(::PlayerItems)
|
createItems(item, playbackPosition, mediaSourceIndex).let(::PlayerItems)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.d(e)
|
Timber.d(e)
|
||||||
PlayerItemError(e.toString())
|
PlayerItemError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
playerItems.tryEmit(items)
|
playerItems.tryEmit(items)
|
||||||
|
@ -195,6 +195,6 @@ class PlayerViewModel @Inject internal constructor(
|
||||||
|
|
||||||
sealed class PlayerItemState
|
sealed class PlayerItemState
|
||||||
|
|
||||||
data class PlayerItemError(val message: String) : PlayerItemState()
|
data class PlayerItemError(val error: Exception) : PlayerItemState()
|
||||||
data class PlayerItems(val items: List<PlayerItem>) : PlayerItemState()
|
data class PlayerItems(val items: List<PlayerItem>) : PlayerItemState()
|
||||||
}
|
}
|
|
@ -8,7 +8,6 @@ import dev.jdtech.jellyfin.models.FavoriteSection
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -25,7 +24,7 @@ constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val sections: List<FavoriteSection>) : UiState()
|
data class Normal(val sections: List<FavoriteSection>) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -74,7 +73,7 @@ constructor(
|
||||||
|
|
||||||
uiState.emit(UiState.Normal(sections))
|
uiState.emit(UiState.Normal(sections))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dev.jdtech.jellyfin.adapters.EpisodeItem
|
import dev.jdtech.jellyfin.adapters.EpisodeItem
|
||||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
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.*
|
import java.util.*
|
||||||
|
@ -22,7 +21,7 @@ constructor(
|
||||||
sealed class UiState {
|
sealed class UiState {
|
||||||
data class Normal(val episodes: List<EpisodeItem>) : UiState()
|
data class Normal(val episodes: List<EpisodeItem>) : UiState()
|
||||||
object Loading : UiState()
|
object Loading : UiState()
|
||||||
data class Error(val message: String?) : UiState()
|
data class Error(val error: Exception) : UiState()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
fun onUiState(scope: LifecycleCoroutineScope, collector: (UiState) -> Unit) {
|
||||||
|
@ -36,7 +35,7 @@ constructor(
|
||||||
val episodes = getEpisodes(seriesId, seasonId)
|
val episodes = getEpisodes(seriesId, seasonId)
|
||||||
uiState.emit(UiState.Normal(episodes))
|
uiState.emit(UiState.Normal(episodes))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
uiState.emit(UiState.Error(e.message))
|
uiState.emit(UiState.Error(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,7 @@ import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -43,10 +41,8 @@ constructor(
|
||||||
* @param server The server
|
* @param server The server
|
||||||
*/
|
*/
|
||||||
fun deleteServer(server: Server) {
|
fun deleteServer(server: Server) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
withContext(Dispatchers.IO) {
|
database.delete(server.id)
|
||||||
database.delete(server.id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue