From 5ec443916bc9f7bf3e2e5d63f1c1f9992f1a058e Mon Sep 17 00:00:00 2001 From: Martin Filo Date: Wed, 5 Apr 2023 00:47:22 +0200 Subject: [PATCH] feat: add remote sync capability - update scheduling logic --- .../cloudstream3/syncproviders/BackupAPI.kt | 85 +++++++++++++++++-- .../syncproviders/providers/GoogleDriveApi.kt | 60 +++++++------ .../cloudstream3/ui/player/GeneratorPlayer.kt | 3 +- .../ui/settings/SettingsGeneral.kt | 13 ++- .../ui/settings/SettingsPlayer.kt | 3 +- .../ui/settings/SettingsProviders.kt | 3 +- .../cloudstream3/ui/settings/SettingsUI.kt | 3 +- .../ui/settings/SettingsUpdates.kt | 3 +- .../ui/setup/SetupFragmentLanguage.kt | 3 +- .../ui/setup/SetupFragmentLayout.kt | 3 +- .../ui/setup/SetupFragmentMedia.kt | 3 +- .../ui/setup/SetupFragmentProviderLanguage.kt | 3 +- .../ui/subtitles/SubtitlesFragment.kt | 2 + .../lagradost/cloudstream3/utils/DataStore.kt | 11 +-- .../cloudstream3/utils/InAppUpdater.kt | 5 +- 15 files changed, 148 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/BackupAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/BackupAPI.kt index b184117b..6934273e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/BackupAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/BackupAPI.kt @@ -1,36 +1,103 @@ package com.lagradost.cloudstream3.syncproviders import android.content.Context +import android.content.SharedPreferences +import android.os.Handler +import android.os.Looper +import android.util.Log import com.lagradost.cloudstream3.mvvm.launchSafe import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.seconds interface BackupAPI { - private companion object { - val DEBOUNCE_TIME_MS = 15.seconds + companion object { + val UPLOAD_THROTTLE = 10.seconds + val DOWNLOAD_THROTTLE = 60.seconds + + fun createBackupScheduler() = Scheduler>( + UPLOAD_THROTTLE.inWholeMilliseconds + ) { input -> + if (input == null) { + throw IllegalStateException() + } + + AccountManager.BackupApis.forEach { it.addToQueue(input.first, input.second) } + } + + fun SharedPreferences.attachListener(isSettings: Boolean = true): Pair>> { + val scheduler = createBackupScheduler() + registerOnSharedPreferenceChangeListener { _, key -> + scheduler.work(Pair(key, isSettings)) + } + + return Pair( + this, + scheduler + ) + } } fun downloadSyncData() fun uploadSyncData() - fun shouldUpdate(): Boolean + fun shouldUpdate(changedKey: String, isSettings: Boolean): Boolean fun Context.mergeBackup(incomingData: String) fun Context.createBackup(loginData: LOGIN_DATA) var uploadJob: Job? - fun addToQueue() { - if (!shouldUpdate()) { + fun addToQueue(changedKey: String, isSettings: Boolean) { + if (!shouldUpdate(changedKey, isSettings)) { + Log.d("SYNC_API", "upload not required, data is same") return } - uploadJob?.cancel() + if (uploadJob != null && uploadJob!!.isActive) { + Log.d("SYNC_API", "upload is canceled, scheduling new") + uploadJob?.cancel() + } + + // we should ensure job will before app is closed uploadJob = CoroutineScope(Dispatchers.IO).launchSafe { - delay(DEBOUNCE_TIME_MS) + Log.d("SYNC_API", "upload is running now") uploadSyncData() } } -} \ No newline at end of file + + class Scheduler( + private val throttleTimeMs: Long, + private val onWork: (INPUT?) -> Unit + ) { + private companion object { + var SCHEDULER_ID = 1 + } + + private val id = SCHEDULER_ID++ + private val handler = Handler(Looper.getMainLooper()) + private var runnable: Runnable? = null + + fun work(input: INPUT? = null) { + Log.d("SYNC_API", "[$id] wants to schedule") + throttle(input) + } + + fun stop() { + runnable?.let { + handler.removeCallbacks(it) + runnable = null + } + } + + private fun throttle(input: INPUT?) { + stop() + + runnable = Runnable { + Log.d("SYNC_API", "[$id] schedule success") + onWork(input) + } + handler.postDelayed(runnable!!, throttleTimeMs) + } + } +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/GoogleDriveApi.kt b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/GoogleDriveApi.kt index 9d3858dd..d04d0ce0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/GoogleDriveApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/GoogleDriveApi.kt @@ -2,6 +2,7 @@ package com.lagradost.cloudstream3.syncproviders.providers import android.content.Context import android.net.Uri +import android.util.Log import androidx.browser.customtabs.CustomTabsIntent import androidx.fragment.app.FragmentActivity import com.fasterxml.jackson.module.kotlin.readValue @@ -19,7 +20,6 @@ import com.google.api.services.drive.model.File import com.lagradost.cloudstream3.AcraApplication import com.lagradost.cloudstream3.CommonActivity import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.mvvm.launchSafe import com.lagradost.cloudstream3.syncproviders.AuthAPI import com.lagradost.cloudstream3.syncproviders.BackupAPI import com.lagradost.cloudstream3.syncproviders.InAppOAuth2API @@ -29,11 +29,9 @@ import com.lagradost.cloudstream3.utils.BackupUtils import com.lagradost.cloudstream3.utils.BackupUtils.getBackup import com.lagradost.cloudstream3.utils.BackupUtils.restore import com.lagradost.cloudstream3.utils.DataStore +import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs import com.lagradost.cloudstream3.utils.DataStore.removeKey -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.delay import java.io.InputStream import java.util.* @@ -68,8 +66,6 @@ class GoogleDriveApi(index: Int) : var tempAuthFlow: AuthorizationCodeFlow? = null var lastBackupJson: String? = null - var continuousDownloadJob: Job? = null - ///////////////////////////////////////// ///////////////////////////////////////// // OAuth2API implementation @@ -104,7 +100,7 @@ class GoogleDriveApi(index: Int) : ) storeValue(K.TOKEN, googleTokenResponse) - startContinuousDownload() + runDownloader() tempAuthFlow = null return true @@ -118,22 +114,7 @@ class GoogleDriveApi(index: Int) : return } - startContinuousDownload() - } - - private fun startContinuousDownload() { - continuousDownloadJob?.cancel() - continuousDownloadJob = CoroutineScope(Dispatchers.IO).launchSafe { - if (uploadJob?.isActive == true) { - uploadJob!!.invokeOnCompletion { - startContinuousDownload() - } - } else { - downloadSyncData() - delay(1000 * 60) - startContinuousDownload() - } - } + runDownloader() } override fun loginInfo(): AuthAPI.LoginInfo? { @@ -192,13 +173,11 @@ class GoogleDriveApi(index: Int) : removeKey(it) } - restore( newData, restoreSettings = true, restoreDataStore = true ) - } // 🤮 @@ -227,6 +206,7 @@ class GoogleDriveApi(index: Int) : val drive = getDriveService()!! val fileName = loginData.fileName + val syncFileId = loginData.syncFileId val ioFile = java.io.File(AcraApplication.context?.cacheDir, fileName) lastBackupJson = getBackup().toJson() ioFile.writeText(lastBackupJson!!) @@ -250,7 +230,10 @@ class GoogleDriveApi(index: Int) : loginData.syncFileId = file.id } - storeValue(K.LOGIN_DATA, loginData) + // in case we had to create new file + if (syncFileId != loginData.syncFileId) { + storeValue(K.LOGIN_DATA, loginData) + } } override fun downloadSyncData() { @@ -273,11 +256,13 @@ class GoogleDriveApi(index: Int) : try { val inputStream: InputStream = existingFile.executeMediaAsInputStream() val content: String = inputStream.bufferedReader().use { it.readText() } + Log.d("SYNC_API", "downloadSyncData merging") ctx.mergeBackup(content) return } catch (_: Exception) { } } else { + Log.d("SYNC_API", "downloadSyncData file not exists") uploadSyncData() } } @@ -310,12 +295,14 @@ class GoogleDriveApi(index: Int) : override fun uploadSyncData() { val ctx = AcraApplication.context ?: return val loginData = getLatestLoginData() ?: return + Log.d("SYNC_API", "uploadSyncData createBackup") ctx.createBackup(loginData) } - override fun shouldUpdate(): Boolean { + override fun shouldUpdate(changedKey: String, isSettings: Boolean): Boolean { val ctx = AcraApplication.context ?: return false + // would be smarter to check properties, but its called once in UPLOAD_THROTTLE seconds val newBackup = ctx.getBackup().toJson() return lastBackupJson != newBackup } @@ -335,6 +322,25 @@ class GoogleDriveApi(index: Int) : ///////////////////////////////////////// ///////////////////////////////////////// // Internal + private val continuousDownloader = BackupAPI.Scheduler( + BackupAPI.DOWNLOAD_THROTTLE.inWholeMilliseconds + ) { + if (uploadJob?.isActive == true) { + uploadJob!!.invokeOnCompletion { + Log.d("SYNC_API", "upload is running, reschedule download") + runDownloader() + } + } else { + Log.d("SYNC_API", "downloadSyncData will run") + downloadSyncData() + runDownloader() + } + } + + private fun runDownloader() { + continuousDownloader.work() + } + private fun getCredentialsFromStore(): Credential? { val LOGIN_DATA = getLatestLoginData() val TOKEN = getValue(K.TOKEN) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index 46f2bca9..894dfdbf 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -28,6 +28,7 @@ import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.mvvm.* import com.lagradost.cloudstream3.subtitles.AbstractSubtitleEntities import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.subtitleProviders +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.player.CS3IPlayer.Companion.preferredAudioTrackLanguage import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.updateForcedEncoding import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType @@ -664,7 +665,7 @@ class GeneratorPlayer : FullScreenPlayer() { } sourceDialog.subtitles_click_settings?.setOnClickListener { - val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx).attachListener().first val prefNames = ctx.resources.getStringArray(R.array.subtitles_encoding_list) val prefValues = ctx.resources.getStringArray(R.array.subtitles_encoding_values) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt index 4aa859aa..05c956f0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt @@ -25,6 +25,7 @@ import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.network.initClient +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.EasterEggMonke import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom @@ -137,20 +138,26 @@ class SettingsGeneral : PreferenceFragmentCompat() { // Stores the real URI using download_path_key // Important that the URI is stored instead of filepath due to permissions. PreferenceManager.getDefaultSharedPreferences(context) - .edit().putString(getString(R.string.download_path_key), uri.toString()).apply() + .attachListener().first + .edit() + .putString(getString(R.string.download_path_key), uri.toString()) + .apply() // From URI -> File path // File path here is purely for cosmetic purposes in settings (file.filePath ?: uri.toString()).let { PreferenceManager.getDefaultSharedPreferences(context) - .edit().putString(getString(R.string.download_path_pref), it).apply() + .attachListener().first + .edit() + .putString(getString(R.string.download_path_pref), it) + .apply() } } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { hideKeyboard() setPreferencesFromResource(R.xml.settins_general, rootKey) - val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()).attachListener().first fun getCurrent(): MutableList { return getKey>(USER_PROVIDER_API)?.toMutableList() diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsPlayer.kt index e10a5a1a..e065ef12 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsPlayer.kt @@ -7,6 +7,7 @@ import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getFolderSize import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom @@ -27,7 +28,7 @@ class SettingsPlayer : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { hideKeyboard() setPreferencesFromResource(R.xml.settings_player, rootKey) - val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()).attachListener().first getPref(R.string.video_buffer_length_key)?.setOnPreferenceClickListener { val prefNames = resources.getStringArray(R.array.video_buffer_length_names) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsProviders.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsProviders.kt index 42a864a6..e791365b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsProviders.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsProviders.kt @@ -10,6 +10,7 @@ import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom @@ -30,7 +31,7 @@ class SettingsProviders : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { hideKeyboard() setPreferencesFromResource(R.xml.settings_providers, rootKey) - val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()).attachListener().first getPref(R.string.display_sub_key)?.setOnPreferenceClickListener { activity?.getApiDubstatusSettings()?.let { current -> diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt index e2fd24ca..b19c1ee5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt @@ -8,6 +8,7 @@ import androidx.preference.PreferenceManager import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.SearchQuality import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.search.SearchResultBuilder import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom @@ -28,7 +29,7 @@ class SettingsUI : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { hideKeyboard() setPreferencesFromResource(R.xml.settins_ui, rootKey) - val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext()).attachListener().first getPref(R.string.poster_ui_key)?.setOnPreferenceClickListener { val prefNames = resources.getStringArray(R.array.poster_ui_options) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUpdates.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUpdates.kt index f9ac3fee..3590e28e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUpdates.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUpdates.kt @@ -14,6 +14,7 @@ import androidx.preference.PreferenceManager import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar @@ -126,7 +127,7 @@ class SettingsUpdates : PreferenceFragmentCompat() { } getPref(R.string.apk_installer_key)?.setOnPreferenceClickListener { - val settingsManager = PreferenceManager.getDefaultSharedPreferences(it.context) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(it.context).attachListener().first val prefNames = resources.getStringArray(R.array.apk_installer_pref) val prefValues = resources.getIntArray(R.array.apk_installer_values) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLanguage.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLanguage.kt index 80db59ee..63de8c96 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLanguage.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLanguage.kt @@ -15,6 +15,7 @@ import com.lagradost.cloudstream3.CommonActivity import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.plugins.PluginManager +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.settings.appLanguages import com.lagradost.cloudstream3.ui.settings.getCurrentLocale import com.lagradost.cloudstream3.utils.SubtitleHelper @@ -42,7 +43,7 @@ class SetupFragmentLanguage : Fragment() { normalSafeApiCall { with(context) { if (this == null) return@normalSafeApiCall - val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this).attachListener().first val arrayAdapter = ArrayAdapter(this, R.layout.sort_bottom_single_choice) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLayout.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLayout.kt index 50fb37d6..db3d2e49 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLayout.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentLayout.kt @@ -10,6 +10,7 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar import kotlinx.android.synthetic.main.fragment_setup_layout.* import kotlinx.android.synthetic.main.fragment_setup_media.listview1 @@ -33,7 +34,7 @@ class SetupFragmentLayout : Fragment() { with(context) { if (this == null) return - val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this).attachListener().first val prefNames = resources.getStringArray(R.array.app_layout) val prefValues = resources.getIntArray(R.array.app_layout_values) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt index 257ce5c1..5e8a42ae 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentMedia.kt @@ -12,6 +12,7 @@ import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.TvType +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.utils.DataStore.removeKey import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar @@ -32,7 +33,7 @@ class SetupFragmentMedia : Fragment() { with(context) { if (this == null) return - val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this).attachListener().first val arrayAdapter = ArrayAdapter(this, R.layout.sort_bottom_single_choice) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentProviderLanguage.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentProviderLanguage.kt index 51abee90..74b1d77e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentProviderLanguage.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/setup/SetupFragmentProviderLanguage.kt @@ -14,6 +14,7 @@ import com.lagradost.cloudstream3.APIHolder import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings import com.lagradost.cloudstream3.AllLanguagesName import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.utils.SubtitleHelper import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar import kotlinx.android.synthetic.main.fragment_setup_media.* @@ -33,7 +34,7 @@ class SetupFragmentProviderLanguage : Fragment() { with(context) { if (this == null) return - val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this).attachListener().first val arrayAdapter = ArrayAdapter(this, R.layout.sort_bottom_single_choice) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt index ff0e0e82..1799a412 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/subtitles/SubtitlesFragment.kt @@ -27,6 +27,7 @@ import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.Event @@ -447,6 +448,7 @@ class SubtitlesFragment : Fragment() { subtitles_filter_sub_lang?.setOnCheckedChangeListener { _, b -> context?.let { ctx -> PreferenceManager.getDefaultSharedPreferences(ctx) + .attachListener().first .edit() .putBoolean(getString(R.string.filter_sub_lang_key), b) .apply() diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt index 06267048..8c52e221 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt @@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.module.kotlin.KotlinModule import com.lagradost.cloudstream3.mvvm.logError -import com.lagradost.cloudstream3.syncproviders.AccountManager +import com.lagradost.cloudstream3.syncproviders.BackupAPI const val DOWNLOAD_HEADER_CACHE = "download_header_cache" @@ -25,6 +25,8 @@ object DataStore { .configure(DeserializationFeature.USE_LONG_FOR_INTS, true) .build() + private val backupScheduler = BackupAPI.createBackupScheduler() + private fun getPreferences(context: Context): SharedPreferences { return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE) } @@ -83,8 +85,7 @@ object DataStore { val editor: SharedPreferences.Editor = prefs.edit() editor.remove(path) editor.apply() - - AccountManager.BackupApis.forEach { it.addToQueue() } + backupScheduler.work(Pair(path, false)) } } catch (e: Exception) { logError(e) @@ -104,8 +105,7 @@ object DataStore { val editor: SharedPreferences.Editor = getSharedPrefs().edit() editor.putString(path, mapper.writeValueAsString(value)) editor.apply() - - AccountManager.BackupApis.forEach { it.addToQueue() } + backupScheduler.work(Pair(path, false)) } catch (e: Exception) { logError(e) } @@ -115,6 +115,7 @@ object DataStore { setKey(getFolderName(folder, path), value) } + inline fun String.toKotlinObject(): T { return mapper.readValue(this, T::class.java) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt index 8b516e8c..09cf4138 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt @@ -23,6 +23,7 @@ import okio.buffer import okio.sink import java.io.File import android.text.TextUtils +import com.lagradost.cloudstream3.syncproviders.BackupAPI.Companion.attachListener import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus import java.io.BufferedReader import java.io.IOException @@ -73,7 +74,7 @@ class InAppUpdater { private suspend fun Activity.getAppUpdate(): Update { return try { - val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this).attachListener().first if (settingsManager.getBoolean( getString(R.string.prerelease_update_key), resources.getBoolean(R.bool.is_prerelease) @@ -254,7 +255,7 @@ class InAppUpdater { * @param checkAutoUpdate if the update check was launched automatically **/ suspend fun Activity.runAutoUpdate(checkAutoUpdate: Boolean = true): Boolean { - val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this).attachListener().first if (!checkAutoUpdate || settingsManager.getBoolean( getString(R.string.auto_update_key),