Merge pull request #22 from gedoor/master

up
pull/379/head
口口吕 5 years ago committed by GitHub
commit e3cd2ce3d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/build.gradle
  2. 8
      app/proguard-rules.pro
  3. 6
      app/src/main/java/io/legado/app/App.kt
  4. 2
      app/src/main/java/io/legado/app/data/AppDatabase.kt
  5. 14
      app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt
  6. 21
      app/src/main/java/io/legado/app/help/BookHelp.kt
  7. 3
      app/src/main/java/io/legado/app/help/JsExtensions.kt
  8. 5
      app/src/main/java/io/legado/app/help/ReadBookConfig.kt
  9. 20
      app/src/main/java/io/legado/app/help/storage/Restore.kt
  10. 3
      app/src/main/java/io/legado/app/help/storage/WebDavHelp.kt
  11. 24
      app/src/main/java/io/legado/app/service/help/ReadBook.kt
  12. 6
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt
  13. 19
      app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
  14. 4
      app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt
  15. 2
      app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt
  16. 4
      app/src/main/java/io/legado/app/ui/book/read/page/PageFactory.kt
  17. 8
      app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
  18. 10
      app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt
  19. 28
      app/src/main/java/io/legado/app/ui/book/read/page/delegate/HorizontalPageDelegate.kt
  20. 31
      app/src/main/java/io/legado/app/ui/book/read/page/delegate/PageDelegate.kt
  21. 24
      app/src/main/java/io/legado/app/ui/book/read/page/delegate/ScrollPageDelegate.kt
  22. 3
      app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt
  23. 2
      app/src/main/java/io/legado/app/ui/main/MainActivity.kt
  24. 2
      app/src/main/java/io/legado/app/ui/replacerule/edit/ReplaceEditViewModel.kt
  25. 2
      app/src/main/java/io/legado/app/ui/rss/article/RssArticlesActivity.kt
  26. 2
      app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt
  27. 9
      app/src/main/java/io/legado/app/utils/RealPathUtil.kt
  28. 11
      app/src/main/java/io/legado/app/utils/StringExtensions.kt
  29. 2
      build.gradle
  30. 1
      gradle.properties

@ -55,7 +55,7 @@ android {
signingConfig signingConfigs.myConfig
}
applicationIdSuffix '.release'
minifyEnabled false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
@ -106,7 +106,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
//fireBase
implementation 'com.google.firebase:firebase-core:17.2.2'
implementation 'com.google.firebase:firebase-core:17.2.3'
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
//androidX

@ -154,6 +154,8 @@
-keep class **.analyzeRule.**{*;}
# 保持web类
-keep class **.web.**{*;}
#数据类
-keep class **.data.**{*;}
-dontwarn rx.**
@ -166,6 +168,7 @@
-dontnote org.python.core.**
-dontwarn com.hwangjr.rxbus.**
-dontwarn okhttp3.**
-dontwarn org.conscrypt.**
-keep class retrofit2.**{*;}
-keep class okhttp3.**{*;}
@ -206,8 +209,6 @@
-keep class javax.script.** { *; }
-keep class com.sun.script.javascript.** { *; }
-keep class org.mozilla.javascript.** { *; }
-dontwarn org.mozilla.javascript.**
-dontwarn sun.**
###EPUB
-dontwarn nl.siegmann.epublib.**
@ -222,9 +223,6 @@
-keepclassmembers class * {
public <init> (org.json.JSONObject);
}
-keep public class com.kunfei.bookshelf.R$*{
public static final int *;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);

@ -48,12 +48,8 @@ class App : Application() {
versionCode = it.versionCode
versionName = it.versionName
}
if (!ThemeStore.isConfigured(this, versionCode)) applyTheme()
initNightMode()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createChannelId()
applyDayNight()
LiveEventBus.get()
.config()
.supportBroadcast(this)

@ -32,7 +32,7 @@ abstract class AppDatabase : RoomDatabase() {
.fallbackToDestructiveMigration()
.addCallback(object : Callback() {
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
GlobalScope.launch { Restore.restore(Backup.backupPath) }
GlobalScope.launch { Restore.restoreDatabase(Backup.backupPath) }
}
})
.build()

@ -33,14 +33,20 @@ interface ReplaceRuleDao {
fun findByIds(vararg ids: Long): List<ReplaceRule>
@Query(
"""SELECT * FROM replace_rules WHERE isEnabled = 1
AND (scope LIKE '%' || :scope || '%' or scope is null or scope = '')"""
"""
SELECT * FROM replace_rules WHERE isEnabled = 1
AND (scope LIKE '%' || :scope || '%' or scope is null or scope = '')
order by sortOrder
"""
)
fun findEnabledByScope(scope: String): List<ReplaceRule>
@Query(
"""SELECT * FROM replace_rules WHERE isEnabled = 1
AND (scope LIKE '%' || :name || '%' or scope LIKE '%' || :origin || '%' or scope is null or scope = '')"""
"""
SELECT * FROM replace_rules WHERE isEnabled = 1
AND (scope LIKE '%' || :name || '%' or scope LIKE '%' || :origin || '%' or scope is null or scope = '')
order by sortOrder
"""
)
fun findEnabledByScope(name: String, origin: String): List<ReplaceRule>

@ -11,7 +11,10 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.ReplaceRule
import io.legado.app.model.localBook.AnalyzeTxtFile
import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.withContext
import org.apache.commons.text.similarity.JaccardSimilarity
import org.jetbrains.anko.toast
import java.io.File
import kotlin.math.min
@ -262,7 +265,7 @@ object BookHelp {
}
}
fun disposeContent(
suspend fun disposeContent(
title: String,
name: String,
origin: String?,
@ -272,13 +275,19 @@ object BookHelp {
var c = content
if (enableReplace) {
upReplaceRules(name, origin)
for (item in replaceRules) {
replaceRules.forEach { item ->
item.pattern.let {
if (it.isNotEmpty()) {
c = if (item.isRegex) {
c.replace(it.toRegex(), item.replacement)
} else {
c.replace(it, item.replacement)
try {
c = if (item.isRegex) {
c.replace(it.toRegex(), item.replacement)
} else {
c.replace(it, item.replacement)
}
} catch (e: Exception) {
withContext(Main) {
App.INSTANCE.toast("${item.name}替换出错")
}
}
}
}

@ -1,13 +1,14 @@
package io.legado.app.help
import android.util.Base64
import androidx.annotation.Keep
import io.legado.app.constant.AppConst.DATE_FORMAT
import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.MD5Utils
import java.util.*
@Keep
@Suppress("unused")
interface JsExtensions {

@ -4,6 +4,7 @@ import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import androidx.annotation.Keep
import io.legado.app.App
import io.legado.app.R
import io.legado.app.constant.PreferKey
@ -15,6 +16,7 @@ import java.io.File
/**
* 阅读界面配置
*/
@Keep
object ReadBookConfig {
const val readConfigFileName = "readConfig.json"
private val configFilePath =
@ -236,6 +238,7 @@ object ReadBookConfig {
if (shareLayout) shareConfig.footerPaddingTop = value
else durConfig.footerPaddingTop = value
@Keep
class Config(
private var bgStr: String = "#EEEEEE",//白天背景
private var bgStrNight: String = "#000000",//夜间背景
@ -247,7 +250,7 @@ object ReadBookConfig {
private var textColorNight: String = "#ADADAD",//夜间文字颜色
var textBold: Boolean = false,//是否粗体字
var textSize: Int = 20,//文字大小
var letterSpacing: Float = 1f,//字间距
var letterSpacing: Float = 0.5f,//字间距
var lineSpacingExtra: Int = 12,//行间距
var paragraphSpacing: Int = 12,//段距
var titleCenter: Boolean = true,//标题居中

@ -8,6 +8,7 @@ import com.jayway.jsonpath.JsonPath
import com.jayway.jsonpath.Option
import com.jayway.jsonpath.ParseContext
import io.legado.app.App
import io.legado.app.BuildConfig
import io.legado.app.constant.PreferKey
import io.legado.app.data.entities.*
import io.legado.app.help.LauncherIconHelp
@ -16,6 +17,7 @@ import io.legado.app.service.help.ReadBook
import io.legado.app.ui.book.read.page.ChapterProvider
import io.legado.app.utils.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.withContext
import org.jetbrains.anko.defaultSharedPreferences
import java.io.File
@ -60,10 +62,11 @@ object Restore {
}
}
}
restore(Backup.backupPath)
restoreDatabase()
restoreConfig()
}
suspend fun restore(path: String) {
suspend fun restoreDatabase(path: String = Backup.backupPath) {
withContext(IO) {
fileToListT<Book>(path, "bookshelf.json")?.let {
App.db.bookDao().insert(*it.toTypedArray())
@ -83,11 +86,16 @@ object Restore {
fileToListT<ReplaceRule>(path, "replaceRule.json")?.let {
App.db.replaceRuleDao().insert(*it.toTypedArray())
}
}
}
suspend fun restoreConfig(path: String = Backup.backupPath) {
withContext(IO) {
try {
val file =
FileUtils.createFileIfNotExist(path + File.separator + ReadBookConfig.readConfigFileName)
val configFile =
File(App.INSTANCE.filesDir.absolutePath + File.separator + ReadBookConfig.readConfigFileName)
FileUtils.getFile(App.INSTANCE.filesDir, ReadBookConfig.readConfigFileName)
if (file.exists()) {
file.copyTo(configFile, true)
ReadBookConfig.upConfig()
@ -119,7 +127,11 @@ object Restore {
ChapterProvider.upStyle()
ReadBook.loadContent()
}
LauncherIconHelp.changeIcon(App.INSTANCE.getPrefString(PreferKey.launcherIcon))
withContext(Main) {
App.INSTANCE.applyDayNight()
if (!BuildConfig.DEBUG)
LauncherIconHelp.changeIcon(App.INSTANCE.getPrefString(PreferKey.launcherIcon))
}
}
private inline fun <reified T> fileToListT(path: String, fileName: String): List<T>? {

@ -95,7 +95,8 @@ object WebDavHelp {
webDav.downloadTo(zipFilePath, true)
@Suppress("BlockingMethodInNonBlockingContext")
ZipUtils.unzipFile(zipFilePath, Backup.backupPath)
Restore.restore(Backup.backupPath)
Restore.restoreDatabase()
Restore.restoreConfig()
}
}
}.onSuccess {

@ -69,11 +69,11 @@ object ReadBook {
nextTextChapter = null
book?.let {
if (curTextChapter == null) {
loadContent(durChapterIndex)
loadContent(durChapterIndex, upContent)
} else if (upContent) {
callBack?.upContent()
}
loadContent(durChapterIndex.plus(1))
loadContent(durChapterIndex.plus(1), upContent)
GlobalScope.launch(Dispatchers.IO) {
for (i in 2..10) {
delay(100)
@ -99,11 +99,11 @@ object ReadBook {
prevTextChapter = null
book?.let {
if (curTextChapter == null) {
loadContent(durChapterIndex)
loadContent(durChapterIndex, upContent)
} else if (upContent) {
callBack?.upContent()
}
loadContent(durChapterIndex.minus(1))
loadContent(durChapterIndex.minus(1), upContent)
GlobalScope.launch(Dispatchers.IO) {
for (i in -5..-2) {
delay(100)
@ -190,13 +190,13 @@ object ReadBook {
loadContent(durChapterIndex - 1)
}
fun loadContent(index: Int) {
fun loadContent(index: Int, upContent: Boolean = true) {
book?.let { book ->
if (addLoading(index)) {
Coroutine.async {
App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter ->
BookHelp.getContent(book, chapter)?.let {
contentLoadFinish(chapter, it)
contentLoadFinish(chapter, it, upContent)
removeLoading(chapter.index)
} ?: download(chapter)
} ?: removeLoading(index)
@ -262,7 +262,11 @@ object ReadBook {
/**
* 内容加载完成
*/
private fun contentLoadFinish(chapter: BookChapter, content: String) {
private fun contentLoadFinish(
chapter: BookChapter,
content: String,
upContent: Boolean = true
) {
Coroutine.async {
if (chapter.index in durChapterIndex - 1..durChapterIndex + 1) {
val c = BookHelp.disposeContent(
@ -275,18 +279,18 @@ object ReadBook {
when (chapter.index) {
durChapterIndex -> {
curTextChapter = ChapterProvider.getTextChapter(chapter, c, chapterSize)
callBack?.upContent()
if (upContent) callBack?.upContent()
callBack?.upView()
curPageChanged()
callBack?.contentLoadFinish()
}
durChapterIndex - 1 -> {
prevTextChapter = ChapterProvider.getTextChapter(chapter, c, chapterSize)
callBack?.upContent(-1)
if (upContent) callBack?.upContent(-1)
}
durChapterIndex + 1 -> {
nextTextChapter = ChapterProvider.getTextChapter(chapter, c, chapterSize)
callBack?.upContent(1)
if (upContent) callBack?.upContent(1)
}
}
}

@ -23,6 +23,7 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp
import io.legado.app.help.ReadBookConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.storage.SyncBookProgress
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.okButton
@ -31,6 +32,8 @@ import io.legado.app.receiver.TimeBatteryReceiver
import io.legado.app.service.BaseReadAloudService
import io.legado.app.service.help.ReadAloud
import io.legado.app.service.help.ReadBook
import io.legado.app.ui.book.changesource.ChangeSourceDialog
import io.legado.app.ui.book.chapterlist.ChapterListActivity
import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.book.read.config.*
import io.legado.app.ui.book.read.config.BgTextConfigDialog.Companion.BG_COLOR
@ -40,8 +43,6 @@ import io.legado.app.ui.book.read.page.PageView
import io.legado.app.ui.book.read.page.TextPageFactory
import io.legado.app.ui.book.read.page.delegate.PageDelegate
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.book.changesource.ChangeSourceDialog
import io.legado.app.ui.book.chapterlist.ChapterListActivity
import io.legado.app.ui.login.SourceLogin
import io.legado.app.ui.replacerule.ReplaceRuleActivity
import io.legado.app.ui.replacerule.edit.ReplaceEditDialog
@ -660,6 +661,7 @@ class ReadBookActivity : VMBaseActivity<ReadBookViewModel>(R.layout.activity_boo
mHandler.removeCallbacks(keepScreenRunnable)
textActionMenu?.dismiss()
page_view.onDestroy()
SyncBookProgress.uploadBookProgress()
}
override fun observeLiveBus() {

@ -16,6 +16,7 @@ import io.legado.app.ui.book.read.page.entities.TextPage
import io.legado.app.utils.dp
import io.legado.app.utils.getPrefString
import io.legado.app.utils.removePref
import io.legado.app.utils.toStringArray
@Suppress("DEPRECATION")
@ -177,10 +178,10 @@ object ChapterProvider {
var x = 0f
val bodyIndent = ReadBookConfig.bodyIndent
val icw = StaticLayout.getDesiredWidth(bodyIndent, textPaint) / bodyIndent.length
for (i in 0..bodyIndent.lastIndex) {
bodyIndent.toStringArray().forEach {
val x1 = x + icw
textLine.addTextChar(
charData = bodyIndent[i].toString(),
charData = it,
start = paddingLeft + x,
end = paddingLeft + x1
)
@ -203,12 +204,11 @@ object ChapterProvider {
val gapCount: Int = words.length - 1
val d = (visibleWidth - desiredWidth) / gapCount
var x = startX
for (i in words.indices) {
val char = words[i]
val cw = StaticLayout.getDesiredWidth(char.toString(), textPaint)
for ((i, char) in words.toStringArray().withIndex()) {
val cw = StaticLayout.getDesiredWidth(char, textPaint)
val x1 = if (i != words.lastIndex) (x + cw + d) else (x + cw)
textLine.addTextChar(
charData = char.toString(),
charData = char,
start = paddingLeft + x,
end = paddingLeft + x1
)
@ -230,12 +230,11 @@ object ChapterProvider {
stringBuilder.append("\n")
textLine.text = "$words\n"
var x = startX
for (i in words.indices) {
val char = words[i].toString()
val cw = StaticLayout.getDesiredWidth(char, textPaint)
words.toStringArray().forEach {
val cw = StaticLayout.getDesiredWidth(it, textPaint)
val x1 = x + cw
textLine.addTextChar(
charData = char,
charData = it,
start = paddingLeft + x,
end = paddingLeft + x1
)

@ -170,13 +170,13 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
} else if (!pageFactory.hasNext() && pageOffset < 0) {
pageOffset = 0f
} else if (pageOffset > 0) {
pageFactory.moveToPrev()
pageFactory.moveToPrev(false)
textPage = pageFactory.currentPage
pageOffset -= textPage.height
upView?.invoke(textPage)
} else if (pageOffset < -textPage.height) {
pageOffset += textPage.height
pageFactory.moveToNext()
pageFactory.moveToNext(false)
textPage = pageFactory.currentPage
upView?.invoke(textPage)
}

@ -16,4 +16,6 @@ interface DataSource {
fun hasNextChapter(): Boolean
fun hasPrevChapter(): Boolean
fun upContent(relativePosition: Int = 0)
}

@ -6,9 +6,9 @@ abstract class PageFactory<DATA>(protected val dataSource: DataSource) {
abstract fun moveToLast()
abstract fun moveToNext():Boolean
abstract fun moveToNext(upContent: Boolean): Boolean
abstract fun moveToPrev(): Boolean
abstract fun moveToPrev(upContent: Boolean): Boolean
abstract val nextPage: DATA

@ -76,12 +76,10 @@ class PageView(context: Context, attrs: AttributeSet) :
fun fillPage(direction: PageDelegate.Direction) {
when (direction) {
PageDelegate.Direction.PREV -> {
pageFactory.moveToPrev()
upContent()
pageFactory.moveToPrev(true)
}
PageDelegate.Direction.NEXT -> {
pageFactory.moveToNext()
upContent()
pageFactory.moveToNext(true)
}
else -> Unit
}
@ -100,7 +98,7 @@ class PageView(context: Context, attrs: AttributeSet) :
upContent()
}
fun upContent(relativePosition: Int = 0) {
override fun upContent(relativePosition: Int) {
if (ReadBookConfig.isScroll) {
curPage.setContent(pageFactory.currentPage)
} else {

@ -31,25 +31,27 @@ class TextPageFactory(dataSource: DataSource) : PageFactory<TextPage>(dataSource
} ?: ReadBook.setPageIndex(0)
}
override fun moveToNext(): Boolean = with(dataSource) {
override fun moveToNext(upContent: Boolean): Boolean = with(dataSource) {
return if (hasNext()) {
if (currentChapter?.isLastIndex(pageIndex) == true) {
ReadBook.moveToNextChapter(false)
ReadBook.moveToNextChapter(upContent)
} else {
ReadBook.setPageIndex(pageIndex.plus(1))
}
if (upContent) upContent()
true
} else
false
}
override fun moveToPrev(): Boolean = with(dataSource) {
override fun moveToPrev(upContent: Boolean): Boolean = with(dataSource) {
return if (hasPrev()) {
if (pageIndex <= 0) {
ReadBook.moveToPrevChapter(false)
ReadBook.moveToPrevChapter(upContent)
} else {
ReadBook.setPageIndex(pageIndex.minus(1))
}
if (upContent) upContent()
true
} else
false

@ -4,7 +4,6 @@ import android.graphics.Bitmap
import android.view.MotionEvent
import io.legado.app.ui.book.read.page.PageView
import io.legado.app.utils.screenshot
import kotlin.math.abs
abstract class HorizontalPageDelegate(pageView: PageView) : PageDelegate(pageView) {
@ -52,12 +51,31 @@ abstract class HorizontalPageDelegate(pageView: PageView) : PageDelegate(pageVie
}
private fun onScroll(event: MotionEvent) {
val action: Int = event.action
val pointerUp =
action and MotionEvent.ACTION_MASK == MotionEvent.ACTION_POINTER_UP
val skipIndex = if (pointerUp) event.actionIndex else -1
// Determine focal point
var sumX = 0f
var sumY = 0f
val count: Int = event.pointerCount
for (i in 0 until count) {
if (skipIndex == i) continue
sumX += event.getX(i)
sumY += event.getY(i)
}
val div = if (pointerUp) count - 1 else count
val focusX = sumX / div
val focusY = sumY / div
//判断是否移动了
if (!isMoved) {
isMoved = abs(startX - event.x) > slop
|| abs(startX - event.x) > abs(startY - event.y)
val deltaX = (focusX - startX).toInt()
val deltaY = (focusY - startY).toInt()
val distance = deltaX * deltaX + deltaY * deltaY
isMoved = distance > slopSquare
if (isMoved) {
if (event.x - startX > 0) {
if (sumX - startX > 0) {
//如果上一页不存在
if (!hasPrev()) {
noNext = true
@ -78,7 +96,7 @@ abstract class HorizontalPageDelegate(pageView: PageView) : PageDelegate(pageVie
isCancel = if (mDirection == Direction.NEXT) touchX > lastX else touchX < lastX
isRunning = true
//设置触摸点
setTouchPoint(event.x, event.y)
setTouchPoint(sumX, sumY)
}
}

@ -23,7 +23,7 @@ abstract class PageDelegate(protected val pageView: PageView) :
pageView.width * 0.66f, pageView.height * 0.66f
)
protected val context: Context = pageView.context
protected val slop = ViewConfiguration.get(context).scaledTouchSlop
//起始点
protected var startX: Float = 0f
protected var startY: Float = 0f
@ -41,18 +41,23 @@ abstract class PageDelegate(protected val pageView: PageView) :
protected var viewWidth: Int = pageView.width
protected var viewHeight: Int = pageView.height
private val snackBar: Snackbar by lazy {
Snackbar.make(pageView, "", Snackbar.LENGTH_SHORT)
}
private val scroller: Scroller by lazy {
Scroller(pageView.context, DecelerateInterpolator())
}
protected val slopSquare by lazy {
val scaledTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
scaledTouchSlop * scaledTouchSlop
}
private val detector: GestureDetector by lazy {
GestureDetector(pageView.context, this)
}
private val snackBar: Snackbar by lazy {
Snackbar.make(pageView, "", Snackbar.LENGTH_SHORT)
}
var isMoved = false
var noNext = true
@ -189,13 +194,17 @@ abstract class PageDelegate(protected val pageView: PageView) :
@CallSuper
open fun onTouch(event: MotionEvent) {
if (isStarted) return
detector.setIsLongpressEnabled(false)
if (!detector.onTouchEvent(event)) {
//GestureDetector.onFling小幅移动不会触发,所以要自己判断
if (event.action == MotionEvent.ACTION_UP && isMoved) {
if (selectedOnDown) {
selectedOnDown = false
when (event.action) {
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL -> if (isMoved) {
if (selectedOnDown) {
selectedOnDown = false
}
if (!noNext) onAnimStart()
}
if (!noNext) onAnimStart()
}
}
}
@ -232,6 +241,10 @@ abstract class PageDelegate(protected val pageView: PageView) :
selectedOnDown = false
return true
}
if (isMoved) {
if (!noNext) onAnimStart()
return true
}
val x = e.x
val y = e.y
if (centerRectF.contains(x, y)) {

@ -4,7 +4,6 @@ import android.view.MotionEvent
import android.view.VelocityTracker
import io.legado.app.ui.book.read.page.ChapterProvider
import io.legado.app.ui.book.read.page.PageView
import kotlin.math.abs
class ScrollPageDelegate(pageView: PageView) : PageDelegate(pageView) {
@ -46,9 +45,28 @@ class ScrollPageDelegate(pageView: PageView) : PageDelegate(pageView) {
private fun onScroll(event: MotionEvent) {
mVelocity.addMovement(event)
mVelocity.computeCurrentVelocity(velocityDuration)
setTouchPoint(event.x, event.y)
val action: Int = event.action
val pointerUp =
action and MotionEvent.ACTION_MASK == MotionEvent.ACTION_POINTER_UP
val skipIndex = if (pointerUp) event.actionIndex else -1
// Determine focal point
var sumX = 0f
var sumY = 0f
val count: Int = event.pointerCount
for (i in 0 until count) {
if (skipIndex == i) continue
sumX += event.getX(i)
sumY += event.getY(i)
}
val div = if (pointerUp) count - 1 else count
val focusX = sumX / div
val focusY = sumY / div
setTouchPoint(sumX, sumY)
if (!isMoved) {
isMoved = abs(startX - event.x) > slop || abs(startY - event.y) > slop
val deltaX = (focusX - startX).toInt()
val deltaY = (focusY - startY).toInt()
val distance = deltaX * deltaX + deltaY * deltaY
isMoved = distance > slopSquare
}
if (isMoved) {
isRunning = true

@ -114,7 +114,8 @@ object BackupRestoreUi {
.onGranted {
Coroutine.async {
AppConfig.backupPath = path
Restore.restore(path)
Restore.restoreDatabase(path)
Restore.restoreConfig(path)
}.onSuccess {
fragment.toast(R.string.restore_success)
}

@ -16,7 +16,6 @@ import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey
import io.legado.app.help.AppConfig
import io.legado.app.help.storage.Backup
import io.legado.app.help.storage.SyncBookProgress
import io.legado.app.lib.theme.ATH
import io.legado.app.service.BaseReadAloudService
import io.legado.app.service.help.ReadAloud
@ -129,7 +128,6 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
override fun finish() {
if (!BuildConfig.DEBUG) {
SyncBookProgress.uploadBookProgress()
Backup.autoBack(this)
}
super.finish()

@ -23,7 +23,7 @@ class ReplaceEditViewModel(application: Application) : BaseViewModel(application
bundle.getString("pattern")?.let { pattern ->
val isRegex = bundle.getBoolean("isRegex")
replaceRuleData.postValue(
ReplaceRule(pattern = pattern, isRegex = isRegex)
ReplaceRule(name = pattern, pattern = pattern, isRegex = isRegex)
)
}
}

@ -60,7 +60,7 @@ class RssArticlesActivity : VMBaseActivity<RssArticlesViewModel>(R.layout.activi
R.id.menu_clear -> {
viewModel.url?.let {
refresh_progress_bar.isAutoLoading = true
viewModel.clear()
viewModel.clearArticles()
}
}
}

@ -106,7 +106,7 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application
}
}
fun clear() {
fun clearArticles() {
execute {
url?.let {
App.db.rssArticleDao().delete(it)

@ -102,8 +102,6 @@ object RealPathUtil {
val projection = arrayOf(
column
)
var input: FileInputStream? = null
var output: FileOutputStream? = null
try {
cursor =
context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
@ -115,6 +113,8 @@ object RealPathUtil {
e.printStackTrace()
val file = File(context.cacheDir, "tmp")
val filePath = file.absolutePath
var input: FileInputStream? = null
var output: FileOutputStream? = null
try {
val pfd =
context.contentResolver.openFileDescriptor(filePathUri!!, "r")
@ -127,11 +127,12 @@ object RealPathUtil {
while (input.read(bytes).also { read = it } != -1) {
output.write(bytes, 0, read)
}
input.close()
output.close()
return File(filePath).absolutePath
} catch (ignored: IOException) {
ignored.printStackTrace()
} finally {
input?.close()
output?.close()
}
} finally {
cursor?.close()

@ -48,6 +48,17 @@ fun String.splitNotBlank(regex: Regex, limit: Int = 0): Array<String> = run {
this.split(regex, limit).map { it.trim() }.filterNot { it.isBlank() }.toTypedArray()
}
fun String.toStringArray(): Array<String> {
var codePointIndex = 0
return Array(codePointCount(0, length)) {
substring(
codePointIndex,
offsetByCodePoints(codePointIndex, 1)
.apply { codePointIndex = this }
)
}
}
fun Char?.isHAN(): Boolean {
this ?: return false
val ub: Character.UnicodeBlock = Character.UnicodeBlock.of(this) ?: return false

@ -13,7 +13,7 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.3'
classpath 'com.google.gms:google-services:4.3.3'
classpath 'io.fabric.tools:gradle:1.31.0'
classpath 'io.fabric.tools:gradle:1.31.2'
}
}

@ -19,4 +19,3 @@ android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.enableR8=false
Loading…
Cancel
Save