mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Add option to send relevant media info to server for bug reports (#840)
## Description Adds a item in the More menu to send information about the media item to the server (and app logs). This includes the "media sources" which is info about the files and stream/tracks in the files. It also includes device info, the playback preferences, and the device's transcoding profile. All of this info is useful for debugging playback issues. ### Related issues N/A ### Testing Emulator testing ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
d5602aa88c
commit
72e5e6ae86
18 changed files with 147 additions and 7 deletions
|
|
@ -0,0 +1,80 @@
|
|||
package com.github.damontecres.wholphin.services
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.github.damontecres.wholphin.data.ServerRepository
|
||||
import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.showToast
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.extensions.clientLogApi
|
||||
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||
import org.jellyfin.sdk.model.ClientInfo
|
||||
import org.jellyfin.sdk.model.DeviceInfo
|
||||
import org.jellyfin.sdk.model.UUID
|
||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class MediaReportService
|
||||
@Inject
|
||||
constructor(
|
||||
@param:ApplicationContext private val context: Context,
|
||||
private val api: ApiClient,
|
||||
private val serverRepository: ServerRepository,
|
||||
private val userPreferencesService: UserPreferencesService,
|
||||
private val clientInfo: ClientInfo,
|
||||
private val deviceInfo: DeviceInfo,
|
||||
private val deviceProfileService: DeviceProfileService,
|
||||
@param:IoCoroutineScope private val ioScope: CoroutineScope,
|
||||
) {
|
||||
val json =
|
||||
Json {
|
||||
encodeDefaults = false
|
||||
}
|
||||
|
||||
fun sendReportFor(itemId: UUID) {
|
||||
ioScope.launchIO(ExceptionHandler(autoToast = true)) {
|
||||
val item = api.userLibraryApi.getItem(itemId = itemId).content
|
||||
sendReportFor(item)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendReportFor(item: BaseItemDto) {
|
||||
val sources =
|
||||
item.mediaSources ?: api.userLibraryApi
|
||||
.getItem(itemId = item.id)
|
||||
.content.mediaSources
|
||||
val sourcesJson = json.encodeToString(sources)
|
||||
val playbackPrefs = userPreferencesService.getCurrent().appPreferences.playbackPreferences
|
||||
val serverVersion = serverRepository.currentServer.value?.serverVersion
|
||||
val deviceProfile =
|
||||
deviceProfileService.getOrCreateDeviceProfile(playbackPrefs, serverVersion)
|
||||
val deviceProfileJson = json.encodeToString(deviceProfile)
|
||||
val body =
|
||||
"""
|
||||
Send media info
|
||||
serverVersion=$serverVersion
|
||||
clientInfo=$clientInfo
|
||||
deviceInfo=$deviceInfo
|
||||
manufacturer=${Build.MANUFACTURER}
|
||||
model=${Build.MODEL}
|
||||
apiLevel=${Build.VERSION.SDK_INT}
|
||||
|
||||
playbackPrefs=${playbackPrefs.toString().replace("\n", ", ").replace("\t", " ")}
|
||||
|
||||
deviceProfile=$deviceProfileJson
|
||||
|
||||
mediaSources=$sourcesJson
|
||||
""".trimIndent()
|
||||
Timber.w(body)
|
||||
val response by api.clientLogApi.logFile(body)
|
||||
showToast(context, "Sent! Filename=${response.fileName}")
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@ import com.github.damontecres.wholphin.data.model.LibraryDisplayInfo
|
|||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.ui.AspectRatios
|
||||
import com.github.damontecres.wholphin.ui.RequestOrRestoreFocus
|
||||
|
|
@ -120,6 +121,7 @@ class CollectionFolderViewModel
|
|||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val backdropService: BackdropService,
|
||||
val navigationManager: NavigationManager,
|
||||
val mediaReportService: MediaReportService,
|
||||
@Assisted itemId: String,
|
||||
@Assisted initialSortAndDirection: SortAndDirection?,
|
||||
@Assisted("recursive") private val recursive: Boolean,
|
||||
|
|
@ -664,6 +666,7 @@ fun CollectionFolderGrid(
|
|||
playlistViewModel.loadPlaylists(MediaType.VIDEO)
|
||||
showPlaylistDialog.makePresent(it)
|
||||
},
|
||||
onSendMediaInfo = viewModel.mediaReportService::sendReportFor,
|
||||
),
|
||||
),
|
||||
onDismissRequest = { moreDialog.makeAbsent() },
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.github.damontecres.wholphin.data.model.BaseItem
|
|||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.ui.OneTimeLaunchedEffect
|
||||
import com.github.damontecres.wholphin.ui.data.AddPlaylistViewModel
|
||||
|
|
@ -46,6 +47,7 @@ abstract class RecommendedViewModel(
|
|||
val context: Context,
|
||||
val navigationManager: NavigationManager,
|
||||
val favoriteWatchManager: FavoriteWatchManager,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val backdropService: BackdropService,
|
||||
) : ViewModel() {
|
||||
abstract fun init()
|
||||
|
|
@ -190,6 +192,7 @@ fun RecommendedContent(
|
|||
playlistViewModel.loadPlaylists(MediaType.VIDEO)
|
||||
showPlaylistDialog.makePresent(it)
|
||||
},
|
||||
onSendMediaInfo = viewModel.mediaReportService::sendReportFor,
|
||||
),
|
||||
),
|
||||
onDismissRequest = { moreDialog.makeAbsent() },
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.github.damontecres.wholphin.preferences.AppPreferences
|
|||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.SuggestionService
|
||||
import com.github.damontecres.wholphin.services.SuggestionsResource
|
||||
|
|
@ -58,8 +59,15 @@ class RecommendedMovieViewModel
|
|||
@Assisted val parentId: UUID,
|
||||
navigationManager: NavigationManager,
|
||||
favoriteWatchManager: FavoriteWatchManager,
|
||||
mediaReportService: MediaReportService,
|
||||
backdropService: BackdropService,
|
||||
) : RecommendedViewModel(context, navigationManager, favoriteWatchManager, backdropService) {
|
||||
) : RecommendedViewModel(
|
||||
context,
|
||||
navigationManager,
|
||||
favoriteWatchManager,
|
||||
mediaReportService,
|
||||
backdropService,
|
||||
) {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(parentId: UUID): RecommendedMovieViewModel
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.github.damontecres.wholphin.preferences.UserPreferences
|
|||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.LatestNextUpService
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.SuggestionService
|
||||
import com.github.damontecres.wholphin.services.SuggestionsResource
|
||||
|
|
@ -62,8 +63,15 @@ class RecommendedTvShowViewModel
|
|||
@Assisted val parentId: UUID,
|
||||
navigationManager: NavigationManager,
|
||||
favoriteWatchManager: FavoriteWatchManager,
|
||||
mediaReportService: MediaReportService,
|
||||
backdropService: BackdropService,
|
||||
) : RecommendedViewModel(context, navigationManager, favoriteWatchManager, backdropService) {
|
||||
) : RecommendedViewModel(
|
||||
context,
|
||||
navigationManager,
|
||||
favoriteWatchManager,
|
||||
mediaReportService,
|
||||
backdropService,
|
||||
) {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(parentId: UUID): RecommendedTvShowViewModel
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ import org.jellyfin.sdk.api.client.ApiClient
|
|||
import org.jellyfin.sdk.api.client.extensions.clientLogApi
|
||||
import org.jellyfin.sdk.model.ClientInfo
|
||||
import org.jellyfin.sdk.model.DeviceInfo
|
||||
import timber.log.Timber
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import javax.inject.Inject
|
||||
|
|
@ -137,9 +138,13 @@ class DebugViewModel
|
|||
Send App Logs
|
||||
clientInfo=$clientInfo
|
||||
deviceInfo=$deviceInfo
|
||||
manufacturer=${Build.MANUFACTURER}
|
||||
model=${Build.MODEL}
|
||||
apiLevel=${Build.VERSION.SDK_INT}
|
||||
|
||||
""".trimIndent() + logcat
|
||||
val response by api.clientLogApi.logFile(body)
|
||||
""".trimIndent()
|
||||
Timber.w(body)
|
||||
val response by api.clientLogApi.logFile(body + logcat)
|
||||
showToast(context, "Sent! Filename=${response.fileName}")
|
||||
}
|
||||
}
|
||||
|
|
@ -253,6 +258,7 @@ fun DebugPage(
|
|||
"DeviceInfo: ${viewModel.deviceInfo}",
|
||||
"Manufacturer: ${Build.MANUFACTURER}",
|
||||
"Model: ${Build.MODEL}",
|
||||
"API Level: ${Build.VERSION.SDK_INT}",
|
||||
"Display Modes:",
|
||||
*viewModel.refreshRateService.supportedDisplayModes,
|
||||
).forEach {
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ import kotlin.time.Duration.Companion.seconds
|
|||
|
||||
data class MoreDialogActions(
|
||||
val navigateTo: (Destination) -> Unit,
|
||||
var onClickWatch: (UUID, Boolean) -> Unit,
|
||||
var onClickFavorite: (UUID, Boolean) -> Unit,
|
||||
var onClickAddPlaylist: (UUID) -> Unit,
|
||||
val onClickWatch: (UUID, Boolean) -> Unit,
|
||||
val onClickFavorite: (UUID, Boolean) -> Unit,
|
||||
val onClickAddPlaylist: (UUID) -> Unit,
|
||||
val onSendMediaInfo: (UUID) -> Unit,
|
||||
)
|
||||
|
||||
enum class ClearChosenStreams {
|
||||
|
|
@ -205,6 +206,14 @@ fun buildMoreDialogItems(
|
|||
)
|
||||
},
|
||||
)
|
||||
add(
|
||||
DialogItem(
|
||||
text = R.string.send_media_info_log_to_server,
|
||||
iconStringRes = R.string.fa_file_video,
|
||||
) {
|
||||
actions.onSendMediaInfo.invoke(item.id)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun buildMoreDialogItemsForHome(
|
||||
|
|
@ -314,6 +323,14 @@ fun buildMoreDialogItemsForHome(
|
|||
},
|
||||
)
|
||||
}
|
||||
add(
|
||||
DialogItem(
|
||||
text = R.string.send_media_info_log_to_server,
|
||||
iconStringRes = R.string.fa_file_video,
|
||||
) {
|
||||
actions.onSendMediaInfo.invoke(itemId)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun buildMoreDialogItemsForPerson(
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ fun DiscoverMovieDetails(
|
|||
onClickWatch = { itemId, watched -> },
|
||||
onClickFavorite = { itemId, favorite -> },
|
||||
onClickAddPlaylist = { itemId -> },
|
||||
onSendMediaInfo = {},
|
||||
)
|
||||
|
||||
when (val state = loading) {
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ fun EpisodeDetails(
|
|||
playlistViewModel.loadPlaylists(MediaType.VIDEO)
|
||||
showPlaylistDialog.makePresent(itemId)
|
||||
},
|
||||
onSendMediaInfo = viewModel.mediaReportService::sendReportFor,
|
||||
)
|
||||
|
||||
when (val state = loading) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.github.damontecres.wholphin.data.model.ItemPlayback
|
|||
import com.github.damontecres.wholphin.preferences.ThemeSongVolume
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.StreamChoiceService
|
||||
import com.github.damontecres.wholphin.services.ThemeSongPlayer
|
||||
|
|
@ -48,6 +49,7 @@ class EpisodeViewModel
|
|||
val serverRepository: ServerRepository,
|
||||
val itemPlaybackRepository: ItemPlaybackRepository,
|
||||
val streamChoiceService: StreamChoiceService,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val themeSongPlayer: ThemeSongPlayer,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val userPreferencesService: UserPreferencesService,
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ fun MovieDetails(
|
|||
playlistViewModel.loadPlaylists(MediaType.VIDEO)
|
||||
showPlaylistDialog.makePresent(itemId)
|
||||
},
|
||||
onSendMediaInfo = viewModel.mediaReportService::sendReportFor,
|
||||
)
|
||||
|
||||
when (val state = loading) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.github.damontecres.wholphin.preferences.ThemeSongVolume
|
|||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.ExtrasService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.PeopleFavorites
|
||||
import com.github.damontecres.wholphin.services.SeerrService
|
||||
|
|
@ -64,6 +65,7 @@ class MovieViewModel
|
|||
val serverRepository: ServerRepository,
|
||||
val itemPlaybackRepository: ItemPlaybackRepository,
|
||||
val streamChoiceService: StreamChoiceService,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val themeSongPlayer: ThemeSongPlayer,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val peopleFavorites: PeopleFavorites,
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ fun SeriesDetails(
|
|||
playlistViewModel.loadPlaylists(MediaType.VIDEO)
|
||||
showPlaylistDialog.makePresent(itemId)
|
||||
},
|
||||
onSendMediaInfo = viewModel.mediaReportService::sendReportFor,
|
||||
),
|
||||
)
|
||||
if (showWatchConfirmation) {
|
||||
|
|
|
|||
|
|
@ -215,6 +215,7 @@ fun SeriesOverview(
|
|||
playlistViewModel.loadPlaylists(MediaType.VIDEO)
|
||||
showPlaylistDialog = it
|
||||
},
|
||||
onSendMediaInfo = viewModel.mediaReportService::sendReportFor,
|
||||
),
|
||||
onChooseVersion = {
|
||||
chooseVersion =
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.github.damontecres.wholphin.data.model.Trailer
|
|||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.ExtrasService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.PeopleFavorites
|
||||
import com.github.damontecres.wholphin.services.SeerrService
|
||||
|
|
@ -85,6 +86,7 @@ class SeriesViewModel
|
|||
private val trailerService: TrailerService,
|
||||
private val extrasService: ExtrasService,
|
||||
val streamChoiceService: StreamChoiceService,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val userPreferencesService: UserPreferencesService,
|
||||
private val backdropService: BackdropService,
|
||||
private val seerrService: SeerrService,
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ fun HomePage(
|
|||
playlistViewModel.loadPlaylists(MediaType.VIDEO)
|
||||
showPlaylistDialog = itemId
|
||||
},
|
||||
onSendMediaInfo = viewModel.mediaReportService::sendReportFor,
|
||||
),
|
||||
)
|
||||
dialog =
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.github.damontecres.wholphin.services.BackdropService
|
|||
import com.github.damontecres.wholphin.services.DatePlayedService
|
||||
import com.github.damontecres.wholphin.services.FavoriteWatchManager
|
||||
import com.github.damontecres.wholphin.services.LatestNextUpService
|
||||
import com.github.damontecres.wholphin.services.MediaReportService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.services.UserPreferencesService
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
|
|
@ -44,6 +45,7 @@ class HomeViewModel
|
|||
val navigationManager: NavigationManager,
|
||||
val serverRepository: ServerRepository,
|
||||
val navDrawerItemRepository: NavDrawerItemRepository,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val datePlayedService: DatePlayedService,
|
||||
private val latestNextUpService: LatestNextUpService,
|
||||
|
|
|
|||
|
|
@ -484,6 +484,7 @@
|
|||
<string name="zoom_out">Zoom out</string>
|
||||
<string name="slideshow_duration">Slideshow duration</string>
|
||||
<string name="play_videos_during_slideshow">Play videos during slideshow</string>
|
||||
<string name="send_media_info_log_to_server">Send media info log to server</string>
|
||||
|
||||
<string-array name="theme_song_volume">
|
||||
<item>Disabled</item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue