mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
parent
405e170750
commit
dc3193e2dc
17 changed files with 127 additions and 61 deletions
|
|
@ -21,6 +21,10 @@ This is not a fork of the [official client](https://github.com/jellyfin/jellyfin
|
|||
- Subtly show playback position along the bottom of the screen while seeking w/ D-Pad
|
||||
- Force Continue Watching & Next Up TV episodes to use their Series posters
|
||||
|
||||
### Roadmap
|
||||
|
||||
See [here for the roadmap](https://github.com/damontecres/Wholphin/wiki#roadmap)
|
||||
|
||||
## Installation
|
||||
|
||||
Downloader Code: `8668671`
|
||||
|
|
|
|||
|
|
@ -106,9 +106,21 @@ class ItemPlaybackRepository
|
|||
saveItemPlayback(toSave)
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the [ItemPlayback] into the database, returning the same object with the rowId updated if needed
|
||||
*/
|
||||
suspend fun saveItemPlayback(itemPlayback: ItemPlayback): ItemPlayback {
|
||||
val rowId = itemPlaybackDao.saveItem(itemPlayback)
|
||||
return itemPlayback.copy(rowId = rowId)
|
||||
val toSave =
|
||||
if (itemPlayback.userId < 0) {
|
||||
val userRowId =
|
||||
serverRepository.currentUser?.rowId?.takeIf { it >= 0 }
|
||||
?: throw IllegalStateException("Trying to save an ItemPlayback without a user, but there is no current user")
|
||||
itemPlayback.copy(userId = userRowId)
|
||||
} else {
|
||||
itemPlayback
|
||||
}
|
||||
val id = itemPlaybackDao.saveItem(toSave)
|
||||
return toSave.copy(rowId = id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,10 +84,23 @@ interface JellyfinServerDao {
|
|||
fun addOrUpdateUser(user: JellyfinUser) {
|
||||
val result = addUser(user)
|
||||
if (result == -1L) {
|
||||
updateUser(user)
|
||||
val toSave =
|
||||
if (user.rowId <= 0) {
|
||||
val temp = getUser(user.serverId, user.id)!!
|
||||
user.copy(rowId = temp.rowId)
|
||||
} else {
|
||||
user
|
||||
}
|
||||
updateUser(toSave)
|
||||
}
|
||||
}
|
||||
|
||||
@Query("SELECT * FROM users WHERE serverId = :serverId AND id = :userId")
|
||||
fun getUser(
|
||||
serverId: UUID,
|
||||
userId: UUID,
|
||||
): JellyfinUser?
|
||||
|
||||
@Query("DELETE FROM servers WHERE id = :serverId")
|
||||
fun deleteServer(serverId: UUID)
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ class ServerRepository
|
|||
id = userDto.id,
|
||||
name = userDto.name,
|
||||
)
|
||||
if (updatedUser.rowId <= 0) {
|
||||
}
|
||||
serverDao.addOrUpdateServer(updatedServer)
|
||||
serverDao.addOrUpdateUser(updatedUser)
|
||||
userPreferencesDataStore.updateData {
|
||||
|
|
@ -119,7 +121,6 @@ class ServerRepository
|
|||
serverDao.getServer(serverId)
|
||||
}
|
||||
if (serverAndUsers != null) {
|
||||
_currentServer = serverAndUsers.server
|
||||
val user = serverAndUsers.users.firstOrNull { it.id == userId }
|
||||
if (user != null) {
|
||||
changeUser(serverAndUsers.server, user)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,19 @@ val DefaultItemFields =
|
|||
ItemFields.TRICKPLAY,
|
||||
ItemFields.SORT_NAME,
|
||||
ItemFields.CHAPTERS,
|
||||
ItemFields.MEDIA_SOURCES,
|
||||
)
|
||||
|
||||
/**
|
||||
* [ItemFields] for higher level displays such as grids or rows
|
||||
*/
|
||||
val SlimItemFields =
|
||||
listOf(
|
||||
ItemFields.PRIMARY_IMAGE_ASPECT_RATIO,
|
||||
ItemFields.SEASON_USER_DATA,
|
||||
ItemFields.CHILD_COUNT,
|
||||
ItemFields.OVERVIEW,
|
||||
ItemFields.SORT_NAME,
|
||||
)
|
||||
|
||||
val DefaultButtonPadding =
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ import androidx.tv.material3.Text
|
|||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||
import com.github.damontecres.wholphin.ui.OneTimeLaunchedEffect
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.data.MovieSortOptions
|
||||
import com.github.damontecres.wholphin.ui.data.SeriesSortOptions
|
||||
import com.github.damontecres.wholphin.ui.data.SortAndDirection
|
||||
|
|
@ -135,7 +135,7 @@ class CollectionFolderViewModel
|
|||
SortOrder.ASCENDING,
|
||||
SortOrder.ASCENDING,
|
||||
),
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
),
|
||||
)
|
||||
val newPager =
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.GetItemsFilter
|
||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||
import com.github.damontecres.wholphin.ui.OneTimeLaunchedEffect
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.cards.GridCard
|
||||
import com.github.damontecres.wholphin.ui.detail.CardGrid
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
|
|
@ -54,7 +54,7 @@ class GenreViewModel
|
|||
val request =
|
||||
GetGenresRequest(
|
||||
parentId = itemId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
)
|
||||
val pager = ApiRequestPager(api, request, GetGenresRequestHandler, viewModelScope).init()
|
||||
withContext(Dispatchers.Main) {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||
import com.github.damontecres.wholphin.ui.OneTimeLaunchedEffect
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.main.HomePageContent
|
||||
import com.github.damontecres.wholphin.ui.main.HomeRow
|
||||
import com.github.damontecres.wholphin.ui.main.HomeSection
|
||||
|
|
@ -52,7 +52,7 @@ class RecommendedMovieViewModel
|
|||
val resumeItemsRequest =
|
||||
GetResumeItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE),
|
||||
enableUserData = true,
|
||||
)
|
||||
|
|
@ -62,7 +62,7 @@ class RecommendedMovieViewModel
|
|||
val recentlyReleasedRequest =
|
||||
GetItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE),
|
||||
recursive = true,
|
||||
enableUserData = true,
|
||||
|
|
@ -75,7 +75,7 @@ class RecommendedMovieViewModel
|
|||
val recentlyAddedRequest =
|
||||
GetItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE),
|
||||
recursive = true,
|
||||
enableUserData = true,
|
||||
|
|
@ -94,7 +94,7 @@ class RecommendedMovieViewModel
|
|||
val unwatchedTopRatedRequest =
|
||||
GetItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE),
|
||||
recursive = true,
|
||||
enableUserData = true,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||
import com.github.damontecres.wholphin.ui.OneTimeLaunchedEffect
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.main.HomePageContent
|
||||
import com.github.damontecres.wholphin.ui.main.HomeRow
|
||||
import com.github.damontecres.wholphin.ui.main.HomeSection
|
||||
|
|
@ -54,7 +54,7 @@ class RecommendedTvShowViewModel
|
|||
val resumeItemsRequest =
|
||||
GetResumeItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.EPISODE),
|
||||
enableUserData = true,
|
||||
)
|
||||
|
|
@ -64,7 +64,7 @@ class RecommendedTvShowViewModel
|
|||
val nextUpRequest =
|
||||
GetNextUpRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
enableUserData = true,
|
||||
)
|
||||
val nextUpItems = ApiRequestPager(api, nextUpRequest, GetNextUpRequestHandler, viewModelScope, useSeriesForPrimary = true)
|
||||
|
|
@ -72,7 +72,7 @@ class RecommendedTvShowViewModel
|
|||
val recentlyReleasedRequest =
|
||||
GetItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.EPISODE),
|
||||
recursive = true,
|
||||
enableUserData = true,
|
||||
|
|
@ -85,7 +85,7 @@ class RecommendedTvShowViewModel
|
|||
val recentlyAddedRequest =
|
||||
GetItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.EPISODE),
|
||||
recursive = true,
|
||||
enableUserData = true,
|
||||
|
|
@ -104,7 +104,7 @@ class RecommendedTvShowViewModel
|
|||
val unwatchedTopRatedRequest =
|
||||
GetItemsRequest(
|
||||
parentId = parentId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
includeItemTypes = listOf(BaseItemKind.SERIES),
|
||||
recursive = true,
|
||||
enableUserData = true,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@ package com.github.damontecres.wholphin.ui.detail
|
|||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowForward
|
||||
import androidx.compose.material.icons.filled.ArrowForward
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
|
|
@ -87,8 +85,7 @@ fun buildMoreDialogItems(
|
|||
add(
|
||||
DialogItem(
|
||||
"Choose Version",
|
||||
Icons.Default.ArrowForward,
|
||||
iconColor = Color.Green.copy(alpha = .8f),
|
||||
R.string.fa_file_video,
|
||||
) {
|
||||
onChooseVersion.invoke()
|
||||
},
|
||||
|
|
@ -104,7 +101,7 @@ fun buildMoreDialogItems(
|
|||
add(
|
||||
DialogItem(
|
||||
"Choose audio",
|
||||
Icons.Default.Settings,
|
||||
R.string.fa_volume_low,
|
||||
) {
|
||||
onChooseTracks.invoke(MediaStreamType.AUDIO)
|
||||
},
|
||||
|
|
@ -114,7 +111,7 @@ fun buildMoreDialogItems(
|
|||
add(
|
||||
DialogItem(
|
||||
"Choose subtitles",
|
||||
Icons.Default.Settings,
|
||||
R.string.fa_closed_captioning,
|
||||
) {
|
||||
onChooseTracks.invoke(MediaStreamType.SUBTITLE)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import com.github.damontecres.wholphin.util.GetEpisodesRequestHandler
|
|||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingExceptionHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
import com.github.damontecres.wholphin.util.profile.Codec
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -135,7 +136,13 @@ class SeriesViewModel
|
|||
val url =
|
||||
api.universalAudioApi.getUniversalAudioStreamUrl(
|
||||
theme.id,
|
||||
container = listOf("opus", "mp3", "aaa", "flac"),
|
||||
container =
|
||||
listOf(
|
||||
Codec.Audio.OPUS,
|
||||
Codec.Audio.MP3,
|
||||
Codec.Audio.AAC,
|
||||
Codec.Audio.FLAC,
|
||||
),
|
||||
)
|
||||
Timber.Forest.v("Found theme song for series $seriesId")
|
||||
withContext(Dispatchers.Main) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.nav.NavigationManager
|
||||
import com.github.damontecres.wholphin.util.LoadingExceptionHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
|
|
@ -119,7 +119,7 @@ class HomeViewModel
|
|||
val request =
|
||||
GetResumeItemsRequest(
|
||||
userId = userId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
limit = limit,
|
||||
includeItemTypes = supportItemKinds,
|
||||
)
|
||||
|
|
@ -140,7 +140,7 @@ class HomeViewModel
|
|||
val request =
|
||||
GetNextUpRequest(
|
||||
userId = userId,
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
imageTypeLimit = 1,
|
||||
parentId = null,
|
||||
limit = limit,
|
||||
|
|
@ -176,7 +176,7 @@ class HomeViewModel
|
|||
view.name?.let { "Recently Added in $it" }
|
||||
val request =
|
||||
GetLatestMediaRequest(
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
imageTypeLimit = 1,
|
||||
parentId = view.id,
|
||||
groupItems = true,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.ui.Cards
|
||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.cards.EpisodeCard
|
||||
import com.github.damontecres.wholphin.ui.cards.ItemRow
|
||||
import com.github.damontecres.wholphin.ui.cards.SeasonCard
|
||||
|
|
@ -78,7 +78,7 @@ class SearchViewModel
|
|||
searchTerm = query,
|
||||
recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.MOVIE),
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
limit = 25,
|
||||
)
|
||||
val pager = ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope)
|
||||
|
|
@ -93,7 +93,7 @@ class SearchViewModel
|
|||
searchTerm = query,
|
||||
recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.SERIES),
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
limit = 25,
|
||||
)
|
||||
val pager = ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope)
|
||||
|
|
@ -108,7 +108,7 @@ class SearchViewModel
|
|||
searchTerm = query,
|
||||
recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.EPISODE),
|
||||
fields = DefaultItemFields,
|
||||
fields = SlimItemFields,
|
||||
limit = 25,
|
||||
)
|
||||
val pager = ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import androidx.media3.common.Tracks
|
|||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import com.github.damontecres.wholphin.data.ItemPlaybackDao
|
||||
import com.github.damontecres.wholphin.data.ItemPlaybackRepository
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.Chapter
|
||||
|
|
@ -100,6 +101,7 @@ class PlaybackViewModel
|
|||
val navigationManager: NavigationManager,
|
||||
val itemPlaybackDao: ItemPlaybackDao,
|
||||
val serverRepository: ServerRepository,
|
||||
val itemPlaybackRepository: ItemPlaybackRepository,
|
||||
) : ViewModel(),
|
||||
Player.Listener {
|
||||
val player: ExoPlayer =
|
||||
|
|
@ -461,10 +463,9 @@ class PlaybackViewModel
|
|||
if (userInitiated) {
|
||||
viewModelScope.launch(Dispatchers.IO + ExceptionHandler()) {
|
||||
Timber.v("Saving user initiated item playback: %s", itemPlayback)
|
||||
val rowId = itemPlaybackDao.saveItem(itemPlayback)
|
||||
val updated = itemPlaybackRepository.saveItemPlayback(itemPlayback)
|
||||
withContext(Dispatchers.Main) {
|
||||
this@PlaybackViewModel.currentItemPlayback.value =
|
||||
itemPlayback.copy(rowId = rowId)
|
||||
this@PlaybackViewModel.currentItemPlayback.value = updated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,9 +125,7 @@ fun SwitchUserContent(
|
|||
LaunchedEffect(Unit) {
|
||||
viewModel.clearSwitchUserState()
|
||||
if (useQuickConnect) {
|
||||
viewModel.initiateQuickConnect(server) {
|
||||
viewModel.navigationManager.goToHome()
|
||||
}
|
||||
viewModel.initiateQuickConnect(server)
|
||||
}
|
||||
}
|
||||
BasicDialog(
|
||||
|
|
@ -180,10 +178,18 @@ fun SwitchUserContent(
|
|||
)
|
||||
when (val s = userState) {
|
||||
is LoadingState.Error -> {
|
||||
Text(
|
||||
text = s.message ?: s.exception?.localizedMessage ?: "Error",
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
s.message?.let {
|
||||
Text(
|
||||
text = it,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
}
|
||||
s.exception?.localizedMessage?.let {
|
||||
Text(
|
||||
text = it,
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
|
|
@ -208,6 +214,7 @@ fun SwitchUserContent(
|
|||
autoCorrectEnabled = false,
|
||||
keyboardType = KeyboardType.Text,
|
||||
),
|
||||
isInputValid = { userState !is LoadingState.Error },
|
||||
modifier = Modifier.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
|
|
@ -235,6 +242,7 @@ fun SwitchUserContent(
|
|||
KeyboardActions(
|
||||
onDone = { onSubmit.invoke() },
|
||||
),
|
||||
isInputValid = { userState !is LoadingState.Error },
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class SwitchUserViewModel
|
|||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error switching user")
|
||||
setError(ex)
|
||||
setError("Error switching user", ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -178,15 +178,19 @@ class SwitchUserViewModel
|
|||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error logging in user")
|
||||
setError(ex)
|
||||
if (ex is InvalidStatusException && ex.status == 401) {
|
||||
withContext(Dispatchers.Main) {
|
||||
switchUserState.value =
|
||||
LoadingState.Error("Invalid username or password")
|
||||
}
|
||||
} else {
|
||||
setError("Error during login", ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun initiateQuickConnect(
|
||||
server: JellyfinServer,
|
||||
onAuthenticated: () -> Unit,
|
||||
) {
|
||||
fun initiateQuickConnect(server: JellyfinServer) {
|
||||
quickConnectJob?.cancel()
|
||||
viewModelScope.launchIO {
|
||||
try {
|
||||
|
|
@ -218,19 +222,21 @@ class SwitchUserViewModel
|
|||
)
|
||||
serverRepository.changeUser(server.url, authenticationResult)
|
||||
withContext(Dispatchers.Main) {
|
||||
onAuthenticated.invoke()
|
||||
navigationManager.goToHome()
|
||||
}
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error during quick connect")
|
||||
if (ex is InvalidStatusException && ex.status == 401) {
|
||||
quickConnectState.value = null
|
||||
serverQuickConnect.value =
|
||||
serverQuickConnect.value!!.toMutableMap().apply {
|
||||
put(server.id, false)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
quickConnectState.value = null
|
||||
serverQuickConnect.value =
|
||||
serverQuickConnect.value!!.toMutableMap().apply {
|
||||
put(server.id, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
setError(ex)
|
||||
setError("Error with Quick Connect", ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -329,8 +335,10 @@ class SwitchUserViewModel
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun setError(ex: Exception) =
|
||||
withContext(Dispatchers.Main) {
|
||||
switchUserState.value = LoadingState.Error(ex)
|
||||
}
|
||||
private suspend fun setError(
|
||||
msg: String? = null,
|
||||
ex: Exception? = null,
|
||||
) = withContext(Dispatchers.Main) {
|
||||
switchUserState.value = LoadingState.Error(msg, ex)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,4 +34,6 @@
|
|||
<string name="fa_shuffle" translatable="false"></string>
|
||||
<string name="fa_open_folder" translatable="false"></string>
|
||||
<string name="fa_list_ul" translatable="false"></string>
|
||||
<string name="fa_file_video" translatable="false"></string>
|
||||
<string name="fa_volume_low" translatable="false"></string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue