Эх сурвалжийг харах

同步进度功能补充 (#4352)

* 进度同步补充:
在初始阅读界面时拉取云端进度 --> 初始阅读界面保留原有拉取逻辑,除此之外的阅读界面处于已恢复状态时执行同步云端进度,若云端进度快于本地则弹窗提醒是否同步
无 --> 监听到网络切换到有网环境时执行同步云端进度,若云端进度快于本地则弹窗提醒是否同步
页面进入已暂停状态时上传阅读进度 --> 页面进入已暂停状态时执行同步云端进度

以上新增的同步云端进度逻辑为:如果本地进度快于服务器进度或者没有进度则进行上传,如果慢与服务器进度则返回云端进度按需执行

* 点击区域增加同步阅读进度功能

* 阅读界面初始化同步逻辑修改

* merge

* merge

* merge

* 增加覆盖云端进度

* merge

* merge

* 多次弹窗问题修改

* 补充的同步功能增加配置开关

* Revert "优化"

This reverts commit 8d4fba2e2f111b30d3273852b30af51e9b79dabe.

* merge

---------

Co-authored-by: mozhu <lcl_em@163.com>
lcdgit 2 жил өмнө
parent
commit
fdd88a8510

+ 1 - 0
app/src/main/java/io/legado/app/constant/PreferKey.kt

@@ -88,6 +88,7 @@ object PreferKey {
     const val importKeepGroup = "importKeepGroup"
     const val importKeepGroup = "importKeepGroup"
     const val screenOrientation = "screenOrientation"
     const val screenOrientation = "screenOrientation"
     const val syncBookProgress = "syncBookProgress"
     const val syncBookProgress = "syncBookProgress"
+    const val syncBookProgressPlus = "syncBookProgressPlus"
     const val cronet = "Cronet"
     const val cronet = "Cronet"
     const val antiAlias = "antiAlias"
     const val antiAlias = "antiAlias"
     const val bitmapCacheSize = "bitmapCacheSize"
     const val bitmapCacheSize = "bitmapCacheSize"

+ 2 - 0
app/src/main/java/io/legado/app/help/config/AppConfig.kt

@@ -451,6 +451,8 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
 
 
     val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true)
     val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true)
 
 
+    val syncBookProgressPlus get() = appCtx.getPrefBoolean(PreferKey.syncBookProgressPlus, false)
+
     val mediaButtonOnExit get() = appCtx.getPrefBoolean("mediaButtonOnExit", true)
     val mediaButtonOnExit get() = appCtx.getPrefBoolean("mediaButtonOnExit", true)
 
 
     val readAloudByMediaButton
     val readAloudByMediaButton

+ 38 - 1
app/src/main/java/io/legado/app/model/ReadBook.kt

@@ -199,12 +199,47 @@ object ReadBook : CoroutineScope by MainScope() {
         nextTextChapter?.clearSearchResult()
         nextTextChapter?.clearSearchResult()
     }
     }
 
 
-    fun uploadProgress() {
+    fun uploadProgress(successAction: (() -> Unit)? = null) {
         book?.let {
         book?.let {
             launch(IO) {
             launch(IO) {
                 AppWebDav.uploadBookProgress(it)
                 AppWebDav.uploadBookProgress(it)
                 ensureActive()
                 ensureActive()
                 it.update()
                 it.update()
+                successAction?.invoke()
+            }
+        }
+    }
+
+    /**
+     * 同步阅读进度
+     * 如果当前进度快于服务器进度或者没有进度进行上传,如果慢与服务器进度则执行传入动作
+     */
+    fun syncProgress(
+        newProgressAction: ((progress: BookProgress) -> Unit)? = null,
+        uploadSuccessAction: (() -> Unit)? = null,
+        syncSuccessAction: (() -> Unit)? = null) {
+        if (!AppConfig.syncBookProgress) return
+        book?.let {
+            Coroutine.async {
+                AppWebDav.getBookProgress(it)
+            }.onError {
+                AppLog.put("拉取阅读进度失败", it)
+            }.onSuccess { progress ->
+                if (progress == null || progress.durChapterIndex < it.durChapterIndex ||
+                    (progress.durChapterIndex == it.durChapterIndex
+                            && progress.durChapterPos < it.durChapterPos)) {
+                    // 服务器没有进度或者进度比服务器快,上传现有进度
+                    Coroutine.async {
+                        AppWebDav.uploadBookProgress(BookProgress(it), uploadSuccessAction)
+                        it.save()
+                    }
+                } else if (progress.durChapterIndex > it.durChapterIndex ||
+                    progress.durChapterPos > it.durChapterPos) {
+                    // 进度比服务器慢,执行传入动作
+                    newProgressAction?.invoke(progress)
+                } else {
+                    syncSuccessAction?.invoke()
+                }
             }
             }
         }
         }
     }
     }
@@ -893,6 +928,8 @@ object ReadBook : CoroutineScope by MainScope() {
 
 
         fun notifyBookChanged()
         fun notifyBookChanged()
 
 
+        fun sureNewProgress(progress: BookProgress)
+
         fun cancelSelect()
         fun cancelSelect()
     }
     }
 
 

+ 49 - 53
app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt

@@ -7,15 +7,10 @@ import android.content.res.Configuration
 import android.net.Uri
 import android.net.Uri
 import android.os.Bundle
 import android.os.Bundle
 import android.os.Looper
 import android.os.Looper
-import android.view.Gravity
-import android.view.InputDevice
-import android.view.KeyEvent
-import android.view.Menu
-import android.view.MenuItem
-import android.view.MotionEvent
-import android.view.View
+import android.view.*
 import androidx.activity.addCallback
 import androidx.activity.addCallback
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AlertDialog
 import androidx.appcompat.widget.PopupMenu
 import androidx.appcompat.widget.PopupMenu
 import androidx.core.view.get
 import androidx.core.view.get
 import androidx.core.view.isVisible
 import androidx.core.view.isVisible
@@ -24,12 +19,7 @@ import androidx.lifecycle.lifecycleScope
 import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
 import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
 import io.legado.app.BuildConfig
 import io.legado.app.BuildConfig
 import io.legado.app.R
 import io.legado.app.R
-import io.legado.app.constant.AppConst
-import io.legado.app.constant.AppLog
-import io.legado.app.constant.BookType
-import io.legado.app.constant.EventBus
-import io.legado.app.constant.PreferKey
-import io.legado.app.constant.Status
+import io.legado.app.constant.*
 import io.legado.app.data.appDb
 import io.legado.app.data.appDb
 import io.legado.app.data.entities.Book
 import io.legado.app.data.entities.Book
 import io.legado.app.data.entities.BookChapter
 import io.legado.app.data.entities.BookChapter
@@ -39,14 +29,7 @@ import io.legado.app.exception.NoStackTraceException
 import io.legado.app.help.AppWebDav
 import io.legado.app.help.AppWebDav
 import io.legado.app.help.IntentData
 import io.legado.app.help.IntentData
 import io.legado.app.help.TTS
 import io.legado.app.help.TTS
-import io.legado.app.help.book.BookHelp
-import io.legado.app.help.book.ContentProcessor
-import io.legado.app.help.book.isAudio
-import io.legado.app.help.book.isEpub
-import io.legado.app.help.book.isLocal
-import io.legado.app.help.book.isLocalTxt
-import io.legado.app.help.book.isMobi
-import io.legado.app.help.book.removeType
+import io.legado.app.help.book.*
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.ReadBookConfig
 import io.legado.app.help.config.ReadBookConfig
 import io.legado.app.help.config.ReadTipConfig
 import io.legado.app.help.config.ReadTipConfig
@@ -59,6 +42,7 @@ import io.legado.app.lib.theme.accentColor
 import io.legado.app.model.ReadAloud
 import io.legado.app.model.ReadAloud
 import io.legado.app.model.ReadBook
 import io.legado.app.model.ReadBook
 import io.legado.app.model.analyzeRule.AnalyzeRule
 import io.legado.app.model.analyzeRule.AnalyzeRule
+import io.legado.app.receiver.NetworkChangedListener
 import io.legado.app.model.localBook.EpubFile
 import io.legado.app.model.localBook.EpubFile
 import io.legado.app.model.localBook.MobiFile
 import io.legado.app.model.localBook.MobiFile
 import io.legado.app.receiver.TimeBatteryReceiver
 import io.legado.app.receiver.TimeBatteryReceiver
@@ -69,7 +53,7 @@ import io.legado.app.ui.book.bookmark.BookmarkDialog
 import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
 import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
 import io.legado.app.ui.book.changesource.ChangeChapterSourceDialog
 import io.legado.app.ui.book.changesource.ChangeChapterSourceDialog
 import io.legado.app.ui.book.info.BookInfoActivity
 import io.legado.app.ui.book.info.BookInfoActivity
-import io.legado.app.ui.book.read.config.AutoReadDialog
+import io.legado.app.ui.book.read.config.*
 import io.legado.app.ui.book.read.config.BgTextConfigDialog.Companion.BG_COLOR
 import io.legado.app.ui.book.read.config.BgTextConfigDialog.Companion.BG_COLOR
 import io.legado.app.ui.book.read.config.BgTextConfigDialog.Companion.TEXT_COLOR
 import io.legado.app.ui.book.read.config.BgTextConfigDialog.Companion.TEXT_COLOR
 import io.legado.app.ui.book.read.config.MoreConfigDialog
 import io.legado.app.ui.book.read.config.MoreConfigDialog
@@ -96,38 +80,10 @@ import io.legado.app.ui.replace.ReplaceRuleActivity
 import io.legado.app.ui.replace.edit.ReplaceEditActivity
 import io.legado.app.ui.replace.edit.ReplaceEditActivity
 import io.legado.app.ui.widget.PopupAction
 import io.legado.app.ui.widget.PopupAction
 import io.legado.app.ui.widget.dialog.PhotoDialog
 import io.legado.app.ui.widget.dialog.PhotoDialog
-import io.legado.app.utils.ACache
-import io.legado.app.utils.Debounce
-import io.legado.app.utils.LogUtils
-import io.legado.app.utils.StartActivityContract
-import io.legado.app.utils.applyOpenTint
-import io.legado.app.utils.buildMainHandler
-import io.legado.app.utils.getPrefBoolean
-import io.legado.app.utils.getPrefString
-import io.legado.app.utils.hexString
-import io.legado.app.utils.iconItemOnLongClick
-import io.legado.app.utils.invisible
-import io.legado.app.utils.isAbsUrl
-import io.legado.app.utils.isTrue
-import io.legado.app.utils.launch
-import io.legado.app.utils.navigationBarGravity
-import io.legado.app.utils.observeEvent
-import io.legado.app.utils.observeEventSticky
-import io.legado.app.utils.postEvent
-import io.legado.app.utils.showDialogFragment
-import io.legado.app.utils.showHelp
-import io.legado.app.utils.startActivity
-import io.legado.app.utils.sysScreenOffTime
-import io.legado.app.utils.throttle
-import io.legado.app.utils.toastOnUi
-import io.legado.app.utils.visible
+import io.legado.app.utils.*
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.Dispatchers.Main
 import kotlinx.coroutines.Dispatchers.Main
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.ensureActive
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
+import kotlinx.coroutines.*
 
 
 /**
 /**
  * 阅读界面
  * 阅读界面
@@ -245,6 +201,11 @@ class ReadBookActivity : BaseReadBookActivity(),
 
 
     //恢复跳转前进度对话框的交互结果
     //恢复跳转前进度对话框的交互结果
     private var confirmRestoreProcess: Boolean? = null
     private var confirmRestoreProcess: Boolean? = null
+    private val networkChangedListener by lazy {
+        NetworkChangedListener(this)
+    }
+    private var justInitData: Boolean = false
+    private var syncDialog: AlertDialog? = null
 
 
     @SuppressLint("ClickableViewAccessibility")
     @SuppressLint("ClickableViewAccessibility")
     override fun onActivityCreated(savedInstanceState: Bundle?) {
     override fun onActivityCreated(savedInstanceState: Bundle?) {
@@ -289,6 +250,7 @@ class ReadBookActivity : BaseReadBookActivity(),
             viewModel.initData(intent)
             viewModel.initData(intent)
             false
             false
         }
         }
+        justInitData = true
     }
     }
 
 
     override fun onNewIntent(intent: Intent) {
     override fun onNewIntent(intent: Intent) {
@@ -318,6 +280,7 @@ class ReadBookActivity : BaseReadBookActivity(),
             bookChanged = false
             bookChanged = false
             ReadBook.callBack = this
             ReadBook.callBack = this
             viewModel.initData(intent)
             viewModel.initData(intent)
+            justInitData = true
         } else {
         } else {
             //web端阅读时,app处于阅读界面,本地记录会覆盖web保存的进度,在此处恢复
             //web端阅读时,app处于阅读界面,本地记录会覆盖web保存的进度,在此处恢复
             ReadBook.webBookProgress?.let {
             ReadBook.webBookProgress?.let {
@@ -329,6 +292,14 @@ class ReadBookActivity : BaseReadBookActivity(),
         registerReceiver(timeBatteryReceiver, timeBatteryReceiver.filter)
         registerReceiver(timeBatteryReceiver, timeBatteryReceiver.filter)
         binding.readView.upTime()
         binding.readView.upTime()
         screenOffTimerStart()
         screenOffTimerStart()
+        // 网络监听,当从无网切换到网络环境时同步进度(注意注册的同时就会收到监听,因此界面激活时无需重复执行同步操作)
+        networkChangedListener.register()
+        networkChangedListener.onNetworkChanged = {
+            // 当网络是可用状态且无需初始化时同步进度(初始化中已有同步进度逻辑)
+            if (AppConfig.syncBookProgressPlus && NetworkUtils.isAvailable() && !justInitData) {
+                ReadBook.syncProgress({progress -> sureNewProgress(progress)}, null)
+            }
+        }
     }
     }
 
 
     override fun onPause() {
     override fun onPause() {
@@ -339,9 +310,15 @@ class ReadBookActivity : BaseReadBookActivity(),
         unregisterReceiver(timeBatteryReceiver)
         unregisterReceiver(timeBatteryReceiver)
         upSystemUiVisibility()
         upSystemUiVisibility()
         if (!BuildConfig.DEBUG) {
         if (!BuildConfig.DEBUG) {
-            ReadBook.uploadProgress()
+            if (AppConfig.syncBookProgressPlus) {
+                ReadBook.syncProgress()
+            } else {
+                ReadBook.uploadProgress()
+            }
             Backup.autoBack(this)
             Backup.autoBack(this)
         }
         }
+        justInitData = false
+        networkChangedListener.unRegister()
     }
     }
 
 
     override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
     override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
@@ -408,6 +385,9 @@ class ReadBookActivity : BaseReadBookActivity(),
             menu.findItem(R.id.menu_get_progress)?.isVisible = withContext(IO) {
             menu.findItem(R.id.menu_get_progress)?.isVisible = withContext(IO) {
                 AppWebDav.isOk
                 AppWebDav.isOk
             }
             }
+            menu.findItem(R.id.menu_cover_progress)?.isVisible = withContext(IO) {
+                AppWebDav.isOk
+            }
         }
         }
     }
     }
 
 
@@ -551,6 +531,10 @@ class ReadBookActivity : BaseReadBookActivity(),
                 }
                 }
             }
             }
 
 
+            R.id.menu_cover_progress -> ReadBook.book?.let {
+                ReadBook.uploadProgress({ toastOnUi(R.string.upload_book_success) })
+            }
+
             R.id.menu_same_title_removed -> {
             R.id.menu_same_title_removed -> {
                 ReadBook.book?.let {
                 ReadBook.book?.let {
                     val contentProcessor = ContentProcessor.get(it)
                     val contentProcessor = ContentProcessor.get(it)
@@ -1499,6 +1483,18 @@ class ReadBookActivity : BaseReadBookActivity(),
         }
         }
     }
     }
 
 
+    override fun sureNewProgress(progress: BookProgress) {
+        syncDialog?.dismiss()
+        syncDialog = alert(R.string.get_book_progress) {
+            setMessage(R.string.cloud_progress_exceeds_current)
+            okButton {
+                ReadBook.setProgress(progress)
+                ReadBook.saveRead()
+            }
+            noButton()
+        }
+    }
+
     override fun finish() {
     override fun finish() {
         val book = ReadBook.book ?: return super.finish()
         val book = ReadBook.book ?: return super.finish()
 
 

+ 5 - 1
app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt

@@ -125,7 +125,11 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
             // 有章节跳转不同步阅读进度
             // 有章节跳转不同步阅读进度
             ReadBook.chapterChanged = false
             ReadBook.chapterChanged = false
         } else if (!isSameBook || !BaseReadAloudService.isRun) {
         } else if (!isSameBook || !BaseReadAloudService.isRun) {
-            syncBookProgress(book)
+            if (AppConfig.syncBookProgressPlus) {
+                ReadBook.syncProgress({ progress -> ReadBook.callBack?.sureNewProgress(progress) }, null)
+            } else {
+                syncBookProgress(book)
+            }
         }
         }
         if (!book.isLocal && ReadBook.bookSource == null) {
         if (!book.isLocal && ReadBook.bookSource == null) {
             autoChangeSource(book.name, book.author)
             autoChangeSource(book.name, book.author)

+ 2 - 1
app/src/main/java/io/legado/app/ui/book/read/config/ClickActionConfigDialog.kt

@@ -35,7 +35,8 @@ class ClickActionConfigDialog : BaseDialogFragment(R.layout.dialog_click_action_
             Pair(8, getString(R.string.edit_content)),
             Pair(8, getString(R.string.edit_content)),
             Pair(9, getString(R.string.replace_state_change)),
             Pair(9, getString(R.string.replace_state_change)),
             Pair(10, getString(R.string.chapter_list)),
             Pair(10, getString(R.string.chapter_list)),
-            Pair(11, getString(R.string.search_content))
+            Pair(11, getString(R.string.search_content)),
+            Pair(12, getString(R.string.sync_book_progress_t))
         )
         )
     }
     }
 
 

+ 7 - 0
app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt

@@ -10,7 +10,9 @@ import android.view.MotionEvent
 import android.view.ViewConfiguration
 import android.view.ViewConfiguration
 import android.view.WindowInsets
 import android.view.WindowInsets
 import android.widget.FrameLayout
 import android.widget.FrameLayout
+import io.legado.app.R
 import io.legado.app.constant.PageAnim
 import io.legado.app.constant.PageAnim
+import io.legado.app.data.entities.BookProgress
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.ReadBookConfig
 import io.legado.app.help.config.ReadBookConfig
 import io.legado.app.model.ReadAloud
 import io.legado.app.model.ReadAloud
@@ -34,6 +36,7 @@ import io.legado.app.ui.book.read.page.provider.TextPageFactory
 import io.legado.app.utils.activity
 import io.legado.app.utils.activity
 import io.legado.app.utils.canvasrecorder.pools.BitmapPool
 import io.legado.app.utils.canvasrecorder.pools.BitmapPool
 import io.legado.app.utils.invisible
 import io.legado.app.utils.invisible
+import io.legado.app.utils.longToastOnUi
 import io.legado.app.utils.showDialogFragment
 import io.legado.app.utils.showDialogFragment
 import io.legado.app.utils.throttle
 import io.legado.app.utils.throttle
 import java.text.BreakIterator
 import java.text.BreakIterator
@@ -434,6 +437,9 @@ class ReadView(context: Context, attrs: AttributeSet) :
             9 -> callBack.changeReplaceRuleState()
             9 -> callBack.changeReplaceRuleState()
             10 -> callBack.openChapterList()
             10 -> callBack.openChapterList()
             11 -> callBack.openSearchActivity(null)
             11 -> callBack.openSearchActivity(null)
+            12 -> ReadBook.syncProgress({progress -> callBack.sureNewProgress(progress)},
+                { context.longToastOnUi(context.getString(R.string.upload_book_success)) },
+                { context.longToastOnUi(context.getString(R.string.sync_book_progress_success)) })
         }
         }
     }
     }
 
 
@@ -726,5 +732,6 @@ class ReadView(context: Context, attrs: AttributeSet) :
         fun changeReplaceRuleState()
         fun changeReplaceRuleState()
         fun openSearchActivity(searchWord: String?)
         fun openSearchActivity(searchWord: String?)
         fun upSystemUiVisibility()
         fun upSystemUiVisibility()
+        fun sureNewProgress(progress: BookProgress)
     }
     }
 }
 }

+ 6 - 0
app/src/main/res/menu/book_read.xml

@@ -65,6 +65,12 @@
         android:visible="false"
         android:visible="false"
         app:showAsAction="never" />
         app:showAsAction="never" />
 
 
+    <item
+        android:id="@+id/menu_cover_progress"
+        android:title="@string/cover_book_progress"
+        android:visible="false"
+        app:showAsAction="never" />
+
     <item
     <item
         android:id="@+id/menu_reverse_content"
         android:id="@+id/menu_reverse_content"
         android:title="@string/reverse_content"
         android:title="@string/reverse_content"

+ 5 - 0
app/src/main/res/values-es-rES/strings.xml

@@ -806,9 +806,12 @@
     <string name="rule_subscription">Suscripción de reglsa</string>
     <string name="rule_subscription">Suscripción de reglsa</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
     <string name="get_book_progress">Obtener progreso en la nube</string>
     <string name="get_book_progress">Obtener progreso en la nube</string>
+    <string name="cover_book_progress">Cobertura del progreso en la nube</string>
     <string name="current_progress_exceeds_cloud">El progreso actual excede el progreso de la nube. ¿Quieres sincronizar?</string>
     <string name="current_progress_exceeds_cloud">El progreso actual excede el progreso de la nube. ¿Quieres sincronizar?</string>
     <string name="sync_book_progress_t">Progreso de lectura sincronizado</string>
     <string name="sync_book_progress_t">Progreso de lectura sincronizado</string>
     <string name="sync_book_progress_s">Sincronizar el progreso de la lectura al entrar y salir de la pantalla de lectura</string>
     <string name="sync_book_progress_s">Sincronizar el progreso de la lectura al entrar y salir de la pantalla de lectura</string>
+    <string name="sync_book_progress_plus_t">Mejora de Sincronización</string>
+    <string name="sync_book_progress_plus_s">Sincronizar el progreso en la nube al volver a entrar en la página (por ejemplo, tras apagar la pantalla o al regresar desde el fondo) o cuando la red esté disponible</string>
     <string name="create_bookmark_error">No se pudo marcar</string>
     <string name="create_bookmark_error">No se pudo marcar</string>
     <string name="single_url">URL única</string>
     <string name="single_url">URL única</string>
     <string name="export_bookshelf">Exportar lista de libros</string>
     <string name="export_bookshelf">Exportar lista de libros</string>
@@ -1129,8 +1132,10 @@
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="export_wait">等待导出</string>
     <string name="export_wait">等待导出</string>
     <string name="default_home_page">默认主页</string>
     <string name="default_home_page">默认主页</string>
+    <string name="sync_book_progress_success">" Sincronización del progreso exitosa"</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
+    <string name="cloud_progress_exceeds_current">The cloud progress exceeds the current progress. Do you want to synchronize?</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="screen_portrait_reversed">反向竖屏</string>
     <string name="screen_portrait_reversed">反向竖屏</string>

+ 6 - 1
app/src/main/res/values-ja-rJP/strings.xml

@@ -808,10 +808,13 @@
     <string name="header_footer">footer <![CDATA[&]]> header</string>
     <string name="header_footer">footer <![CDATA[&]]> header</string>
     <string name="rule_subscription">Rule Subscription</string>
     <string name="rule_subscription">Rule Subscription</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
-    <string name="get_book_progress">Pull the cloud  progress</string>
+    <string name="get_book_progress">クラウド上の進捗状況のカバー</string>
+    <string name="cover_book_progress">Cobertura do progresso na nuvem</string>
     <string name="current_progress_exceeds_cloud">The current progress exceeds the cloud progress. Do you want to synchronize?</string>
     <string name="current_progress_exceeds_cloud">The current progress exceeds the cloud progress. Do you want to synchronize?</string>
     <string name="sync_book_progress_t">Synchronous reading progress</string>
     <string name="sync_book_progress_t">Synchronous reading progress</string>
     <string name="sync_book_progress_s">Synchronize reading progress when entering / exiting the reading interface</string>
     <string name="sync_book_progress_s">Synchronize reading progress when entering / exiting the reading interface</string>
+    <string name="sync_book_progress_plus_t">同期強化</string>
+    <string name="sync_book_progress_plus_s">ページに再入力する時(スリープ解除やバックグラウンドから復帰など)、またはネットワークが利用可能になるとクラウド進捗を同期します</string>
     <string name="create_bookmark_error">Failed to create bookmark</string>
     <string name="create_bookmark_error">Failed to create bookmark</string>
     <string name="single_url">Single URL</string>
     <string name="single_url">Single URL</string>
     <string name="export_bookshelf">Export the list of books</string>
     <string name="export_bookshelf">Export the list of books</string>
@@ -1132,8 +1135,10 @@
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="export_wait">等待导出</string>
     <string name="export_wait">等待导出</string>
     <string name="default_home_page">默认主页</string>
     <string name="default_home_page">默认主页</string>
+    <string name="sync_book_progress_success">Sync progress success</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
+    <string name="cloud_progress_exceeds_current">The cloud progress exceeds the current progress. Do you want to synchronize?</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="screen_portrait_reversed">反向竖屏</string>
     <string name="screen_portrait_reversed">反向竖屏</string>

+ 5 - 0
app/src/main/res/values-pt-rBR/strings.xml

@@ -807,9 +807,12 @@
     <string name="rule_subscription">Assinatura de regras</string>
     <string name="rule_subscription">Assinatura de regras</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
     <string name="get_book_progress">Obter o progresso da nuvem</string>
     <string name="get_book_progress">Obter o progresso da nuvem</string>
+    <string name="cover_book_progress">Phủ sóng tiến độ trên đám mây</string>
     <string name="current_progress_exceeds_cloud">O progresso atual excede o progresso da nuvem. Você quer sincronizar?</string>
     <string name="current_progress_exceeds_cloud">O progresso atual excede o progresso da nuvem. Você quer sincronizar?</string>
     <string name="sync_book_progress_t">Progresso de leitura sincronizada</string>
     <string name="sync_book_progress_t">Progresso de leitura sincronizada</string>
     <string name="sync_book_progress_s">Sincronizar o progresso da leitura ao entrar e sair da tela de leitura</string>
     <string name="sync_book_progress_s">Sincronizar o progresso da leitura ao entrar e sair da tela de leitura</string>
+    <string name="sync_book_progress_plus_t">Aprimoramento de Sincronização</string>
+    <string name="sync_book_progress_plus_s">Sincronizar o progresso na nuvem ao reentrar na página (por exemplo, após desligar a tela ou ao retornar do fundo) ou quando a rede estiver disponível</string>
     <string name="create_bookmark_error">Falha ao marcar como favorito</string>
     <string name="create_bookmark_error">Falha ao marcar como favorito</string>
     <string name="single_url">URL única</string>
     <string name="single_url">URL única</string>
     <string name="export_bookshelf">Exportar a lista de livros</string>
     <string name="export_bookshelf">Exportar a lista de livros</string>
@@ -1132,8 +1135,10 @@
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="export_wait">等待导出</string>
     <string name="export_wait">等待导出</string>
     <string name="default_home_page">默认主页</string>
     <string name="default_home_page">默认主页</string>
+    <string name="sync_book_progress_success">Sincronização de progresso bem-sucedida</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
+    <string name="cloud_progress_exceeds_current">The cloud progress exceeds the current progress. Do you want to synchronize?</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="screen_portrait_reversed">反向竖屏</string>
     <string name="screen_portrait_reversed">反向竖屏</string>

+ 5 - 0
app/src/main/res/values-vi/strings.xml

@@ -808,9 +808,12 @@ Còn </string>
     <string name="rule_subscription">Quy tắc đăng ký</string>
     <string name="rule_subscription">Quy tắc đăng ký</string>
     <string name="rule_sub_empty_msg">Thêm địa chỉ nhập quy tắc do các ông chủ cung cấp\\nNhấp để nhập quy tắc sau khi thêm</string>
     <string name="rule_sub_empty_msg">Thêm địa chỉ nhập quy tắc do các ông chủ cung cấp\\nNhấp để nhập quy tắc sau khi thêm</string>
     <string name="get_book_progress">Kéo tiến độ đám mây</string>
     <string name="get_book_progress">Kéo tiến độ đám mây</string>
+    <string name="cover_book_progress">Phủ sóng tiến độ trên đám mây</string>
     <string name="current_progress_exceeds_cloud">Tiến độ hiện tại vượt quá tiến độ đám mây. Bạn có muốn đồng bộ hóa?</string>
     <string name="current_progress_exceeds_cloud">Tiến độ hiện tại vượt quá tiến độ đám mây. Bạn có muốn đồng bộ hóa?</string>
     <string name="sync_book_progress_t">Tiến độ đọc đồng bộ</string>
     <string name="sync_book_progress_t">Tiến độ đọc đồng bộ</string>
     <string name="sync_book_progress_s">Đồng bộ tiến độ đọc khi vào/ra khỏi giao diện đọc</string>
     <string name="sync_book_progress_s">Đồng bộ tiến độ đọc khi vào/ra khỏi giao diện đọc</string>
+    <string name="sync_book_progress_plus_t">Cải Tiến Đồng Bộ</string>
+    <string name="sync_book_progress_plus_s">Đồng bộ tiến độ trên đám mây khi quay lại trang (ví dụ: sau khi tắt màn hình, quay trở lại từ nền, v.v.) hoặc khi mạng trở nên khả dụng</string>
     <string name="create_bookmark_error">Không thể tạo dấu trang</string>
     <string name="create_bookmark_error">Không thể tạo dấu trang</string>
     <string name="single_url">URL đơn</string>
     <string name="single_url">URL đơn</string>
     <string name="export_bookshelf">Xuất bookshelf</string>
     <string name="export_bookshelf">Xuất bookshelf</string>
@@ -1127,9 +1130,11 @@ Còn </string>
     <string name="change_source_delay">换源间隔</string>
     <string name="change_source_delay">换源间隔</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="export_wait">等待导出</string>
     <string name="export_wait">等待导出</string>
+    <string name="sync_book_progress_success">" Đồng bộ hóa tiến trình thành công"</string>
     <string name="default_home_page">默认主页</string>
     <string name="default_home_page">默认主页</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
+    <string name="cloud_progress_exceeds_current">The cloud progress exceeds the current progress. Do you want to synchronize?</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="screen_portrait_reversed">反向竖屏</string>
     <string name="screen_portrait_reversed">反向竖屏</string>

+ 5 - 0
app/src/main/res/values-zh-rHK/strings.xml

@@ -807,9 +807,12 @@
     <string name="rule_subscription">規則訂閱</string>
     <string name="rule_subscription">規則訂閱</string>
     <string name="rule_sub_empty_msg">添加大佬們提供的規則匯入地址 添加後點擊可匯入規則</string>
     <string name="rule_sub_empty_msg">添加大佬們提供的規則匯入地址 添加後點擊可匯入規則</string>
     <string name="get_book_progress">拉取雲端進度</string>
     <string name="get_book_progress">拉取雲端進度</string>
+    <string name="cover_book_progress">覆蓋雲端進度</string>
     <string name="current_progress_exceeds_cloud">目前進度超過雲端進度,係咪同步?</string>
     <string name="current_progress_exceeds_cloud">目前進度超過雲端進度,係咪同步?</string>
     <string name="sync_book_progress_t">同步閱讀進度</string>
     <string name="sync_book_progress_t">同步閱讀進度</string>
     <string name="sync_book_progress_s">進入退出閱讀介面時同步閱讀進度</string>
     <string name="sync_book_progress_s">進入退出閱讀介面時同步閱讀進度</string>
+    <string name="sync_book_progress_plus_t">同步增強</string>
+    <string name="sync_book_progress_plus_s">重新進入頁面(熄屏、返回背景等)或者當網絡可用時同步雲端進度</string>
     <string name="create_bookmark_error">建立書籤失敗</string>
     <string name="create_bookmark_error">建立書籤失敗</string>
     <string name="single_url">單URL</string>
     <string name="single_url">單URL</string>
     <string name="export_bookshelf">導出書單</string>
     <string name="export_bookshelf">導出書單</string>
@@ -1128,9 +1131,11 @@
     <string name="change_source_delay">换源间隔</string>
     <string name="change_source_delay">换源间隔</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="export_wait">等待导出</string>
     <string name="export_wait">等待导出</string>
+    <string name="sync_book_progress_success">進度同步成功</string>
     <string name="default_home_page">默认主页</string>
     <string name="default_home_page">默认主页</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
+    <string name="cloud_progress_exceeds_current">雲端進度超過目前進度,是否同步?</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="screen_portrait_reversed">反向竖屏</string>
     <string name="screen_portrait_reversed">反向竖屏</string>

+ 5 - 0
app/src/main/res/values-zh-rTW/strings.xml

@@ -810,9 +810,12 @@
     <string name="rule_subscription">規則訂閱</string>
     <string name="rule_subscription">規則訂閱</string>
     <string name="rule_sub_empty_msg">新增大佬們提供的規則匯入地址\n新增後點擊可匯入規則</string>
     <string name="rule_sub_empty_msg">新增大佬們提供的規則匯入地址\n新增後點擊可匯入規則</string>
     <string name="get_book_progress">拉取雲端進度</string>
     <string name="get_book_progress">拉取雲端進度</string>
+    <string name="cover_book_progress">覆蓋雲端進度</string>
     <string name="current_progress_exceeds_cloud">目前進度超過雲端進度,是否同步?</string>
     <string name="current_progress_exceeds_cloud">目前進度超過雲端進度,是否同步?</string>
     <string name="sync_book_progress_t">同步閱讀進度</string>
     <string name="sync_book_progress_t">同步閱讀進度</string>
     <string name="sync_book_progress_s">進入退出閱讀介面時同步閱讀進度</string>
     <string name="sync_book_progress_s">進入退出閱讀介面時同步閱讀進度</string>
+    <string name="sync_book_progress_plus_t">同步增強</string>
+    <string name="sync_book_progress_plus_s">重新進入頁面(熄屏、背景返回等)或網路變為可用時同步雲端進度</string>
     <string name="create_bookmark_error">建立書籤失敗</string>
     <string name="create_bookmark_error">建立書籤失敗</string>
     <string name="single_url">單URL</string>
     <string name="single_url">單URL</string>
     <string name="export_bookshelf">匯出書單</string>
     <string name="export_bookshelf">匯出書單</string>
@@ -1130,9 +1133,11 @@
     <string name="change_source_delay">换源间隔</string>
     <string name="change_source_delay">换源间隔</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="export_wait">等待导出</string>
     <string name="export_wait">等待导出</string>
+    <string name="sync_book_progress_success">進度同步成功</string>
     <string name="default_home_page">默认主页</string>
     <string name="default_home_page">默认主页</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
+    <string name="cloud_progress_exceeds_current">雲端進度超過目前進度,是否同步?</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="screen_portrait_reversed">反向竖屏</string>
     <string name="screen_portrait_reversed">反向竖屏</string>

+ 5 - 0
app/src/main/res/values-zh/strings.xml

@@ -813,9 +813,12 @@
     <string name="rule_subscription">规则订阅</string>
     <string name="rule_subscription">规则订阅</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
     <string name="rule_sub_empty_msg">添加大佬们提供的规则导入地址\n添加后点击可导入规则</string>
     <string name="get_book_progress">拉取云端进度</string>
     <string name="get_book_progress">拉取云端进度</string>
+    <string name="cover_book_progress">覆盖云端进度</string>
     <string name="current_progress_exceeds_cloud">当前进度超过云端进度,是否同步?</string>
     <string name="current_progress_exceeds_cloud">当前进度超过云端进度,是否同步?</string>
     <string name="sync_book_progress_t">同步阅读进度</string>
     <string name="sync_book_progress_t">同步阅读进度</string>
     <string name="sync_book_progress_s">进入退出阅读界面时同步阅读进度</string>
     <string name="sync_book_progress_s">进入退出阅读界面时同步阅读进度</string>
+    <string name="sync_book_progress_plus_t">同步增强</string>
+    <string name="sync_book_progress_plus_s">重新进入页面(息屏、后台返回等)或者网络变为可用时同步云端进度</string>
     <string name="create_bookmark_error">创建书签失败</string>
     <string name="create_bookmark_error">创建书签失败</string>
     <string name="single_url">单 URL</string>
     <string name="single_url">单 URL</string>
     <string name="export_bookshelf">导出书单</string>
     <string name="export_bookshelf">导出书单</string>
@@ -1130,9 +1133,11 @@
     <string name="change_source_delay">换源间隔</string>
     <string name="change_source_delay">换源间隔</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="open_book_info_by_click_title">点击书名打开详情</string>
     <string name="export_wait">等待导出</string>
     <string name="export_wait">等待导出</string>
+    <string name="sync_book_progress_success">进度同步成功</string>
     <string name="default_home_page">默认主页</string>
     <string name="default_home_page">默认主页</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="show_bookshelf_fast_scroller">显示快速滚动条</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
     <string name="export_all_use_book_source">导出所有书的书源</string>
+    <string name="cloud_progress_exceeds_current">云端进度超过当前进度,是否同步?</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="keep_enable">保留启用状态</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="preview_image_by_click">点击预览图片</string>
     <string name="screen_portrait_reversed">反向竖屏</string>
     <string name="screen_portrait_reversed">反向竖屏</string>

+ 5 - 0
app/src/main/res/values/strings.xml

@@ -812,9 +812,14 @@
     <string name="rule_subscription">Rule Subscription</string>
     <string name="rule_subscription">Rule Subscription</string>
     <string name="rule_sub_empty_msg">Add the rule import address provided by the bosses\nClick to import rules after adding</string>
     <string name="rule_sub_empty_msg">Add the rule import address provided by the bosses\nClick to import rules after adding</string>
     <string name="get_book_progress">Pull the cloud  progress</string>
     <string name="get_book_progress">Pull the cloud  progress</string>
+    <string name="cover_book_progress">Overlay Cloud Progress</string>
     <string name="current_progress_exceeds_cloud">The current progress exceeds the cloud progress. Do you want to synchronize?</string>
     <string name="current_progress_exceeds_cloud">The current progress exceeds the cloud progress. Do you want to synchronize?</string>
+    <string name="cloud_progress_exceeds_current">The cloud progress exceeds the current progress. Do you want to synchronize?</string>
     <string name="sync_book_progress_t">Synchronous reading progress</string>
     <string name="sync_book_progress_t">Synchronous reading progress</string>
     <string name="sync_book_progress_s">Synchronize reading progress when entering / exiting the reading interface</string>
     <string name="sync_book_progress_s">Synchronize reading progress when entering / exiting the reading interface</string>
+    <string name="sync_book_progress_plus_t">Sync Enhancement</string>
+    <string name="sync_book_progress_plus_s">Sync cloud progress when re-entering the page (e.g., after screen off, returning from background, etc.) or when the network becomes available</string>
+    <string name="sync_book_progress_success">Sync progress success</string>
     <string name="create_bookmark_error">Failed to create bookmark</string>
     <string name="create_bookmark_error">Failed to create bookmark</string>
     <string name="single_url">Single URL</string>
     <string name="single_url">Single URL</string>
     <string name="export_bookshelf">Export the list of books</string>
     <string name="export_bookshelf">Export the list of books</string>

+ 10 - 0
app/src/main/res/xml/pref_config_backup.xml

@@ -50,6 +50,16 @@
             app:allowDividerBelow="false"
             app:allowDividerBelow="false"
             app:iconSpaceReserved="false" />
             app:iconSpaceReserved="false" />
 
 
+        <io.legado.app.lib.prefs.SwitchPreference
+            android:key="syncBookProgressPlus"
+            android:defaultValue="false"
+            android:title="@string/sync_book_progress_plus_t"
+            android:summary="@string/sync_book_progress_plus_s"
+            android:dependency="syncBookProgress"
+            app:allowDividerAbove="false"
+            app:allowDividerBelow="false"
+            app:iconSpaceReserved="false" />
+
     </io.legado.app.lib.prefs.PreferenceCategory>
     </io.legado.app.lib.prefs.PreferenceCategory>
 
 
     <io.legado.app.lib.prefs.PreferenceCategory
     <io.legado.app.lib.prefs.PreferenceCategory