refactor: replace SharedFlows with Channels for sending events
This commit is contained in:
parent
6c3360f8e7
commit
218b4f1af4
22 changed files with 170 additions and 116 deletions
|
@ -42,6 +42,7 @@ import dev.jdtech.jellyfin.mpv.TrackType
|
|||
import dev.jdtech.jellyfin.utils.PlayerGestureHelper
|
||||
import dev.jdtech.jellyfin.utils.PreviewScrubListener
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerEvents
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
@ -169,8 +170,10 @@ class PlayerActivity : BasePlayerActivity() {
|
|||
}
|
||||
|
||||
launch {
|
||||
viewModel.navigateBack.collect {
|
||||
if (it) finish()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is PlayerEvents.NavigateBack -> finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import androidx.navigation.fragment.findNavController
|
|||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dev.jdtech.jellyfin.adapters.DiscoveredServerListAdapter
|
||||
import dev.jdtech.jellyfin.databinding.FragmentAddServerBinding
|
||||
import dev.jdtech.jellyfin.viewmodels.AddServerEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.AddServerViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -81,9 +82,9 @@ class AddServerFragment : Fragment() {
|
|||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.navigateToLogin.collect {
|
||||
if (it) {
|
||||
navigateToLoginFragment()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is AddServerEvent.NavigateToLogin -> navigateToLoginFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import dev.jdtech.jellyfin.models.FindroidItem
|
|||
import dev.jdtech.jellyfin.models.FindroidMovie
|
||||
import dev.jdtech.jellyfin.models.FindroidShow
|
||||
import dev.jdtech.jellyfin.utils.restart
|
||||
import dev.jdtech.jellyfin.viewmodels.DownloadsEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.DownloadsViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -48,14 +49,18 @@ class DownloadsFragment : Fragment() {
|
|||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
launch {
|
||||
viewModel.connectionError.collect {
|
||||
Snackbar.make(binding.root, CoreR.string.no_server_connection, Snackbar.LENGTH_INDEFINITE)
|
||||
.setTextMaxLines(2)
|
||||
.setAction(CoreR.string.offline_mode) {
|
||||
appPreferences.offlineMode = true
|
||||
activity?.restart()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is DownloadsEvent.ConnectionError -> {
|
||||
Snackbar.make(binding.root, CoreR.string.no_server_connection, Snackbar.LENGTH_INDEFINITE)
|
||||
.setTextMaxLines(2)
|
||||
.setAction(CoreR.string.offline_mode) {
|
||||
appPreferences.offlineMode = true
|
||||
activity?.restart()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
launch {
|
||||
|
|
|
@ -33,6 +33,7 @@ import dev.jdtech.jellyfin.models.UiText
|
|||
import dev.jdtech.jellyfin.models.isDownloaded
|
||||
import dev.jdtech.jellyfin.models.isDownloading
|
||||
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
|
||||
import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetViewModel
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -122,14 +123,11 @@ class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
|
|||
}
|
||||
|
||||
launch {
|
||||
viewModel.downloadError.collect { uiText ->
|
||||
createErrorDialog(uiText)
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
viewModel.navigateBack.collect {
|
||||
if (it) findNavController().navigateUp()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is EpisodeBottomSheetEvent.NavigateBack -> findNavController().navigateUp()
|
||||
is EpisodeBottomSheetEvent.DownloadError -> createErrorDialog(event.uiText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import dev.jdtech.jellyfin.AppPreferences
|
|||
import dev.jdtech.jellyfin.adapters.UserLoginListAdapter
|
||||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
||||
import dev.jdtech.jellyfin.databinding.FragmentLoginBinding
|
||||
import dev.jdtech.jellyfin.viewmodels.LoginEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.LoginViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -123,9 +124,9 @@ class LoginFragment : Fragment() {
|
|||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.navigateToMain.collect {
|
||||
if (it) {
|
||||
navigateToHomeFragment()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is LoginEvent.NavigateToHome -> navigateToHomeFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import dev.jdtech.jellyfin.models.isDownloaded
|
|||
import dev.jdtech.jellyfin.models.isDownloading
|
||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
||||
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
|
||||
import dev.jdtech.jellyfin.viewmodels.MovieEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.MovieViewModel
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -118,14 +119,11 @@ class MovieFragment : Fragment() {
|
|||
}
|
||||
|
||||
launch {
|
||||
viewModel.downloadError.collect { uiText ->
|
||||
createErrorDialog(uiText)
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
viewModel.navigateBack.collect {
|
||||
if (it) findNavController().navigateUp()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is MovieEvent.NavigateBack -> findNavController().navigateUp()
|
||||
is MovieEvent.DownloadError -> createErrorDialog(event.uiText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import dev.jdtech.jellyfin.models.FindroidEpisode
|
|||
import dev.jdtech.jellyfin.models.PlayerItem
|
||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
||||
import dev.jdtech.jellyfin.viewmodels.SeasonEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.SeasonViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -60,8 +61,10 @@ class SeasonFragment : Fragment() {
|
|||
}
|
||||
|
||||
launch {
|
||||
viewModel.navigateBack.collect {
|
||||
if (it) findNavController().navigateUp()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is SeasonEvent.NavigateBack -> findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import dev.jdtech.jellyfin.adapters.ServerAddressAdapter
|
|||
import dev.jdtech.jellyfin.databinding.FragmentServerAddressesBinding
|
||||
import dev.jdtech.jellyfin.dialogs.AddServerAddressDialog
|
||||
import dev.jdtech.jellyfin.dialogs.DeleteServerAddressDialog
|
||||
import dev.jdtech.jellyfin.viewmodels.ServerAddressesEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.ServerAddressesViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -57,9 +58,9 @@ class ServerAddressesFragment : Fragment() {
|
|||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.navigateToMain.collect {
|
||||
if (it) {
|
||||
navigateToMainActivity()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is ServerAddressesEvent.NavigateToHome -> navigateToMainActivity()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import dev.jdtech.jellyfin.adapters.ServerGridAdapter
|
||||
import dev.jdtech.jellyfin.databinding.FragmentServerSelectBinding
|
||||
import dev.jdtech.jellyfin.dialogs.DeleteServerDialogFragment
|
||||
import dev.jdtech.jellyfin.viewmodels.ServerSelectEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.ServerSelectViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -61,13 +62,11 @@ class ServerSelectFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
launch {
|
||||
viewModel.navigateToMain.collect {
|
||||
if (it) navigateToMainActivity()
|
||||
}
|
||||
}
|
||||
launch {
|
||||
viewModel.navigateToLogin.collect {
|
||||
if (it) navigateToLoginFragment()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is ServerSelectEvent.NavigateToHome -> navigateToMainActivity()
|
||||
is ServerSelectEvent.NavigateToLogin -> navigateToLoginFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import dev.jdtech.jellyfin.models.isDownloaded
|
|||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
||||
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
|
||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
||||
import dev.jdtech.jellyfin.viewmodels.ShowEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.ShowViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -79,8 +80,10 @@ class ShowFragment : Fragment() {
|
|||
}
|
||||
|
||||
launch {
|
||||
viewModel.navigateBack.collect {
|
||||
if (it) findNavController().navigateUp()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is ShowEvent.NavigateBack -> findNavController().navigateUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import dev.jdtech.jellyfin.AppNavigationDirections
|
|||
import dev.jdtech.jellyfin.adapters.UserListAdapter
|
||||
import dev.jdtech.jellyfin.databinding.FragmentUsersBinding
|
||||
import dev.jdtech.jellyfin.dialogs.DeleteUserDialogFragment
|
||||
import dev.jdtech.jellyfin.viewmodels.UsersEvent
|
||||
import dev.jdtech.jellyfin.viewmodels.UsersViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -54,9 +55,9 @@ class UsersFragment : Fragment() {
|
|||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.navigateToMain.collect {
|
||||
if (it) {
|
||||
navigateToMainActivity()
|
||||
viewModel.eventsChannelFlow.collect { event ->
|
||||
when (event) {
|
||||
is UsersEvent.NavigateToHome -> navigateToMainActivity()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,10 @@ import dev.jdtech.jellyfin.models.ServerAddress
|
|||
import dev.jdtech.jellyfin.models.UiText
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jellyfin.sdk.discovery.RecommendedServerInfo
|
||||
|
@ -38,11 +38,12 @@ constructor(
|
|||
) : ViewModel() {
|
||||
private val _uiState = MutableStateFlow<UiState>(UiState.Normal)
|
||||
val uiState = _uiState.asStateFlow()
|
||||
private val _navigateToLogin = MutableSharedFlow<Boolean>()
|
||||
val navigateToLogin = _navigateToLogin.asSharedFlow()
|
||||
private val _discoveredServersState = MutableStateFlow<DiscoveredServersState>(DiscoveredServersState.Loading)
|
||||
val discoveredServersState = _discoveredServersState.asStateFlow()
|
||||
|
||||
private val eventsChannel = Channel<AddServerEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
private val discoveredServers = mutableListOf<DiscoveredServer>()
|
||||
private var serverFound = false
|
||||
|
||||
|
@ -206,7 +207,7 @@ constructor(
|
|||
}
|
||||
|
||||
_uiState.emit(UiState.Normal)
|
||||
_navigateToLogin.emit(true)
|
||||
eventsChannel.send(AddServerEvent.NavigateToLogin)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,3 +270,7 @@ constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface AddServerEvent {
|
||||
data object NavigateToLogin : AddServerEvent
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@ import dev.jdtech.jellyfin.models.FindroidMovie
|
|||
import dev.jdtech.jellyfin.models.FindroidShow
|
||||
import dev.jdtech.jellyfin.models.UiText
|
||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -28,8 +28,9 @@ constructor(
|
|||
) : ViewModel() {
|
||||
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
|
||||
val uiState = _uiState.asStateFlow()
|
||||
private val _connectionError = MutableSharedFlow<Exception>()
|
||||
val connectionError = _connectionError.asSharedFlow()
|
||||
|
||||
private val eventsChannel = Channel<DownloadsEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
sealed class UiState {
|
||||
data class Normal(val sections: List<FavoriteSection>) : UiState()
|
||||
|
@ -49,7 +50,7 @@ constructor(
|
|||
// Give the UI a chance to load
|
||||
delay(100)
|
||||
} catch (e: Exception) {
|
||||
_connectionError.emit(e)
|
||||
eventsChannel.send(DownloadsEvent.ConnectionError(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,3 +89,7 @@ constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface DownloadsEvent {
|
||||
data class ConnectionError(val error: Exception) : DownloadsEvent
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ import dev.jdtech.jellyfin.models.UiText
|
|||
import dev.jdtech.jellyfin.models.isDownloading
|
||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||
import dev.jdtech.jellyfin.utils.Downloader
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
|
@ -37,11 +37,8 @@ constructor(
|
|||
private val _downloadStatus = MutableStateFlow(Pair(0, 0))
|
||||
val downloadStatus = _downloadStatus.asStateFlow()
|
||||
|
||||
private val _downloadError = MutableSharedFlow<UiText>()
|
||||
val downloadError = _downloadError.asSharedFlow()
|
||||
|
||||
private val _navigateBack = MutableSharedFlow<Boolean>()
|
||||
val navigateBack = _navigateBack.asSharedFlow()
|
||||
private val eventsChannel = Channel<EpisodeBottomSheetEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
|
@ -75,7 +72,7 @@ constructor(
|
|||
)
|
||||
} catch (_: NullPointerException) {
|
||||
// Navigate back because item does not exist (probably because it's been deleted)
|
||||
_navigateBack.emit(true)
|
||||
eventsChannel.send(EpisodeBottomSheetEvent.NavigateBack)
|
||||
} catch (e: Exception) {
|
||||
_uiState.emit(UiState.Error(e))
|
||||
}
|
||||
|
@ -133,7 +130,7 @@ constructor(
|
|||
_downloadStatus.emit(Pair(10, Random.nextInt()))
|
||||
|
||||
if (result.second != null) {
|
||||
_downloadError.emit(result.second!!)
|
||||
eventsChannel.send(EpisodeBottomSheetEvent.DownloadError(result.second!!))
|
||||
}
|
||||
|
||||
loadEpisode(item.id)
|
||||
|
@ -188,3 +185,8 @@ constructor(
|
|||
handler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface EpisodeBottomSheetEvent {
|
||||
data object NavigateBack : EpisodeBottomSheetEvent
|
||||
data class DownloadError(val uiText: UiText) : EpisodeBottomSheetEvent
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@ import dev.jdtech.jellyfin.models.UiText
|
|||
import dev.jdtech.jellyfin.models.User
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jellyfin.sdk.api.client.extensions.authenticateWithQuickConnect
|
||||
|
@ -38,8 +38,9 @@ constructor(
|
|||
val usersState = _usersState.asStateFlow()
|
||||
private val _quickConnectUiState = MutableStateFlow<QuickConnectUiState>(QuickConnectUiState.Disabled)
|
||||
val quickConnectUiState = _quickConnectUiState.asStateFlow()
|
||||
private val _navigateToMain = MutableSharedFlow<Boolean>()
|
||||
val navigateToMain = _navigateToMain.asSharedFlow()
|
||||
|
||||
private val eventsChannel = Channel<LoginEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
private var quickConnectJob: Job? = null
|
||||
|
||||
|
@ -121,7 +122,7 @@ constructor(
|
|||
saveAuthenticationResult(authenticationResult)
|
||||
|
||||
_uiState.emit(UiState.Normal)
|
||||
_navigateToMain.emit(true)
|
||||
eventsChannel.send(LoginEvent.NavigateToHome)
|
||||
} catch (e: Exception) {
|
||||
val message =
|
||||
if (e.message?.contains("401") == true) {
|
||||
|
@ -157,7 +158,7 @@ constructor(
|
|||
saveAuthenticationResult(authenticationResult)
|
||||
|
||||
_quickConnectUiState.emit(QuickConnectUiState.Normal)
|
||||
_navigateToMain.emit(true)
|
||||
eventsChannel.send(LoginEvent.NavigateToHome)
|
||||
} catch (_: Exception) {
|
||||
_quickConnectUiState.emit(QuickConnectUiState.Normal)
|
||||
}
|
||||
|
@ -189,3 +190,7 @@ constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface LoginEvent {
|
||||
data object NavigateToHome : LoginEvent
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ import dev.jdtech.jellyfin.repository.JellyfinRepository
|
|||
import dev.jdtech.jellyfin.utils.Downloader
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Runnable
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jellyfin.sdk.model.api.BaseItemPerson
|
||||
|
@ -49,11 +49,8 @@ constructor(
|
|||
private val _downloadStatus = MutableStateFlow(Pair(0, 0))
|
||||
val downloadStatus = _downloadStatus.asStateFlow()
|
||||
|
||||
private val _downloadError = MutableSharedFlow<UiText>()
|
||||
val downloadError = _downloadError.asSharedFlow()
|
||||
|
||||
private val _navigateBack = MutableSharedFlow<Boolean>()
|
||||
val navigateBack = _navigateBack.asSharedFlow()
|
||||
private val eventsChannel = Channel<MovieEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
|
@ -115,7 +112,7 @@ constructor(
|
|||
)
|
||||
} catch (_: NullPointerException) {
|
||||
// Navigate back because item does not exist (probably because it's been deleted)
|
||||
_navigateBack.emit(true)
|
||||
eventsChannel.send(MovieEvent.NavigateBack)
|
||||
} catch (e: Exception) {
|
||||
_uiState.emit(UiState.Error(e))
|
||||
}
|
||||
|
@ -330,7 +327,7 @@ constructor(
|
|||
_downloadStatus.emit(Pair(10, Random.nextInt()))
|
||||
|
||||
if (result.second != null) {
|
||||
_downloadError.emit(result.second!!)
|
||||
eventsChannel.send(MovieEvent.DownloadError(result.second!!))
|
||||
}
|
||||
|
||||
loadData(item.id)
|
||||
|
@ -385,3 +382,8 @@ constructor(
|
|||
handler.removeCallbacksAndMessages(null)
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface MovieEvent {
|
||||
data object NavigateBack : MovieEvent
|
||||
data class DownloadError(val uiText: UiText) : MovieEvent
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||
import dev.jdtech.jellyfin.models.EpisodeItem
|
||||
import dev.jdtech.jellyfin.models.FindroidSeason
|
||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.sdk.model.api.ItemFields
|
||||
import java.util.UUID
|
||||
|
@ -24,8 +24,8 @@ constructor(
|
|||
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
private val _navigateBack = MutableSharedFlow<Boolean>()
|
||||
val navigateBack = _navigateBack.asSharedFlow()
|
||||
private val eventsChannel = Channel<SeasonEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
sealed class UiState {
|
||||
data class Normal(val episodes: List<EpisodeItem>) : UiState()
|
||||
|
@ -44,7 +44,7 @@ constructor(
|
|||
_uiState.emit(UiState.Normal(episodes))
|
||||
} catch (_: NullPointerException) {
|
||||
// Navigate back because item does not exist (probably because it's been deleted)
|
||||
_navigateBack.emit(true)
|
||||
eventsChannel.send(SeasonEvent.NavigateBack)
|
||||
} catch (e: Exception) {
|
||||
_uiState.emit(UiState.Error(e))
|
||||
}
|
||||
|
@ -63,3 +63,7 @@ constructor(
|
|||
return listOf(header) + episodes.map { EpisodeItem.Episode(it) }
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface SeasonEvent {
|
||||
data object NavigateBack : SeasonEvent
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ import dev.jdtech.jellyfin.api.JellyfinApi
|
|||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
||||
import dev.jdtech.jellyfin.models.ServerAddress
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
|
@ -32,8 +32,8 @@ constructor(
|
|||
data class Error(val error: Exception) : UiState()
|
||||
}
|
||||
|
||||
private val _navigateToMain = MutableSharedFlow<Boolean>()
|
||||
val navigateToMain = _navigateToMain.asSharedFlow()
|
||||
private val eventsChannel = Channel<ServerAddressesEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
private var currentServerId: String = ""
|
||||
|
||||
|
@ -75,7 +75,7 @@ constructor(
|
|||
|
||||
jellyfinApi.api.baseUrl = address.address
|
||||
|
||||
_navigateToMain.emit(true)
|
||||
eventsChannel.send(ServerAddressesEvent.NavigateToHome)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,3 +87,7 @@ constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface ServerAddressesEvent {
|
||||
data object NavigateToHome : ServerAddressesEvent
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@ import dev.jdtech.jellyfin.api.JellyfinApi
|
|||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
||||
import dev.jdtech.jellyfin.models.Server
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -26,11 +26,8 @@ constructor(
|
|||
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
private val _navigateToMain = MutableSharedFlow<Boolean>()
|
||||
val navigateToMain = _navigateToMain.asSharedFlow()
|
||||
|
||||
private val _navigateToLogin = MutableSharedFlow<Boolean>()
|
||||
val navigateToLogin = _navigateToLogin.asSharedFlow()
|
||||
private val eventsChannel = Channel<ServerSelectEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
sealed class UiState {
|
||||
data class Normal(val servers: List<Server>) : UiState()
|
||||
|
@ -75,7 +72,7 @@ constructor(
|
|||
userId = null
|
||||
}
|
||||
appPreferences.currentServer = server.id
|
||||
_navigateToLogin.emit(true)
|
||||
eventsChannel.send(ServerSelectEvent.NavigateToLogin)
|
||||
return@launch
|
||||
}
|
||||
|
||||
|
@ -87,7 +84,12 @@ constructor(
|
|||
|
||||
appPreferences.currentServer = server.id
|
||||
|
||||
_navigateToMain.emit(true)
|
||||
eventsChannel.send(ServerSelectEvent.NavigateToHome)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface ServerSelectEvent {
|
||||
data object NavigateToHome : ServerSelectEvent
|
||||
data object NavigateToLogin : ServerSelectEvent
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@ import dev.jdtech.jellyfin.models.FindroidSeason
|
|||
import dev.jdtech.jellyfin.models.FindroidShow
|
||||
import dev.jdtech.jellyfin.repository.JellyfinRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jellyfin.sdk.model.api.BaseItemPerson
|
||||
|
@ -27,8 +27,8 @@ constructor(
|
|||
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
private val _navigateBack = MutableSharedFlow<Boolean>()
|
||||
val navigateBack = _navigateBack.asSharedFlow()
|
||||
private val eventsChannel = Channel<ShowEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
sealed class UiState {
|
||||
data class Normal(
|
||||
|
@ -93,7 +93,7 @@ constructor(
|
|||
)
|
||||
} catch (_: NullPointerException) {
|
||||
// Navigate back because item does not exist (probably because it's been deleted)
|
||||
_navigateBack.emit(true)
|
||||
eventsChannel.send(ShowEvent.NavigateBack)
|
||||
} catch (e: Exception) {
|
||||
_uiState.emit(UiState.Error(e))
|
||||
}
|
||||
|
@ -189,3 +189,7 @@ constructor(
|
|||
return dateRange.joinToString(separator = " - ")
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface ShowEvent {
|
||||
data object NavigateBack : ShowEvent
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ import dev.jdtech.jellyfin.api.JellyfinApi
|
|||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
||||
import dev.jdtech.jellyfin.models.User
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
@ -31,8 +31,8 @@ constructor(
|
|||
data class Error(val error: Exception) : UiState()
|
||||
}
|
||||
|
||||
private val _navigateToMain = MutableSharedFlow<Boolean>()
|
||||
val navigateToMain = _navigateToMain.asSharedFlow()
|
||||
private val eventsChannel = Channel<UsersEvent>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
private var currentServerId: String = ""
|
||||
|
||||
|
@ -77,7 +77,11 @@ constructor(
|
|||
userId = user.id
|
||||
}
|
||||
|
||||
_navigateToMain.emit(true)
|
||||
eventsChannel.send(UsersEvent.NavigateToHome)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface UsersEvent {
|
||||
data object NavigateToHome : UsersEvent
|
||||
}
|
||||
|
|
|
@ -27,11 +27,11 @@ import dev.jdtech.jellyfin.utils.bif.BifUtil
|
|||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -60,8 +60,8 @@ constructor(
|
|||
)
|
||||
val uiState = _uiState.asStateFlow()
|
||||
|
||||
private val _navigateBack = MutableSharedFlow<Boolean>()
|
||||
val navigateBack = _navigateBack.asSharedFlow()
|
||||
private val eventsChannel = Channel<PlayerEvents>()
|
||||
val eventsChannelFlow = eventsChannel.receiveAsFlow()
|
||||
|
||||
private val intros: MutableMap<UUID, Intro> = mutableMapOf()
|
||||
|
||||
|
@ -317,7 +317,7 @@ constructor(
|
|||
}
|
||||
ExoPlayer.STATE_ENDED -> {
|
||||
stateString = "ExoPlayer.STATE_ENDED -"
|
||||
_navigateBack.tryEmit(true)
|
||||
eventsChannel.trySend(PlayerEvents.NavigateBack)
|
||||
}
|
||||
}
|
||||
Timber.d("Changed player state to $stateString")
|
||||
|
@ -366,3 +366,7 @@ constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface PlayerEvents {
|
||||
data object NavigateBack : PlayerEvents
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue