diff --git a/app/src/main/java/com/vanced/manager/core/App.kt b/app/src/main/java/com/vanced/manager/core/App.kt index 92466b33..e0727a57 100644 --- a/app/src/main/java/com/vanced/manager/core/App.kt +++ b/app/src/main/java/com/vanced/manager/core/App.kt @@ -11,13 +11,15 @@ import com.crowdin.platform.data.remote.NetworkType import com.downloader.PRDownloader import com.vanced.manager.BuildConfig.* import com.vanced.manager.utils.InternetTools.loadJson +import kotlinx.coroutines.* open class App: Application() { private val prefs by lazy { getDefaultSharedPreferences(this) } + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) override fun onCreate() { - loadJson(this) + scope.launch { loadJson(this@App) } super.onCreate() PRDownloader.initialize(this) @@ -46,6 +48,4 @@ open class App: Application() { super.onConfigurationChanged(newConfig) Crowdin.onConfigurationChanged() } - - } diff --git a/app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt index 55d9ffe4..bf2872a4 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt @@ -13,22 +13,21 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -object MicrogDownloader { +object MicrogDownloader : CoroutineScope by CoroutineScope(Dispatchers.IO) { fun downloadMicrog( context: Context, - ) { - CoroutineScope(Dispatchers.IO).launch { - val url = microg.get()?.string("url") + ) = launch { + val url = microg.get()?.string("url") - downloadProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("microg")?.path, "microg.apk") - .build() - .setOnStartOrResumeListener { - downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, url?.let { getFileNameFromUrl(it) })) - } - .setOnProgressListener { progress -> - downloadProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt()) - } + downloadProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("microg")?.path, "microg.apk") + .build() + .setOnStartOrResumeListener { + downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, url?.let { getFileNameFromUrl(it) })) + } + .setOnProgressListener { progress -> + downloadProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt()) + } .start(object : OnDownloadListener { override fun onDownloadComplete() { startMicrogInstall(context) @@ -40,12 +39,10 @@ object MicrogDownloader { }) } - } fun startMicrogInstall(context: Context) { downloadProgress.get()?.installing?.set(true) downloadProgress.get()?.reset() install("${context.getExternalFilesDir("microg")}/microg.apk", context) } - } diff --git a/app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt index 44570a05..ea8fb719 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt @@ -1,7 +1,7 @@ package com.vanced.manager.core.downloader import android.content.Context -import androidx.preference.PreferenceManager.getDefaultSharedPreferences +import androidx.preference.PreferenceManager.* import com.downloader.Error import com.downloader.OnDownloadListener import com.downloader.PRDownloader @@ -22,8 +22,9 @@ import com.vanced.manager.utils.PackageHelper.installMusicRoot import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlin.coroutines.suspendCoroutine -object MusicDownloader { +object MusicDownloader: CoroutineScope by CoroutineScope(Dispatchers.IO) { private var variant: String? = null private var version: String? = null @@ -45,60 +46,56 @@ object MusicDownloader { } private fun downloadApk(context: Context, apk: String = "music") { - CoroutineScope(Dispatchers.IO).launch { - val url = - if (apk == "stock") - "$baseurl/stock/${getArch()}.apk" - else - "$baseurl/$variant.apk" - - downloadProgress.get()?.currentDownload = PRDownloader.download(url, downloadPath, getFileNameFromUrl(url)) - .build() - .setOnStartOrResumeListener { - downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, getFileNameFromUrl(url))) - } - .setOnProgressListener { progress -> - downloadProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt()) - } - .start(object : OnDownloadListener { - override fun onDownloadComplete() { - if (variant == "root" && apk != "stock") { - downloadApk(context, "stock") - return - } - - when (apk) { - "music" -> { - if (variant == "root") { - if (validateTheme(downloadPath!!, "root", hashUrl!!, context)) { - if (downloadStockCheck(musicRootPkg, versionCode!!, context)) - downloadApk(context, "stock") - else - startMusicInstall(context) - } else { - downloadApk(context, apk) - } - } else - startMusicInstall(context) + launch { + val url = if (apk == "stock") "$baseurl/stock/${getArch()}.apk" else "$baseurl/$variant.apk" + suspendCoroutine { + downloadProgress.get()?.currentDownload = PRDownloader.download(url, downloadPath, getFileNameFromUrl(url)) + .build() + .setOnStartOrResumeListener { + downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, getFileNameFromUrl(url))) + } + .setOnProgressListener { progress -> + downloadProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt()) + } + .start(object : OnDownloadListener { + override fun onDownloadComplete() { + if (variant == "root" && apk != "stock") { + downloadApk(context, "stock") // recursive in coroutine its so bad... + return } + + when (apk) { + "music" -> { + if (variant == "root") { + if (validateTheme(downloadPath!!, "root", hashUrl!!, context)) { + if (downloadStockCheck(musicRootPkg, versionCode!!, context)) + downloadApk(context, "stock") + else + startMusicInstall(context) + } else { + downloadApk(context, apk) + } + } else + startMusicInstall(context) + } + } + + startMusicInstall(context) } - startMusicInstall(context) - } + override fun onError(error: Error?) { + if (baseurl != backupUrl) { + baseurl = "$backupUrl/music/v$version" + downloadApk(context, apk) + return + } - override fun onError(error: Error?) { - if (baseurl != backupUrl) { - baseurl = "$backupUrl/music/v$version" - downloadApk(context, apk) - return + downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.error_downloading, "Music")) } - - downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.error_downloading, "Music")) - } - }) + }) + } } - } fun startMusicInstall(context: Context) { @@ -109,5 +106,4 @@ object MusicDownloader { else install("${context.getExternalFilesDir("music/nonroot")}/nonroot.apk", context) } - } diff --git a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt index d906685d..4c96d677 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt @@ -28,7 +28,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.io.File -object VancedDownloader { +object VancedDownloader: CoroutineScope by CoroutineScope(Dispatchers.IO) { private lateinit var prefs: SharedPreferences private lateinit var defPrefs: SharedPreferences @@ -73,7 +73,7 @@ object VancedDownloader { context: Context, type: String = "theme" ) { - CoroutineScope(Dispatchers.IO).launch { + launch { val url = when (type) { "theme" -> "$themePath/$theme.apk" @@ -160,8 +160,4 @@ object VancedDownloader { else installVanced(context) } - - - - -} +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt index a949ec4e..7a52a35d 100644 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil +import androidx.lifecycle.lifecycleScope import androidx.preference.PreferenceManager.getDefaultSharedPreferences import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.vanced.manager.R @@ -13,6 +14,7 @@ import com.vanced.manager.core.downloader.MusicDownloader.startMusicInstall import com.vanced.manager.core.downloader.VancedDownloader.startVancedInstall import com.vanced.manager.databinding.DialogInstallationFilesDetectedBinding import com.vanced.manager.utils.Extensions.show +import kotlinx.coroutines.launch class InstallationFilesDetectedDialog(private val app: String) : BottomSheetDialogFragment() { diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt index 5e36ce19..cf90fe12 100644 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt @@ -12,6 +12,7 @@ import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.downloader.PRDownloader import com.vanced.manager.R @@ -19,6 +20,7 @@ import com.vanced.manager.databinding.DialogManagerUpdateBinding import com.vanced.manager.utils.DownloadHelper.downloadManager import com.vanced.manager.utils.DownloadHelper.downloadProgress import com.vanced.manager.utils.InternetTools.isUpdateAvailable +import kotlinx.coroutines.launch class ManagerUpdateDialog( private val forceUpdate: Boolean @@ -51,15 +53,18 @@ class ManagerUpdateDialog( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - if (forceUpdate) { - binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient) - downloadManager(requireActivity()) - } else - checkUpdates() + lifecycleScope.launch { + if (forceUpdate) { + binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient) + downloadManager(requireActivity()) + } else { + checkUpdates() + } - binding.managerUpdateCancel.setOnClickListener { - PRDownloader.cancel(downloadProgress.get()!!.currentDownload) - dismiss() + binding.managerUpdateCancel.setOnClickListener { + PRDownloader.cancel(downloadProgress.get()!!.currentDownload) + dismiss() + } } } @@ -68,12 +73,13 @@ class ManagerUpdateDialog( registerReceiver() } - private fun checkUpdates() { + private suspend fun checkUpdates() { if (isUpdateAvailable()) { binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient) downloadManager(requireActivity()) - } else + } else { binding.managerUpdatePatient.text = requireActivity().getString(R.string.update_not_found) + } } private fun registerReceiver() { diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt index 2e2a67d3..05dfdbce 100644 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt @@ -10,11 +10,13 @@ import android.widget.EditText import android.widget.TextView import androidx.core.content.edit import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope import androidx.preference.PreferenceManager.getDefaultSharedPreferences import com.google.android.material.button.MaterialButton import com.vanced.manager.R import com.vanced.manager.utils.Extensions.fetchData import com.vanced.manager.utils.InternetTools.baseUrl +import kotlinx.coroutines.launch class URLChangeDialog : DialogFragment() { @@ -46,9 +48,10 @@ class URLChangeDialog : DialogFragment() { } private fun saveUrl(url: String) { - getDefaultSharedPreferences(requireActivity()).edit { putString("install_url", url) } - requireActivity().fetchData() - dismiss() + lifecycleScope.launch { + getDefaultSharedPreferences(requireActivity()).edit { putString("install_url", url) } + requireActivity().fetchData() + dismiss() + } } - } diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt index ddfa8bf0..929acdca 100644 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt @@ -12,6 +12,8 @@ import android.widget.LinearLayout import android.widget.Toast import androidx.core.content.edit import androidx.core.content.res.ResourcesCompat +import androidx.lifecycle.coroutineScope +import androidx.lifecycle.lifecycleScope import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.button.MaterialButton import com.google.android.material.checkbox.MaterialCheckBox @@ -23,6 +25,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.* +import kotlin.coroutines.coroutineContext class VancedLanguageSelectionDialog : BottomSheetDialogFragment() { @@ -36,7 +39,6 @@ class VancedLanguageSelectionDialog : BottomSheetDialogFragment() { return inflater.inflate(R.layout.dialog_vanced_language_selection, container, false) } - @ExperimentalStdlibApi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) langs = vanced.get()?.array("langs")?.value ?: mutableListOf("null") @@ -60,9 +62,8 @@ class VancedLanguageSelectionDialog : BottomSheetDialogFragment() { } } - @ExperimentalStdlibApi private fun loadBoxes(ll: LinearLayout) { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch { // default Main //// But why is it here? val langPrefs = prefs.getString("lang", getDefaultVancedLanguages()) if (this@VancedLanguageSelectionDialog::langs.isInitialized) { if (!langs.contains("null")) { @@ -78,8 +79,9 @@ class VancedLanguageSelectionDialog : BottomSheetDialogFragment() { ll.addView(box, MATCH_PARENT, WRAP_CONTENT) } } - } else + } else { loadBoxes(ll) + } } } diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt index ac602fcc..adeb7651 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt @@ -10,6 +10,7 @@ import androidx.core.content.ContextCompat.startActivity import androidx.databinding.ObservableField import androidx.fragment.app.FragmentActivity import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import androidx.preference.PreferenceManager.getDefaultSharedPreferences import com.crowdin.platform.Crowdin import com.google.android.material.button.MaterialButton @@ -35,6 +36,7 @@ import com.vanced.manager.utils.PackageHelper.musicApkExists import com.vanced.manager.utils.PackageHelper.uninstallApk import com.vanced.manager.utils.PackageHelper.uninstallRootApk import com.vanced.manager.utils.PackageHelper.vancedInstallFilesExist +import kotlinx.coroutines.launch open class HomeViewModel(private val activity: FragmentActivity): ViewModel() { @@ -48,10 +50,12 @@ open class HomeViewModel(private val activity: FragmentActivity): ViewModel() { val manager = ObservableField() fun fetchData() { - activity.setRefreshing(true) - loadJson(activity) - Crowdin.forceUpdate(activity) - activity.setRefreshing(false) + viewModelScope.launch { + activity.setRefreshing(true) + loadJson(activity) + Crowdin.forceUpdate(activity) + activity.setRefreshing(false) + } } private val microgToast = Toast.makeText(activity, R.string.no_microg, Toast.LENGTH_LONG) @@ -122,7 +126,13 @@ open class HomeViewModel(private val activity: FragmentActivity): ViewModel() { } - fun uninstallPackage(pkg: String) = if (prefs.getString("vanced_variant", "nonroot") == "root" && uninstallRootApk(pkg)) activity.fetchData() else uninstallApk(pkg, activity) + fun uninstallPackage(pkg: String) { + if (prefs.getString("vanced_variant", "nonroot") == "root" && uninstallRootApk(pkg)) { + viewModelScope.launch { activity.fetchData() } + } else { + uninstallApk(pkg, activity) + } + } init { activity.setRefreshing(true) @@ -134,5 +144,4 @@ open class HomeViewModel(private val activity: FragmentActivity): ViewModel() { manager.set(DataModel(InternetTools.manager, activity, managerPkg, activity.getString(R.string.app_name), ContextCompat.getDrawable(activity, R.mipmap.ic_launcher))) activity.setRefreshing(false) } - } diff --git a/app/src/main/java/com/vanced/manager/utils/AppUtils.kt b/app/src/main/java/com/vanced/manager/utils/AppUtils.kt index 2641598b..1649a799 100644 --- a/app/src/main/java/com/vanced/manager/utils/AppUtils.kt +++ b/app/src/main/java/com/vanced/manager/utils/AppUtils.kt @@ -15,7 +15,7 @@ import java.io.File import java.io.IOException import java.security.MessageDigest -object AppUtils { +object AppUtils: CoroutineScope by CoroutineScope(Dispatchers.IO) { const val vancedPkg = "com.vanced.android.youtube" const val vancedRootPkg = "com.google.android.youtube" @@ -24,25 +24,25 @@ object AppUtils { const val microgPkg = "com.mgoogle.android.gms" const val managerPkg = APPLICATION_ID - fun sendRefresh(context: Context) { - CoroutineScope(Dispatchers.IO).launch { + fun sendRefresh(context: Context): Job { + return launch { delay(700) LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(HomeFragment.REFRESH_HOME)) } } - fun sendCloseDialog(context: Context) { + fun sendCloseDialog(context: Context): Job { downloadProgress.get()?.installing?.set(false) - CoroutineScope(Dispatchers.IO).launch { + return launch { delay(700) LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(AppDownloadDialog.CLOSE_DIALOG)) } } - fun sendFailure(status: Int, context: Context) { + fun sendFailure(status: Int, context: Context): Job { downloadProgress.get()?.installing?.set(false) //Delay error broadcast until activity (and fragment) get back to the screen - CoroutineScope(Dispatchers.IO).launch { + return launch { delay(700) val intent = Intent(HomeFragment.INSTALL_FAILED) intent.putExtra("errorMsg", getErrorMessage(status, context)) @@ -50,9 +50,9 @@ object AppUtils { } } - fun sendFailure(error: MutableList, context: Context) { + fun sendFailure(error: MutableList, context: Context): Job { downloadProgress.get()?.installing?.set(false) - CoroutineScope(Dispatchers.IO).launch { + return launch { delay(700) val intent = Intent(HomeFragment.INSTALL_FAILED) intent.putExtra("errorMsg", getErrorMessage(error.joinToString(), context)) @@ -134,6 +134,4 @@ object AppUtils { context.getString(R.string.installation_failed) } } - - -} +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt b/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt index 6d9b61d7..faeba16b 100644 --- a/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt +++ b/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt @@ -16,9 +16,8 @@ import com.downloader.PRDownloader import com.vanced.manager.R import com.vanced.manager.model.ProgressModel import com.vanced.manager.utils.AppUtils.sendCloseDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.File object DownloadHelper { @@ -41,8 +40,8 @@ object DownloadHelper { downloadProgress.set(ProgressModel()) } - fun downloadManager(context: Context) { - CoroutineScope(Dispatchers.IO).launch { + suspend fun downloadManager(context: Context) = + withContext(Dispatchers.IO) { val url = "https://github.com/YTVanced/VancedManager/releases/latest/download/manager.apk" downloadProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("manager")?.path, "manager.apk") .build() @@ -82,6 +81,4 @@ object DownloadHelper { }) } - } - } diff --git a/app/src/main/java/com/vanced/manager/utils/Extensions.kt b/app/src/main/java/com/vanced/manager/utils/Extensions.kt index 6c3fdd45..2d5c5754 100644 --- a/app/src/main/java/com/vanced/manager/utils/Extensions.kt +++ b/app/src/main/java/com/vanced/manager/utils/Extensions.kt @@ -28,7 +28,7 @@ object Extensions { show(activity.supportFragmentManager, "") } - fun Activity.fetchData() { + suspend fun Activity.fetchData() { val refreshLayout = findViewById(R.id.home_refresh) setRefreshing(true, refreshLayout) loadJson(this) diff --git a/app/src/main/java/com/vanced/manager/utils/InternetTools.kt b/app/src/main/java/com/vanced/manager/utils/InternetTools.kt index d189c051..b80614c2 100644 --- a/app/src/main/java/com/vanced/manager/utils/InternetTools.kt +++ b/app/src/main/java/com/vanced/manager/utils/InternetTools.kt @@ -7,16 +7,15 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.core.content.ContextCompat import androidx.core.net.toUri import androidx.databinding.ObservableField -import androidx.preference.PreferenceManager.getDefaultSharedPreferences +import androidx.preference.PreferenceManager.* import com.beust.klaxon.JsonArray import com.beust.klaxon.JsonObject import com.vanced.manager.BuildConfig import com.vanced.manager.R import com.vanced.manager.utils.AppUtils.generateChecksum import com.vanced.manager.utils.Extensions.getDefaultPrefs -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.File import java.text.SimpleDateFormat import java.util.* @@ -49,19 +48,20 @@ object InternetTools { context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri()).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) } - fun getFileNameFromUrl(url: String) = url.substring(url.lastIndexOf('/')+1, url.length) + fun getFileNameFromUrl(url: String) = url.substring(url.lastIndexOf('/') + 1, url.length) - fun loadJson(context: Context) = CoroutineScope(Dispatchers.IO).launch { - val installUrl = context.getDefaultPrefs().getString("install_url", baseUrl) - val latest = JsonHelper.getJson("$installUrl/latest.json?fetchTime=${SimpleDateFormat("HHmmss", Locale.ROOT)}") - val versions = JsonHelper.getJson("$installUrl/versions.json?fetchTime=${SimpleDateFormat("HHmmss", Locale.ROOT)}") + suspend fun loadJson(context: Context) = + withContext(Dispatchers.IO) { + val installUrl = context.getDefaultPrefs().getString("install_url", baseUrl) + val latest = JsonHelper.getJson("$installUrl/latest.json?fetchTime=${SimpleDateFormat("HHmmss", Locale.ROOT)}") + val versions = JsonHelper.getJson("$installUrl/versions.json?fetchTime=${SimpleDateFormat("HHmmss", Locale.ROOT)}") // braveTiers.apply { // set(getJson("$installUrl/sponsor.json")) // notifyChange() // } - vanced.apply { - set(latest?.obj("vanced")) + vanced.apply { + set(latest?.obj("vanced")) notifyChange() } vancedVersions.set(versions?.array("vanced"))