diff --git a/app/src/main/kotlin/li/songe/gkd/MainViewModel.kt b/app/src/main/kotlin/li/songe/gkd/MainViewModel.kt index e564fbac7..d86ec3b51 100644 --- a/app/src/main/kotlin/li/songe/gkd/MainViewModel.kt +++ b/app/src/main/kotlin/li/songe/gkd/MainViewModel.kt @@ -3,7 +3,7 @@ package li.songe.gkd import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.SubsItem @@ -17,8 +17,6 @@ import li.songe.gkd.util.logZipDir import li.songe.gkd.util.newVersionApkDir import li.songe.gkd.util.snapshotZipDir import li.songe.gkd.util.storeFlow -import li.songe.gkd.util.subsIdToRawFlow -import li.songe.gkd.util.subsItemsFlow import li.songe.gkd.util.updateSubscription class MainViewModel : ViewModel() { @@ -34,23 +32,16 @@ class MainViewModel : ViewModel() { id = -2, order = -2, mtime = System.currentTimeMillis() ) viewModelScope.launchTry(Dispatchers.IO) { - subsItemsFlow.debounce(1000).collect { subsItems -> - if (!subsItems.any { s -> s.id == localSubsItem.id }) { - DbSet.subsItemDao.insert(localSubsItem) - } - } - } - viewModelScope.launchTry(Dispatchers.IO) { - subsIdToRawFlow.debounce(1000).collect { subsIdToRaw -> - if (!subsIdToRaw.containsKey(localSubsItem.id)) { - updateSubscription( - RawSubscription( - id = localSubsItem.id, - name = "本地订阅", - version = 0 - ) + val subsItems = DbSet.subsItemDao.query().first() + if (!subsItems.any { s -> s.id == localSubsItem.id }) { + updateSubscription( + RawSubscription( + id = localSubsItem.id, + name = "本地订阅", + version = 0 ) - } + ) + DbSet.subsItemDao.insert(localSubsItem) } } diff --git a/app/src/main/kotlin/li/songe/gkd/service/GkdAbService.kt b/app/src/main/kotlin/li/songe/gkd/service/GkdAbService.kt index 39823e226..825fd1705 100644 --- a/app/src/main/kotlin/li/songe/gkd/service/GkdAbService.kt +++ b/app/src/main/kotlin/li/songe/gkd/service/GkdAbService.kt @@ -17,9 +17,6 @@ import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityNodeInfo import com.blankj.utilcode.util.LogUtils import com.blankj.utilcode.util.ScreenUtils -import io.ktor.client.call.body -import io.ktor.client.request.get -import io.ktor.client.statement.bodyAsText import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview @@ -39,25 +36,19 @@ import li.songe.gkd.data.ActionResult import li.songe.gkd.data.AppRule import li.songe.gkd.data.AttrInfo import li.songe.gkd.data.GkdAction -import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.RpcError import li.songe.gkd.data.RuleStatus -import li.songe.gkd.data.SubsVersion import li.songe.gkd.data.getActionFc -import li.songe.gkd.db.DbSet import li.songe.gkd.debug.SnapshotExt import li.songe.gkd.shizuku.shizukuIsSafeOK import li.songe.gkd.shizuku.useSafeGetTasksFc import li.songe.gkd.shizuku.useShizukuAliveState import li.songe.gkd.util.VOLUME_CHANGED_ACTION -import li.songe.gkd.util.client +import li.songe.gkd.util.checkSubsUpdate import li.songe.gkd.util.launchTry import li.songe.gkd.util.map import li.songe.gkd.util.storeFlow -import li.songe.gkd.util.subsIdToRawFlow -import li.songe.gkd.util.subsItemsFlow import li.songe.gkd.util.toast -import li.songe.gkd.util.updateSubscription import li.songe.selector.Selector import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -325,46 +316,6 @@ class GkdAbService : CompositionAbService({ } } - fun checkSubsUpdate() = scope.launchTry(Dispatchers.IO) { // 自动从网络更新订阅文件 - LogUtils.d("开始自动检测更新") - subsItemsFlow.value.forEach { subsItem -> - if (subsItem.updateUrl == null) return@forEach - try { - val oldSubsRaw = subsIdToRawFlow.value[subsItem.id] - if (oldSubsRaw?.checkUpdateUrl != null) { - try { - val subsVersion = - client.get(oldSubsRaw.checkUpdateUrl).body() - LogUtils.d("快速检测更新成功", subsVersion) - if (subsVersion.id == oldSubsRaw.id && subsVersion.version <= oldSubsRaw.version) { - return@forEach - } - } catch (e: Exception) { - LogUtils.d("快速检测更新失败", subsItem, e) - } - } - val newSubsRaw = RawSubscription.parse( - client.get(oldSubsRaw?.updateUrl ?: subsItem.updateUrl).bodyAsText() - ) - if (newSubsRaw.id != subsItem.id) { - return@forEach - } - if (oldSubsRaw != null && newSubsRaw.version <= oldSubsRaw.version) { - return@forEach - } - updateSubscription(newSubsRaw) - val newItem = subsItem.copy( - mtime = System.currentTimeMillis() - ) - DbSet.subsItemDao.update(newItem) - LogUtils.d("更新订阅文件:${newSubsRaw.name}") - } catch (e: Exception) { - e.printStackTrace() - LogUtils.d("检测更新失败", e) - } - } - } - var lastUpdateSubsTime = 0L onAccessibilityEvent {// 借助 无障碍事件 触发自动检测更新 if (it.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {// 筛选降低判断频率 diff --git a/app/src/main/kotlin/li/songe/gkd/ui/home/HomeVm.kt b/app/src/main/kotlin/li/songe/gkd/ui/home/HomeVm.kt index 2c760cfab..e25a49ba7 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/home/HomeVm.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/home/HomeVm.kt @@ -171,7 +171,7 @@ class HomeVm @Inject constructor() : ViewModel() { var errorNum = 0 val oldSubItems = subsItemsFlow.value val newSubsItems = oldSubItems.mapNotNull { oldItem -> - if (oldItem.updateUrl == null) return@mapNotNull null + if (oldItem.updateUrl == null || oldItem.id < 0) return@mapNotNull null val oldSubsRaw = subsIdToRawFlow.value[oldItem.id] try { if (oldSubsRaw?.checkUpdateUrl != null) { diff --git a/app/src/main/kotlin/li/songe/gkd/util/SubsState.kt b/app/src/main/kotlin/li/songe/gkd/util/SubsState.kt index 71181890f..4e4bcfb29 100644 --- a/app/src/main/kotlin/li/songe/gkd/util/SubsState.kt +++ b/app/src/main/kotlin/li/songe/gkd/util/SubsState.kt @@ -1,6 +1,9 @@ package li.songe.gkd.util import com.blankj.utilcode.util.LogUtils +import io.ktor.client.call.body +import io.ktor.client.request.get +import io.ktor.client.statement.bodyAsText import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.persistentListOf @@ -23,6 +26,7 @@ import li.songe.gkd.data.CategoryConfig import li.songe.gkd.data.GlobalRule import li.songe.gkd.data.RawSubscription import li.songe.gkd.data.SubsConfig +import li.songe.gkd.data.SubsVersion import li.songe.gkd.db.DbSet val subsItemsFlow by lazy { @@ -236,22 +240,68 @@ fun initSubsState() { subsItemsFlow.value appScope.launchTry(Dispatchers.IO) { if (subsFolder.exists() && subsFolder.isDirectory) { - val fileRegex = Regex("^-?\\d+\\.json$") - val files = - subsFolder.listFiles { f -> f.isFile && f.name.matches(fileRegex) } ?: emptyArray() - val subscriptions = files.mapNotNull { f -> - try { - RawSubscription.parse(f.readText()) - } catch (e: Exception) { - LogUtils.d("加载订阅文件失败", e) - null + updateSubsFileMutex.withLock { + val fileRegex = Regex("^-?\\d+\\.json$") + val files = + subsFolder.listFiles { f -> f.isFile && f.name.matches(fileRegex) } + ?: emptyArray() + val subscriptions = files.mapNotNull { f -> + try { + RawSubscription.parse(f.readText()) + } catch (e: Exception) { + LogUtils.d("加载订阅文件失败", e) + null + } + } + val newMap = subsIdToRawFlow.value.toMutableMap() + subscriptions.forEach { s -> + newMap[s.id] = s } + subsIdToRawFlow.value = newMap.toImmutableMap() } - val newMap = subsIdToRawFlow.value.toMutableMap() - subscriptions.forEach { s -> - newMap[s.id] = s + } + } +} + +fun checkSubsUpdate() = appScope.launchTry(Dispatchers.IO) { // 自动从网络更新订阅文件 + updateSubsFileMutex.withLock { + LogUtils.d("开始自动检测更新") + subsItemsFlow.value.forEach { subsItem -> + if (subsItem.updateUrl == null) return@forEach + try { + val oldSubsRaw = subsIdToRawFlow.value[subsItem.id] + if (oldSubsRaw?.checkUpdateUrl != null) { + try { + val subsVersion = + client.get(oldSubsRaw.checkUpdateUrl).body() + LogUtils.d("快速检测更新成功", subsVersion) + if (subsVersion.id == oldSubsRaw.id && subsVersion.version <= oldSubsRaw.version) { + return@forEach + } + } catch (e: Exception) { + LogUtils.d("快速检测更新失败", subsItem, e) + } + } + val newSubsRaw = RawSubscription.parse( + client.get(oldSubsRaw?.updateUrl ?: subsItem.updateUrl).bodyAsText() + ) + if (newSubsRaw.id != subsItem.id) { + return@forEach + } + if (oldSubsRaw != null && newSubsRaw.version <= oldSubsRaw.version) { + return@forEach + } + updateSubscription(newSubsRaw) + val newItem = subsItem.copy( + mtime = System.currentTimeMillis() + ) + DbSet.subsItemDao.update(newItem) + LogUtils.d("更新订阅文件:${newSubsRaw.name}") + } catch (e: Exception) { + e.printStackTrace() + LogUtils.d("检测更新失败", e) } - subsIdToRawFlow.value = newMap.toImmutableMap() } + LogUtils.d("自动检测更新结束") } -} \ No newline at end of file +}