mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Option to load from server plugin
This commit is contained in:
parent
f02f66c506
commit
a27bb2a962
8 changed files with 104 additions and 5 deletions
|
|
@ -16,6 +16,7 @@ import com.github.damontecres.wholphin.util.EqualityMutableLiveData
|
|||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jellyfin.sdk.Jellyfin
|
||||
|
|
@ -54,6 +55,8 @@ class ServerRepository
|
|||
val currentServer: LiveData<JellyfinServer?> get() = _current.map { it?.server }
|
||||
val currentUser: LiveData<JellyfinUser?> get() = _current.map { it?.user }
|
||||
|
||||
val serverPluginInstalled = MutableStateFlow<Boolean>(false)
|
||||
|
||||
/**
|
||||
* Adds a server to the app database and updated the [ApiClient] to the server's URL
|
||||
*
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ class HomeSettingsService
|
|||
try {
|
||||
block.invoke()
|
||||
} catch (ex: Exception) {
|
||||
Timber.w(ex, "Error loading local settings")
|
||||
Timber.w(ex, "Error loading settings")
|
||||
null
|
||||
}
|
||||
|
||||
|
|
@ -213,6 +213,7 @@ class HomeSettingsService
|
|||
suspend fun loadCurrentSettings(userId: UUID) {
|
||||
Timber.v("Getting setting for %s", userId)
|
||||
// User local then server/remote otherwise create a default
|
||||
// TODO figure out priority order
|
||||
val settings =
|
||||
tryLoad {
|
||||
serverPluginApi.fetchHomePageSettings()
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ class UserSwitchListener
|
|||
private val seerrServerDao: SeerrServerDao,
|
||||
private val seerrApi: SeerrApi,
|
||||
private val homeSettingsService: HomeSettingsService,
|
||||
private val serverPluginApi: ServerPluginApi,
|
||||
) {
|
||||
init {
|
||||
context as AppCompatActivity
|
||||
|
|
@ -289,8 +290,19 @@ class UserSwitchListener
|
|||
|
||||
private suspend fun switchUser(user: JellyfinUser) =
|
||||
supervisorScope {
|
||||
// Check for home settings
|
||||
// Check if plugin is installed, then for home settings
|
||||
launchIO {
|
||||
val serverPluginInstalled =
|
||||
try {
|
||||
serverPluginApi.public()
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex, "Error checking for server plugin")
|
||||
false
|
||||
}
|
||||
Timber.i("Server plugin installed: %s", serverPluginInstalled)
|
||||
serverRepository.serverPluginInstalled.value = serverPluginInstalled
|
||||
|
||||
// Check for home settings
|
||||
homeSettingsService.loadCurrentSettings(user.id)
|
||||
}
|
||||
if (BuildConfig.DISCOVER_ENABLED) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import okhttp3.OkHttpClient
|
|||
import okhttp3.Request
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.exception.ApiClientException
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
|
|
@ -22,8 +23,24 @@ class ServerPluginApi
|
|||
private fun createUrl(path: String): String? =
|
||||
api.baseUrl?.let { if (it.endsWith("/")) "${it}wholphin/$path" else "$it/wholphin/$path" }
|
||||
|
||||
private val json =
|
||||
Json {
|
||||
ignoreUnknownKeys = false
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val HOME_CONFIG_PATH = "home"
|
||||
private const val HOME_CONFIG_PATH = "homesettings"
|
||||
}
|
||||
|
||||
suspend fun public(): Boolean {
|
||||
val url = createUrl("public") ?: return false
|
||||
val request =
|
||||
Request
|
||||
.Builder()
|
||||
.url(url)
|
||||
.get()
|
||||
.build()
|
||||
return okHttpClient.newCall(request).execute().isSuccessful
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
|
|
@ -37,11 +54,12 @@ class ServerPluginApi
|
|||
.build()
|
||||
return okHttpClient.newCall(request).execute().use { res ->
|
||||
if (res.isSuccessful) {
|
||||
Json.decodeFromStream<HomePageSettings>(res.body.byteStream())
|
||||
json.decodeFromStream<HomePageSettings>(res.body.byteStream())
|
||||
} else if (res.code == 404) {
|
||||
Timber.w("fetchHomePageSettings returned 404")
|
||||
null
|
||||
} else {
|
||||
throw ApiClientException(res.body.string())
|
||||
throw ApiClientException(res.code.toString() + " " + res.body.string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ fun HomeSettingsGlobal(
|
|||
onClickSave: () -> Unit,
|
||||
onClickLoad: () -> Unit,
|
||||
onClickLoadWeb: () -> Unit,
|
||||
serverPluginActive: Boolean,
|
||||
onClickLoadPlugin: () -> Unit,
|
||||
onClickReset: () -> Unit,
|
||||
onClickViewNextUp: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -166,6 +168,22 @@ fun HomeSettingsGlobal(
|
|||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
if (serverPluginActive) {
|
||||
item {
|
||||
HomeSettingsListItem(
|
||||
selected = false,
|
||||
headlineText = stringResource(R.string.load_from_server_plugin),
|
||||
leadingContent = {
|
||||
Text(
|
||||
text = stringResource(R.string.fa_download),
|
||||
fontFamily = FontAwesome,
|
||||
)
|
||||
},
|
||||
onClick = onClickLoadPlugin,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
HomeSettingsListItem(
|
||||
selected = false,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ fun HomeSettingsPage(
|
|||
var showRemovedNextUpDialog by remember { mutableStateOf(false) }
|
||||
|
||||
val state by viewModel.state.collectAsState()
|
||||
val serverPluginActive by viewModel.serverPluginActive.collectAsState()
|
||||
var position by rememberPosition(0, 0)
|
||||
// TODO discover rows
|
||||
val discoverEnabled = false // by viewModel.discoverEnabled.collectAsState(false)
|
||||
|
|
@ -274,6 +275,13 @@ fun HomeSettingsPage(
|
|||
viewModel.loadFromRemote()
|
||||
}
|
||||
},
|
||||
serverPluginActive = serverPluginActive,
|
||||
onClickLoadPlugin = {
|
||||
showConfirmDialog =
|
||||
ShowConfirm(R.string.overwrite_local_settings) {
|
||||
viewModel.loadFromRemotePlugin()
|
||||
}
|
||||
},
|
||||
onClickLoadWeb = {
|
||||
showConfirmDialog =
|
||||
ShowConfirm(R.string.overwrite_local_settings) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.github.damontecres.wholphin.services.HomeRowConfigDisplay
|
|||
import com.github.damontecres.wholphin.services.HomeSettingsService
|
||||
import com.github.damontecres.wholphin.services.NavDrawerService
|
||||
import com.github.damontecres.wholphin.services.SeerrServerRepository
|
||||
import com.github.damontecres.wholphin.services.ServerPluginApi
|
||||
import com.github.damontecres.wholphin.services.UnsupportedHomeSettingsVersionException
|
||||
import com.github.damontecres.wholphin.services.UserPreferencesService
|
||||
import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
|
||||
|
|
@ -74,12 +75,15 @@ class HomeSettingsViewModel
|
|||
private val navDrawerService: NavDrawerService,
|
||||
private val backdropService: BackdropService,
|
||||
private val seerrServerRepository: SeerrServerRepository,
|
||||
private val serverPluginApi: ServerPluginApi,
|
||||
val preferencesDataStore: DataStore<AppPreferences>,
|
||||
@param:IoCoroutineScope private val ioScope: CoroutineScope,
|
||||
) : ViewModel() {
|
||||
private val _state = MutableStateFlow(HomePageSettingsState.EMPTY)
|
||||
val state: StateFlow<HomePageSettingsState> = _state
|
||||
|
||||
val serverPluginActive get() = serverRepository.serverPluginInstalled
|
||||
|
||||
private var idCounter by Delegates.notNull<Int>()
|
||||
|
||||
val discoverEnabled = seerrServerRepository.active
|
||||
|
|
@ -767,6 +771,40 @@ class HomeSettingsViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loadFromRemotePlugin() {
|
||||
viewModelScope.launchIO {
|
||||
Timber.d("Loading home settings from server plugin")
|
||||
try {
|
||||
// TODO should this remove local settings?
|
||||
// TODO how to set up priorities
|
||||
_state.update { it.copy(loading = LoadingState.Loading) }
|
||||
val result = serverPluginApi.fetchHomePageSettings()
|
||||
if (result != null) {
|
||||
Timber.v("Got remote settings")
|
||||
val newRows =
|
||||
result.rows.mapIndexed { index, config ->
|
||||
homeSettingsService.resolve(index, config)
|
||||
}
|
||||
idCounter = newRows.maxOfOrNull { it.id }?.plus(1) ?: 0
|
||||
_state.update {
|
||||
it.copy(rows = newRows)
|
||||
}
|
||||
} else {
|
||||
Timber.v("No server plugin settings")
|
||||
showToast(context, "No server plugin settings found")
|
||||
}
|
||||
fetchRowData()
|
||||
} catch (ex: UnsupportedHomeSettingsVersionException) {
|
||||
// TODO
|
||||
Timber.w(ex)
|
||||
showToast(context, "Error: ${ex.localizedMessage}")
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex)
|
||||
showToast(context, "Error: ${ex.localizedMessage}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class HomePageSettingsState(
|
||||
|
|
|
|||
|
|
@ -774,6 +774,7 @@
|
|||
<string name="skip_behavior_summary">For intros, credits, etc</string>
|
||||
<string name="play_with">Play with</string>
|
||||
<string name="transcoding">Transcoding</string>
|
||||
<string name="load_from_server_plugin">Load default from server</string>
|
||||
<array name="ass_subtitle_modes">
|
||||
<item>@string/ass_subtitle_mode_libass</item>
|
||||
<item>@string/ass_subtitle_mode_exoplayer</item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue