Compare commits
102 commits
fm/tv-slic
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6fc10b7af2 | |||
| 9061384ad1 | |||
| 9bbb4bab25 | |||
| 57cf17aaad | |||
| 51799669e7 | |||
| 383802611c | |||
| 94a69de25f | |||
| c78a8dfa8d | |||
| d171aaae9e | |||
| 83ebf25d9f | |||
| 37ad87d058 | |||
| 2b8c729f62 | |||
| 271cee2cea | |||
| ee3f3ae11e | |||
| 19df50c0f1 | |||
| 7a0cbdf909 | |||
| e189d9318a | |||
| 152dac97c0 | |||
| 19bb587c95 | |||
| 165a3f5e7d | |||
| c3e9b3cd3b | |||
| 017004bf39 | |||
| b44519f01b | |||
| a0237fa975 | |||
| c2f7ccc438 | |||
| fe44a3c24f | |||
| 00e8e83bb6 | |||
| b80b67f736 | |||
| fdff85c8a1 | |||
| 332fc6476d | |||
| d18a05bdb0 | |||
| 1668445418 | |||
| fd48426fa7 | |||
| 052d0b8898 | |||
| acb72335e3 | |||
| 53a2cff2c8 | |||
| 327f631f0d | |||
| e340d470c1 | |||
| f4fb6e22c9 | |||
| 5bd2affc1a | |||
| 8e40ac0869 | |||
| 54c23e076a | |||
|
|
159edc875d | ||
| 12fd12f754 | |||
| 7b88f9b54b | |||
| 5162c299db | |||
| 9d2471c5b1 | |||
| 278335f009 | |||
| deb24e3c9f | |||
| 556d633e88 | |||
| 34087d8eb5 | |||
| 33dc65bf18 | |||
| ef3ae3f21b | |||
| d0e38306b3 | |||
| 5306f8ddc4 | |||
| 59f4a06815 | |||
| 427b18cdc5 | |||
| 93a41ea2d3 | |||
| 1c21f50acb | |||
| e8d0c52088 | |||
| db2541feff | |||
| f37ad0f0fe | |||
| 92c5661be0 | |||
| b9ea593735 | |||
| 711dbebf28 | |||
| 6e0f9952cf | |||
| c17447c528 | |||
| 9e15dbee8c | |||
| 53b8358317 | |||
| 5a84666074 | |||
| 22850632ec | |||
| afff383b75 | |||
| d401ebc355 | |||
| e794dec253 | |||
| 4e6377b628 | |||
| e9a92eba49 | |||
| 81073c410d | |||
| 04b1bdd6aa | |||
| bfe3dbbb16 | |||
| ec32346c71 | |||
| 34ea983a51 | |||
| 09f1d72f30 | |||
| 78322f588a | |||
| a00db96dc8 | |||
| 71a055987c | |||
|
|
bd46ff3e03 | ||
| 844530404d | |||
| 59c2728d9c | |||
| f53defad90 | |||
| abec496305 | |||
| cd625b4227 | |||
| fc02ce8646 | |||
| 2fdd459037 | |||
| e243894a20 | |||
| 43ae716157 | |||
| a8951827ba | |||
| 3bfb8cd779 | |||
| fc7eb94cc1 | |||
| 0ca13e684f | |||
| 6d7df0fb19 | |||
| 0c94e8f910 | |||
| 0db05174b1 |
12
Makefile
|
|
@ -4,7 +4,7 @@ WOLFSKIN_GRADLE_VOLUME ?= wolfskin-gradle
|
||||||
WOLFSKIN_SECRETS_DIR ?= /opt/stacks/ventoy/machine-parity/manifest-tank/secrets/wolfskin
|
WOLFSKIN_SECRETS_DIR ?= /opt/stacks/ventoy/machine-parity/manifest-tank/secrets/wolfskin
|
||||||
export WOLFSKIN_BUILD_IMAGE WOLFSKIN_GRADLE_VOLUME WOLFSKIN_SECRETS_DIR
|
export WOLFSKIN_BUILD_IMAGE WOLFSKIN_GRADLE_VOLUME WOLFSKIN_SECRETS_DIR
|
||||||
|
|
||||||
.PHONY: build-image apk apk-debug test release-tag
|
.PHONY: build-image apk apk-debug test release-tag tv-release tv-publish tv-tooling-test
|
||||||
build-image:
|
build-image:
|
||||||
docker build --platform linux/amd64 --tag "$(WOLFSKIN_BUILD_IMAGE)" docker
|
docker build --platform linux/amd64 --tag "$(WOLFSKIN_BUILD_IMAGE)" docker
|
||||||
|
|
||||||
|
|
@ -19,3 +19,13 @@ test: build-image
|
||||||
|
|
||||||
release-tag:
|
release-tag:
|
||||||
@bash docker/release-tag.sh
|
@bash docker/release-tag.sh
|
||||||
|
|
||||||
|
TV_RELEASE_DIR ?= /var/tmp/wolfskin-tv-release-$(VERSION)
|
||||||
|
tv-release: build-image
|
||||||
|
@python3 docker/tv_release.py --version "$(VERSION)" --version-code "$(VERSION_CODE)" --output "$(TV_RELEASE_DIR)" $(TV_RELEASE_FLAGS)
|
||||||
|
|
||||||
|
tv-publish:
|
||||||
|
@python3 docker/tv_publish.py --directory "$(TV_RELEASE_DIR)" $(TV_PUBLISH_FLAGS)
|
||||||
|
|
||||||
|
tv-tooling-test:
|
||||||
|
@python3 -m unittest discover -s docker -p 'test_tv_*.py' -v
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,14 @@ Wolfskin is an Android TV client for one household. It is released through Forge
|
||||||
|
|
||||||
The app uses Wolfskin launcher artwork and a lilac-on-`#07070a` theme by default on a fresh install. Existing theme choices and all upstream colour themes remain available under Settings → App theme. Settings → About credits and links to Wholphin by damontecres.
|
The app uses Wolfskin launcher artwork and a lilac-on-`#07070a` theme by default on a fresh install. Existing theme choices and all upstream colour themes remain available under Settings → App theme. Settings → About credits and links to Wholphin by damontecres.
|
||||||
|
|
||||||
|
## Wolfskin TV updates
|
||||||
|
|
||||||
|
Settings opens on Requests. Press Down, then OK to open Updates; the row and screen show the installed app version. Left/Right selects an action, Down reaches Auto-check, and Up returns to the remembered action. Release notes keep focus inside the notes panel: Up/Down scrolls, and Back returns to the Release notes button.
|
||||||
|
|
||||||
|
Auto-check uses the same preference as classic settings and only checks for updates. Manual checks remain available when it is off. Download and Install update are separate, explicit actions; Android owns installation permission and confirmation. Returning from Android refreshes the installed version. Back can leave a download running, and returning to Updates shows the controller's current state.
|
||||||
|
|
||||||
|
Classic settings (trial) is the final Settings row. It opens the full original settings, including About → Update and More/Advanced → Updates. All existing settings groups remain available.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Wholphin - an OSS Android TV client for Jellyfin
|
# Wholphin - an OSS Android TV client for Jellyfin
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,10 @@ val gitDescribe =
|
||||||
.standardOutput.asText
|
.standardOutput.asText
|
||||||
.getOrElse("v0.0.0")
|
.getOrElse("v0.0.0")
|
||||||
|
|
||||||
|
val tvVersion = providers.gradleProperty("tvVersion").orElse("1.1.1")
|
||||||
|
val tvVersionCode = providers.gradleProperty("tvVersionCode")
|
||||||
|
apply(from = "household-version.gradle.kts")
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
compilerOptions {
|
compilerOptions {
|
||||||
languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3
|
languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3
|
||||||
|
|
@ -82,6 +86,7 @@ configure<ApplicationExtension> {
|
||||||
testInstrumentationRunner = "com.github.damontecres.wholphin.test.WholphinTestRunner"
|
testInstrumentationRunner = "com.github.damontecres.wholphin.test.WholphinTestRunner"
|
||||||
|
|
||||||
buildConfigField("long", "BUILD_TIME", System.currentTimeMillis().toString())
|
buildConfigField("long", "BUILD_TIME", System.currentTimeMillis().toString())
|
||||||
|
buildConfigField("String", "CONDUCTARR_BASE_URL", "\"https://wolfskin-tv.justinvisser.org\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
|
@ -132,6 +137,13 @@ configure<ApplicationExtension> {
|
||||||
isDebuggable = true
|
isDebuggable = true
|
||||||
applicationIdSuffix = ".debug"
|
applicationIdSuffix = ".debug"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create("optimized") {
|
||||||
|
initWith(getByName("release"))
|
||||||
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
|
applicationIdSuffix = ".opt"
|
||||||
|
matchingFallbacks += "release"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
flavorDimensions += "version"
|
flavorDimensions += "version"
|
||||||
productFlavors {
|
productFlavors {
|
||||||
|
|
@ -198,6 +210,10 @@ configure<ApplicationExtension> {
|
||||||
kotlin.directories += "$buildDir/generated/seerr_api/src/main/kotlin"
|
kotlin.directories += "$buildDir/generated/seerr_api/src/main/kotlin"
|
||||||
kotlin.directories += "src/wolfskin/java"
|
kotlin.directories += "src/wolfskin/java"
|
||||||
}
|
}
|
||||||
|
getByName("optimized") {
|
||||||
|
kotlin.directories += "src/release/java"
|
||||||
|
baselineProfiles.directories += "src/optimized/baselineProfiles"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testOptions {
|
testOptions {
|
||||||
|
|
@ -216,6 +232,13 @@ configure<ApplicationExtension> {
|
||||||
|
|
||||||
androidComponents {
|
androidComponents {
|
||||||
onVariants(selector().all()) { variant ->
|
onVariants(selector().all()) { variant ->
|
||||||
|
if (variant.name == "defaultOptimized") {
|
||||||
|
variant.outputs.forEach {
|
||||||
|
it.versionName.set(tvVersion)
|
||||||
|
// The sentinel is configuration-only: optimized tasks require the explicit input above.
|
||||||
|
it.versionCode.set(tvVersionCode.map(String::toInt).orElse(1))
|
||||||
|
}
|
||||||
|
}
|
||||||
variant.outputs
|
variant.outputs
|
||||||
.map { it as com.android.build.api.variant.impl.VariantOutputImpl }
|
.map { it as com.android.build.api.variant.impl.VariantOutputImpl }
|
||||||
.forEach { output ->
|
.forEach { output ->
|
||||||
|
|
@ -227,6 +250,11 @@ androidComponents {
|
||||||
"Wholphin-${variant.flavorName}-${variant.buildType}-${output.versionName.get()}-${output.versionCode.get()}$abi.apk"
|
"Wholphin-${variant.flavorName}-${variant.buildType}-${output.versionName.get()}-${output.versionCode.get()}$abi.apk"
|
||||||
output.outputFileName = outputFileName
|
output.outputFileName = outputFileName
|
||||||
}
|
}
|
||||||
|
if (variant.name == "defaultOptimized") {
|
||||||
|
tasks.withType<Test>().configureEach {
|
||||||
|
systemProperty("wolfskin.optimizedVersionName", variant.outputs.first().versionName.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
if (variant.name == "defaultDebug") {
|
if (variant.name == "defaultDebug") {
|
||||||
val packagedApks = variant.artifacts.get(SingleArtifact.APK)
|
val packagedApks = variant.artifacts.get(SingleArtifact.APK)
|
||||||
val artifactLoader = variant.artifacts.getBuiltArtifactsLoader()
|
val artifactLoader = variant.artifacts.getBuiltArtifactsLoader()
|
||||||
|
|
@ -448,6 +476,7 @@ dependencies {
|
||||||
testImplementation(libs.mockk.android)
|
testImplementation(libs.mockk.android)
|
||||||
testImplementation(libs.mockk.agent)
|
testImplementation(libs.mockk.agent)
|
||||||
testImplementation(libs.kotlinx.coroutines.test)
|
testImplementation(libs.kotlinx.coroutines.test)
|
||||||
|
testImplementation("com.squareup.okhttp3:mockwebserver3")
|
||||||
testImplementation(libs.androidx.core.testing)
|
testImplementation(libs.androidx.core.testing)
|
||||||
testImplementation(libs.robolectric)
|
testImplementation(libs.robolectric)
|
||||||
testImplementation(libs.hilt.android.testing)
|
testImplementation(libs.hilt.android.testing)
|
||||||
|
|
|
||||||
18
app/household-version.gradle.kts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Household assembly inputs remain mandatory even through aggregate Gradle tasks.
|
||||||
|
val tvVersion = providers.gradleProperty("tvVersion").orElse("1.1.1")
|
||||||
|
val tvVersionCode = providers.gradleProperty("tvVersionCode")
|
||||||
|
|
||||||
|
fun requireHouseholdVersion() {
|
||||||
|
require(tvVersionCode.isPresent) { "Household builds require -PtvVersionCode=<monotonic code>" }
|
||||||
|
require(tvVersionCode.get().toInt() in 1..2100000000) { "Invalid household versionCode" }
|
||||||
|
require(Regex("""\d+\.\d+\.\d+""").matches(tvVersion.get())) { "Household versionName must be plain major.minor.patch" }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gradle.startParameter.taskNames.any { it.contains("Optimized", ignoreCase = true) }) {
|
||||||
|
requireHouseholdVersion()
|
||||||
|
}
|
||||||
|
tasks.configureEach {
|
||||||
|
if (name.contains("DefaultOptimized", ignoreCase = true)) {
|
||||||
|
doFirst { requireHouseholdVersion() }
|
||||||
|
}
|
||||||
|
}
|
||||||
1
app/src/debug/assets/wolfskin-titles.json
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 140 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 76 KiB |