Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add info switch functionality #32

Merged
merged 7 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ android {
applicationId = "com.chouten.app"
minSdk = 23
targetSdk = 34
versionCode = 6
versionName = "0.0.6"
versionCode = 7
versionName = "0.1.0"
buildConfigField("String", "WEBHOOK_URL", "\"${properties.getProperty("bug_webhook")}\"")

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import android.util.Log
import android.webkit.JavascriptInterface
import android.webkit.WebView
import android.webkit.WebViewClient
import com.chouten.app.BuildConfig
import com.chouten.app.R
import com.chouten.app.domain.model.Payloads_V2.Action_V2
import com.chouten.app.domain.repository.WebviewHandler
import com.chouten.app.domain.repository.postWebMessage
import com.chouten.app.presentation.ui.screens.info.SwitchConfig
import com.lagradost.nicehttp.Requests
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
Expand All @@ -37,6 +39,8 @@ class WebviewHandlerImpl<BaseResultPayload : WebviewHandler.Companion.ActionPayl
private lateinit var webview: WebView
private lateinit var commonCode: String

private lateinit var switchConfig: SwitchConfig
private var isSwitchToggled = false

@OptIn(ExperimentalSerializationApi::class)
private val json = Json {
Expand All @@ -57,7 +61,7 @@ class WebviewHandlerImpl<BaseResultPayload : WebviewHandler.Companion.ActionPayl
webview.settings.javaScriptEnabled = true
webview.settings.domStorageEnabled = true
webview.addJavascriptInterface(this, "Native")
WebView.setWebContentsDebuggingEnabled(true)
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG)
}
if (!::commonCode.isInitialized) {
commonCode = getCommonCode(context)
Expand Down Expand Up @@ -252,6 +256,46 @@ class WebviewHandlerImpl<BaseResultPayload : WebviewHandler.Companion.ActionPayl
}
}

@JavascriptInterface
fun getSwitchValue(): Int {
if (!::switchConfig.isInitialized) {
return 0
}
// If the toggle is switched (1) but the default value is also 1,
// we want to return 0 instead
return if (isSwitchToggled xor (switchConfig.default == 0)) 1 else 0
}

override fun <T> getGenericValue(key: String): T? {
return when (key) {
"switchConfig" -> {
if (::switchConfig.isInitialized) {
switchConfig as? T
} else null
}

"switchValue" -> {
return SwitchConfig.isToggled(isSwitchToggled, switchConfig) as T?
}

else -> throw IllegalArgumentException("Invalid key $key")
}
}

override fun <T> setGenericValue(key: String, value: T) {
when (key) {
"switchConfig" -> {
switchConfig = value as SwitchConfig
}

"switchValue" -> {
isSwitchToggled = (value as Boolean) xor (switchConfig.default == 0)
}

else -> throw IllegalArgumentException("Invalid key $key")
}
}

/**
* Used by the JS code to log a message
*/
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/chouten/app/di/WebviewModuleV2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.chouten.app.data.repository.WebviewHandlerImpl
import com.chouten.app.domain.model.Payloads_V2
import com.chouten.app.domain.repository.WebviewHandler
import com.chouten.app.presentation.ui.screens.info.InfoResult
import com.chouten.app.presentation.ui.screens.info.SwitchConfig
import com.chouten.app.presentation.ui.screens.search.SearchResult
import com.chouten.app.presentation.ui.screens.watch.WatchResult
import com.lagradost.nicehttp.Requests
Expand All @@ -28,6 +29,19 @@ object WebviewModuleV2 {
}
}

@OptIn(ExperimentalSerializationApi::class)
@Provides
fun provideSwitchConfigWebviewHandler(client: Requests): WebviewHandler<Payloads_V2.Action_V2, Payloads_V2.GenericPayload<SwitchConfig>> {
val json = Json {
ignoreUnknownKeys = true
isLenient = true
explicitNulls = false
}
return WebviewHandlerImpl(client) { action, result: String ->
Payloads_V2.GenericPayload(action, json.decodeFromString(result))
}
}

@OptIn(ExperimentalSerializationApi::class)
@Provides
fun provideInfoMetadataWebviewHandler(client: Requests): WebviewHandler<Payloads_V2.Action_V2, Payloads_V2.GenericPayload<InfoResult>> {
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/com/chouten/app/domain/model/Payloads_V2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ object Payloads_V2 {
@SerialName("info")
GET_INFO,

@SerialName("switchConfig")
GET_SWITCH_CONFIG,

@SerialName("metadata")
GET_METADATA,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ interface WebviewHandler<Action : Enum<Action>, ResultPayload : WebviewHandler.C
*/
suspend fun getCommonCode(context: Context): String

fun <T> getGenericValue(key: String): T?
fun <T> setGenericValue(key: String, value: T)

companion object {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewModelScope
import coil.compose.AsyncImage
import coil.compose.SubcomposeAsyncImage
import coil.compose.SubcomposeAsyncImageContent
Expand All @@ -85,6 +86,7 @@ import com.chouten.app.presentation.ui.screens.destinations.WatchViewDestination
import com.chouten.app.presentation.ui.screens.watch.WatchBundle
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import java.net.URLDecoder

Expand All @@ -106,11 +108,19 @@ fun InfoView(

val selectedSeason by infoViewModel.selectedSeason.collectAsState()
var lastUrl by rememberSaveable { mutableStateOf(url) }
val switchValue by infoViewModel.switchValue.collectAsState()
val switchConfig by infoViewModel.switchConfig.collectAsState()

LaunchedEffect(infoResults, selectedSeason) {
LaunchedEffect(infoResults, selectedSeason, switchValue) {
when (infoResults) {
is Resource.Success -> {
val urls = infoResults.data?.epListURLs ?: listOf()
if (switchConfig?.options?.size == 2 && infoViewModel.cachedSwitchResults.firstOrNull()?.size == 2) {
// We will force the viewmodel to emit the cached results
infoViewModel.toggleSwitch(switchValue)
return@LaunchedEffect
}

selectedSeason?.let {
if ((lastUrl != it.url) && (infoViewModel.getMediaList().find { media ->
media.title == it.name
Expand Down Expand Up @@ -145,7 +155,7 @@ fun InfoView(
}

LaunchedEffect(episodeList) {
if (infoViewModel.paginatedAll && infoViewModel.seasonCount <= 1) {
if (infoViewModel.paginatedAll && infoViewModel.seasonCount <= 1 && (switchConfig?.options?.size == 2 && infoViewModel.cachedSwitchResults.firstOrNull()?.size == 2)) {
// We have no further episodes to load
// so don't need the webview anymore.
infoViewModel.epListHandler.destroy()
Expand Down Expand Up @@ -325,19 +335,33 @@ fun InfoView(
}
}

Row(
Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically
AnimatedVisibility(
visible = switchConfig?.options != null
) {
Switch(checked = false, onCheckedChange = {})
Text(
"Subbed",
color = MaterialTheme.colorScheme.onSurface,
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(
vertical = 6.dp, horizontal = 12.dp
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Switch(checked = switchValue, onCheckedChange = {
infoViewModel.viewModelScope.launch {
infoViewModel.toggleSwitch()
}
})
Text(
switchConfig?.options?.get(
if (SwitchConfig.isToggled(
switchValue, switchConfig!!
)
) 1 else 0
) ?: "",
color = MaterialTheme.colorScheme.onSurface,
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(
vertical = 6.dp, horizontal = 12.dp
)
)
)
}
}

AnimatedVisibility(visible = !infoResults.data?.seasons.isNullOrEmpty()) {
Expand Down
Loading