diff --git a/app/build.gradle b/app/build.gradle index 6741567bb..dee80474e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,6 +37,11 @@ android { versionName version testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" project.ext.set("archivesBaseName", name + "_" + version) + javaCompileOptions { + annotationProcessorOptions { + arguments = ["room.incremental":"true"] + } + } } buildTypes { release { diff --git a/app/src/debug/google-services .json b/app/src/debug/google-services .json deleted file mode 100644 index 8cc19b1d5..000000000 --- a/app/src/debug/google-services .json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "project_info": { - "project_number": "453392274790", - "firebase_url": "https://legado-fca69.firebaseio.com", - "project_id": "legado-fca69", - "storage_bucket": "legado-fca69.appspot.com" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:453392274790:android:1d2b1eefbe0e78cff624a7", - "android_client_info": { - "package_name": "io.legado.app" - } - }, - "oauth_client": [ - { - "client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyD90mfNLhA7cAzzI9SonpSz5mrF5BnmyJA" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:453392274790:android:c4eac14b1410eec5f624a7", - "android_client_info": { - "package_name": "io.legado.app.debug" - } - }, - "oauth_client": [ - { - "client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyD90mfNLhA7cAzzI9SonpSz5mrF5BnmyJA" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "453392274790-hnbpatpce9hbjiggj76hgo7queu86atq.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - } - ], - "configuration_version": "1" -} \ No newline at end of file diff --git a/app/google-services .json b/app/src/debug/google-services.json similarity index 100% rename from app/google-services .json rename to app/src/debug/google-services.json diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8ce35a34b..230455575 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -56,12 +56,24 @@ android:configChanges="locale|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize|stateHidden" /> - - - - - - + + + + + + @@ -79,7 +91,9 @@ - + diff --git a/app/src/main/java/io/legado/app/data/dao/BookDao.kt b/app/src/main/java/io/legado/app/data/dao/BookDao.kt index ba1d7e67e..2a356e933 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookDao.kt @@ -53,4 +53,6 @@ interface BookDao { @Query("delete from books where bookUrl = :bookUrl") fun delete(bookUrl: String) + @Query("update books set durChapterPos = :pos where bookUrl = :bookUrl") + fun upProgress(bookUrl: String, pos: Int) } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/BlurTransformation.kt b/app/src/main/java/io/legado/app/help/BlurTransformation.kt index 9d60a9047..fec7d0eef 100644 --- a/app/src/main/java/io/legado/app/help/BlurTransformation.kt +++ b/app/src/main/java/io/legado/app/help/BlurTransformation.kt @@ -13,17 +13,23 @@ import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool import com.bumptech.glide.load.resource.bitmap.BitmapTransformation import java.security.MessageDigest +import kotlin.math.min +import kotlin.math.roundToInt + /** * 模糊 + * @radius: 0..25 */ class BlurTransformation(context: Context, private val radius: Int) : BitmapTransformation() { private val rs: RenderScript = RenderScript.create(context) @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap { - val blurredBitmap = toTransform.copy(Bitmap.Config.ARGB_8888, true) - + //图片缩小1/2 + val width = (min(outWidth, toTransform.width) / 2f).roundToInt() + val height = (min(outHeight, toTransform.height) / 2f).roundToInt() + val blurredBitmap = Bitmap.createScaledBitmap(toTransform, width, height, false); // Allocate memory for Renderscript to work with //分配用于渲染脚本的内存 val input = Allocation.createFromBitmap( @@ -40,7 +46,7 @@ class BlurTransformation(context: Context, private val radius: Int) : BitmapTran script.setInput(input) // Set the blur radius - //设置模糊半径 + //设置模糊半径0..25 script.setRadius(radius.toFloat()) // Start the ScriptIntrinsicBlur diff --git a/app/src/main/java/io/legado/app/help/ImageLoader.kt b/app/src/main/java/io/legado/app/help/ImageLoader.kt index 836cb6e1d..26a9063d6 100644 --- a/app/src/main/java/io/legado/app/help/ImageLoader.kt +++ b/app/src/main/java/io/legado/app/help/ImageLoader.kt @@ -4,264 +4,45 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.net.Uri -import android.widget.ImageView import androidx.annotation.DrawableRes import com.bumptech.glide.Glide import com.bumptech.glide.RequestBuilder -import com.bumptech.glide.RequestManager -import com.bumptech.glide.load.Transformation -import com.bumptech.glide.load.engine.DiskCacheStrategy -import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions -import com.bumptech.glide.load.resource.bitmap.CenterCrop -import com.bumptech.glide.load.resource.bitmap.RoundedCorners -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions -import com.bumptech.glide.load.resource.gif.GifDrawable -import com.bumptech.glide.request.RequestOptions -import com.bumptech.glide.request.transition.Transition import java.io.File object ImageLoader { - fun load(context: Context, url: String?): ImageLoadBuilder { - return ImageLoadBuilder(context, url) - } - - fun load(context: Context, @DrawableRes resId: Int?): ImageLoadBuilder { - return ImageLoadBuilder(context, resId) - } - - fun load(context: Context, file: File?): ImageLoadBuilder { - return ImageLoadBuilder(context, file) - } - - fun load(context: Context, uri: Uri?): ImageLoadBuilder { - return ImageLoadBuilder(context, uri) - } - - fun load(context: Context, drawable: Drawable?): ImageLoadBuilder { - return ImageLoadBuilder(context, drawable) + fun load(context: Context, path: String?): RequestBuilder { + if (path?.startsWith("http", true) == true) { + return Glide.with(context).load(path) + } + kotlin.runCatching { + return Glide.with(context).load(File(path)) + } + return Glide.with(context).load(path) } - fun load(context: Context, bitmap: Bitmap?): ImageLoadBuilder { - return ImageLoadBuilder(context, bitmap) + fun load(context: Context, @DrawableRes resId: Int?): RequestBuilder { + return Glide.with(context).load(resId) } - fun load(context: Context, bytes: ByteArray?): ImageLoadBuilder { - return ImageLoadBuilder(context, bytes) + fun load(context: Context, file: File?): RequestBuilder { + return Glide.with(context).load(file) } - - fun with(context: Context): ImageLoadBuilder { - return ImageLoadBuilder(context) + fun load(context: Context, uri: Uri?): RequestBuilder { + return Glide.with(context).load(uri) } - fun clear(imageView: ImageView) { - with(imageView.context).clear(imageView) + fun load(context: Context, drawable: Drawable?): RequestBuilder { + return Glide.with(context).load(drawable) } - class ImageLoadBuilder constructor(context: Context, private var source: S? = null) { - - private val manager: RequestManager = Glide.with(context) - private var requestOptions: RequestOptions = RequestOptions() - private var crossFade: Boolean = false - private var noCache: Boolean = false - - fun load(source: S): ImageLoadBuilder { - this.source = source - return this - } - - fun bitmapTransform(transformation: Transformation): ImageLoadBuilder { - requestOptions = requestOptions.apply(RequestOptions.bitmapTransform(transformation)) - return this - } - - fun toRound(corner: Int): ImageLoadBuilder { - requestOptions = requestOptions.transform(RoundedCorners(corner)) - return this - } - - fun toCropRound(corner: Int): ImageLoadBuilder { - requestOptions = requestOptions.transform(CenterCrop(), RoundedCorners(corner)) - return this - } - - fun toCircle(): ImageLoadBuilder { - requestOptions = requestOptions.circleCrop() - return this - } - - fun centerInside(): ImageLoadBuilder { - requestOptions = requestOptions.centerInside() - return this - } - - fun fitCenter(): ImageLoadBuilder { - requestOptions = requestOptions.fitCenter() - return this - } - - fun centerCrop(): ImageLoadBuilder { - requestOptions = requestOptions.centerCrop() - return this - } - - fun crossFade(): ImageLoadBuilder { - crossFade = true - return this - } - - fun noCache(): ImageLoadBuilder { - noCache = true - return this - } - - fun placeholder(placeholder: Drawable): ImageLoadBuilder { - requestOptions = requestOptions.placeholder(placeholder) - return this - } - - fun placeholder(@DrawableRes resId: Int): ImageLoadBuilder { - requestOptions = requestOptions.placeholder(resId) - return this - } - - fun error(drawable: Drawable): ImageLoadBuilder { - requestOptions = requestOptions.error(drawable) - return this - } - - fun error(@DrawableRes resId: Int): ImageLoadBuilder { - requestOptions = requestOptions.error(resId) - return this - } - - fun override(width: Int, height: Int): ImageLoadBuilder { - requestOptions = requestOptions.override(width, height) - return this - } - - fun override(size: Int): ImageLoadBuilder { - requestOptions = requestOptions.override(size) - return this - } - - fun clear(imageView: ImageView) { - manager.clear(imageView) - } - - fun downloadOnly(target: ImageViewTarget) { - manager.downloadOnly().load(source).into(Target(target)) - } - - fun setAsDrawable(imageView: ImageView) { - asDrawable().into(imageView) - } - - fun setAsDrawable(target: ImageViewTarget) { - asDrawable().into(Target(target)) - } - - fun setAsBitmap(imageView: ImageView) { - asBitmap().into(imageView) - } - - fun setAsBitmap(target: ImageViewTarget) { - asBitmap().into(Target(target)) - } - - fun setAsGif(imageView: ImageView) { - asGif().into(imageView) - } - - fun setAsGif(target: ImageViewTarget) { - asGif().into(Target(target)) - } - - fun setAsFile(imageView: ImageView) { - asFile().into(imageView) - } - - fun setAsFile(target: ImageViewTarget) { - asFile().into(Target(target)) - } - - private fun asDrawable(): RequestBuilder { - var builder: RequestBuilder = ensureOptions(manager.asDrawable().load(source)) - - if (crossFade) { - builder = builder.transition(DrawableTransitionOptions.withCrossFade()) - } - - return builder - } - - private fun asBitmap(): RequestBuilder { - var builder: RequestBuilder = ensureOptions(manager.asBitmap().load(source)) - - if (crossFade) { - builder = builder.transition(BitmapTransitionOptions.withCrossFade()) - } - - return builder - } - - private fun asGif(): RequestBuilder { - var builder: RequestBuilder = ensureOptions(manager.asGif().load(source)) - - if (crossFade) { - builder = builder.transition(DrawableTransitionOptions.withCrossFade()) - } - - return builder - } - - private fun asFile(): RequestBuilder { - return manager.asFile().load(source) - } - - private fun ensureOptions(builder: RequestBuilder): RequestBuilder { - return builder.apply(requestOptions.diskCacheStrategy(if (noCache) DiskCacheStrategy.NONE else DiskCacheStrategy.AUTOMATIC)) - } - - private inner class Target constructor(private val target: ImageViewTarget) : - com.bumptech.glide.request.target.ImageViewTarget(target.view) { - - init { - if (this.target.waitForLayout) { - waitForLayout() - } - } - - override fun onResourceReady(resource: R, transition: Transition?) { - if (!target.onResourceReady(resource)) { - super.onResourceReady(resource, transition) - } - } - - override fun setResource(resource: R?) { - target.setResource(resource) - } - } + fun load(context: Context, bitmap: Bitmap?): RequestBuilder { + return Glide.with(context).load(bitmap) } - abstract class ImageViewTarget(val view: ImageView) { - internal var waitForLayout: Boolean = false - - fun waitForLayout(): ImageViewTarget { - waitForLayout = true - return this - } - - fun setResource(resource: R?) { - - } - - fun onResourceReady(resource: R?): Boolean { - return false - } - + fun load(context: Context, bytes: ByteArray?): RequestBuilder { + return Glide.with(context).load(bytes) } - } diff --git a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt index 1df892cda..330956351 100644 --- a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt +++ b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt @@ -4,11 +4,18 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.view.KeyEvent +import io.legado.app.App import io.legado.app.constant.Bus +import io.legado.app.data.entities.Book import io.legado.app.help.ActivityHelp import io.legado.app.ui.audio.AudioPlayActivity import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.utils.postEvent +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.Dispatchers.Main +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext /** @@ -33,15 +40,24 @@ class MediaButtonReceiver : BroadcastReceiver() { } private fun readAloud(context: Context) { - if (ActivityHelp.isExist(AudioPlayActivity::class.java)) { - postEvent(Bus.AUDIO_PLAY_BUTTON, true) - } else if (!ActivityHelp.isExist(ReadBookActivity::class.java)) { - val intent = Intent(context, ReadBookActivity::class.java) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - intent.putExtra("readAloud", true) - context.startActivity(intent) - } else { - postEvent(Bus.READ_ALOUD_BUTTON, true) + when { + ActivityHelp.isExist(AudioPlayActivity::class.java) -> + postEvent(Bus.AUDIO_PLAY_BUTTON, true) + ActivityHelp.isExist(ReadBookActivity::class.java) -> + postEvent(Bus.READ_ALOUD_BUTTON, true) + else -> { + GlobalScope.launch(Main) { + val lastBook: Book? = withContext(IO) { + App.db.bookDao().lastReadBook + } + lastBook?.let { + val intent = Intent(context, ReadBookActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + intent.putExtra("readAloud", true) + context.startActivity(intent) + } + } + } } } } diff --git a/app/src/main/java/io/legado/app/service/AudioPlayService.kt b/app/src/main/java/io/legado/app/service/AudioPlayService.kt index fb7e85e68..fb15d022d 100644 --- a/app/src/main/java/io/legado/app/service/AudioPlayService.kt +++ b/app/src/main/java/io/legado/app/service/AudioPlayService.kt @@ -24,6 +24,7 @@ import io.legado.app.help.IntentHelp import io.legado.app.help.MediaHelp import io.legado.app.receiver.MediaButtonReceiver import io.legado.app.ui.book.read.ReadBookActivity +import io.legado.app.utils.LogUtils import io.legado.app.utils.postEvent import kotlinx.coroutines.launch import org.jetbrains.anko.toast @@ -73,7 +74,7 @@ class AudioPlayService : BaseService(), Action.play -> { title = intent.getStringExtra("title") ?: "" subtitle = intent.getStringExtra("subtitle") ?: "" - position = intent.getIntExtra("pageIndex", 0) + position = intent.getIntExtra("position", 0) play(intent.getStringExtra("url")) } Action.pause -> pause(true) @@ -107,8 +108,10 @@ class AudioPlayService : BaseService(), mediaPlayer.setDataSource(url) mediaPlayer.prepareAsync() } catch (e: Exception) { + LogUtils.d("AudioPlayService", e.localizedMessage + " " + url) launch { toast(e.localizedMessage + " " + url) + stopSelf() } } } @@ -153,6 +156,9 @@ class AudioPlayService : BaseService(), } override fun onError(mp: MediaPlayer?, what: Int, extra: Int): Boolean { + launch { + toast("error: $what $extra") + } return true } diff --git a/app/src/main/java/io/legado/app/service/help/AudioPlay.kt b/app/src/main/java/io/legado/app/service/help/AudioPlay.kt index 48d3f5b15..10d6d6026 100644 --- a/app/src/main/java/io/legado/app/service/help/AudioPlay.kt +++ b/app/src/main/java/io/legado/app/service/help/AudioPlay.kt @@ -13,7 +13,7 @@ object AudioPlay { intent.putExtra("title", title) intent.putExtra("subtitle", subtitle) intent.putExtra("url", url) - intent.putExtra("dataKey", position) + intent.putExtra("position", position) context.startService(intent) } diff --git a/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt b/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt index d2a7e19ce..5fadc7be7 100644 --- a/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt +++ b/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt @@ -1,23 +1,38 @@ package io.legado.app.ui.audio +import android.app.Activity +import android.content.Intent +import android.graphics.drawable.Drawable import android.os.Bundle import android.widget.SeekBar import androidx.lifecycle.Observer +import com.bumptech.glide.RequestBuilder +import com.bumptech.glide.request.RequestOptions +import io.legado.app.BuildConfig import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.Bus import io.legado.app.constant.Status -import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.BlurTransformation import io.legado.app.help.ImageLoader +import io.legado.app.help.storage.Backup +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.service.help.AudioPlay +import io.legado.app.ui.chapterlist.ChapterListActivity +import io.legado.app.ui.main.MainActivity +import io.legado.app.utils.applyTint import io.legado.app.utils.getViewModel import io.legado.app.utils.observeEvent import kotlinx.android.synthetic.main.activity_audio_play.* import kotlinx.android.synthetic.main.view_title_bar.* +import org.apache.commons.lang3.time.DateFormatUtils import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onLongClick +import org.jetbrains.anko.startActivity +import org.jetbrains.anko.startActivityForResult class AudioPlayActivity : VMBaseActivity(R.layout.activity_audio_play), AudioPlayViewModel.CallBack { @@ -25,13 +40,15 @@ class AudioPlayActivity : VMBaseActivity(R.layout.activity_a override val viewModel: AudioPlayViewModel get() = getViewModel(AudioPlayViewModel::class.java) + private var requestCodeChapter = 8461 private var adjustProgress = false private var status = Status.STOP override fun onActivityCreated(savedInstanceState: Bundle?) { setSupportActionBar(toolbar) viewModel.callBack = this - viewModel.bookData.observe(this, Observer { upView(it) }) + viewModel.titleData.observe(this, Observer { title_bar.title = it }) + viewModel.coverData.observe(this, Observer { upCover(it) }) viewModel.initData(intent) initView() } @@ -45,14 +62,14 @@ class AudioPlayActivity : VMBaseActivity(R.layout.activity_a true } iv_skip_next.onClick { - + viewModel.moveToNext() } iv_skip_previous.onClick { - + viewModel.moveToPrev() } player_progress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { - + tv_dur_time.text = DateFormatUtils.format(progress.toLong(), "mm:ss") } override fun onStartTrackingTouch(seekBar: SeekBar?) { @@ -64,43 +81,89 @@ class AudioPlayActivity : VMBaseActivity(R.layout.activity_a AudioPlay.adjustProgress(this@AudioPlayActivity, player_progress.progress) } }) + iv_chapter.onClick { + viewModel.book?.let { + startActivityForResult( + requestCodeChapter, + Pair("bookUrl", it.bookUrl) + ) + } + } } - private fun upView(book: Book) { - actionBar?.title = book.name - ImageLoader.load(this, book.getDisplayCover()) + private fun upCover(path: String) { + ImageLoader.load(this, path) .placeholder(R.drawable.image_cover_default) .error(R.drawable.image_cover_default) .centerCrop() - .setAsDrawable(iv_cover) - ImageLoader.load(this, book.getDisplayCover()) - .placeholder(R.drawable.image_cover_default) - .error(R.drawable.image_cover_default) + .into(iv_cover) + ImageLoader.load(this, path) + .thumbnail(defaultCover()) .centerCrop() - .bitmapTransform(BlurTransformation(this, 25)) - .setAsDrawable(iv_bg) + .apply(RequestOptions.bitmapTransform(BlurTransformation(this, 25))) + .into(iv_bg) + } + + private fun defaultCover(): RequestBuilder { + return ImageLoader.load(this, R.drawable.image_cover_default) + .apply(RequestOptions.bitmapTransform(BlurTransformation(this, 25))) } private fun playButton() { when (status) { Status.PLAY -> AudioPlay.pause(this) Status.PAUSE -> AudioPlay.resume(this) - else -> viewModel.bookData.value?.let { - viewModel.loadContent(it, viewModel.durChapterIndex) - } + else -> viewModel.loadContent(viewModel.durChapterIndex) } } override fun contentLoadFinish(bookChapter: BookChapter, content: String) { AudioPlay.play( this, - viewModel.bookData.value?.name, + viewModel.book?.name, bookChapter.title, content, viewModel.durPageIndex ) - viewModel.bookData.value?.let { - viewModel.loadContent(it, viewModel.durChapterIndex + 1) + viewModel.loadContent(viewModel.durChapterIndex + 1) + } + + override fun finish() { + viewModel.book?.let { + if (!viewModel.inBookshelf) { + this.alert(title = getString(R.string.add_to_shelf)) { + message = getString(R.string.check_add_bookshelf, it.name) + okButton { viewModel.inBookshelf = true } + noButton { viewModel.removeFromBookshelf { super.finish() } } + }.show().applyTint() + } else { + if (status == Status.PLAY) { + startActivity() + } else { + super.finish() + } + } + } ?: super.finish() + } + + override fun onDestroy() { + super.onDestroy() + AudioPlay.stop(this) + if (!BuildConfig.DEBUG) { + Backup.autoBackup() + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (resultCode == Activity.RESULT_OK) { + when (requestCode) { + requestCodeChapter -> data?.getIntExtra("index", viewModel.durChapterIndex)?.let { + if (it != viewModel.durChapterIndex) { + viewModel.loadContent(it) + } + } + } } } @@ -120,10 +183,15 @@ class AudioPlayActivity : VMBaseActivity(R.layout.activity_a } } observeEvent(Bus.AUDIO_PROGRESS) { + viewModel.durPageIndex = it if (!adjustProgress) player_progress.progress = it + tv_dur_time.text = DateFormatUtils.format(it.toLong(), "mm:ss") + viewModel.saveProgress() } observeEvent(Bus.AUDIO_SIZE) { player_progress.max = it + tv_all_time.text = DateFormatUtils.format(it.toLong(), "mm:ss") } } + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt b/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt index 458097f54..191c03d1d 100644 --- a/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt @@ -6,7 +6,6 @@ import androidx.lifecycle.MutableLiveData import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel -import io.legado.app.constant.BookType import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp @@ -16,13 +15,14 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class AudioPlayViewModel(application: Application) : BaseViewModel(application) { + var titleData = MutableLiveData() + var coverData = MutableLiveData() + var book: Book? = null var inBookshelf = false - var bookData = MutableLiveData() - var chapterSize = 0 + private var chapterSize = 0 var callBack: CallBack? = null var durChapterIndex = 0 var durPageIndex = 0 - var isLocalBook = true var webBook: WebBook? = null private val loadingChapters = arrayListOf() @@ -30,16 +30,16 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) execute { inBookshelf = intent.getBooleanExtra("inBookshelf", true) val bookUrl = intent.getStringExtra("bookUrl") - val book = if (!bookUrl.isNullOrEmpty()) { + book = if (!bookUrl.isNullOrEmpty()) { App.db.bookDao().getBook(bookUrl) } else { App.db.bookDao().lastReadBook } - book?.let { + book?.let { book -> + titleData.postValue(book.name) + coverData.postValue(book.getDisplayCover()) durChapterIndex = book.durChapterIndex durPageIndex = book.durChapterPos - isLocalBook = book.origin == BookType.local - bookData.postValue(book) App.db.bookSourceDao().getBookSource(book.origin)?.let { webBook = WebBook(it) } @@ -57,7 +57,7 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) chapterSize = count } } - saveRead(book) + saveRead() } } @@ -96,36 +96,40 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) } } - fun loadContent(book: Book, index: Int) { - if (addLoading(index)) { - execute { - App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter -> - BookHelp.getContent(book, chapter)?.let { - contentLoadFinish(chapter, it) - removeLoading(chapter.index) - } ?: download(book, chapter) - } ?: removeLoading(index) - }.onError { - removeLoading(index) + fun loadContent(index: Int) { + book?.let { book -> + if (addLoading(index)) { + execute { + App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter -> + BookHelp.getContent(book, chapter)?.let { + contentLoadFinish(chapter, it) + removeLoading(chapter.index) + } ?: download(chapter) + } ?: removeLoading(index) + }.onError { + removeLoading(index) + } } } } - private fun download(book: Book, chapter: BookChapter) { - webBook?.getContent(book, chapter, scope = this) - ?.onSuccess(Dispatchers.IO) { content -> - if (content.isNullOrEmpty()) { - contentLoadFinish(chapter, context.getString(R.string.content_empty)) - removeLoading(chapter.index) - } else { - BookHelp.saveContent(book, chapter, content) - contentLoadFinish(chapter, content) + private fun download(chapter: BookChapter) { + book?.let { book -> + webBook?.getContent(book, chapter, scope = this) + ?.onSuccess(Dispatchers.IO) { content -> + if (content.isNullOrEmpty()) { + contentLoadFinish(chapter, context.getString(R.string.content_empty)) + removeLoading(chapter.index) + } else { + BookHelp.saveContent(book, chapter, content) + contentLoadFinish(chapter, content) + removeLoading(chapter.index) + } + }?.onError { + contentLoadFinish(chapter, it.localizedMessage) removeLoading(chapter.index) } - }?.onError { - contentLoadFinish(chapter, it.localizedMessage) - removeLoading(chapter.index) - } + } } private fun addLoading(index: Int): Boolean { @@ -148,23 +152,23 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) } } - fun changeTo(book: Book) { + fun changeTo(book1: Book) { execute { - bookData.value?.let { + book?.let { App.db.bookDao().delete(it.bookUrl) } withContext(Dispatchers.Main) { } - App.db.bookDao().insert(book) - bookData.postValue(book) - App.db.bookSourceDao().getBookSource(book.origin)?.let { + App.db.bookDao().insert(book1) + book = book1 + App.db.bookSourceDao().getBookSource(book1.origin)?.let { webBook = WebBook(it) } - if (book.tocUrl.isEmpty()) { - loadBookInfo(book) { upChangeDurChapterIndex(book, it) } + if (book1.tocUrl.isEmpty()) { + loadBookInfo(book1) { upChangeDurChapterIndex(book1, it) } } else { - loadChapterList(book) { upChangeDurChapterIndex(book, it) } + loadChapterList(book1) { upChangeDurChapterIndex(book1, it) } } } } @@ -184,20 +188,29 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) } } + fun moveToPrev() { + if (durChapterIndex > 0) { + durChapterIndex-- + durPageIndex = 0 + book?.durChapterIndex = durChapterIndex + saveRead() + loadContent(durChapterIndex) + } + } + fun moveToNext() { if (durChapterIndex < chapterSize - 1) { durChapterIndex++ - bookData.value?.let { - it.durChapterIndex = durChapterIndex - saveRead(it) - loadContent(it, durChapterIndex) - } + durPageIndex = 0 + book?.durChapterIndex = durChapterIndex + saveRead() + loadContent(durChapterIndex) } else { AudioPlay.stop(context) } } - fun saveRead(book: Book? = bookData.value) { + private fun saveRead() { execute { book?.let { book -> book.lastCheckCount = 0 @@ -209,6 +222,24 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) } } + fun saveProgress() { + execute { + book?.let { + App.db.bookDao().upProgress(it.bookUrl, durPageIndex) + } + } + } + + fun removeFromBookshelf(success: (() -> Unit)?) { + execute { + book?.let { + App.db.bookDao().delete(it.bookUrl) + } + }.onSuccess { + success?.invoke() + } + } + interface CallBack { fun contentLoadFinish(bookChapter: BookChapter, content: String) } diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt index 53890274b..d6258f319 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt @@ -89,7 +89,7 @@ class BookInfoActivity : VMBaseActivity(R.layout.activity_boo .placeholder(R.drawable.image_cover_default) .error(R.drawable.image_cover_default) .centerCrop() - .setAsDrawable(iv_cover) + .into(iv_cover) } val kinds = book.getKindList() if (kinds.isEmpty()) { diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index b2dd3dae0..f945a3197 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -64,6 +64,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo override val viewModel: ReadBookViewModel get() = getViewModel(ReadBookViewModel::class.java) + private val requestCodeChapterList = 568 private val requestCodeEditSource = 111 private var timeElectricityReceiver: TimeElectricityReceiver? = null override var readAloudStatus = Status.STOP @@ -73,7 +74,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo setSupportActionBar(toolbar) initView() viewModel.callBack = this - viewModel.bookData.observe(this, Observer { title_bar.title = it.name }) + viewModel.titleDate.observe(this, Observer { title_bar.title = it }) viewModel.initData(intent) } @@ -140,12 +141,12 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo when (item.itemId) { R.id.menu_change_source -> { read_menu.runMenuOut() - viewModel.bookData.value?.let { + viewModel.book?.let { ChangeSourceDialog.show(supportFragmentManager, it.name, it.author) } } R.id.menu_refresh -> { - viewModel.bookData.value?.let { + viewModel.book?.let { viewModel.curTextChapter = null page_view.upContent() viewModel.refreshContent(it) @@ -198,7 +199,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo override fun onKeyLongPress(keyCode: Int, event: KeyEvent?): Boolean { when (keyCode) { KeyEvent.KEYCODE_BACK -> { - page_view.snackbar("转到后台", "确定") { + page_view.snackbar(R.string.to_backstage, R.string.ok) { startActivity() } return true @@ -254,20 +255,16 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo * 加载章节内容 */ override fun loadContent() { - viewModel.bookData.value?.let { - viewModel.loadContent(it, viewModel.durChapterIndex) - viewModel.loadContent(it, viewModel.durChapterIndex + 1) - viewModel.loadContent(it, viewModel.durChapterIndex - 1) - } + viewModel.loadContent(viewModel.durChapterIndex) + viewModel.loadContent(viewModel.durChapterIndex + 1) + viewModel.loadContent(viewModel.durChapterIndex - 1) } /** * 加载章节内容, index章节序号 */ override fun loadContent(index: Int) { - viewModel.bookData.value?.let { - viewModel.loadContent(it, index) - } + viewModel.loadContent(index) } /** @@ -336,10 +333,10 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo } override val curOrigin: String? - get() = viewModel.bookData.value?.origin + get() = viewModel.book?.origin override val oldBook: Book? - get() = viewModel.bookData.value + get() = viewModel.book override fun changeTo(book: Book) { viewModel.changeTo(book) @@ -435,8 +432,11 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo } override fun openChapterList() { - viewModel.bookData.value?.let { - startActivity(Pair("bookUrl", it.bookUrl)) + viewModel.book?.let { + startActivityForResult( + requestCodeChapterList, + Pair("bookUrl", it.bookUrl) + ) } } @@ -471,7 +471,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo * 朗读 */ private fun readAloud(play: Boolean = true) { - val book = viewModel.bookData.value + val book = viewModel.book val textChapter = viewModel.curTextChapter if (book != null && textChapter != null) { val key = IntentDataHelp.putData(textChapter) @@ -510,12 +510,16 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo if (resultCode == Activity.RESULT_OK) { when (requestCode) { requestCodeEditSource -> viewModel.upBookSource() + requestCodeChapterList -> + data?.getIntExtra("index", viewModel.durChapterIndex)?.let { + viewModel.openChapter(it) + } } } } override fun finish() { - viewModel.bookData.value?.let { + viewModel.book?.let { if (!viewModel.inBookshelf) { this.alert(title = getString(R.string.add_to_shelf)) { message = getString(R.string.check_add_bookshelf, it.name) @@ -552,7 +556,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo observeEvent(Bus.TIME_CHANGED) { page_view.upTime() } observeEvent(Bus.BATTERY_CHANGED) { page_view.upBattery(it) } observeEvent(Bus.OPEN_CHAPTER) { - viewModel.openChapter(it) + viewModel.openChapter(it.index) page_view.upContent() } observeEvent(Bus.READ_ALOUD_BUTTON) { diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt index daf901f60..e84a7020d 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt @@ -21,8 +21,9 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext class ReadBookViewModel(application: Application) : BaseViewModel(application) { + var titleDate = MutableLiveData() + var book: Book? = null var inBookshelf = false - var bookData = MutableLiveData() var chapterSize = 0 var callBack: CallBack? = null var durChapterIndex = 0 @@ -38,22 +39,23 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { execute { inBookshelf = intent.getBooleanExtra("inBookshelf", true) IntentDataHelp.getData(intent.getStringExtra("key"))?.let { - setBook(it) + initBook(it) } ?: intent.getStringExtra("bookUrl")?.let { App.db.bookDao().getBook(it)?.let { book -> - setBook(book) + initBook(book) } } ?: App.db.bookDao().lastReadBook?.let { - setBook(it) + initBook(it) } } } - private fun setBook(book: Book) { + private fun initBook(book: Book) { + this.book = book + titleDate.postValue(book.name) durChapterIndex = book.durChapterIndex durPageIndex = book.durChapterPos isLocalBook = book.origin == BookType.local - bookData.postValue(book) App.db.bookSourceDao().getBookSource(book.origin)?.let { webBook = WebBook(it) } @@ -72,7 +74,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { callBack?.loadContent() } if (inBookshelf) { - saveRead(book) + saveRead() } } @@ -117,19 +119,17 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { prevTextChapter = curTextChapter curTextChapter = nextTextChapter nextTextChapter = null - bookData.value?.let { + book?.let { if (curTextChapter == null) { - loadContent(it, durChapterIndex) + loadContent(durChapterIndex) } else if (upContent) { callBack?.upContent() } - loadContent(it, durChapterIndex.plus(1)) + loadContent(durChapterIndex.plus(1)) launch(IO) { for (i in 2..10) { delay(100) - bookData.value?.let { book -> - download(book, durChapterIndex + i) - } + download(durChapterIndex + i) } } } @@ -140,70 +140,74 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { nextTextChapter = curTextChapter curTextChapter = prevTextChapter prevTextChapter = null - bookData.value?.let { + book?.let { if (curTextChapter == null) { - loadContent(it, durChapterIndex) + loadContent(durChapterIndex) } else if (upContent) { callBack?.upContent() } - loadContent(it, durChapterIndex.minus(1)) + loadContent(durChapterIndex.minus(1)) launch(IO) { for (i in -5..-2) { delay(100) - bookData.value?.let { book -> - download(book, durChapterIndex + i) - } + download(durChapterIndex + i) } } } } - fun loadContent(book: Book, index: Int) { - if (addLoading(index)) { - execute { - App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter -> - BookHelp.getContent(book, chapter)?.let { - contentLoadFinish(chapter, it) - removeLoading(chapter.index) - } ?: download(book, chapter) - } ?: removeLoading(index) - }.onError { - removeLoading(index) + fun loadContent(index: Int) { + book?.let { book -> + if (addLoading(index)) { + execute { + App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter -> + BookHelp.getContent(book, chapter)?.let { + contentLoadFinish(chapter, it) + removeLoading(chapter.index) + } ?: download(chapter) + } ?: removeLoading(index) + }.onError { + removeLoading(index) + } } } } - private fun download(book: Book, index: Int) { - if (addLoading(index)) { - execute { - App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter -> - if (BookHelp.hasContent(book, chapter)) { - removeLoading(chapter.index) - } else { - download(book, chapter) - } - } ?: removeLoading(index) - }.onError { - removeLoading(index) + private fun download(index: Int) { + book?.let { book -> + if (addLoading(index)) { + execute { + App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter -> + if (BookHelp.hasContent(book, chapter)) { + removeLoading(chapter.index) + } else { + download(chapter) + } + } ?: removeLoading(index) + }.onError { + removeLoading(index) + } } } } - private fun download(book: Book, chapter: BookChapter) { - webBook?.getContent(book, chapter, scope = this) - ?.onSuccess(IO) { content -> - if (content.isNullOrEmpty()) { - contentLoadFinish(chapter, context.getString(R.string.content_empty)) - removeLoading(chapter.index) - } else { - BookHelp.saveContent(book, chapter, content) - contentLoadFinish(chapter, content) + private fun download(chapter: BookChapter) { + book?.let { book -> + webBook?.getContent(book, chapter, scope = this) + ?.onSuccess(IO) { content -> + if (content.isNullOrEmpty()) { + contentLoadFinish(chapter, context.getString(R.string.content_empty)) + removeLoading(chapter.index) + } else { + BookHelp.saveContent(book, chapter, content) + contentLoadFinish(chapter, content) + removeLoading(chapter.index) + } + }?.onError { + contentLoadFinish(chapter, it.localizedMessage) removeLoading(chapter.index) } - }?.onError { - contentLoadFinish(chapter, it.localizedMessage) - removeLoading(chapter.index) - } + } } private fun addLoading(index: Int): Boolean { @@ -225,19 +229,19 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { if (chapter.index in durChapterIndex - 1..durChapterIndex + 1) { val c = BookHelp.disposeContent( chapter.title, - bookData.value!!.name, + book!!.name, webBook?.bookSource?.bookSourceUrl, content, - bookData.value!!.useReplaceRule + book!!.useReplaceRule ) callBack?.contentLoadFinish(chapter, c) } } } - fun changeTo(book: Book) { + fun changeTo(book1: Book) { execute { - bookData.value?.let { + book?.let { App.db.bookDao().delete(it.bookUrl) } prevTextChapter = null @@ -246,15 +250,15 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { withContext(Main) { callBack?.upContent() } - App.db.bookDao().insert(book) - bookData.postValue(book) - App.db.bookSourceDao().getBookSource(book.origin)?.let { + App.db.bookDao().insert(book1) + book = book1 + App.db.bookSourceDao().getBookSource(book1.origin)?.let { webBook = WebBook(it) } - if (book.tocUrl.isEmpty()) { - loadBookInfo(book) { upChangeDurChapterIndex(book, it) } + if (book1.tocUrl.isEmpty()) { + loadBookInfo(book1) { upChangeDurChapterIndex(book1, it) } } else { - loadChapterList(book) { upChangeDurChapterIndex(book, it) } + loadChapterList(book1) { upChangeDurChapterIndex(book1, it) } } } } @@ -279,19 +283,19 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { } } - fun openChapter(chapter: BookChapter) { + fun openChapter(index: Int) { prevTextChapter = null curTextChapter = null nextTextChapter = null - if (chapter.index != durChapterIndex) { - durChapterIndex = chapter.index + if (index != durChapterIndex) { + durChapterIndex = index durPageIndex = 0 } saveRead() callBack?.loadContent() } - fun saveRead(book: Book? = bookData.value) { + fun saveRead() { execute { book?.let { book -> book.lastCheckCount = 0 @@ -308,7 +312,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { fun removeFromBookshelf(success: (() -> Unit)?) { execute { - bookData.value?.let { + book?.let { App.db.bookDao().delete(it.bookUrl) } }.onSuccess { @@ -318,7 +322,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { fun upBookSource() { execute { - bookData.value?.let { book -> + book?.let { book -> App.db.bookSourceDao().getBookSource(book.origin)?.let { webBook = WebBook(it) } @@ -330,7 +334,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { execute { App.db.bookChapterDao().getChapter(book.bookUrl, durChapterIndex)?.let { chapter -> BookHelp.delContent(book, chapter) - loadContent(book, durChapterIndex) + loadContent(durChapterIndex) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt index d8112b538..194e89daf 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt @@ -153,7 +153,7 @@ class BgTextConfigDialog : DialogFragment() { with(holder.itemView) { ImageLoader.load(context, context.assets.open("bg/$item").readBytes()) .centerCrop() - .setAsBitmap(iv_bg) + .into(iv_bg) tv_name.text = item.substringBeforeLast(".") this.onClick { ReadBookConfig.getConfig().setBg(1, item) diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt index d64fc4db9..f88a7a0e7 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt @@ -248,7 +248,7 @@ class ReadStyleDialog : DialogFragment() { } ReadBookConfig.getConfig(i).apply { when (bgType()) { - 2 -> ImageLoader.load(requireContext(), bgStr()).centerCrop().setAsDrawable(iv) + 2 -> ImageLoader.load(requireContext(), bgStr()).centerCrop().into(iv) else -> iv.setImageDrawable(bgDrawable(100, 150)) } } diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchAdapter.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchAdapter.kt index 7339ba392..04d2e46f8 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchAdapter.kt @@ -72,7 +72,7 @@ class SearchAdapter(context: Context, val callBack: CallBack) : .placeholder(R.drawable.image_cover_default) .error(R.drawable.image_cover_default) .centerCrop() - .setAsDrawable(iv_cover) + .into(iv_cover) } onClick { callBack.showBookInfo(searchBook.name, searchBook.author) @@ -89,7 +89,7 @@ class SearchAdapter(context: Context, val callBack: CallBack) : .placeholder(R.drawable.image_cover_default) .error(R.drawable.image_cover_default) .centerCrop() - .setAsDrawable(iv_cover) + .into(iv_cover) } 3 -> { val kinds = searchBook.getKindList() @@ -136,6 +136,8 @@ class SearchAdapter(context: Context, val callBack: CallBack) : } 5 -> tv_introduce.text = context.getString(R.string.intro_show, searchBook.intro) + else -> { + } } } } diff --git a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListActivity.kt b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListActivity.kt index ef5be2761..514c2dc68 100644 --- a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListActivity.kt +++ b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListActivity.kt @@ -27,9 +27,10 @@ class ChapterListActivity : VMBaseActivity(R.layout.activi override fun onActivityCreated(savedInstanceState: Bundle?) { setSupportActionBar(toolbar) viewModel.bookUrl = intent.getStringExtra("bookUrl") - viewModel.loadBook() - view_pager.adapter = TabFragmentPageAdapter(supportFragmentManager) - tab_layout.setupWithViewPager(view_pager) + viewModel.loadBook { + view_pager.adapter = TabFragmentPageAdapter(supportFragmentManager) + tab_layout.setupWithViewPager(view_pager) + } } override fun onCompatCreateOptionsMenu(menu: Menu): Boolean { diff --git a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt index 4d3e947b6..18449147e 100644 --- a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt +++ b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListFragment.kt @@ -1,5 +1,7 @@ package io.legado.app.ui.chapterlist +import android.app.Activity.RESULT_OK +import android.content.Intent import android.os.Bundle import android.view.View import android.widget.LinearLayout @@ -9,11 +11,9 @@ import androidx.recyclerview.widget.LinearLayoutManager import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseFragment -import io.legado.app.constant.Bus import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.utils.getViewModelOfActivity -import io.legado.app.utils.postEvent import kotlinx.android.synthetic.main.fragment_chapter_list.* import org.jetbrains.anko.sdk27.listeners.onClick @@ -45,14 +45,13 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme } private fun initData() { - viewModel.bookDate.observe(viewLifecycleOwner, Observer { - loadBookFinish(it) - }) viewModel.bookUrl?.let { bookUrl -> App.db.bookChapterDao().observeByBook(bookUrl).observe(viewLifecycleOwner, Observer { adapter.setItems(it) - viewModel.bookDate.value?.let { book -> - loadBookFinish(book) + viewModel.book?.let { + durChapterIndex = it.durChapterIndex + tv_current_chapter_info.text = it.durChapterTitle + recycler_view.scrollToPosition(durChapterIndex) } }) } @@ -66,28 +65,22 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme } } tv_current_chapter_info.onClick { - viewModel.bookDate.value?.let { + viewModel.book?.let { recycler_view.scrollToPosition(it.durChapterIndex) } } } - private fun loadBookFinish(book: Book) { - durChapterIndex = book.durChapterIndex - tv_current_chapter_info.text = book.durChapterTitle - recycler_view.scrollToPosition(durChapterIndex) - } - override fun durChapterIndex(): Int { return durChapterIndex } override fun openChapter(bookChapter: BookChapter) { - postEvent(Bus.OPEN_CHAPTER, bookChapter) + activity?.setResult(RESULT_OK, Intent().putExtra("index", bookChapter.index)) activity?.finish() } override fun book(): Book? { - return viewModel.bookDate.value + return viewModel.book } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListViewModel.kt b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListViewModel.kt index 11d1b38e9..d11aa73dc 100644 --- a/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/chapterlist/ChapterListViewModel.kt @@ -2,23 +2,21 @@ package io.legado.app.ui.chapterlist import android.app.Application -import androidx.lifecycle.MutableLiveData import io.legado.app.App import io.legado.app.base.BaseViewModel import io.legado.app.data.entities.Book class ChapterListViewModel(application: Application) : BaseViewModel(application) { - - var bookDate = MutableLiveData() var bookUrl: String? = null + var book: Book? = null - fun loadBook() { + fun loadBook(success: () -> Unit) { execute { bookUrl?.let { - App.db.bookDao().getBook(it)?.let { book -> - bookDate.postValue(book) - } + book = App.db.bookDao().getBook(it) } + }.onSuccess { + success() } } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/explore/ExploreShowAdapter.kt b/app/src/main/java/io/legado/app/ui/explore/ExploreShowAdapter.kt index 5daa76472..d25e7f255 100644 --- a/app/src/main/java/io/legado/app/ui/explore/ExploreShowAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/explore/ExploreShowAdapter.kt @@ -63,7 +63,7 @@ class ExploreShowAdapter(context: Context, val callBack: CallBack) : .placeholder(R.drawable.image_cover_default) .error(R.drawable.image_cover_default) .centerCrop() - .setAsDrawable(iv_cover) + .into(iv_cover) } onClick { callBack.showBookInfo(item.toBook()) diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BooksAdapter.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BooksAdapter.kt index 25de68e9a..75b0f7787 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BooksAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BooksAdapter.kt @@ -30,7 +30,7 @@ class BooksAdapter(context: Context, private val callBack: CallBack) : .placeholder(R.drawable.image_cover_default) .error(R.drawable.image_cover_default) .centerCrop() - .setAsDrawable(iv_cover) + .into(iv_cover) } onClick { callBack.open(item) } onLongClick { diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt index 205cf4e2c..c0d19851f 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreAdapter.kt @@ -73,6 +73,7 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca kindList.map { kind -> val tv = LayoutInflater.from(context) .inflate(R.layout.item_text, gl_child, false) + gl_child.addView(tv) tv.text_view.text = kind.title tv.text_view.onClick { kind.url?.let { kindUrl -> @@ -83,7 +84,6 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca ) } } - gl_child.addView(tv) } } }.onFinally { diff --git a/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt b/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt index b490c8ec8..63bec82e2 100644 --- a/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt @@ -19,7 +19,7 @@ class RssAdapter(context: Context, val callBack: CallBack) : .centerCrop() .placeholder(R.drawable.image_rss) .error(R.drawable.image_rss) - .setAsBitmap(iv_icon) + .into(iv_icon) onClick { callBack.openRss(item) } } } diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt index 03546d957..4105e1958 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt @@ -28,7 +28,7 @@ class RssArticlesAdapter(context: Context, val callBack: CallBack) : } else { image_view.visible() ImageLoader.load(context, item.image) - .setAsBitmap(image_view) + .into(image_view) } if (item.read) { tv_title.textColorResource = R.color.tv_text_summary diff --git a/app/src/main/res/layout/activity_audio_play.xml b/app/src/main/res/layout/activity_audio_play.xml index 3c2a02ca5..9ef78bdd8 100644 --- a/app/src/main/res/layout/activity_audio_play.xml +++ b/app/src/main/res/layout/activity_audio_play.xml @@ -33,10 +33,8 @@ android:id="@+id/iv_cover" android:layout_width="260dp" android:layout_height="260dp" - android:layout_gravity="center" android:contentDescription="@string/img_cover" android:scaleType="centerCrop" - android:src="@drawable/image_cover_default" app:civ_border_width="2dp" app:civ_border_color="@color/colorAccent" app:layout_constraintBottom_toTopOf="@+id/ll_player_progress" @@ -50,27 +48,33 @@ android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal" - android:paddingStart="5dp" - android:paddingEnd="5dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" app:layout_constraintBottom_toTopOf="@+id/ll_play_menu"> + android:text="00:00" + android:textColor="@color/md_white_1000" + tools:ignore="HardcodedText,RtlSymmetry" /> + android:layout_weight="1" + android:progressBackgroundTint="@color/md_dark_secondary" /> + android:layout_height="wrap_content" + android:text="00:00" + android:textColor="@color/md_white_1000" + tools:ignore="HardcodedText" /> @@ -78,8 +82,8 @@ android:id="@+id/ll_play_menu" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingLeft="15dp" - android:paddingRight="15dp" + android:paddingLeft="24dp" + android:paddingRight="24dp" android:gravity="center_vertical" android:orientation="horizontal" app:layout_constraintBottom_toBottomOf="parent"> diff --git a/app/src/main/res/layout/item_text.xml b/app/src/main/res/layout/item_text.xml index 87687a713..331bd8a2c 100644 --- a/app/src/main/res/layout/item_text.xml +++ b/app/src/main/res/layout/item_text.xml @@ -6,12 +6,10 @@ android:layout_height="wrap_content" android:layout_margin="3dp" android:background="@drawable/selector_fillet_btn_bg" - android:clickable="true" android:ellipsize="end" - android:focusable="true" android:gravity="center" android:padding="5dp" - android:singleLine="true" + android:maxLines="1" android:textColor="@color/tv_text_default" android:textSize="14sp" tools:ignore="UnusedAttribute" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index adf54661f..54eafa2b4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -556,5 +556,6 @@ 类型: 文本 音频 + 转到后台 diff --git a/build.gradle b/build.gradle index f880bb0e5..dd59b4c6c 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { maven { url 'https://plugins.gradle.org/m2/' } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.1' + classpath 'com.android.tools.build:gradle:3.5.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.3' classpath 'com.google.gms:google-services:4.3.2'