Feature/graphql server settings (#629)

* Add "uiName" to WebUI enum

* Add "Custom" WebUI to enum

* Rename "WebUI" enum to "WebUIFlavor"

* Add "WebUIInterface" enum

* Add query for server settings

* Add mutation for server settings

* Add mutation to reset the server settings

* Only update the config in case the value changed

In case the value of the config is already the same as the new value of the state flow, it is not necessary to update the config file
This commit is contained in:
schroda
2023-08-12 18:03:25 +02:00
committed by GitHub
parent 321fbe22dd
commit a31446557d
8 changed files with 371 additions and 31 deletions

View File

@@ -111,6 +111,16 @@ open class ConfigManager {
} }
} }
fun resetUserConfig(): ConfigDocument {
val serverConfigFileContent = this::class.java.getResource("/server-reference.conf")?.readText()
val serverConfigDoc = ConfigDocumentFactory.parseString(serverConfigFileContent)
userConfigFile.writeText(serverConfigDoc.render())
getUserConfig().entrySet().forEach { internalConfig = internalConfig.withValue(it.key, it.value) }
return serverConfigDoc
}
/** /**
* Makes sure the "UserConfig" is up-to-date. * Makes sure the "UserConfig" is up-to-date.
* *
@@ -118,7 +128,6 @@ open class ConfigManager {
* - removes outdated settings * - removes outdated settings
*/ */
fun updateUserConfig() { fun updateUserConfig() {
val serverConfigFileContent = this::class.java.getResource("/server-reference.conf")?.readText()
val serverConfig = ConfigFactory.parseResources("server-reference.conf") val serverConfig = ConfigFactory.parseResources("server-reference.conf")
val userConfig = getUserConfig() val userConfig = getUserConfig()
@@ -131,10 +140,7 @@ open class ConfigManager {
logger.debug { "user config is out of date, updating... (missingSettings= $hasMissingSettings, outdatedSettings= $hasOutdatedSettings" } logger.debug { "user config is out of date, updating... (missingSettings= $hasMissingSettings, outdatedSettings= $hasOutdatedSettings" }
val serverConfigDoc = ConfigDocumentFactory.parseString(serverConfigFileContent) var newUserConfigDoc: ConfigDocument = resetUserConfig()
userConfigFile.writeText(serverConfigDoc.render())
var newUserConfigDoc: ConfigDocument = serverConfigDoc
userConfig.entrySet().filter { serverConfig.hasPath(it.key) }.forEach { newUserConfigDoc = newUserConfigDoc.withValue(it.key, it.value) } userConfig.entrySet().filter { serverConfig.hasPath(it.key) }.forEach { newUserConfigDoc = newUserConfigDoc.withValue(it.key, it.value) }
userConfigFile.writeText(newUserConfigDoc.render()) userConfigFile.writeText(newUserConfigDoc.render())

View File

@@ -0,0 +1,89 @@
package suwayomi.tachidesk.graphql.mutations
import suwayomi.tachidesk.graphql.types.PartialSettingsType
import suwayomi.tachidesk.graphql.types.Settings
import suwayomi.tachidesk.graphql.types.SettingsType
import suwayomi.tachidesk.server.SERVER_CONFIG_MODULE_NAME
import suwayomi.tachidesk.server.ServerConfig
import suwayomi.tachidesk.server.serverConfig
import xyz.nulldev.ts.config.GlobalConfigManager
class SettingsMutation {
data class SetSettingsInput(
val clientMutationId: String? = null,
val settings: PartialSettingsType
)
data class SetSettingsPayload(
val clientMutationId: String?,
val settings: SettingsType
)
private fun updateSettings(settings: Settings) {
if (settings.ip != null) serverConfig.ip.value = settings.ip!!
if (settings.port != null) serverConfig.port.value = settings.port!!
if (settings.socksProxyEnabled != null) serverConfig.socksProxyEnabled.value = settings.socksProxyEnabled!!
if (settings.socksProxyHost != null) serverConfig.socksProxyHost.value = settings.socksProxyHost!!
if (settings.socksProxyPort != null) serverConfig.socksProxyPort.value = settings.socksProxyPort!!
if (settings.webUIFlavor != null) serverConfig.webUIFlavor.value = settings.webUIFlavor!!.uiName
if (settings.initialOpenInBrowserEnabled != null) serverConfig.initialOpenInBrowserEnabled.value = settings.initialOpenInBrowserEnabled!!
if (settings.webUIInterface != null) serverConfig.webUIInterface.value = settings.webUIInterface!!.name.lowercase()
if (settings.electronPath != null) serverConfig.electronPath.value = settings.electronPath!!
if (settings.webUIChannel != null) serverConfig.webUIChannel.value = settings.webUIChannel!!.name.lowercase()
if (settings.webUIUpdateCheckInterval != null) serverConfig.webUIUpdateCheckInterval.value = settings.webUIUpdateCheckInterval!!
if (settings.downloadAsCbz != null) serverConfig.downloadAsCbz.value = settings.downloadAsCbz!!
if (settings.downloadsPath != null) serverConfig.downloadsPath.value = settings.downloadsPath!!
if (settings.autoDownloadNewChapters != null) serverConfig.autoDownloadNewChapters.value = settings.autoDownloadNewChapters!!
if (settings.maxSourcesInParallel != null) serverConfig.maxSourcesInParallel.value = settings.maxSourcesInParallel!!
if (settings.excludeUnreadChapters != null) serverConfig.excludeUnreadChapters.value = settings.excludeUnreadChapters!!
if (settings.excludeNotStarted != null) serverConfig.excludeNotStarted.value = settings.excludeNotStarted!!
if (settings.excludeCompleted != null) serverConfig.excludeCompleted.value = settings.excludeCompleted!!
if (settings.globalUpdateInterval != null) serverConfig.globalUpdateInterval.value = settings.globalUpdateInterval!!
if (settings.basicAuthEnabled != null) serverConfig.basicAuthEnabled.value = settings.basicAuthEnabled!!
if (settings.basicAuthUsername != null) serverConfig.basicAuthUsername.value = settings.basicAuthUsername!!
if (settings.basicAuthPassword != null) serverConfig.basicAuthPassword.value = settings.basicAuthPassword!!
if (settings.debugLogsEnabled != null) serverConfig.debugLogsEnabled.value = settings.debugLogsEnabled!!
if (settings.systemTrayEnabled != null) serverConfig.systemTrayEnabled.value = settings.systemTrayEnabled!!
if (settings.backupPath != null) serverConfig.backupPath.value = settings.backupPath!!
if (settings.backupTime != null) serverConfig.backupTime.value = settings.backupTime!!
if (settings.backupInterval != null) serverConfig.backupInterval.value = settings.backupInterval!!
if (settings.backupTTL != null) serverConfig.backupTTL.value = settings.backupTTL!!
if (settings.localSourcePath != null) serverConfig.localSourcePath.value = settings.localSourcePath!!
}
fun setSettings(input: SetSettingsInput): SetSettingsPayload {
val (clientMutationId, settings) = input
updateSettings(settings)
return SetSettingsPayload(clientMutationId, SettingsType())
}
data class ResetSettingsInput(val clientMutationId: String? = null)
data class ResetSettingsPayload(
val clientMutationId: String?,
val settings: SettingsType
)
fun resetSettings(input: ResetSettingsInput): ResetSettingsPayload {
val (clientMutationId) = input
GlobalConfigManager.resetUserConfig()
val defaultServerConfig = ServerConfig({ GlobalConfigManager.config.getConfig(SERVER_CONFIG_MODULE_NAME) })
val settings = SettingsType(defaultServerConfig)
updateSettings(settings)
return ResetSettingsPayload(clientMutationId, settings)
}
}

View File

@@ -0,0 +1,9 @@
package suwayomi.tachidesk.graphql.queries
import suwayomi.tachidesk.graphql.types.SettingsType
class SettingsQuery {
fun settings(): SettingsType {
return SettingsType()
}
}

View File

@@ -21,6 +21,7 @@ import suwayomi.tachidesk.graphql.mutations.ExtensionMutation
import suwayomi.tachidesk.graphql.mutations.InfoMutation import suwayomi.tachidesk.graphql.mutations.InfoMutation
import suwayomi.tachidesk.graphql.mutations.MangaMutation import suwayomi.tachidesk.graphql.mutations.MangaMutation
import suwayomi.tachidesk.graphql.mutations.MetaMutation import suwayomi.tachidesk.graphql.mutations.MetaMutation
import suwayomi.tachidesk.graphql.mutations.SettingsMutation
import suwayomi.tachidesk.graphql.mutations.SourceMutation import suwayomi.tachidesk.graphql.mutations.SourceMutation
import suwayomi.tachidesk.graphql.mutations.UpdateMutation import suwayomi.tachidesk.graphql.mutations.UpdateMutation
import suwayomi.tachidesk.graphql.queries.BackupQuery import suwayomi.tachidesk.graphql.queries.BackupQuery
@@ -31,6 +32,7 @@ import suwayomi.tachidesk.graphql.queries.ExtensionQuery
import suwayomi.tachidesk.graphql.queries.InfoQuery import suwayomi.tachidesk.graphql.queries.InfoQuery
import suwayomi.tachidesk.graphql.queries.MangaQuery import suwayomi.tachidesk.graphql.queries.MangaQuery
import suwayomi.tachidesk.graphql.queries.MetaQuery import suwayomi.tachidesk.graphql.queries.MetaQuery
import suwayomi.tachidesk.graphql.queries.SettingsQuery
import suwayomi.tachidesk.graphql.queries.SourceQuery import suwayomi.tachidesk.graphql.queries.SourceQuery
import suwayomi.tachidesk.graphql.queries.UpdateQuery import suwayomi.tachidesk.graphql.queries.UpdateQuery
import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.Cursor
@@ -67,6 +69,7 @@ val schema = toSchema(
TopLevelObject(InfoQuery()), TopLevelObject(InfoQuery()),
TopLevelObject(MangaQuery()), TopLevelObject(MangaQuery()),
TopLevelObject(MetaQuery()), TopLevelObject(MetaQuery()),
TopLevelObject(SettingsQuery()),
TopLevelObject(SourceQuery()), TopLevelObject(SourceQuery()),
TopLevelObject(UpdateQuery()) TopLevelObject(UpdateQuery())
), ),
@@ -79,6 +82,7 @@ val schema = toSchema(
TopLevelObject(InfoMutation()), TopLevelObject(InfoMutation()),
TopLevelObject(MangaMutation()), TopLevelObject(MangaMutation()),
TopLevelObject(MetaMutation()), TopLevelObject(MetaMutation()),
TopLevelObject(SettingsMutation()),
TopLevelObject(SourceMutation()), TopLevelObject(SourceMutation()),
TopLevelObject(UpdateMutation()) TopLevelObject(UpdateMutation())
), ),

View File

@@ -0,0 +1,208 @@
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
package suwayomi.tachidesk.graphql.types
import suwayomi.tachidesk.graphql.server.primitives.Node
import suwayomi.tachidesk.server.ServerConfig
import suwayomi.tachidesk.server.serverConfig
import suwayomi.tachidesk.server.util.WebUIChannel
import suwayomi.tachidesk.server.util.WebUIFlavor
import suwayomi.tachidesk.server.util.WebUIInterface
interface Settings : Node {
val ip: String?
val port: Int?
// proxy
val socksProxyEnabled: Boolean?
val socksProxyHost: String?
val socksProxyPort: String?
// webUI
// requires restart (found no way to mutate (serve + "unserve") served files during runtime), exclude for now
// val webUIEnabled: Boolean,
val webUIFlavor: WebUIFlavor?
val initialOpenInBrowserEnabled: Boolean?
val webUIInterface: WebUIInterface?
val electronPath: String?
val webUIChannel: WebUIChannel?
val webUIUpdateCheckInterval: Double?
// downloader
val downloadAsCbz: Boolean?
val downloadsPath: String?
val autoDownloadNewChapters: Boolean?
// requests
val maxSourcesInParallel: Int?
// updater
val excludeUnreadChapters: Boolean?
val excludeNotStarted: Boolean?
val excludeCompleted: Boolean?
val globalUpdateInterval: Double?
// Authentication
val basicAuthEnabled: Boolean?
val basicAuthUsername: String?
val basicAuthPassword: String?
// misc
val debugLogsEnabled: Boolean?
val systemTrayEnabled: Boolean?
// backup
val backupPath: String?
val backupTime: String?
val backupInterval: Int?
val backupTTL: Int?
// local source
val localSourcePath: String?
}
data class PartialSettingsType(
override val ip: String?,
override val port: Int?,
// proxy
override val socksProxyEnabled: Boolean?,
override val socksProxyHost: String?,
override val socksProxyPort: String?,
// webUI
override val webUIFlavor: WebUIFlavor?,
override val initialOpenInBrowserEnabled: Boolean?,
override val webUIInterface: WebUIInterface?,
override val electronPath: String?,
override val webUIChannel: WebUIChannel?,
override val webUIUpdateCheckInterval: Double?,
// downloader
override val downloadAsCbz: Boolean?,
override val downloadsPath: String?,
override val autoDownloadNewChapters: Boolean?,
// requests
override val maxSourcesInParallel: Int?,
// updater
override val excludeUnreadChapters: Boolean?,
override val excludeNotStarted: Boolean?,
override val excludeCompleted: Boolean?,
override val globalUpdateInterval: Double?,
// Authentication
override val basicAuthEnabled: Boolean?,
override val basicAuthUsername: String?,
override val basicAuthPassword: String?,
// misc
override val debugLogsEnabled: Boolean?,
override val systemTrayEnabled: Boolean?,
// backup
override val backupPath: String?,
override val backupTime: String?,
override val backupInterval: Int?,
override val backupTTL: Int?,
// local source
override val localSourcePath: String?
) : Settings
class SettingsType(
override val ip: String,
override val port: Int,
// proxy
override val socksProxyEnabled: Boolean,
override val socksProxyHost: String,
override val socksProxyPort: String,
// webUI
override val webUIFlavor: WebUIFlavor,
override val initialOpenInBrowserEnabled: Boolean,
override val webUIInterface: WebUIInterface,
override val electronPath: String,
override val webUIChannel: WebUIChannel,
override val webUIUpdateCheckInterval: Double,
// downloader
override val downloadAsCbz: Boolean,
override val downloadsPath: String,
override val autoDownloadNewChapters: Boolean,
// requests
override val maxSourcesInParallel: Int,
// updater
override val excludeUnreadChapters: Boolean,
override val excludeNotStarted: Boolean,
override val excludeCompleted: Boolean,
override val globalUpdateInterval: Double,
// Authentication
override val basicAuthEnabled: Boolean,
override val basicAuthUsername: String,
override val basicAuthPassword: String,
// misc
override val debugLogsEnabled: Boolean,
override val systemTrayEnabled: Boolean,
// backup
override val backupPath: String,
override val backupTime: String,
override val backupInterval: Int,
override val backupTTL: Int,
// local source
override val localSourcePath: String
) : Settings {
constructor(config: ServerConfig = serverConfig) : this(
config.ip.value,
config.port.value,
config.socksProxyEnabled.value,
config.socksProxyHost.value,
config.socksProxyPort.value,
WebUIFlavor.from(config.webUIFlavor.value),
config.initialOpenInBrowserEnabled.value,
WebUIInterface.from(config.webUIInterface.value),
config.electronPath.value,
WebUIChannel.from(config.webUIChannel.value),
config.webUIUpdateCheckInterval.value,
config.downloadAsCbz.value,
config.downloadsPath.value,
config.autoDownloadNewChapters.value,
config.maxSourcesInParallel.value,
config.excludeUnreadChapters.value,
config.excludeNotStarted.value,
config.excludeCompleted.value,
config.globalUpdateInterval.value,
config.basicAuthEnabled.value,
config.basicAuthUsername.value,
config.basicAuthPassword.value,
config.debugLogsEnabled.value,
config.systemTrayEnabled.value,
config.backupPath.value,
config.backupTime.value,
config.backupInterval.value,
config.backupTTL.value,
config.localSourcePath.value
)
}

View File

@@ -18,6 +18,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import xyz.nulldev.ts.config.GlobalConfigManager import xyz.nulldev.ts.config.GlobalConfigManager
@@ -26,8 +27,8 @@ import kotlin.reflect.KProperty
val mutableConfigValueScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) val mutableConfigValueScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
private const val MODULE_NAME = "server" const val SERVER_CONFIG_MODULE_NAME = "server"
class ServerConfig(getConfig: () -> Config, val moduleName: String = MODULE_NAME) : SystemPropertyOverridableConfigModule(getConfig, moduleName) { class ServerConfig(getConfig: () -> Config, val moduleName: String = SERVER_CONFIG_MODULE_NAME) : SystemPropertyOverridableConfigModule(getConfig, moduleName) {
inner class OverrideConfigValue<T>(private val configAdapter: ConfigAdapter<T>) { inner class OverrideConfigValue<T>(private val configAdapter: ConfigAdapter<T>) {
private var flow: MutableStateFlow<T>? = null private var flow: MutableStateFlow<T>? = null
@@ -36,14 +37,15 @@ class ServerConfig(getConfig: () -> Config, val moduleName: String = MODULE_NAME
return flow!! return flow!!
} }
val value = configAdapter.toType(overridableConfig.getValue<ServerConfig, String>(thisRef, property)) val getValueFromConfig = { configAdapter.toType(overridableConfig.getValue<ServerConfig, String>(thisRef, property)) }
val value = getValueFromConfig()
val stateFlow = MutableStateFlow(value) val stateFlow = MutableStateFlow(value)
flow = stateFlow flow = stateFlow
stateFlow.drop(1).distinctUntilChanged().onEach { stateFlow.drop(1).distinctUntilChanged().filter { it != getValueFromConfig() }
GlobalConfigManager.updateValue("$moduleName.${property.name}", it as Any) .onEach { GlobalConfigManager.updateValue("$moduleName.${property.name}", it as Any) }
}.launchIn(mutableConfigValueScope) .launchIn(mutableConfigValueScope)
return stateFlow return stateFlow
} }
@@ -131,6 +133,6 @@ class ServerConfig(getConfig: () -> Config, val moduleName: String = MODULE_NAME
} }
companion object { companion object {
fun register(getConfig: () -> Config) = ServerConfig({ getConfig().getConfig(MODULE_NAME) }) fun register(getConfig: () -> Config) = ServerConfig({ getConfig().getConfig(SERVER_CONFIG_MODULE_NAME) })
} }
} }

View File

@@ -22,7 +22,7 @@ object Browser {
if (serverConfig.webUIEnabled.value) { if (serverConfig.webUIEnabled.value) {
val appBaseUrl = getAppBaseUrl() val appBaseUrl = getAppBaseUrl()
if (serverConfig.webUIInterface.value == ("electron")) { if (serverConfig.webUIInterface.value == WebUIInterface.ELECTRON.name.lowercase()) {
try { try {
val electronPath = serverConfig.electronPath.value val electronPath = serverConfig.electronPath.value
electronInstances.add(ProcessBuilder(electronPath, appBaseUrl).start()) electronInstances.add(ProcessBuilder(electronPath, appBaseUrl).start())

View File

@@ -63,33 +63,55 @@ private fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte
class BundledWebUIMissing : Exception("No bundled webUI version found") class BundledWebUIMissing : Exception("No bundled webUI version found")
enum class WebUIInterface {
BROWSER,
ELECTRON;
companion object {
fun from(value: String): WebUIInterface = WebUIInterface.values().find { it.name.lowercase() == value.lowercase() } ?: BROWSER
}
}
enum class WebUIChannel { enum class WebUIChannel {
BUNDLED, // the default webUI version bundled with the server release BUNDLED, // the default webUI version bundled with the server release
STABLE, STABLE,
PREVIEW; PREVIEW;
companion object { companion object {
fun from(channel: String): WebUIChannel = WebUIChannel.values().find { it.name.lowercase() == channel.lowercase() } ?: STABLE
fun doesConfigChannelEqual(channel: WebUIChannel): Boolean { fun doesConfigChannelEqual(channel: WebUIChannel): Boolean {
return serverConfig.webUIChannel.value.equals(channel.toString(), true) return serverConfig.webUIChannel.value.equals(channel.name, true)
} }
} }
} }
enum class WebUI( enum class WebUIFlavor(
val repoUrl: String, val uiName: String, val repoUrl: String,
val versionMappingUrl: String, val versionMappingUrl: String,
val latestReleaseInfoUrl: String, val latestReleaseInfoUrl: String,
val baseFileName: String val baseFileName: String
) { ) {
WEBUI( WEBUI(
"WebUI",
"https://github.com/Suwayomi/Tachidesk-WebUI-preview", "https://github.com/Suwayomi/Tachidesk-WebUI-preview",
"https://raw.githubusercontent.com/Suwayomi/Tachidesk-WebUI/master/versionToServerVersionMapping.json", "https://raw.githubusercontent.com/Suwayomi/Tachidesk-WebUI/master/versionToServerVersionMapping.json",
"https://api.github.com/repos/Suwayomi/Tachidesk-WebUI-preview/releases/latest", "https://api.github.com/repos/Suwayomi/Tachidesk-WebUI-preview/releases/latest",
"Tachidesk-WebUI" "Tachidesk-WebUI"
); ),
}
const val DEFAULT_WEB_UI = "WebUI" CUSTOM(
"Custom",
"repoURL",
"versionMappingUrl",
"latestReleaseInfoURL",
"baseFileName"
);
companion object {
fun from(value: String): WebUIFlavor = WebUIFlavor.values().find { it.name == value } ?: WEBUI
}
}
object WebInterfaceManager { object WebInterfaceManager {
private val logger = KotlinLogging.logger {} private val logger = KotlinLogging.logger {}
@@ -141,7 +163,7 @@ object WebInterfaceManager {
private fun scheduleWebUIUpdateCheck() { private fun scheduleWebUIUpdateCheck() {
HAScheduler.descheduleCron(currentUpdateTaskId) HAScheduler.descheduleCron(currentUpdateTaskId)
val isAutoUpdateDisabled = !isAutoUpdateEnabled() || serverConfig.webUIFlavor.value == "Custom" val isAutoUpdateDisabled = !isAutoUpdateEnabled() || serverConfig.webUIFlavor.value == WebUIFlavor.CUSTOM.uiName
if (isAutoUpdateDisabled) { if (isAutoUpdateDisabled) {
return return
} }
@@ -174,7 +196,7 @@ object WebInterfaceManager {
} }
suspend fun setupWebUI() { suspend fun setupWebUI() {
if (serverConfig.webUIFlavor.value == "Custom") { if (serverConfig.webUIFlavor.value == WebUIFlavor.CUSTOM.uiName) {
return return
} }
@@ -195,7 +217,7 @@ object WebInterfaceManager {
// check if the bundled webUI version is a newer version than the current used version // check if the bundled webUI version is a newer version than the current used version
// this could be the case in case no compatible webUI version is available and a newer server version was installed // this could be the case in case no compatible webUI version is available and a newer server version was installed
val shouldUpdateToBundledVersion = val shouldUpdateToBundledVersion =
serverConfig.webUIFlavor.value == DEFAULT_WEB_UI && extractVersion(getLocalVersion()) < extractVersion( serverConfig.webUIFlavor.value == WebUIFlavor.WEBUI.uiName && extractVersion(getLocalVersion()) < extractVersion(
BuildConfig.WEBUI_TAG BuildConfig.WEBUI_TAG
) )
if (shouldUpdateToBundledVersion) { if (shouldUpdateToBundledVersion) {
@@ -241,10 +263,10 @@ object WebInterfaceManager {
return return
} }
if (serverConfig.webUIFlavor.value != DEFAULT_WEB_UI) { if (serverConfig.webUIFlavor.value != WebUIFlavor.WEBUI.uiName) {
logger.warn { "doInitialSetup: fallback to default webUI \"$DEFAULT_WEB_UI\"" } logger.warn { "doInitialSetup: fallback to default webUI \"${WebUIFlavor.WEBUI.uiName}\"" }
serverConfig.webUIFlavor.value = DEFAULT_WEB_UI serverConfig.webUIFlavor.value = WebUIFlavor.WEBUI.uiName
val fallbackToBundledVersion = !doDownload() { getLatestCompatibleVersion() } val fallbackToBundledVersion = !doDownload() { getLatestCompatibleVersion() }
if (!fallbackToBundledVersion) { if (!fallbackToBundledVersion) {
@@ -252,7 +274,7 @@ object WebInterfaceManager {
} }
} }
logger.warn { "doInitialSetup: fallback to bundled default webUI \"$DEFAULT_WEB_UI\"" } logger.warn { "doInitialSetup: fallback to bundled default webUI \"${WebUIFlavor.WEBUI.uiName}\"" }
try { try {
setupBundledWebUI() setupBundledWebUI()
@@ -278,7 +300,7 @@ object WebInterfaceManager {
logger.info { "extractBundledWebUI: Using the bundled WebUI zip..." } logger.info { "extractBundledWebUI: Using the bundled WebUI zip..." }
val webUIZip = WebUI.WEBUI.baseFileName val webUIZip = WebUIFlavor.WEBUI.baseFileName
val webUIZipPath = "$tmpDir/$webUIZip" val webUIZipPath = "$tmpDir/$webUIZip"
val webUIZipFile = File(webUIZipPath) val webUIZipFile = File(webUIZipPath)
resourceWebUI.use { input -> resourceWebUI.use { input ->
@@ -309,7 +331,7 @@ object WebInterfaceManager {
} }
private fun getDownloadUrlFor(version: String): String { private fun getDownloadUrlFor(version: String): String {
val baseReleasesUrl = "${WebUI.WEBUI.repoUrl}/releases" val baseReleasesUrl = "${WebUIFlavor.WEBUI.repoUrl}/releases"
val downloadSpecificVersionBaseUrl = "$baseReleasesUrl/download" val downloadSpecificVersionBaseUrl = "$baseReleasesUrl/download"
return "$downloadSpecificVersionBaseUrl/$version" return "$downloadSpecificVersionBaseUrl/$version"
@@ -399,7 +421,7 @@ object WebInterfaceManager {
private suspend fun fetchPreviewVersion(): String { private suspend fun fetchPreviewVersion(): String {
return executeWithRetry(KotlinLogging.logger("${logger.name} fetchPreviewVersion"), { return executeWithRetry(KotlinLogging.logger("${logger.name} fetchPreviewVersion"), {
val releaseInfoJson = network.client.newCall(GET(WebUI.WEBUI.latestReleaseInfoUrl)).await().body.string() val releaseInfoJson = network.client.newCall(GET(WebUIFlavor.WEBUI.latestReleaseInfoUrl)).await().body.string()
Json.decodeFromString<JsonObject>(releaseInfoJson)["tag_name"]?.jsonPrimitive?.content Json.decodeFromString<JsonObject>(releaseInfoJson)["tag_name"]?.jsonPrimitive?.content
?: throw Exception("Failed to get the preview version tag") ?: throw Exception("Failed to get the preview version tag")
}) })
@@ -410,7 +432,7 @@ object WebInterfaceManager {
KotlinLogging.logger("$logger fetchServerMappingFile"), KotlinLogging.logger("$logger fetchServerMappingFile"),
{ {
json.parseToJsonElement( json.parseToJsonElement(
network.client.newCall(GET(WebUI.WEBUI.versionMappingUrl)).await().body.string() network.client.newCall(GET(WebUIFlavor.WEBUI.versionMappingUrl)).await().body.string()
).jsonArray ).jsonArray
} }
) )
@@ -476,7 +498,7 @@ object WebInterfaceManager {
emitStatus(version, DOWNLOADING, 0) emitStatus(version, DOWNLOADING, 0)
try { try {
val webUIZip = "${WebUI.WEBUI.baseFileName}-$version.zip" val webUIZip = "${WebUIFlavor.WEBUI.baseFileName}-$version.zip"
val webUIZipPath = "$tmpDir/$webUIZip" val webUIZipPath = "$tmpDir/$webUIZip"
val webUIZipURL = "${getDownloadUrlFor(version)}/$webUIZip" val webUIZipURL = "${getDownloadUrlFor(version)}/$webUIZip"