Files
Suwayomi-Server/server/build.gradle.kts
Constantin Piber 00861d7750 Switch to JCEF (#2038)
* Switch to JCEF

This is a full implementation, but it does not yet include downloading
CEF as KCEF did

* Download CEF automatically

* Handle and propagate CEF init errors

* Lint

* Simplify jcef version extract

* CEF: Download async

* Copy StartupAsync to support handling errors

Startup failures are simply swallowed, since they are recorded in the
future, but there is no way to get that exception

* CEF: Search for release file recursively

On Mac, the file is buried a bit deeper than first level, like on Win
and Linux

* KcefWebViewProvider: Suppress deprecation

We need to send those events, even if they are deprecated

* Update readme

* Optimize imports

* Suggestion

Co-authored-by: Mitchell Syer <syer10@users.noreply.github.com>

* Refactor: stick to `Path` instead of `File`

Also extracts the downloading of CEF to a separate method

* Lint

* Support disabling CEF

Co-authored-by: Kolby Moroz Liebl <31669092+kolbyml@users.noreply.github.com>

* Move JBR version to build constants

Allows embedding into Manifest so docker can later extract the proper version

* Create test to verify JCEF dependency matches downloaded JBR

* Update server/src/main/kotlin/suwayomi/tachidesk/server/util/CEFManager.kt

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>

* Fix compile, apply Path suggestions

* Download progress

* Lint

* Fix exception on non-posix

* Delete recursively

Others can be non-empty

* Support disabling CEF at will

Not really functional, but nice

* Fix test

* Exclude masstest unless explicitly requested

* PR-CI: Run tests

* Add Changelog entry

---------

Co-authored-by: Mitchell Syer <syer10@users.noreply.github.com>
Co-authored-by: Kolby Moroz Liebl <31669092+kolbyml@users.noreply.github.com>
2026-05-19 17:05:59 -04:00

271 lines
7.3 KiB
Kotlin

import de.undercouch.gradle.tasks.download.Download
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
import java.time.Instant
plugins {
id(
libs.plugins.kotlin.jvm
.get()
.pluginId,
)
id(
libs.plugins.kotlin.serialization
.get()
.pluginId,
)
id(
libs.plugins.ktlint
.get()
.pluginId,
)
application
alias(libs.plugins.shadowjar)
id(
libs.plugins.buildconfig
.get()
.pluginId,
)
id(
libs.plugins.jte
.get()
.pluginId,
)
}
dependencies {
// Shared
implementation(libs.bundles.shared)
testImplementation(libs.bundles.sharedTest)
// WebView
implementation(libs.gluegen)
implementation(libs.jogl)
// OkHttp
implementation(libs.bundles.okhttp)
implementation(libs.okio)
// Javalin api
implementation(libs.bundles.javalin)
implementation(libs.bundles.jackson)
// GraphQL
implementation(libs.graphql.kotlin.server)
implementation(libs.graphql.kotlin.scheme)
implementation(libs.graphql.java.scalars)
// Exposed ORM
implementation(libs.bundles.exposed)
implementation(libs.postgres)
implementation(libs.h2)
implementation(libs.hikaricp)
// Exposed Migrations
implementation(libs.exposed.migrations)
// tray icon
implementation(libs.bundles.systemtray)
// dependencies of Mihon (Tachiyomi) extensions, some are duplicate, keeping it here for reference
implementation(libs.injekt)
implementation(libs.okhttp.core)
implementation(libs.rxjava)
implementation(libs.jsoup)
// ComicInfo
implementation(libs.serialization.xml.core)
implementation(libs.serialization.xml)
// Sort
implementation(libs.sort)
// asm for ByteCodeEditor(fixing SimpleDateFormat) (must match Dex2Jar version)
implementation(libs.asm)
// Disk & File
implementation(libs.cache4k)
implementation(libs.zip4j)
implementation(libs.commonscompress)
implementation(libs.junrar)
// AES/CBC/PKCS7Padding Cypher provider for zh.copymanga
implementation(libs.bouncycastle)
// AndroidCompat
implementation(projects.androidCompat)
implementation(projects.androidCompat.config)
// i18n
implementation(projects.server.i18n)
// Settings module
implementation(projects.server.serverConfig)
// uncomment to test extensions directly
// implementation(fileTree("lib/"))
implementation(kotlin("script-runtime"))
testImplementation(libs.mockk)
implementation(libs.cron4j)
implementation(libs.cronUtils)
implementation(libs.jwt)
compileOnly(libs.kte)
}
jte {
generate()
}
application {
applicationDefaultJvmArgs =
listOf(
"-Djunrar.extractor.thread-keep-alive-seconds=30",
)
mainClass.set(MainClass)
}
sourceSets {
main {
resources {
srcDir("src/main/resources")
srcDir("build/generated/src/main/resources")
}
kotlin {
srcDir("build/generated/src/main/kotlin")
}
}
test {
resources {
srcDir("build/generated/src/test/resources")
}
}
}
buildConfig {
className("BuildConfig")
packageName("suwayomi.tachidesk.server.generated")
useKotlinOutput()
fun quoteWrap(obj: Any): String = """"$obj""""
buildConfigField("String", "NAME", quoteWrap(rootProject.name))
buildConfigField("String", "VERSION", quoteWrap(getTachideskVersion()))
buildConfigField("String", "REVISION", quoteWrap(getTachideskRevision()))
buildConfigField("String", "BUILD_TYPE", quoteWrap(if (System.getenv("ProductBuildType") == "Stable") "Stable" else "Preview"))
buildConfigField("long", "BUILD_TIME", Instant.now().epochSecond.toString())
buildConfigField("String", "WEBUI_TAG", quoteWrap(webUIRevisionTag))
buildConfigField("String", "GITHUB", quoteWrap("https://github.com/Suwayomi/Suwayomi-Server"))
buildConfigField("String", "DISCORD", quoteWrap("https://discord.gg/DDZdqZWaHA"))
buildConfigField("String", "JCEF_VERSION", quoteWrap(libs.versions.jcef.get()))
buildConfigField("String", "JCEF_JBR_RELEASE", quoteWrap(webviewJbrRelease))
}
tasks {
shadowJar {
isZip64 = true
manifest {
attributes(
"Main-Class" to MainClass,
"Implementation-Title" to rootProject.name,
"Implementation-Vendor" to "The Suwayomi Project",
"Specification-Version" to getTachideskVersion(),
"Implementation-Version" to getTachideskRevision(),
"Multi-Release" to true, // needed for polyglot
"X-JBR-Release" to webviewJbrRelease,
)
}
archiveBaseName.set(rootProject.name)
archiveVersion.set(getTachideskVersion())
archiveClassifier.set("")
destinationDirectory.set(File("$rootDir/server/build"))
mergeServiceFiles()
}
test {
useJUnitPlatform {
if (!project.hasProperty("masstest")) {
exclude("**/masstest/*")
}
}
testLogging {
showStandardStreams = true
events("passed", "skipped", "failed")
}
}
withType<KotlinJvmCompile> {
compilerOptions {
freeCompilerArgs.add(
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
)
}
}
named<Copy>("processResources") {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
mustRunAfter("downloadWebUI")
}
register<Download>("downloadWebUI") {
src("https://github.com/Suwayomi/Suwayomi-WebUI-preview/releases/download/$webUIRevisionTag/Suwayomi-WebUI-$webUIRevisionTag.zip")
dest("src/main/resources/WebUI.zip")
fun shouldOverwrite(): Boolean {
val zipPath = project.projectDir.absolutePath + "/src/main/resources/WebUI.zip"
val zipFile = net.lingala.zip4j.ZipFile(zipPath)
var shouldOverwrite = true
if (zipFile.isValidZipFile) {
val zipRevision =
zipFile.getInputStream(zipFile.getFileHeader("revision")).bufferedReader().use {
it.readText().trim()
}
if (zipRevision == webUIRevisionTag) {
shouldOverwrite = false
}
}
return shouldOverwrite
}
overwrite(shouldOverwrite())
}
register("runElectron") {
group = "application"
finalizedBy(run)
doFirst {
application.applicationDefaultJvmArgs =
listOf(
"-Dsuwayomi.tachidesk.config.server.webUIInterface=electron",
// Change this to the installed electron application
"-Dsuwayomi.tachidesk.config.server.electronPath=/usr/bin/electron",
)
}
}
runKtlintCheckOverMainSourceSet {
mustRunAfter(generateJte)
}
compileKotlin {
dependsOn(":server:server-config-generate:generateSettings")
}
processResources {
dependsOn(":server:server-config-generate:generateSettings")
}
processTestResources {
dependsOn(":server:server-config-generate:generateSettings")
}
}