Create FireTV specific app variant (#1230)

## Description
Adds a variant of Wholphin targeted for the Amazon Fire TV App store.

### Related issues
See #1192 for more details

### Testing
Emulator

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Ray 2026-04-11 19:30:23 -04:00 committed by GitHub
parent 97e10f57ca
commit 287a7b0c69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 73 additions and 47 deletions

View file

@ -36,7 +36,7 @@ jobs:
ORG_GRADLE_PROJECT_WholphinExtensionsUsername: "${{ secrets.EXTENSIONS_USERNAME }}" ORG_GRADLE_PROJECT_WholphinExtensionsUsername: "${{ secrets.EXTENSIONS_USERNAME }}"
ORG_GRADLE_PROJECT_WholphinExtensionsPassword: "${{ secrets.EXTENSIONS_PASSWORD }}" ORG_GRADLE_PROJECT_WholphinExtensionsPassword: "${{ secrets.EXTENSIONS_PASSWORD }}"
run: | run: |
./gradlew clean assembleDefaultRelease bundleAppstoreRelease --no-daemon ./gradlew clean assembleDefaultRelease bundleAppstoreRelease bundleFiretvRelease --no-daemon
- name: Verify signatures - name: Verify signatures
run: | run: |

View file

@ -1,3 +1,4 @@
import com.android.build.api.dsl.ProductFlavor
import com.google.protobuf.gradle.id import com.google.protobuf.gradle.id
import com.mikepenz.aboutlibraries.plugin.DuplicateMode import com.mikepenz.aboutlibraries.plugin.DuplicateMode
import com.mikepenz.aboutlibraries.plugin.DuplicateRule import com.mikepenz.aboutlibraries.plugin.DuplicateRule
@ -112,16 +113,34 @@ android {
} }
flavorDimensions += "version" flavorDimensions += "version"
productFlavors { productFlavors {
val featureLeanback = "leanback"
val featureUpdate = "UPDATING_ENABLED"
val featureDiscover = "DISCOVER_ENABLED"
fun ProductFlavor.setFeatureFlag(
name: String,
enabled: Boolean,
) {
this.buildConfigField("boolean", name, "Boolean.parseBoolean(\"${enabled}\")")
}
create("default") { create("default") {
dimension = "version" dimension = "version"
isDefault = true isDefault = true
manifestPlaceholders += mapOf("leanback" to false) manifestPlaceholders += mapOf(featureLeanback to false)
buildConfigField("boolean", "UPDATING_ENABLED", "true") setFeatureFlag(featureUpdate, true)
setFeatureFlag(featureDiscover, true)
} }
create("appstore") { create("appstore") {
dimension = "version" dimension = "version"
manifestPlaceholders += mapOf("leanback" to true) manifestPlaceholders += mapOf(featureLeanback to true)
buildConfigField("boolean", "UPDATING_ENABLED", "false") setFeatureFlag(featureUpdate, false)
setFeatureFlag(featureDiscover, true)
}
create("firetv") {
dimension = "version"
manifestPlaceholders += mapOf(featureLeanback to true)
setFeatureFlag(featureUpdate, false)
setFeatureFlag(featureDiscover, false)
} }
} }
compileOptions { compileOptions {

View file

@ -5,6 +5,7 @@ import androidx.annotation.ArrayRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.github.damontecres.wholphin.BuildConfig
import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.WholphinApplication import com.github.damontecres.wholphin.WholphinApplication
import com.github.damontecres.wholphin.services.UpdateChecker import com.github.damontecres.wholphin.services.UpdateChecker
@ -1085,10 +1086,12 @@ val basicPreferences =
PreferenceGroup( PreferenceGroup(
title = R.string.more, title = R.string.more,
preferences = preferences =
listOf( buildList {
AppPreference.SeerrIntegration, if (BuildConfig.DISCOVER_ENABLED) {
AppPreference.AdvancedSettings, add(AppPreference.SeerrIntegration)
), }
add(AppPreference.AdvancedSettings)
},
), ),
) )

View file

@ -1,5 +1,6 @@
package com.github.damontecres.wholphin.services package com.github.damontecres.wholphin.services
import com.github.damontecres.wholphin.BuildConfig
import com.github.damontecres.wholphin.api.seerr.SeerrApiClient import com.github.damontecres.wholphin.api.seerr.SeerrApiClient
import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.isNotNullOrBlank
import com.github.damontecres.wholphin.ui.setup.seerr.createSeerrApiUrl import com.github.damontecres.wholphin.ui.setup.seerr.createSeerrApiUrl
@ -19,7 +20,7 @@ class SeerrApi(
) )
private set private set
val active: Boolean get() = api.baseUrl.isNotNullOrBlank() val active: Boolean get() = api.baseUrl.isNotNullOrBlank() && BuildConfig.DISCOVER_ENABLED
fun update( fun update(
baseUrl: String, baseUrl: String,

View file

@ -4,6 +4,7 @@ import android.content.Context
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.github.damontecres.wholphin.BuildConfig
import com.github.damontecres.wholphin.api.seerr.SeerrApiClient import com.github.damontecres.wholphin.api.seerr.SeerrApiClient
import com.github.damontecres.wholphin.api.seerr.model.AuthJellyfinPostRequest import com.github.damontecres.wholphin.api.seerr.model.AuthJellyfinPostRequest
import com.github.damontecres.wholphin.api.seerr.model.AuthLocalPostRequest import com.github.damontecres.wholphin.api.seerr.model.AuthLocalPostRequest
@ -292,44 +293,46 @@ class UserSwitchListener
launchIO { launchIO {
homeSettingsService.loadCurrentSettings(user.id) homeSettingsService.loadCurrentSettings(user.id)
} }
// Check for seerr server if (BuildConfig.DISCOVER_ENABLED) {
launchIO { // Check for seerr server
seerrServerDao launchIO {
.getUsersByJellyfinUser(user.rowId) seerrServerDao
.lastOrNull() .getUsersByJellyfinUser(user.rowId)
?.let { seerrUser -> .lastOrNull()
val server = ?.let { seerrUser ->
seerrServerDao.getServer(seerrUser.serverId)?.server val server =
if (server != null) { seerrServerDao.getServer(seerrUser.serverId)?.server
Timber.i("Found a seerr user & server") if (server != null) {
try { Timber.i("Found a seerr user & server")
seerrApi.update(server.url, seerrUser.credential) try {
val userConfig = seerrApi.update(server.url, seerrUser.credential)
if (seerrUser.authMethod != SeerrAuthMethod.API_KEY) { val userConfig =
login( if (seerrUser.authMethod != SeerrAuthMethod.API_KEY) {
seerrApi.api, login(
seerrUser.authMethod, seerrApi.api,
seerrUser.username, seerrUser.authMethod,
seerrUser.password, seerrUser.username,
) seerrUser.password,
} else { )
seerrApi.api.usersApi.authMeGet() } else {
} seerrApi.api.usersApi.authMeGet()
seerrServerRepository.set( }
server, seerrServerRepository.set(
seerrUser, server,
userConfig, seerrUser,
) userConfig,
} catch (ex: Exception) { )
Timber.w( } catch (ex: Exception) {
ex, Timber.w(
"Error logging into %s", ex,
server.url, "Error logging into %s",
) server.url,
seerrServerRepository.error(server, seerrUser, ex) )
seerrServerRepository.error(server, seerrUser, ex)
}
} }
} }
} }
} }
} }
} }

View file

@ -65,7 +65,7 @@ class UpdateChecker
private val NOTE_REGEX = Regex("<!-- app-note:(.+) -->") private val NOTE_REGEX = Regex("<!-- app-note:(.+) -->")
const val ACTIVE = BuildConfig.UPDATING_ENABLED val ACTIVE = BuildConfig.UPDATING_ENABLED
} }
/** /**