Merge pull request #21 from gedoor/master

up
pull/379/head
口口吕 5 years ago committed by GitHub
commit 77fde70d94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      app/src/main/assets/updateLog.md
  2. 1
      app/src/main/java/io/legado/app/constant/PreferKey.kt
  3. 20
      app/src/main/java/io/legado/app/data/dao/BookDao.kt
  4. 9
      app/src/main/java/io/legado/app/data/entities/BookProgress.kt
  5. 8
      app/src/main/java/io/legado/app/help/ReadBookConfig.kt
  6. 50
      app/src/main/java/io/legado/app/help/storage/SyncBookProgress.kt
  7. 39
      app/src/main/java/io/legado/app/help/storage/WebDavHelp.kt
  8. 1
      app/src/main/java/io/legado/app/lib/webdav/WebDav.kt
  9. 17
      app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
  10. 8
      app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
  11. 4
      app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
  12. 120
      app/src/main/java/io/legado/app/ui/book/read/page/ChapterProvider.kt
  13. 20
      app/src/main/java/io/legado/app/ui/book/read/page/delegate/CoverPageDelegate.kt
  14. 39
      app/src/main/java/io/legado/app/ui/book/read/page/delegate/HorizontalPageDelegate.kt
  15. 91
      app/src/main/java/io/legado/app/ui/book/read/page/delegate/SimulationPageDelegate.kt
  16. 25
      app/src/main/java/io/legado/app/ui/book/read/page/delegate/SlidePageDelegate.kt
  17. 4
      app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt
  18. 2
      app/src/main/java/io/legado/app/ui/main/MainActivity.kt
  19. 2
      app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt
  20. 33
      app/src/main/java/io/legado/app/utils/BitmapUtils.kt
  21. 2
      app/src/main/res/values/strings.xml
  22. 7
      app/src/main/res/xml/pref_config_backup.xml

@ -2,6 +2,15 @@
* 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
* 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。
**2020/03/04**
* 修复仿真翻页动画
* 添加阅读记录同步,正常退出进入软件时同步阅读记录
**2020/03/03**
* 修复bug
* 优化排版,确保段距为0时每行在相同的位置
* 修复底部遮挡
**2020/03/02**
* 添加书源登录
* 替换规则实时生效

@ -32,6 +32,7 @@ object PreferKey {
const val webDavUrl = "web_dav_url"
const val webDavAccount = "web_dav_account"
const val webDavPassword = "web_dav_password"
const val webDavCreateDir = "webDavCreateDir"
const val changeSourceLoadToc = "changeSourceLoadToc"
const val chineseConverterType = "chineseConverterType"
const val launcherIcon = "launcherIcon"

@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData
import androidx.room.*
import io.legado.app.constant.BookType
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookProgress
@Dao
interface BookDao {
@ -67,4 +68,23 @@ interface BookDao {
@Query("update books set `group` = :newGroupId where `group` = :oldGroupId")
fun upGroup(oldGroupId: Int, newGroupId: Int)
@get:Query("select bookUrl, durChapterIndex, durChapterPos, durChapterTime, durChapterTitle from books")
val allBookProgress: List<BookProgress>
@Query(
"""
update books set
durChapterIndex = :durChapterIndex, durChapterPos = :durChapterPos,
durChapterTime = :durChapterTime, durChapterTitle = :durChapterTitle
where bookUrl = :bookUrl and durChapterTime < :durChapterTime
"""
)
fun upBookProgress(
bookUrl: String,
durChapterIndex: Int,
durChapterPos: Int,
durChapterTime: Long,
durChapterTitle: String?
)
}

@ -0,0 +1,9 @@
package io.legado.app.data.entities
data class BookProgress(
val bookUrl: String,
val durChapterIndex: Int,
val durChapterPos: Int,
val durChapterTime: Long,
val durChapterTitle: String?
)

@ -27,6 +27,7 @@ object ReadBookConfig {
val durConfig get() = getConfig(styleSelect)
private val shareConfig get() = getConfig(5)
var bg: Drawable? = null
var bgMeanColor: Int = 0
init {
upConfig()
@ -68,6 +69,13 @@ object ReadBookConfig {
val width = dm.widthPixels
val height = dm.heightPixels
bg = durConfig.bgDrawable(width, height)
bg?.let {
if (it is BitmapDrawable) {
bgMeanColor = BitmapUtils.getMeanColor(it.bitmap)
} else if (it is ColorDrawable) {
bgMeanColor = it.color
}
}
}
fun save() {

@ -0,0 +1,50 @@
package io.legado.app.help.storage
import io.legado.app.App
import io.legado.app.data.entities.BookProgress
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.lib.webdav.WebDav
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonArray
@Suppress("BlockingMethodInNonBlockingContext")
object SyncBookProgress {
const val fileName = "bookProgress.json"
private val file = FileUtils.createFileIfNotExist(App.INSTANCE.cacheDir, fileName)
private val webDavUrl = "${WebDavHelp.rootWebDavUrl}$fileName"
fun uploadBookProgress() {
Coroutine.async {
val value = App.db.bookDao().allBookProgress
if (value.isNotEmpty()) {
val json = GSON.toJson(value)
file.writeText(json)
if (WebDavHelp.initWebDav()) {
WebDav(webDavUrl).upload(file.absolutePath)
}
}
}
}
fun downloadBookProgress() {
Coroutine.async {
if (WebDavHelp.initWebDav()) {
WebDav(webDavUrl).downloadTo(file.absolutePath, true)
if (file.exists()) {
val json = file.readText()
GSON.fromJsonArray<BookProgress>(json)?.forEach {
App.db.bookDao().upBookProgress(
it.bookUrl,
it.durChapterIndex,
it.durChapterPos,
it.durChapterTime,
it.durChapterTitle
)
}
}
}
}
}
}

@ -10,6 +10,7 @@ import io.legado.app.lib.webdav.WebDav
import io.legado.app.lib.webdav.http.HttpAuth
import io.legado.app.utils.FileUtils
import io.legado.app.utils.ZipUtils
import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.getPrefString
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
@ -25,31 +26,36 @@ object WebDavHelp {
private const val defaultWebDavUrl = "https://dav.jianguoyun.com/dav/"
private val zipFilePath = "${FileUtils.getCachePath()}${File.separator}backup.zip"
private fun getWebDavUrl(): String {
val rootWebDavUrl: String
get() {
var url = App.INSTANCE.getPrefString(PreferKey.webDavUrl)
if (url.isNullOrEmpty()) {
url = defaultWebDavUrl
}
if (!url.endsWith("/")) url += "/"
if (!url.endsWith("/")) url = "${url}/"
if (App.INSTANCE.getPrefBoolean(PreferKey.webDavCreateDir, true)) {
url = "${url}legado/"
}
return url
}
private fun initWebDav(): Boolean {
fun initWebDav(): Boolean {
val account = App.INSTANCE.getPrefString(PreferKey.webDavAccount)
val password = App.INSTANCE.getPrefString(PreferKey.webDavPassword)
if (!account.isNullOrBlank() && !password.isNullOrBlank()) {
HttpAuth.auth = HttpAuth.Auth(account, password)
WebDav(rootWebDavUrl).makeAsDir()
return true
}
return false
}
private fun getWebDavFileNames(): ArrayList<String> {
val url = getWebDavUrl()
val url = rootWebDavUrl
val names = arrayListOf<String>()
if (initWebDav()) {
try {
var files = WebDav(url + "legado/").listFiles()
var files = WebDav(url).listFiles()
files = files.reversed()
for (index: Int in 0 until min(10, files.size)) {
files[index].displayName?.let {
@ -81,12 +87,16 @@ object WebDavHelp {
private fun restoreWebDav(name: String, success: () -> Unit) {
Coroutine.async {
getWebDavUrl().let {
val file = WebDav(it + "legado/" + name)
file.downloadTo(zipFilePath, true)
@Suppress("BlockingMethodInNonBlockingContext")
ZipUtils.unzipFile(zipFilePath, Backup.backupPath)
Restore.restore(Backup.backupPath)
rootWebDavUrl.let {
if (name == SyncBookProgress.fileName) {
SyncBookProgress.downloadBookProgress()
} else {
val webDav = WebDav(it + name)
webDav.downloadTo(zipFilePath, true)
@Suppress("BlockingMethodInNonBlockingContext")
ZipUtils.unzipFile(zipFilePath, Backup.backupPath)
Restore.restore(Backup.backupPath)
}
}
}.onSuccess {
success.invoke()
@ -102,10 +112,9 @@ object WebDavHelp {
}
FileUtils.deleteFile(zipFilePath)
if (ZipUtils.zipFiles(paths, zipFilePath)) {
WebDav(getWebDavUrl() + "legado").makeAsDir()
val putUrl = getWebDavUrl() + "legado/backup" +
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
.format(Date(System.currentTimeMillis())) + ".zip"
val backupDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
.format(Date(System.currentTimeMillis()))
val putUrl = "${rootWebDavUrl}backup${backupDate}.zip"
WebDav(putUrl).upload(zipFilePath)
}
}

@ -202,7 +202,6 @@ constructor(urlStr: String) {
* 上传文件
*/
@Throws(IOException::class)
@JvmOverloads
fun upload(localPath: String, contentType: String? = null): Boolean {
val file = File(localPath)
if (!file.exists()) return false

@ -30,15 +30,16 @@ object LocalBook {
}
fun deleteBook(book: Book, deleteOriginal: Boolean) {
if (book.isTxt()) {
val bookFile =
FileUtils.getFile(AnalyzeTxtFile.cacheFolder, book.originName, subDirs = *arrayOf())
bookFile.delete()
}
kotlin.runCatching {
if (book.isTxt()) {
val bookFile = FileUtils.getFile(AnalyzeTxtFile.cacheFolder, book.originName)
bookFile.delete()
}
if (deleteOriginal) {
val uri = Uri.parse(book.bookUrl)
DocumentFile.fromSingleUri(App.INSTANCE, uri)?.delete()
if (deleteOriginal) {
val uri = Uri.parse(book.bookUrl)
DocumentFile.fromSingleUri(App.INSTANCE, uri)?.delete()
}
}
}
}

@ -21,8 +21,6 @@ import io.legado.app.help.BlurTransformation
import io.legado.app.help.ImageLoader
import io.legado.app.help.IntentDataHelp
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.dialogs.noButton
import io.legado.app.lib.dialogs.okButton
import io.legado.app.ui.audio.AudioPlayActivity
import io.legado.app.ui.book.changecover.ChangeCoverDialog
import io.legado.app.ui.book.changesource.ChangeSourceDialog
@ -232,17 +230,17 @@ class BookInfoActivity :
titleResource = R.string.sure,
messageResource = R.string.sure_delete_book_file
) {
okButton {
positiveButton(R.string.yes) {
viewModel.delBook(true) {
finish()
}
}
noButton {
negativeButton(R.string.no) {
viewModel.delBook(false) {
finish()
}
}
}
}.show()
} else {
viewModel.delBook {
upTvBookshelf()

@ -202,12 +202,12 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
fun delBook(deleteOriginal: Boolean = false, success: (() -> Unit)? = null) {
execute {
bookData.value?.let {
App.db.bookDao().delete(it)
inBookshelf = false
if (it.isLocalBook()) {
LocalBook.deleteBook(it, deleteOriginal)
}
App.db.bookDao().delete(it)
}
inBookshelf = false
}.onSuccess {
success?.invoke()
}

@ -28,7 +28,7 @@ object ChapterProvider {
var visibleHeight = 0
var visibleRight = 0
var visibleBottom = 0
private var lineSpacingExtra = 0f
private var lineSpacingExtra = 0
private var paragraphSpacing = 0
var typeface: Typeface = Typeface.SANS_SERIF
var titlePaint = TextPaint()
@ -51,7 +51,7 @@ object ChapterProvider {
val pageLengths = arrayListOf<Int>()
val stringBuilder = StringBuilder()
var surplusText = content
var durY = 0
var durY = 0f
textPages.add(TextPage())
while (surplusText.isNotEmpty()) {
if (textPages.first().textLines.isEmpty()) {
@ -60,7 +60,9 @@ object ChapterProvider {
if (end > 0) {
val title = surplusText.substring(0, end)
surplusText = surplusText.substring(end + 1)
durY = joinTitle(title, durY, textPages, pageLines, pageLengths, stringBuilder)
durY = setTypeText(
title, durY, textPages, pageLines, pageLengths, stringBuilder, true
)
}
} else {
//正文
@ -73,7 +75,8 @@ object ChapterProvider {
text = surplusText
surplusText = ""
}
durY = joinBody(text, durY, textPages, pageLines, pageLengths, stringBuilder)
durY =
setTypeText(text, durY, textPages, pageLines, pageLengths, stringBuilder, false)
}
}
textPages.last().height = durY + 20.dp
@ -103,116 +106,59 @@ object ChapterProvider {
}
/**
* 标题
* 排版文字
*/
private fun joinTitle(
title: String,
y: Int,
textPages: ArrayList<TextPage>,
pageLines: ArrayList<Int>,
pageLengths: ArrayList<Int>,
stringBuilder: StringBuilder
): Int {
var durY = y
val layout = StaticLayout(
title, titlePaint, visibleWidth,
Layout.Alignment.ALIGN_NORMAL, 1f, lineSpacingExtra, true
)
for (lineIndex in 0 until layout.lineCount) {
textPages.last().height = durY
val textLine = TextLine(isTitle = true)
if (durY + layout.getLineBaseline(lineIndex) - layout.getLineTop(lineIndex)
+ contentPaint.fontMetrics.descent < visibleHeight
) {
textPages.last().textLines.add(textLine)
durY = durY + layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex)
} else {
textPages.last().text = stringBuilder.toString()
stringBuilder.clear()
pageLines.add(textPages.last().textLines.size)
pageLengths.add(textPages.last().text.length)
//新页面
durY = layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex)
textPages.add(TextPage())
textPages.last().textLines.add(textLine)
}
textLine.lineTop = (paddingTop + durY -
(layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex))).toFloat()
textLine.lineBase = (paddingTop + durY -
(layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex))).toFloat()
textLine.lineBottom = textLine.lineBase + contentPaint.fontMetrics.descent
val words =
title.substring(layout.getLineStart(lineIndex), layout.getLineEnd(lineIndex))
stringBuilder.append(words)
textLine.text = words
val desiredWidth = layout.getLineWidth(lineIndex)
if (lineIndex != layout.lineCount - 1) {
addCharsToLineMiddle(textLine, words, titlePaint, desiredWidth, 0f)
} else {
//最后一行
val x = if (ReadBookConfig.titleCenter)
(visibleWidth - layout.getLineWidth(lineIndex)) / 2
else 0f
addCharsToLineLast(textLine, words, stringBuilder, titlePaint, x)
}
}
durY += paragraphSpacing
return durY
}
/**
* 正文
*/
private fun joinBody(
private fun setTypeText(
text: String,
y: Int,
y: Float,
textPages: ArrayList<TextPage>,
pageLines: ArrayList<Int>,
pageLengths: ArrayList<Int>,
stringBuilder: StringBuilder
): Int {
stringBuilder: StringBuilder,
isTitle: Boolean
): Float {
var durY = y
val textPaint = if (isTitle) titlePaint else contentPaint
val layout = StaticLayout(
text, contentPaint, visibleWidth,
Layout.Alignment.ALIGN_NORMAL, 1f, lineSpacingExtra, true
text, textPaint, visibleWidth,
Layout.Alignment.ALIGN_NORMAL, 0f, 0f, true
)
for (lineIndex in 0 until layout.lineCount) {
textPages.last().height = durY
val textLine = TextLine()
if (durY + layout.getLineBaseline(lineIndex) - layout.getLineTop(lineIndex)
+ contentPaint.fontMetrics.descent < visibleHeight
) {
val textLine = TextLine(isTitle = isTitle)
if (durY + textPaint.textHeight < visibleHeight) {
textPages.last().textLines.add(textLine)
durY = durY + layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex)
durY += textPaint.textHeight + lineSpacingExtra
} else {
textPages.last().text = stringBuilder.toString()
stringBuilder.clear()
pageLines.add(textPages.last().textLines.size)
pageLengths.add(textPages.last().text.length)
//新页面
durY = layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex)
durY = textPaint.textHeight + lineSpacingExtra
textPages.add(TextPage())
textPages.last().textLines.add(textLine)
}
textLine.lineTop = (paddingTop + durY -
(layout.getLineBottom(lineIndex) - layout.getLineTop(lineIndex))).toFloat()
textLine.lineBase = (paddingTop + durY -
(layout.getLineBottom(lineIndex) - layout.getLineBaseline(lineIndex))).toFloat()
textLine.lineBottom = textLine.lineBase + contentPaint.fontMetrics.descent
textLine.lineBottom = paddingTop + durY - lineSpacingExtra
textLine.lineBase = textLine.lineBottom - textPaint.fontMetrics.descent
textLine.lineTop = textLine.lineBottom - textPaint.textHeight
val words =
text.substring(layout.getLineStart(lineIndex), layout.getLineEnd(lineIndex))
stringBuilder.append(words)
textLine.text = words
val desiredWidth = layout.getLineWidth(lineIndex)
if (lineIndex == 0 && layout.lineCount > 1) {
if (lineIndex == 0 && layout.lineCount > 1 && !isTitle) {
//第一行
addCharsToLineFirst(textLine, words, contentPaint, desiredWidth)
addCharsToLineFirst(textLine, words, textPaint, desiredWidth)
} else if (lineIndex == layout.lineCount - 1) {
//最后一行
addCharsToLineLast(textLine, words, stringBuilder, contentPaint, 0f)
val x = if (isTitle && ReadBookConfig.titleCenter)
(visibleWidth - layout.getLineWidth(lineIndex)) / 2
else 0f
addCharsToLineLast(textLine, words, stringBuilder, textPaint, x)
} else {
//中间行
addCharsToLineMiddle(textLine, words, contentPaint, desiredWidth, 0f)
addCharsToLineMiddle(textLine, words, textPaint, desiredWidth, 0f)
}
}
durY += paragraphSpacing
@ -346,7 +292,7 @@ object ChapterProvider {
val bold = if (ReadBookConfig.textBold) Typeface.BOLD else Typeface.NORMAL
contentPaint.typeface = Typeface.create(typeface, bold)
//间距
lineSpacingExtra = ReadBookConfig.lineSpacingExtra.dp.toFloat()
lineSpacingExtra = ReadBookConfig.lineSpacingExtra.dp
paragraphSpacing = ReadBookConfig.paragraphSpacing.dp
titlePaint.textSize = (ReadBookConfig.textSize + 2).dp.toFloat()
contentPaint.textSize = ReadBookConfig.textSize.dp.toFloat()
@ -366,4 +312,8 @@ object ChapterProvider {
visibleBottom = paddingTop + visibleHeight
}
private val TextPaint.textHeight: Float
get() {
return this.fontMetrics.descent - fontMetrics.ascent + fontMetrics.leading
}
}

@ -1,11 +1,12 @@
package io.legado.app.ui.book.read.page.delegate
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.drawable.GradientDrawable
import io.legado.app.ui.book.read.page.PageView
class CoverPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageView) {
private val bitmapMatrix = Matrix()
private val shadowDrawableR: GradientDrawable
init {
@ -16,13 +17,6 @@ class CoverPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageView) {
shadowDrawableR.gradientType = GradientDrawable.LINEAR_GRADIENT
}
override fun setStartPoint(x: Float, y: Float, invalidate: Boolean) {
curPage.x = 0.toFloat()
prevPage.x = -viewWidth.toFloat()
nextPage.x = 0.toFloat()
super.setStartPoint(x, y, invalidate)
}
override fun onDraw(canvas: Canvas) {
val offsetX = touchX - startX
@ -33,10 +27,14 @@ class CoverPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageView) {
val distanceX = if (offsetX > 0) offsetX - viewWidth else offsetX + viewWidth
if (!isRunning) return
if (mDirection == Direction.PREV) {
prevPage.translationX = offsetX - viewWidth
bitmapMatrix.setTranslate(distanceX, 0.toFloat())
curBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
prevBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) }
addShadow(distanceX.toInt(), canvas)
} else if (mDirection == Direction.NEXT) {
curPage.translationX = offsetX
bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat())
nextBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) }
addShadow(distanceX.toInt(), canvas)
}
}
@ -52,8 +50,6 @@ class CoverPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageView) {
}
override fun onAnimStop() {
curPage.x = 0.toFloat()
prevPage.x = -viewWidth.toFloat()
if (!isCancel) {
pageView.fillPage(mDirection)
}

@ -1,11 +1,40 @@
package io.legado.app.ui.book.read.page.delegate
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) {
protected var curBitmap: Bitmap? = null
protected var prevBitmap: Bitmap? = null
protected var nextBitmap: Bitmap? = null
override fun setDirection(direction: Direction) {
super.setDirection(direction)
setBitmap()
}
private fun setBitmap() {
when (mDirection) {
Direction.PREV -> {
prevBitmap?.recycle()
prevBitmap = prevPage.screenshot()
curBitmap?.recycle()
curBitmap = curPage.screenshot()
}
Direction.NEXT -> {
nextBitmap?.recycle()
nextBitmap = nextPage.screenshot()
curBitmap?.recycle()
curBitmap = curPage.screenshot()
}
else -> Unit
}
}
override fun onTouch(event: MotionEvent) {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
@ -69,4 +98,14 @@ abstract class HorizontalPageDelegate(pageView: PageView) : PageDelegate(pageVie
onAnimStart()
}
override fun onDestroy() {
super.onDestroy()
prevBitmap?.recycle()
prevBitmap = null
curBitmap?.recycle()
curBitmap = null
nextBitmap?.recycle()
nextBitmap = null
}
}

@ -3,8 +3,8 @@ package io.legado.app.ui.book.read.page.delegate
import android.graphics.*
import android.graphics.drawable.GradientDrawable
import android.os.Build
import io.legado.app.help.ReadBookConfig
import io.legado.app.ui.book.read.page.PageView
import io.legado.app.utils.screenshot
import kotlin.math.*
@Suppress("DEPRECATION")
@ -73,10 +73,6 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
private val mPaint: Paint = Paint().apply { style = Paint.Style.FILL }
private var curBitmap: Bitmap? = null
private var prevBitmap: Bitmap? = null
private var nextBitmap: Bitmap? = null
init {
//设置颜色数组
val color = intArrayOf(0x333333, -0x4fcccccd)
@ -118,31 +114,21 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
mMaxLength = hypot(viewWidth.toDouble(), viewHeight.toDouble()).toFloat()
}
override fun onDestroy() {
super.onDestroy()
prevBitmap?.recycle()
prevBitmap = null
curBitmap?.recycle()
curBitmap = null
nextBitmap?.recycle()
nextBitmap = null
}
override fun setStartPoint(x: Float, y: Float, invalidate: Boolean) {
super.setStartPoint(x, y, invalidate)
super.setStartPoint(x, y, false)
calcCornerXY(x, y)
}
override fun setTouchPoint(x: Float, y: Float, invalidate: Boolean) {
super.setTouchPoint(x, y, false)
//触摸y中间位置吧y变成屏幕高度
if ((startY > viewHeight / 3.0 && startY < viewHeight * 2 / 3.0)
if ((startY > viewHeight / 3 && startY < viewHeight * 2 / 3)
|| mDirection == Direction.PREV
) {
touchY = viewHeight.toFloat()
}
if (startY > viewHeight / 3.0 && startY < viewHeight / 2.0
if (startY > viewHeight / 3 && startY < viewHeight / 2
&& mDirection == Direction.NEXT
) {
touchY = 1f
@ -152,37 +138,22 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
override fun setDirection(direction: Direction) {
super.setDirection(direction)
setBitmap()
when (direction) {
Direction.PREV ->
//上一页滑动不出现对角
if (startX > viewWidth / 2.0) {
if (startX > viewWidth / 2) {
calcCornerXY(startX, viewHeight.toFloat())
} else {
calcCornerXY(viewWidth - startX, viewHeight.toFloat())
}
Direction.NEXT ->
if (viewWidth / 2.0 > startX) {
if (viewWidth / 2 > startX) {
calcCornerXY(viewWidth - startX, startY)
}
else -> Unit
}
}
private fun setBitmap() {
when (mDirection) {
Direction.PREV -> {
prevBitmap = prevPage.screenshot()
curBitmap = curPage.screenshot()
}
Direction.NEXT -> {
nextBitmap = nextPage.screenshot()
curBitmap = curPage.screenshot()
}
else -> Unit
}
}
override fun onAnimStart() {
var dx: Float
val dy: Float
@ -223,6 +194,7 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
}
override fun onDraw(canvas: Canvas) {
if (!isRunning) return
when (mDirection) {
Direction.NEXT -> {
calcPoints()
@ -297,6 +269,7 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
mMatrix.setValues(mMatrixArray)
mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y)
mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y)
canvas.drawColor(ReadBookConfig.bgMeanColor)
canvas.drawBitmap(bitmap, mMatrix, mPaint)
mPaint.colorFilter = null
canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y)
@ -485,8 +458,8 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
* 计算拖拽点对应的拖拽脚
*/
private fun calcCornerXY(x: Float, y: Float) {
mCornerX = if (x <= viewWidth / 2.0) 0 else viewWidth
mCornerY = if (y <= viewHeight / 2.0) 0 else viewHeight
mCornerX = if (x <= viewWidth / 2) 0 else viewWidth
mCornerY = if (y <= viewHeight / 2) 0 else viewHeight
mIsRtOrLb = (mCornerX == 0 && mCornerY == viewHeight)
|| (mCornerY == 0 && mCornerX == viewWidth)
}
@ -497,21 +470,23 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
mMiddleX = (mTouchX + mCornerX) / 2
mMiddleY = (mTouchY + mCornerY) / 2
mBezierControl1.x =
mMiddleX - (mCornerY - mMiddleY) * (mCornerY - mMiddleY) / (mCornerX - mMiddleX)
mBezierControl1.y = mCornerY.toFloat()
mBezierControl2.x = mCornerX.toFloat()
mBezierControl2.y = if ((mCornerY - mMiddleY).toInt() == 0) {
mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1f
val f4 = mCornerY - mMiddleY
if (f4 == 0f) {
mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1f
} else {
mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY)
mBezierControl2.y =
mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY)
}
mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) / 2
mBezierStart1.y = mCornerY.toFloat()
//固定左边上下两个点
// 固定左边上下两个点
if (mTouchX > 0 && mTouchX < viewWidth) {
if (mBezierStart1.x < 0 || mBezierStart1.x > viewWidth) {
if (mBezierStart1.x < 0)
@ -520,6 +495,7 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
val f1 = abs(mCornerX - mTouchX)
val f2 = viewWidth * f1 / mBezierStart1.x
mTouchX = abs(mCornerX - f2)
val f3 = abs(mCornerX - mTouchX) * abs(mCornerY - mTouchY) / f1
mTouchY = abs(mCornerY - f3)
@ -531,10 +507,14 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
mBezierControl1.y = mCornerY.toFloat()
mBezierControl2.x = mCornerX.toFloat()
mBezierControl2.y = if ((mCornerY - mMiddleY).toInt() == 0) {
mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1f
val f5 = mCornerY - mMiddleY
if (f5 == 0f) {
mBezierControl2.y =
mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1f
} else {
mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY)
mBezierControl2.y =
mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / (mCornerY - mMiddleY)
}
mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x) / 2
@ -543,12 +523,19 @@ class SimulationPageDelegate(pageView: PageView) : HorizontalPageDelegate(pageVi
mBezierStart2.x = mCornerX.toFloat()
mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y) / 2
mTouchToCornerDis = hypot(mTouchX - mCornerX, touchY - mCornerY)
mTouchToCornerDis = hypot(
(mTouchX - mCornerX).toDouble(),
(mTouchY - mCornerY).toDouble()
).toFloat()
mBezierEnd1 =
getCross(PointF(mTouchX, mTouchY), mBezierControl1, mBezierStart1, mBezierStart2)
mBezierEnd2 =
getCross(PointF(mTouchX, mTouchY), mBezierControl2, mBezierStart1, mBezierStart2)
mBezierEnd1 = getCross(
PointF(mTouchX, mTouchY), mBezierControl1, mBezierStart1,
mBezierStart2
)
mBezierEnd2 = getCross(
PointF(mTouchX, mTouchY), mBezierControl2, mBezierStart1,
mBezierStart2
)
mBezierVertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4
mBezierVertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4

@ -1,16 +1,12 @@
package io.legado.app.ui.book.read.page.delegate
import android.graphics.Canvas
import android.graphics.Matrix
import io.legado.app.ui.book.read.page.PageView
class SlidePageDelegate(pageView: PageView) : HorizontalPageDelegate(pageView) {
override fun setStartPoint(x: Float, y: Float, invalidate: Boolean) {
curPage.x = 0f
prevPage.x = -viewWidth.toFloat()
nextPage.x = viewWidth.toFloat()
super.setStartPoint(x, y, invalidate)
}
private val bitmapMatrix = Matrix()
override fun onAnimStart() {
val distanceX: Float
@ -41,21 +37,22 @@ class SlidePageDelegate(pageView: PageView) : HorizontalPageDelegate(pageView) {
if ((mDirection == Direction.NEXT && offsetX > 0)
|| (mDirection == Direction.PREV && offsetX < 0)
) return
val distanceX = if (offsetX > 0) offsetX - viewWidth else offsetX + viewWidth
if (!isRunning) return
if (mDirection == Direction.PREV) {
curPage.translationX = offsetX
prevPage.translationX = offsetX - viewWidth
bitmapMatrix.setTranslate(distanceX + viewWidth, 0.toFloat())
curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) }
bitmapMatrix.setTranslate(distanceX, 0.toFloat())
prevBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) }
} else if (mDirection == Direction.NEXT) {
curPage.translationX = offsetX
nextPage.translationX = offsetX + viewWidth
bitmapMatrix.setTranslate(distanceX, 0.toFloat())
nextBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) }
bitmapMatrix.setTranslate(distanceX - viewWidth, 0.toFloat())
curBitmap?.let { canvas.drawBitmap(it, bitmapMatrix, null) }
}
}
override fun onAnimStop() {
curPage.x = 0f
prevPage.x = -viewWidth.toFloat()
nextPage.x = viewWidth.toFloat()
if (!isCancel) {
pageView.fillPage(mDirection)
}

@ -14,7 +14,7 @@ data class TextPage(
var pageSize: Int = 0,
var chapterSize: Int = 0,
var chapterIndex: Int = 0,
var height: Int = 0
var height: Float = 0f
) {
@Suppress("DEPRECATION")
@ -46,7 +46,7 @@ data class TextPage(
}
textLines.add(textLine)
}
height = ChapterProvider.visibleHeight
height = ChapterProvider.visibleHeight.toFloat()
}
return this
}

@ -16,6 +16,7 @@ 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
@ -128,6 +129,7 @@ class MainActivity : VMBaseActivity<MainViewModel>(R.layout.activity_main),
override fun finish() {
if (!BuildConfig.DEBUG) {
SyncBookProgress.uploadBookProgress()
Backup.autoBack(this)
}
super.finish()

@ -8,6 +8,7 @@ import io.legado.app.R
import io.legado.app.base.BaseActivity
import io.legado.app.help.AppConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.storage.SyncBookProgress
import io.legado.app.lib.theme.accentColor
import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.main.MainActivity
@ -41,6 +42,7 @@ open class WelcomeActivity : BaseActivity(R.layout.activity_welcome) {
else -> null
}
}
SyncBookProgress.downloadBookProgress()
root_view.postDelayed({ startMainActivity() }, 300)
}

@ -5,6 +5,7 @@ import android.graphics.Bitmap
import android.graphics.Bitmap.Config
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Color
import android.renderscript.Allocation
import android.renderscript.Element
import android.renderscript.RenderScript
@ -12,10 +13,7 @@ import android.renderscript.ScriptIntrinsicBlur
import android.view.View
import io.legado.app.App
import java.io.IOException
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.min
import kotlin.math.sqrt
import kotlin.math.*
@Suppress("unused", "WeakerAccess")
@ -257,4 +255,31 @@ object BitmapUtils {
return blurredBitmap
}
fun getMeanColor(bitmap: Bitmap): Int {
val width: Int = bitmap.width
val height: Int = bitmap.height
var pixel: Int
var pixelSumRed = 0
var pixelSumBlue = 0
var pixelSumGreen = 0
for (i in 0..99) {
for (j in 70..99) {
pixel = bitmap.getPixel(
(i * width / 100.toFloat()).roundToInt(),
(j * height / 100.toFloat()).roundToInt()
)
pixelSumRed += Color.red(pixel)
pixelSumGreen += Color.green(pixel)
pixelSumBlue += Color.blue(pixel)
}
}
val averagePixelRed = pixelSumRed / 3000
val averagePixelBlue = pixelSumBlue / 3000
val averagePixelGreen = pixelSumGreen / 3000
return Color.rgb(
averagePixelRed + 3,
averagePixelGreen + 3, averagePixelBlue + 3
)
}
}

@ -614,7 +614,7 @@
<string name="selectText">长按选择文本</string>
<string name="header">页眉</string>
<string name="main_body">正文</string>
<string name="footer"></string>
<string name="footer"></string>
<string name="select_end">文本选择结束位置</string>
<string name="select_start">文本选择开始位置</string>
<string name="share_layout">共用布局</string>

@ -24,6 +24,13 @@
android:summary="@string/web_dav_pw_s"
app:iconSpaceReserved="false" />
<io.legado.app.ui.widget.prefs.SwitchPreference
android:key="webDavCreateDir"
android:defaultValue="true"
android:title="创建子文件夹"
android:summary="创建legado文件夹作为备份文件夹"
app:iconSpaceReserved="false" />
</io.legado.app.ui.widget.prefs.PreferenceCategory>
<io.legado.app.ui.widget.prefs.PreferenceCategory app:iconSpaceReserved="false">

Loading…
Cancel
Save