Add network settings (#192)

* Add new network settings with socket timeout option

* Add socketTimeout to AppPreferences

* Format with ktlint

* Add request timeout and connect timeout as options
This commit is contained in:
Jarne Demeulemeester 2022-11-05 23:59:44 +01:00 committed by GitHub
parent 2c4fb8d7fe
commit 5895b2c8d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 146 additions and 8 deletions

View file

@ -2,7 +2,9 @@ package dev.jdtech.jellyfin.api
import android.content.Context
import dev.jdtech.jellyfin.BuildConfig
import dev.jdtech.jellyfin.utils.Constants
import java.util.UUID
import org.jellyfin.sdk.api.client.HttpClientOptions
import org.jellyfin.sdk.api.client.extensions.devicesApi
import org.jellyfin.sdk.api.client.extensions.itemsApi
import org.jellyfin.sdk.api.client.extensions.mediaInfoApi
@ -21,15 +23,27 @@ import org.jellyfin.sdk.model.ClientInfo
* Jellyfin API class using org.jellyfin.sdk:jellyfin-platform-android
*
* @param androidContext The context
* @param socketTimeout The socket timeout
* @constructor Creates a new [JellyfinApi] instance
*/
class JellyfinApi(androidContext: Context) {
class JellyfinApi(
androidContext: Context,
requestTimeout: Long = Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT,
connectTimeout: Long = Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT,
socketTimeout: Long = Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT
) {
val jellyfin = createJellyfin {
clientInfo =
ClientInfo(name = androidContext.applicationInfo.loadLabel(androidContext.packageManager).toString(), version = BuildConfig.VERSION_NAME)
context = androidContext
}
val api = jellyfin.createApi()
val api = jellyfin.createApi(
httpClientOptions = HttpClientOptions(
requestTimeout = requestTimeout,
connectTimeout = connectTimeout,
socketTimeout = socketTimeout
)
)
var userId: UUID? = null
val devicesApi = api.devicesApi
@ -48,11 +62,21 @@ class JellyfinApi(androidContext: Context) {
@Volatile
private var INSTANCE: JellyfinApi? = null
fun getInstance(context: Context): JellyfinApi {
fun getInstance(
context: Context,
requestTimeout: Long = Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT,
connectTimeout: Long = Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT,
socketTimeout: Long = Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT
): JellyfinApi {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = JellyfinApi(context.applicationContext)
instance = JellyfinApi(
androidContext = context.applicationContext,
requestTimeout = requestTimeout,
connectTimeout = connectTimeout,
socketTimeout = socketTimeout
)
INSTANCE = instance
}
return instance

View file

@ -9,6 +9,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dev.jdtech.jellyfin.api.JellyfinApi
import dev.jdtech.jellyfin.database.ServerDatabaseDao
import dev.jdtech.jellyfin.utils.AppPreferences
import javax.inject.Singleton
@Module
@ -19,9 +20,15 @@ object ApiModule {
fun provideJellyfinApi(
@ApplicationContext application: Context,
sharedPreferences: SharedPreferences,
appPreferences: AppPreferences,
serverDatabase: ServerDatabaseDao
): JellyfinApi {
val jellyfinApi = JellyfinApi.getInstance(application)
val jellyfinApi = JellyfinApi.getInstance(
context = application,
requestTimeout = appPreferences.requestTimeout,
connectTimeout = appPreferences.connectTimeout,
socketTimeout = appPreferences.socketTimeout
)
val serverId = sharedPreferences.getString("selectedServer", null)
if (serverId != null) {

View file

@ -10,7 +10,7 @@ import dev.jdtech.jellyfin.utils.serializable
import java.io.Serializable
import java.lang.IllegalStateException
class ErrorDialogFragment: DialogFragment() {
class ErrorDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val error = requireArguments().serializable<Exception>("error")!!
return activity?.let {

View file

@ -0,0 +1,19 @@
package dev.jdtech.jellyfin.fragments
import android.os.Bundle
import android.text.InputType
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceFragmentCompat
import dev.jdtech.jellyfin.R
import dev.jdtech.jellyfin.utils.Constants
@Suppress("unused")
class SettingsNetworkFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.fragment_settings_network, rootKey)
findPreference<EditTextPreference>(Constants.PREF_NETWORK_SOCKET_TIMEOUT)?.setOnBindEditTextListener { editText ->
editText.inputType = InputType.TYPE_CLASS_NUMBER
}
}
}

View file

@ -43,4 +43,20 @@ constructor(
DEFAULT_SEEK_FORWARD_INCREMENT_MS.toString()
)!!.toLongOrNull() ?: DEFAULT_SEEK_FORWARD_INCREMENT_MS
val mpvDisableHwDec = sharedPreferences.getBoolean("mpv_disable_hwdec", false)
// Network
val requestTimeout = sharedPreferences.getString(
Constants.PREF_NETWORK_REQUEST_TIMEOUT,
Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT.toString()
)!!.toLongOrNull() ?: Constants.NETWORK_DEFAULT_REQUEST_TIMEOUT
val connectTimeout = sharedPreferences.getString(
Constants.PREF_NETWORK_CONNECT_TIMEOUT,
Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT.toString()
)!!.toLongOrNull() ?: Constants.NETWORK_DEFAULT_CONNECT_TIMEOUT
val socketTimeout = sharedPreferences.getString(
Constants.PREF_NETWORK_SOCKET_TIMEOUT,
Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT.toString()
)!!.toLongOrNull() ?: Constants.NETWORK_DEFAULT_SOCKET_TIMEOUT
}

View file

@ -19,6 +19,9 @@ object Constants {
const val PREF_IMAGE_CACHE_SIZE = "pref_image_cache_size"
const val PREF_THEME = "theme"
const val PREF_DYNAMIC_COLORS = "dynamic_colors"
const val PREF_NETWORK_REQUEST_TIMEOUT = "pref_network_request_timeout"
const val PREF_NETWORK_CONNECT_TIMEOUT = "pref_network_connect_timeout"
const val PREF_NETWORK_SOCKET_TIMEOUT = "pref_network_socket_timeout"
// caching
const val DEFAULT_CACHE_SIZE = 20
@ -27,4 +30,9 @@ object Constants {
const val FAVORITE_TYPE_MOVIES = 0
const val FAVORITE_TYPE_SHOWS = 1
const val FAVORITE_TYPE_EPISODES = 2
// network
const val NETWORK_DEFAULT_REQUEST_TIMEOUT = 30_000L
const val NETWORK_DEFAULT_CONNECT_TIMEOUT = 6_000L
const val NETWORK_DEFAULT_SOCKET_TIMEOUT = 10_000L
}

View file

@ -12,9 +12,9 @@ import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import dev.jdtech.jellyfin.AppNavigationDirections
import dev.jdtech.jellyfin.models.View
import java.io.Serializable
import org.jellyfin.sdk.model.api.BaseItemDto
import timber.log.Timber
import java.io.Serializable
fun BaseItemDto.toView(): View {
return View(
@ -58,4 +58,4 @@ fun ImageButton.setTintColorAttribute(@AttrRes attributeId: Int, theme: Resource
inline fun <reified T : Serializable> Bundle.serializable(key: String): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializable(key, T::class.java)
else -> @Suppress("DEPRECATION") getSerializable(key) as? T
}
}

View file

@ -0,0 +1,37 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:pathData="M9,2h6v6h-6z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="@android:color/white"
android:strokeLineCap="round"/>
<path
android:pathData="M16,16h6v6h-6z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="@android:color/white"
android:strokeLineCap="round"/>
<path
android:pathData="M2,16h6v6h-6z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="@android:color/white"
android:strokeLineCap="round"/>
<path
android:pathData="M5,16v-4h14v4"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="@android:color/white"
android:strokeLineCap="round"/>
<path
android:pathData="M12,12V8"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:strokeColor="@android:color/white"
android:strokeLineCap="round"/>
</vector>

View file

@ -138,4 +138,8 @@
<string name="theme_system">Follow system</string>
<string name="theme_light">Light</string>
<string name="theme_dark">Dark</string>
<string name="settings_category_network">Network</string>
<string name="settings_request_timeout">Request timeout (ms)</string>
<string name="settings_connect_timeout">Connect timeout (ms)</string>
<string name="settings_socket_timeout">Socket timeout (ms)</string>
</resources>

View file

@ -31,6 +31,11 @@
app:title="@string/settings_category_device"
app:icon="@drawable/ic_smartphone" />
<Preference
app:fragment="dev.jdtech.jellyfin.fragments.SettingsNetworkFragment"
app:title="@string/settings_category_network"
app:icon="@drawable/ic_network"/>
<Preference
app:fragment="dev.jdtech.jellyfin.fragments.SettingsCacheFragment"
app:title="@string/settings_category_cache" />

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<EditTextPreference
app:defaultValue="30000"
app:key="pref_network_request_timeout"
app:title="@string/settings_request_timeout"
app:useSimpleSummaryProvider="true" />
<EditTextPreference
app:defaultValue="6000"
app:key="pref_network_connect_timeout"
app:title="@string/settings_connect_timeout"
app:useSimpleSummaryProvider="true" />
<EditTextPreference
app:defaultValue="10000"
app:key="pref_network_socket_timeout"
app:title="@string/settings_socket_timeout"
app:useSimpleSummaryProvider="true" />
</PreferenceScreen>