Skip to content

Commit

Permalink
Merge branch 'gedoor:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
niu-hb authored Feb 15, 2024
2 parents 60fa348 + 7bf089a commit 4095f83
Show file tree
Hide file tree
Showing 27 changed files with 530 additions and 363 deletions.
1 change: 0 additions & 1 deletion app/src/main/java/io/legado/app/constant/PreferKey.kt
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ object PreferKey {
const val welcomeShowIconDark = "welcomeShowIconDark"
const val pageTouchSlop = "pageTouchSlop"
const val showAddToShelfAlert = "showAddToShelfAlert"
const val asyncLoadImage = "asyncLoadImage"
const val ignoreAudioFocus = "ignoreAudioFocus"
const val parallelExportBook = "parallelExportBook"
const val progressBarBehavior = "progressBarBehavior"
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/io/legado/app/help/config/AppConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
}
}

val textSelectAble: Boolean
get() = appCtx.getPrefBoolean(PreferKey.textSelectAble, true)

val isTransparentStatusBar: Boolean
get() = appCtx.getPrefBoolean(PreferKey.transparentStatusBar, true)

Expand Down Expand Up @@ -457,8 +460,6 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {

val showAddToShelfAlert get() = appCtx.getPrefBoolean(PreferKey.showAddToShelfAlert, true)

val asyncLoadImage get() = appCtx.getPrefBoolean(PreferKey.asyncLoadImage, false)

val ignoreAudioFocus get() = appCtx.getPrefBoolean(PreferKey.ignoreAudioFocus, false)

val onlyLatestBackup get() = appCtx.getPrefBoolean(PreferKey.onlyLatestBackup, true)
Expand Down
48 changes: 3 additions & 45 deletions app/src/main/java/io/legado/app/model/ImageProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,19 @@ package io.legado.app.model

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import android.util.Size
import androidx.collection.LruCache
import io.legado.app.R
import io.legado.app.constant.AppLog
import io.legado.app.constant.AppLog.putDebug
import io.legado.app.constant.PageAnim
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookSource
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.book.BookHelp
import io.legado.app.help.book.isEpub
import io.legado.app.help.book.isPdf
import io.legado.app.help.config.AppConfig
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.localBook.EpubFile
import io.legado.app.model.localBook.PdfFile
import io.legado.app.utils.BitmapCache
import io.legado.app.utils.BitmapUtils
import io.legado.app.utils.FileUtils
import io.legado.app.utils.SvgUtils
Expand All @@ -29,8 +24,6 @@ import kotlinx.coroutines.withContext
import splitties.init.appCtx
import java.io.File
import java.io.FileOutputStream
import java.util.concurrent.ConcurrentHashMap
import kotlin.math.min

object ImageProvider {

Expand All @@ -50,12 +43,6 @@ object ImageProvider {
}
return AppConfig.bitmapCacheSize * M
}
private val maxCacheSize = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
min(128 * M, Runtime.getRuntime().maxMemory().toInt())
} else {
256 * M
}
private val asyncLoadingImages = ConcurrentHashMap.newKeySet<String>()
val bitmapLruCache = object : LruCache<String, Bitmap>(cacheSize) {

override fun sizeOf(filePath: String, bitmap: Bitmap): Int {
Expand All @@ -70,8 +57,7 @@ object ImageProvider {
) {
//错误图片不能释放,占位用,防止一直重复获取图片
if (oldBitmap != errorBitmap) {
BitmapCache.add(oldBitmap)
//oldBitmap.recycle()
oldBitmap.recycle()
//putDebug("ImageProvider: trigger bitmap recycle. URI: $filePath")
//putDebug("ImageProvider : cacheUsage ${size()}bytes / ${maxSize()}bytes")
}
Expand Down Expand Up @@ -160,9 +146,8 @@ object ImageProvider {
book: Book,
src: String,
width: Int,
height: Int? = null,
block: (() -> Unit)? = null
): Bitmap? {
height: Int? = null
): Bitmap {
//src为空白时 可能被净化替换掉了 或者规则失效
if (book.getUseReplaceRule() && src.isBlank()) {
book.setUseReplaceRule(false)
Expand All @@ -174,32 +159,6 @@ object ImageProvider {
//bitmapLruCache的key同一改成缓存文件的路径
val cacheBitmap = getNotRecycled(vFile.absolutePath)
if (cacheBitmap != null) return cacheBitmap
if (height != null && AppConfig.asyncLoadImage && ReadBook.pageAnim() == PageAnim.scrollPageAnim) {
if (asyncLoadingImages.contains(vFile.absolutePath)) {
return null
}
asyncLoadingImages.add(vFile.absolutePath)
Coroutine.async {
BitmapUtils.decodeBitmap(vFile.absolutePath, width, height)
?: SvgUtils.createBitmap(vFile.absolutePath, width, height)
?: throw NoStackTraceException(appCtx.getString(R.string.error_decode_bitmap))
}.onSuccess {
bitmapLruCache.run {
if (maxSize() < maxCacheSize && size() + it.byteCount > maxSize() && putCount() - evictionCount() < 5) {
resize(min(maxCacheSize, maxSize() + it.byteCount))
AppLog.put("图片缓存太小,自动扩增至${(maxSize() / M)}MB。")
}
}
bitmapLruCache.put(vFile.absolutePath, it)
}.onError {
//错误图片占位,防止重复获取
bitmapLruCache.put(vFile.absolutePath, errorBitmap)
}.onFinally {
asyncLoadingImages.remove(vFile.absolutePath)
block?.invoke()
}
return null
}
return kotlin.runCatching {
val bitmap = BitmapUtils.decodeBitmap(vFile.absolutePath, width, height)
?: SvgUtils.createBitmap(vFile.absolutePath, width, height)
Expand All @@ -214,7 +173,6 @@ object ImageProvider {

fun clear() {
bitmapLruCache.evictAll()
BitmapCache.clear()
}

}
58 changes: 32 additions & 26 deletions app/src/main/java/io/legado/app/model/ReadBook.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import splitties.init.appCtx
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.math.min


Expand Down Expand Up @@ -63,6 +65,7 @@ object ReadBook : CoroutineScope by MainScope() {
val downloadFailChapters = hashMapOf<Int, Int>()
var contentProcessor: ContentProcessor? = null
val downloadScope = CoroutineScope(SupervisorJob() + IO)
val executor: ExecutorService = Executors.newSingleThreadExecutor()

//暂时保存跳转前进度
fun saveCurrentBookProcess() {
Expand Down Expand Up @@ -158,10 +161,10 @@ object ReadBook : CoroutineScope by MainScope() {
}

fun upReadTime() {
if (!AppConfig.enableReadRecord) {
return
}
Coroutine.async(executeContext = IO) {
executor.execute {
if (!AppConfig.enableReadRecord) {
return@execute
}
readRecord.readTime = readRecord.readTime + System.currentTimeMillis() - readStartTime
readStartTime = System.currentTimeMillis()
readRecord.lastRead = System.currentTimeMillis()
Expand Down Expand Up @@ -275,7 +278,7 @@ object ReadBook : CoroutineScope by MainScope() {
textChapter.getPage(index - 2)?.recyclePictures()
}
if (index < pageIndex) {
textChapter.getPage(index + 2)?.recyclePictures()
textChapter.getPage(index + 3)?.recyclePictures()
}
}
durChapterPos = curTextChapter?.getReadLength(index) ?: index
Expand Down Expand Up @@ -536,8 +539,8 @@ object ReadBook : CoroutineScope by MainScope() {
}

fun saveRead(pageChanged: Boolean = false) {
Coroutine.async(executeContext = IO) {
val book = book ?: return@async
executor.execute {
val book = book ?: return@execute
book.lastCheckCount = 0
book.durChapterTime = System.currentTimeMillis()
val chapterChanged = book.durChapterIndex != durChapterIndex
Expand All @@ -560,26 +563,29 @@ object ReadBook : CoroutineScope by MainScope() {
*/
private fun preDownload() {
if (book?.isLocal == true) return
if (AppConfig.preDownloadNum < 2) {
return
}
preDownloadTask?.cancel()
preDownloadTask = Coroutine.async(executeContext = IO) {
//预下载
launch {
val maxChapterIndex = min(durChapterIndex + AppConfig.preDownloadNum, chapterSize)
for (i in durChapterIndex.plus(2)..maxChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)
}
executor.execute {
if (AppConfig.preDownloadNum < 2) {
return@execute
}
launch {
val minChapterIndex = durChapterIndex - min(5, AppConfig.preDownloadNum)
for (i in durChapterIndex.minus(2) downTo minChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)
preDownloadTask?.cancel()
preDownloadTask = Coroutine.async(executeContext = IO) {
//预下载
launch {
val maxChapterIndex =
min(durChapterIndex + AppConfig.preDownloadNum, chapterSize)
for (i in durChapterIndex.plus(2)..maxChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)
}
}
launch {
val minChapterIndex = durChapterIndex - min(5, AppConfig.preDownloadNum)
for (i in durChapterIndex.minus(2) downTo minChapterIndex) {
if (downloadedChapters.contains(i)) continue
if ((downloadFailChapters[i] ?: 0) >= 3) continue
downloadIndex(i)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class HttpReadAloudService : BaseReadAloudService(),
playIndexJob?.cancel()
}

private fun playNext() {
private fun updateNextPos() {
readAloudNumber += contentList[nowSpeak].length + 1 - paragraphStartPos
paragraphStartPos = 0
if (nowSpeak < contentList.lastIndex) {
Expand Down Expand Up @@ -355,14 +355,14 @@ class HttpReadAloudService : BaseReadAloudService(),
Player.STATE_ENDED -> {
// 结束
playErrorNo = 0
playNext()
updateNextPos()
}
}
}

override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED) return
playNext()
updateNextPos()
upPlayPos()
}

Expand All @@ -375,7 +375,8 @@ class HttpReadAloudService : BaseReadAloudService(),
AppLog.put("朗读连续5次错误, 最后一次错误代码(${error.localizedMessage})", error)
ReadAloud.pause(this)
} else {
playNext()
updateNextPos()
exoPlayer.seekToNextMediaItem()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ abstract class BaseReadBookActivity :
override val binding by viewBinding(ActivityBookReadBinding::inflate)
override val viewModel by viewModels<ReadBookViewModel>()
var bottomDialog = 0
set(value) {
if (field != value) {
field = value
onBottomDialogChange()
}
}
private val selectBookFolderResult = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
ReadBook.book?.let { book ->
Expand Down Expand Up @@ -94,6 +100,21 @@ abstract class BaseReadBookActivity :
}
}

private fun onBottomDialogChange() {
when (bottomDialog) {
0 -> onMenuHide()
1 -> onMenuShow()
}
}

open fun onMenuShow() {

}

open fun onMenuHide() {

}

fun showPaddingConfig() {
showDialogFragment<PaddingConfigDialog>()
}
Expand Down
Loading

0 comments on commit 4095f83

Please sign in to comment.