Update dependencies and improve server discovery
This commit is contained in:
parent
69503f504d
commit
e9e849d9e4
4 changed files with 85 additions and 31 deletions
|
@ -84,8 +84,8 @@ dependencies {
|
||||||
implementation("androidx.preference:preference-ktx:$preferenceVersion")
|
implementation("androidx.preference:preference-ktx:$preferenceVersion")
|
||||||
|
|
||||||
// Jellyfin
|
// Jellyfin
|
||||||
val jellyfinVersion = "1.0.3"
|
val jellyfinVersion = "1.1.0"
|
||||||
implementation("org.jellyfin.sdk:jellyfin-platform-android:$jellyfinVersion")
|
implementation("org.jellyfin.sdk:jellyfin-core:$jellyfinVersion")
|
||||||
|
|
||||||
// Glide
|
// Glide
|
||||||
val glideVersion = "4.12.0"
|
val glideVersion = "4.12.0"
|
||||||
|
@ -93,12 +93,12 @@ dependencies {
|
||||||
kapt("com.github.bumptech.glide:compiler:$glideVersion")
|
kapt("com.github.bumptech.glide:compiler:$glideVersion")
|
||||||
|
|
||||||
// Hilt
|
// Hilt
|
||||||
val hiltVersion = "2.38.1"
|
val hiltVersion = "2.39.1"
|
||||||
implementation("com.google.dagger:hilt-android:$hiltVersion")
|
implementation("com.google.dagger:hilt-android:$hiltVersion")
|
||||||
kapt("com.google.dagger:hilt-compiler:$hiltVersion")
|
kapt("com.google.dagger:hilt-compiler:$hiltVersion")
|
||||||
|
|
||||||
// ExoPlayer
|
// ExoPlayer
|
||||||
val exoplayerVersion = "2.15.0"
|
val exoplayerVersion = "2.15.1"
|
||||||
implementation("com.google.android.exoplayer:exoplayer-core:$exoplayerVersion")
|
implementation("com.google.android.exoplayer:exoplayer-core:$exoplayerVersion")
|
||||||
implementation("com.google.android.exoplayer:exoplayer-ui:$exoplayerVersion")
|
implementation("com.google.android.exoplayer:exoplayer-ui:$exoplayerVersion")
|
||||||
implementation(files("libs/extension-ffmpeg-release.aar"))
|
implementation(files("libs/extension-ffmpeg-release.aar"))
|
||||||
|
|
|
@ -2,9 +2,8 @@ package dev.jdtech.jellyfin.api
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import dev.jdtech.jellyfin.BuildConfig
|
import dev.jdtech.jellyfin.BuildConfig
|
||||||
import org.jellyfin.sdk.Jellyfin
|
import org.jellyfin.sdk.api.client.extensions.*
|
||||||
import org.jellyfin.sdk.android
|
import org.jellyfin.sdk.createJellyfin
|
||||||
import org.jellyfin.sdk.api.operations.*
|
|
||||||
import org.jellyfin.sdk.model.ClientInfo
|
import org.jellyfin.sdk.model.ClientInfo
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@ -12,29 +11,29 @@ import java.util.*
|
||||||
/**
|
/**
|
||||||
* Jellyfin API class using org.jellyfin.sdk:jellyfin-platform-android
|
* Jellyfin API class using org.jellyfin.sdk:jellyfin-platform-android
|
||||||
*
|
*
|
||||||
* @param context The context
|
* @param androidContext The context
|
||||||
* @param baseUrl The url of the server
|
* @param baseUrl The url of the server
|
||||||
* @constructor Creates a new [JellyfinApi] instance
|
* @constructor Creates a new [JellyfinApi] instance
|
||||||
*/
|
*/
|
||||||
class JellyfinApi(context: Context, baseUrl: String) {
|
class JellyfinApi(androidContext: Context, baseUrl: String) {
|
||||||
val jellyfin = Jellyfin {
|
val jellyfin = createJellyfin {
|
||||||
clientInfo =
|
clientInfo =
|
||||||
ClientInfo(name = context.applicationInfo.loadLabel(context.packageManager).toString(), version = BuildConfig.VERSION_NAME)
|
ClientInfo(name = androidContext.applicationInfo.loadLabel(androidContext.packageManager).toString(), version = BuildConfig.VERSION_NAME)
|
||||||
android(context)
|
context = androidContext
|
||||||
}
|
}
|
||||||
val api = jellyfin.createApi(baseUrl = baseUrl)
|
val api = jellyfin.createApi(baseUrl = baseUrl)
|
||||||
var userId: UUID? = null
|
var userId: UUID? = null
|
||||||
|
|
||||||
val systemApi = SystemApi(api)
|
val systemApi = api.systemApi
|
||||||
val userApi = UserApi(api)
|
val userApi = api.userApi
|
||||||
val viewsApi = UserViewsApi(api)
|
val viewsApi = api.userViewsApi
|
||||||
val itemsApi = ItemsApi(api)
|
val itemsApi = api.itemsApi
|
||||||
val userLibraryApi = UserLibraryApi(api)
|
val userLibraryApi = api.userLibraryApi
|
||||||
val showsApi = TvShowsApi(api)
|
val showsApi = api.tvShowsApi
|
||||||
val sessionApi = SessionApi(api)
|
val sessionApi = api.sessionApi
|
||||||
val videosApi = VideosApi(api)
|
val videosApi = api.videosApi
|
||||||
val mediaInfoApi = MediaInfoApi(api)
|
val mediaInfoApi = api.mediaInfoApi
|
||||||
val playStateApi = PlayStateApi(api)
|
val playStateApi = api.playStateApi
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Volatile
|
@Volatile
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
package dev.jdtech.jellyfin.viewmodels
|
package dev.jdtech.jellyfin.viewmodels
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import dev.jdtech.jellyfin.BaseApplication
|
||||||
import dev.jdtech.jellyfin.api.JellyfinApi
|
import dev.jdtech.jellyfin.api.JellyfinApi
|
||||||
import dev.jdtech.jellyfin.database.Server
|
import dev.jdtech.jellyfin.database.Server
|
||||||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jellyfin.sdk.discovery.RecommendedServerInfo
|
import org.jellyfin.sdk.discovery.RecommendedServerInfo
|
||||||
import org.jellyfin.sdk.discovery.RecommendedServerInfoScore
|
import org.jellyfin.sdk.discovery.RecommendedServerInfoScore
|
||||||
|
import org.jellyfin.sdk.discovery.RecommendedServerIssue
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -21,6 +24,7 @@ import javax.inject.Inject
|
||||||
class AddServerViewModel
|
class AddServerViewModel
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
|
private val application: BaseApplication,
|
||||||
private val jellyfinApi: JellyfinApi,
|
private val jellyfinApi: JellyfinApi,
|
||||||
private val database: ServerDatabaseDao
|
private val database: ServerDatabaseDao
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
@ -45,24 +49,45 @@ constructor(
|
||||||
val candidates = jellyfinApi.jellyfin.discovery.getAddressCandidates(inputValue)
|
val candidates = jellyfinApi.jellyfin.discovery.getAddressCandidates(inputValue)
|
||||||
val recommended = jellyfinApi.jellyfin.discovery.getRecommendedServers(
|
val recommended = jellyfinApi.jellyfin.discovery.getRecommendedServers(
|
||||||
candidates,
|
candidates,
|
||||||
RecommendedServerInfoScore.GOOD
|
RecommendedServerInfoScore.OK
|
||||||
)
|
)
|
||||||
val recommendedServer: RecommendedServerInfo
|
|
||||||
|
|
||||||
try {
|
// Check if any servers have been found
|
||||||
recommendedServer = recommended.first()
|
if (recommended.toList().isNullOrEmpty()) {
|
||||||
} catch (e: NoSuchElementException) {
|
|
||||||
throw Exception("Server not found")
|
throw Exception("Server not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create separate flow of great, good and ok servers.
|
||||||
|
val greatServers =
|
||||||
|
recommended.filter { it.score == RecommendedServerInfoScore.GREAT }
|
||||||
|
val goodServers = recommended.filter { it.score == RecommendedServerInfoScore.GOOD }
|
||||||
|
val okServers = recommended.filter { it.score == RecommendedServerInfoScore.OK }
|
||||||
|
|
||||||
|
// Only allow connecting to great and good servers. Show toast of issues if good server
|
||||||
|
val recommendedServer = if (greatServers.toList().isNotEmpty()) {
|
||||||
|
greatServers.first()
|
||||||
|
} else if (goodServers.toList().isNotEmpty()) {
|
||||||
|
val issuesString = createIssuesString(goodServers.first())
|
||||||
|
Toast.makeText(
|
||||||
|
application,
|
||||||
|
issuesString,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
goodServers.first()
|
||||||
|
} else {
|
||||||
|
val okServer = okServers.first()
|
||||||
|
val issuesString = createIssuesString(okServer)
|
||||||
|
throw Exception(issuesString)
|
||||||
|
}
|
||||||
|
|
||||||
jellyfinApi.apply {
|
jellyfinApi.apply {
|
||||||
api.baseUrl = recommendedServer.address
|
api.baseUrl = recommendedServer.address
|
||||||
api.accessToken = null
|
api.accessToken = null
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.d("Remote server: ${recommendedServer.systemInfo?.id}")
|
Timber.d("Remote server: ${recommendedServer.systemInfo.getOrNull()?.id}")
|
||||||
|
|
||||||
if (serverAlreadyInDatabase(recommendedServer.systemInfo?.id)) {
|
if (serverAlreadyInDatabase(recommendedServer.systemInfo.getOrNull()?.id)) {
|
||||||
_error.value = "Server already added"
|
_error.value = "Server already added"
|
||||||
_navigateToLogin.value = false
|
_navigateToLogin.value = false
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,6 +102,36 @@ constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a presentable string of issues with a server
|
||||||
|
*
|
||||||
|
* @param server The server with issues
|
||||||
|
* @return A presentable string of issues separated with \n
|
||||||
|
*/
|
||||||
|
private fun createIssuesString(server: RecommendedServerInfo): String {
|
||||||
|
val issues = mutableListOf<String>()
|
||||||
|
server.issues.forEach {
|
||||||
|
when (it) {
|
||||||
|
is RecommendedServerIssue.OutdatedServerVersion -> {
|
||||||
|
issues.add("Server version outdated: ${it.version} \nPlease update your server")
|
||||||
|
}
|
||||||
|
is RecommendedServerIssue.InvalidProductName -> {
|
||||||
|
issues.add("Not a Jellyfin server: ${it.productName}")
|
||||||
|
}
|
||||||
|
is RecommendedServerIssue.UnsupportedServerVersion -> {
|
||||||
|
issues.add("Unsupported server version: ${it.version} \nPlease update your server")
|
||||||
|
}
|
||||||
|
is RecommendedServerIssue.SlowResponse -> {
|
||||||
|
issues.add("Server is too slow to respond: ${it.responseTime}")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
issues.add("Unknown error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return issues.joinToString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if server is already in database using server ID
|
* Check if server is already in database using server ID
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,7 +9,7 @@ buildscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("com.android.tools.build:gradle:7.0.2")
|
classpath("com.android.tools.build:gradle:7.0.3")
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|
Loading…
Reference in a new issue