owenclave / app/src/main/java/io/nekohasekai/sagernet/group/GroupUpdater.kt

github - dev - back to tree - upstream
/****************************************************************************** * * * Copyright (C) 2021 by nekohasekai * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ******************************************************************************/ package io.nekohasekai.sagernet.group import io.nekohasekai.sagernet.R import io.nekohasekai.sagernet.SagerNet import io.nekohasekai.sagernet.SubscriptionType import io.nekohasekai.sagernet.database.DataStore import io.nekohasekai.sagernet.database.GroupManager import io.nekohasekai.sagernet.database.ProxyGroup import io.nekohasekai.sagernet.database.SubscriptionBean import io.nekohasekai.sagernet.ktx.* import kotlinx.coroutines.* import java.util.* import java.util.concurrent.atomic.AtomicInteger @Suppress("EXPERIMENTAL_API_USAGE") abstract class GroupUpdater { abstract suspend fun doUpdate( proxyGroup: ProxyGroup, subscription: SubscriptionBean, userInterface: GroupManager.Interface?, byUser: Boolean ) data class Progress( var max: Int ) { var progress by AtomicInteger() } companion object { val updating = Collections.synchronizedSet(mutableSetOf()) val progress = Collections.synchronizedMap(mutableMapOf()) fun startUpdate(proxyGroup: ProxyGroup, byUser: Boolean) { runOnDefaultDispatcher { executeUpdate(proxyGroup, byUser) } } suspend fun executeUpdate(proxyGroup: ProxyGroup, byUser: Boolean): Boolean { return coroutineScope { if (!updating.add(proxyGroup.id)) cancel() GroupManager.postReload(proxyGroup.id) val subscription = proxyGroup.subscription!! val connected = SagerNet.started && DataStore.startedProfile > 0 val userInterface = GroupManager.userInterface if (subscription.updateWhenConnectedOnly && !connected) { if (!byUser || userInterface == null) { finishUpdate(proxyGroup) cancel() } else { if (!userInterface.confirm(app.getString(R.string.update_subscription_warning))) { finishUpdate(proxyGroup) cancel() } } } try { when (subscription.type) { SubscriptionType.RAW -> RawUpdater SubscriptionType.SIP008 -> SIP008Updater SubscriptionType.AGE -> AgeUpdater else -> error("unsupported") }.doUpdate(proxyGroup, subscription, userInterface, byUser) true } catch (e: Throwable) { Logs.w(e) if (byUser && userInterface != null) { userInterface.onUpdateFailure(proxyGroup, e.readableMessage) } finishUpdate(proxyGroup) false } } } suspend fun finishUpdate(proxyGroup: ProxyGroup) { updating.remove(proxyGroup.id) progress.remove(proxyGroup.id) GroupManager.postUpdate(proxyGroup) } } }