Skip to content

Commit

Permalink
Merge pull request #240 from GuoXiCheng/dev-c
Browse files Browse the repository at this point in the history
update custom config
  • Loading branch information
GuoXiCheng authored Sep 19, 2024
2 parents 6fbe549 + 454a708 commit e3fe8a5
Show file tree
Hide file tree
Showing 12 changed files with 186 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import androidx.lifecycle.MutableLiveData
import com.android.skip.R
import com.android.skip.data.network.MyApiNetwork
import com.android.skip.dataclass.ConfigLoadSchema
import com.android.skip.dataclass.ConfigPostSchema
import com.android.skip.dataclass.ConfigReadSchema
import com.android.skip.dataclass.ConfigState
import com.android.skip.dataclass.LoadSkipBound
import com.android.skip.dataclass.LoadSkipId
import com.android.skip.dataclass.LoadSkipText
Expand All @@ -19,6 +21,7 @@ import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.yaml.snakeyaml.Yaml
import java.net.URL
import java.security.MessageDigest
import javax.inject.Inject
import javax.inject.Singleton
Expand All @@ -27,51 +30,61 @@ import javax.inject.Singleton
class ConfigReadRepository @Inject constructor(
private val myApiNetwork: MyApiNetwork
) {
private val _configHashCode = MutableLiveData<String>()
val configHashCode: LiveData<String> = _configHashCode
private val _configPostState = MutableLiveData<ConfigPostSchema>()
val configPostState: LiveData<ConfigPostSchema> = _configPostState

private lateinit var configReadSchemaList: List<ConfigReadSchema>

suspend fun readConfig(): String = withContext(Dispatchers.IO) {
// val configV3 = myApiNetwork.fetchSkipConfigV3()
val url = DataStoreUtils.getSyncData(
suspend fun readConfig() = withContext(Dispatchers.IO) {
val customContent = DataStoreUtils.getSyncData(
getString(R.string.store_custom_config),
getString(R.string.store_default_config)
)
val configV3 = myApiNetwork.fetchConfigFromUrl(url)
val yamlContent = Yaml().load<List<ConfigReadSchema>>(configV3)
getFromJson(getFromYaml(getFromUrl(customContent)))
}

val gson = Gson()
val jsonStr = gson.toJson(yamlContent)
val type = object : TypeToken<List<ConfigReadSchema>>() {}.type
configReadSchemaList = gson.fromJson(jsonStr, type)
private suspend fun getFromUrl(customContent: String): String {
return try {
val parsedUrl = URL(customContent)
if (parsedUrl.protocol == "http" || parsedUrl.protocol == "https") {
return myApiNetwork.fetchConfigFromUrl(customContent)
}
customContent
} catch (e: Exception) {
customContent
}
}

return@withContext jsonStr
private fun getFromYaml(customContent: String): String {
return try {
val yamlContent = Yaml().load<List<ConfigReadSchema>>(customContent)
val gson = Gson()
gson.toJson(yamlContent)
} catch (e: Exception) {
customContent
}
}

private fun getFromJson(customContent: String): ConfigPostSchema {
return try {
val gson = Gson()
val type = object : TypeToken<List<ConfigReadSchema>>() {}.type

val configReadSchemaList = gson.fromJson<List<ConfigReadSchema>>(customContent, type)

ConfigPostSchema(ConfigState.SUCCESS, md5(customContent), configReadSchemaList)
} catch (e: Exception) {
ConfigPostSchema(ConfigState.FAIL, "无效的配置", null)
}
}

fun changeConfigHashCode(jsonStrOrNull: String?) {
_configHashCode.postValue(jsonStrOrNull?.let { md5(it) })
fun changeConfigPostState(configPostSchema: ConfigPostSchema) {
_configPostState.postValue(configPostSchema)
}

// fun readConfig(context: Context) {
// val yamlContent = context.assets.open("skip_config_v3.yaml").use { input ->
// val yaml = Yaml().load<List<ConfigReadSchema>>(input)
// yaml
// }
//
// val gson = Gson()
// val jsonStr = gson.toJson(yamlContent)
// val type = object : TypeToken<List<ConfigReadSchema>>() {}.type
// configReadSchemaList = gson.fromJson(jsonStr, type)
//
// _configHashCode.postValue(md5(jsonStr))
// }

fun handleConfig(): Map<String, ConfigLoadSchema> {
fun handleConfig(configPostSchema: ConfigPostSchema): Map<String, ConfigLoadSchema>? {
val screenWidth = ScreenUtils.getScreenWidth()
val screenHeight = ScreenUtils.getScreenHeight()

return configReadSchemaList.associate { config ->
return configPostSchema.configReadSchemaList?.associate { config ->
val newSkipTexts = config.skipTexts?.map { skipText ->
val clickRect = skipText.click?.let { c ->
convertClick(c, screenWidth, screenHeight)
Expand Down
27 changes: 15 additions & 12 deletions app/src/main/java/com/android/skip/data/config/ConfigViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.android.skip.dataclass.ConfigPostSchema
import com.android.skip.dataclass.ConfigState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand All @@ -13,32 +15,33 @@ class ConfigViewModel @Inject constructor(
private val configReadRepository: ConfigReadRepository,
private val configLoadRepository: ConfigLoadRepository
) : ViewModel() {
var configHashCode: LiveData<String> = configReadRepository.configHashCode
var configPostState: LiveData<ConfigPostSchema> = configReadRepository.configPostState

private val observer = Observer<String?> {
if (it != null) {
val configMap = configReadRepository.handleConfig()
configLoadRepository.loadConfig(configMap)
private val observer = Observer<ConfigPostSchema> {
if (it.status == ConfigState.SUCCESS) {
val configMap = configReadRepository.handleConfig(it)
if (configMap != null) {
configLoadRepository.loadConfig(configMap)
}
}
}

init {
configReadRepository.configHashCode.observeForever(observer)
configReadRepository.configPostState.observeForever(observer)
}

// fun readConfig(context: Context) = configReadRepository.readConfig(context)
fun readConfig() {
viewModelScope.launch {
val jsonStr = configReadRepository.readConfig()
configReadRepository.changeConfigHashCode(jsonStr)
val configPostSchema = configReadRepository.readConfig()
configReadRepository.changeConfigPostState(configPostSchema)
}
}

fun changeConfigHashCode(jsonStrOrNull: String?) =
configReadRepository.changeConfigHashCode(jsonStrOrNull)
fun changeConfigHashCode(configPostSchema: ConfigPostSchema) =
configReadRepository.changeConfigPostState(configPostSchema)

override fun onCleared() {
super.onCleared()
configReadRepository.configHashCode.removeObserver(observer)
configReadRepository.configPostState.removeObserver(observer)
}
}
25 changes: 0 additions & 25 deletions app/src/main/java/com/android/skip/data/network/MyApiNetwork.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
package com.android.skip.data.network

import com.android.skip.data.network.api.MyApiService
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

@Singleton
class MyApiNetwork @Inject constructor() {
private val myApiService = ServiceCreator.create(MyApiService::class.java)

suspend fun fetchSkipConfigV3() = myApiService.getSkipConfigV3().await()

suspend fun fetchConfigFromUrl(url: String): String {
val response = myApiService.getConfigFromUrl(url)
if (response.isSuccessful) {
Expand All @@ -24,21 +16,4 @@ class MyApiNetwork @Inject constructor() {
throw RuntimeException("Failed with error code: ${response.code()}")
}
}

private suspend fun <T> Call<T>.await(): T{
return suspendCoroutine { continuation->
enqueue(object: Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
val body = response.body()
if (body != null) continuation.resume(body)
else continuation.resumeWithException(RuntimeException("response body is null"))
}

override fun onFailure(call: Call<T>, t: Throwable) {
continuation.resumeWithException(t)
}

})
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package com.android.skip.data.network.api

import retrofit2.Call
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Url

interface MyApiService {
@GET("/skip_config_v3.yaml")
fun getSkipConfigV3(): Call<String>

@GET
suspend fun getConfigFromUrl(@Url url: String): Response<String>
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/android/skip/dataclass/ConfigPostSchema.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.android.skip.dataclass

enum class ConfigState {
SUCCESS, PENDING, FAIL
}

data class ConfigPostSchema(
val status: ConfigState,
val value: String,
val configReadSchemaList: List<ConfigReadSchema>? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,28 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import com.android.skip.R
import com.android.skip.data.config.ConfigViewModel
import com.android.skip.dataclass.ConfigPostSchema
import com.android.skip.dataclass.ConfigState
import com.android.skip.ui.components.FlatButton
import com.android.skip.ui.components.RowContent
import com.blankj.utilcode.util.StringUtils.getString

@Composable
fun ConfigVersionButton(configViewModel: ConfigViewModel) {
val configVersion = configViewModel.configHashCode.observeAsState()
val configState = configViewModel.configPostState.observeAsState()

FlatButton(content = {
RowContent(
title = R.string.about_config_version,
subTitle = if (configVersion.value == null) R.string.checking else configVersion.value
subTitle = configState.value?.value
)
}, onClick = {
configViewModel.changeConfigHashCode(null)
configViewModel.changeConfigHashCode(
ConfigPostSchema(
ConfigState.PENDING,
getString(R.string.checking)
)
)
configViewModel.readConfig()
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ package com.android.skip.ui.alive.notificationbar

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.android.skip.R
import com.android.skip.util.DataStoreUtils
import com.blankj.utilcode.util.StringUtils.getString
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class NotificationBarRepository @Inject constructor(){
private val _enable = MutableLiveData(false)
class NotificationBarRepository @Inject constructor() {
private val _enable = MutableLiveData(
DataStoreUtils.getSyncData(getString(R.string.store_resident_notification_bar), false)
)
val enable: LiveData<Boolean> = _enable

fun changeEnable(enable: Boolean) {
_enable.postValue(enable)
DataStoreUtils.putSyncData(getString(R.string.store_resident_notification_bar), enable)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.android.skip.ui.settings

import android.content.Intent
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.viewModels
Expand All @@ -13,6 +14,7 @@ import com.android.skip.ui.settings.strict.StrictViewModel
import com.android.skip.ui.settings.tip.TipButton
import com.android.skip.ui.settings.tip.TipViewModel
import com.android.skip.ui.theme.AppTheme
import com.android.skip.ui.webview.WebViewActivity
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
Expand All @@ -32,7 +34,12 @@ class SettingsActivity : AppCompatActivity() {
ScaffoldPage(R.string.settings, { finish() }, {
TipButton(tipViewModel)
StrictButton(strictViewModel)
CustomButton(configViewModel)
CustomButton(configViewModel) {
val intent = Intent(this, WebViewActivity::class.java).apply {
putExtra("url", R.string.settings_custom_config_url)
}
startActivity(intent)
}
})
}
}
Expand Down
Loading

0 comments on commit e3fe8a5

Please sign in to comment.