From dc3193e2dcb8327ad9e0ee6dbe8c6d2705342182 Mon Sep 17 00:00:00 2001
From: damontecres <154766448+damontecres@users.noreply.github.com>
Date: Sat, 18 Oct 2025 18:45:08 -0400
Subject: [PATCH] Various fixes (#33)
Fixes a few issues to prepare for a release.
---
README.md | 4 ++
.../wholphin/data/ItemPlaybackRepository.kt | 16 ++++++-
.../wholphin/data/JellyfinServer.kt | 15 ++++++-
.../wholphin/data/ServerRepository.kt | 3 +-
.../damontecres/wholphin/ui/UiConstants.kt | 13 ++++++
.../ui/components/CollectionFolderGrid.kt | 4 +-
.../wholphin/ui/components/GenreCardGrid.kt | 4 +-
.../ui/components/RecommendedMovie.kt | 10 ++---
.../ui/components/RecommendedTvShow.kt | 12 +++---
.../wholphin/ui/detail/DetailUtils.kt | 9 ++--
.../wholphin/ui/detail/SeriesViewModel.kt | 9 +++-
.../wholphin/ui/main/HomeViewModel.kt | 8 ++--
.../wholphin/ui/main/SearchPage.kt | 8 ++--
.../wholphin/ui/playback/PlaybackViewModel.kt | 7 ++--
.../wholphin/ui/setup/SwitchUserContent.kt | 22 ++++++----
.../wholphin/ui/setup/SwitchUserViewModel.kt | 42 +++++++++++--------
app/src/main/res/values/fa_strings.xml | 2 +
17 files changed, 127 insertions(+), 61 deletions(-)
diff --git a/README.md b/README.md
index 388d6c8b..7b03d2ab 100644
--- a/README.md
+++ b/README.md
@@ -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`
diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/ItemPlaybackRepository.kt b/app/src/main/java/com/github/damontecres/wholphin/data/ItemPlaybackRepository.kt
index 0a455bf9..27a12d13 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/data/ItemPlaybackRepository.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/data/ItemPlaybackRepository.kt
@@ -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)
}
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/JellyfinServer.kt b/app/src/main/java/com/github/damontecres/wholphin/data/JellyfinServer.kt
index 6451526d..5f00bda7 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/data/JellyfinServer.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/data/JellyfinServer.kt
@@ -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)
diff --git a/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt b/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt
index 1e96f647..d6279eb5 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/data/ServerRepository.kt
@@ -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)
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt
index 9f880250..b03d5950 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/UiConstants.kt
@@ -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 =
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt
index c771ce57..394ed3ca 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt
@@ -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 =
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/GenreCardGrid.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/GenreCardGrid.kt
index 7ad6a5ec..94710301 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/GenreCardGrid.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/GenreCardGrid.kt
@@ -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) {
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedMovie.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedMovie.kt
index 8f643616..d9969914 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedMovie.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedMovie.kt
@@ -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,
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedTvShow.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedTvShow.kt
index 804349a6..96117e4d 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedTvShow.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/RecommendedTvShow.kt
@@ -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,
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/DetailUtils.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/DetailUtils.kt
index eef242b2..a5b1a58b 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/DetailUtils.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/DetailUtils.kt
@@ -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)
},
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/SeriesViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/SeriesViewModel.kt
index 848ea109..266322d3 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/SeriesViewModel.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/SeriesViewModel.kt
@@ -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) {
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt
index 86d6aa72..e962e165 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/HomeViewModel.kt
@@ -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,
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt
index 646b213a..27382274 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/main/SearchPage.kt
@@ -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)
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt
index 42f99791..4805868a 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt
@@ -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
}
}
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt
index b7e656b2..32db86d0 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserContent.kt
@@ -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,
)
}
diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserViewModel.kt
index 83244068..852e4add 100644
--- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserViewModel.kt
+++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchUserViewModel.kt
@@ -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)
+ }
}
diff --git a/app/src/main/res/values/fa_strings.xml b/app/src/main/res/values/fa_strings.xml
index 68a0990e..8d09fb92 100644
--- a/app/src/main/res/values/fa_strings.xml
+++ b/app/src/main/res/values/fa_strings.xml
@@ -34,4 +34,6 @@
+
+