diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8b943cc65..b30b4bf58 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -93,6 +93,34 @@ android:resource="@xml/shortcuts" android:launchMode="singleTask" /> + + + + + + + + + + + + + + + + 【备份与恢复】,选择【导入旧版本数据】。 -* 请关注[开源阅读软件]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。 +* 请关注[开源阅读]()支持我,同时关注合作公众号[小说拾遗](),阅读公众号小编。 + +**2020/03/16** +* 弄了个企业公众号[开源阅读](),后面弄好后会把原来的开源阅读软件迁移过来 +* 修复滚动模式切换章节位置不归0的bug +* 修复文字选择更多菜单在部分手机上报错的bug +* 修复文字选择菜单问题 + +**2020/03/15** +* 加载正文无书源时自动换源 **2020/03/14** * 修改导航栏图标 diff --git a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt index 9ce5c65be..55d5ada4c 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt @@ -50,9 +50,12 @@ interface BookSourceDao { @get:Query("select * from book_sources order by customOrder asc") val all: List - @get:Query("select * from book_sources where enabled = 1 order by customOrder asc") + @get:Query("select * from book_sources where enabled = 1 order by customOrder") val allEnabled: List + @get:Query("select * from book_sources where enabled = 1 and bookSourceType = 0 order by customOrder") + val allTextEnabled: List + @Query("select * from book_sources where bookSourceUrl = :key") fun getBookSource(key: String): BookSource? diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt index 833561f1b..9e50a6d4c 100644 --- a/app/src/main/java/io/legado/app/data/entities/Book.kt +++ b/app/src/main/java/io/legado/app/data/entities/Book.kt @@ -31,8 +31,8 @@ data class Book( var intro: String? = null, // 简介内容(书源获取) var customIntro: String? = null, // 简介内容(用户修改) var charset: String? = null, // 自定义字符集名称(仅适用于本地书籍) - var type: Int = 0, // @BookType - var group: Int = 0, // 自定义分组索引号 + var type: Int = 0, // 0:text 1:audio + var group: Int = 1, // 自定义分组索引号 var latestChapterTitle: String? = null, // 最新章节标题 var latestChapterTime: Long = System.currentTimeMillis(), // 最新章节标题更新时间 var lastCheckTime: Long = System.currentTimeMillis(), // 最近一次更新书籍信息的时间 diff --git a/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt b/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt index 76bcd6116..90c63e4b7 100644 --- a/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt +++ b/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt @@ -5,10 +5,7 @@ import android.content.pm.PackageManager import android.os.Build import io.legado.app.App import io.legado.app.R -import io.legado.app.ui.welcome.Launcher1 -import io.legado.app.ui.welcome.Launcher2 -import io.legado.app.ui.welcome.Launcher3 -import io.legado.app.ui.welcome.WelcomeActivity +import io.legado.app.ui.welcome.* import org.jetbrains.anko.toast /** @@ -20,7 +17,9 @@ object LauncherIconHelp { private val componentNames = arrayListOf( ComponentName(App.INSTANCE, Launcher1::class.java.name), ComponentName(App.INSTANCE, Launcher2::class.java.name), - ComponentName(App.INSTANCE, Launcher3::class.java.name) + ComponentName(App.INSTANCE, Launcher3::class.java.name), + ComponentName(App.INSTANCE, Launcher4::class.java.name), + ComponentName(App.INSTANCE, Launcher5::class.java.name) ) fun changeIcon(icon: String?) { diff --git a/app/src/main/java/io/legado/app/help/storage/Restore.kt b/app/src/main/java/io/legado/app/help/storage/Restore.kt index 5393249c3..f174a6f5e 100644 --- a/app/src/main/java/io/legado/app/help/storage/Restore.kt +++ b/app/src/main/java/io/legado/app/help/storage/Restore.kt @@ -128,7 +128,7 @@ object Restore { bodyIndentCount = App.INSTANCE.getPrefInt(PreferKey.bodyIndent, 2) } ChapterProvider.upStyle() - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = false) } withContext(Main) { if (AppConfig.isNightTheme && AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_YES) { diff --git a/app/src/main/java/io/legado/app/lib/theme/ATH.kt b/app/src/main/java/io/legado/app/lib/theme/ATH.kt index 0bcbb114b..19304862c 100644 --- a/app/src/main/java/io/legado/app/lib/theme/ATH.kt +++ b/app/src/main/java/io/legado/app/lib/theme/ATH.kt @@ -199,13 +199,12 @@ object ATH { fun applyBottomNavigationColor(bottomBar: BottomNavigationView?) { bottomBar?.apply { - setBackgroundColor(ThemeStore.backgroundColor(context)) + setBackgroundColor(ThemeStore.bottomBackground(context)) val colorStateList = Selector.colorBuild() .setDefaultColor(context.getCompatColor(R.color.btn_bg_press_tp)) .setSelectedColor(ThemeStore.accentColor(bottom_navigation_view.context)).create() itemIconTintList = colorStateList itemTextColor = colorStateList - setBackgroundColor(ThemeStore.bottomBackground(context)) } } diff --git a/app/src/main/java/io/legado/app/model/WebBook.kt b/app/src/main/java/io/legado/app/model/WebBook.kt index 69dfb943c..7d14ea8bc 100644 --- a/app/src/main/java/io/legado/app/model/WebBook.kt +++ b/app/src/main/java/io/legado/app/model/WebBook.kt @@ -29,26 +29,34 @@ class WebBook(val bookSource: BookSource) { context: CoroutineContext = Dispatchers.IO ): Coroutine> { return Coroutine.async(scope, context) { - bookSource.searchUrl?.let { searchUrl -> - val analyzeUrl = AnalyzeUrl( - ruleUrl = searchUrl, - key = key, - page = page, - baseUrl = sourceUrl, - headerMapF = bookSource.getHeaderMap() - ) - val res = analyzeUrl.getResponseAwait(bookSource.bookSourceUrl) - BookList.analyzeBookList( - res.body, - bookSource, - analyzeUrl, - res.url, - true - ) - } ?: arrayListOf() + searchBookSuspend(key, page) } } + suspend fun searchBookSuspend( + key: String, + page: Int? = 1 + ): ArrayList { + bookSource.searchUrl?.let { searchUrl -> + val analyzeUrl = AnalyzeUrl( + ruleUrl = searchUrl, + key = key, + page = page, + baseUrl = sourceUrl, + headerMapF = bookSource.getHeaderMap() + ) + val res = analyzeUrl.getResponseAwait(bookSource.bookSourceUrl) + return BookList.analyzeBookList( + res.body, + bookSource, + analyzeUrl, + res.url, + true + ) + } + return arrayListOf() + } + /** * 发现 */ diff --git a/app/src/main/java/io/legado/app/service/help/ReadBook.kt b/app/src/main/java/io/legado/app/service/help/ReadBook.kt index 85f2fff45..68b1601ac 100644 --- a/app/src/main/java/io/legado/app/service/help/ReadBook.kt +++ b/app/src/main/java/io/legado/app/service/help/ReadBook.kt @@ -21,7 +21,6 @@ import org.jetbrains.anko.toast object ReadBook { - var titleDate = MutableLiveData() var book: Book? = null var inBookshelf = false @@ -34,9 +33,10 @@ object ReadBook { var curTextChapter: TextChapter? = null var nextTextChapter: TextChapter? = null var webBook: WebBook? = null + var msg: String? = null private val loadingChapters = arrayListOf() - fun resetData(book: Book) { + fun resetData(book: Book, noSource: (name: String, author: String) -> Unit) { this.book = book titleDate.postValue(book.name) durChapterIndex = book.durChapterIndex @@ -46,12 +46,22 @@ object ReadBook { prevTextChapter = null curTextChapter = null nextTextChapter = null - upWebBook(book.origin) + upWebBook(book, noSource) } - fun upWebBook(origin: String) { - val bookSource = App.db.bookSourceDao().getBookSource(origin) - webBook = if (bookSource != null) WebBook(bookSource) else null + fun upWebBook(book: Book?, noSource: (name: String, author: String) -> Unit) { + book ?: return + if (book.origin == BookType.local) { + webBook = null + } else { + val bookSource = App.db.bookSourceDao().getBookSource(book.origin) + if (bookSource != null) { + webBook = WebBook(bookSource) + } else { + webBook = null + noSource.invoke(book.name, book.author) + } + } } fun moveToNextPage() { @@ -69,11 +79,11 @@ object ReadBook { nextTextChapter = null book?.let { if (curTextChapter == null) { - loadContent(durChapterIndex, upContent) + loadContent(durChapterIndex, upContent, false) } else if (upContent) { callBack?.upContent() } - loadContent(durChapterIndex.plus(1), upContent) + loadContent(durChapterIndex.plus(1), upContent, false) GlobalScope.launch(Dispatchers.IO) { for (i in 2..10) { delay(100) @@ -99,11 +109,11 @@ object ReadBook { prevTextChapter = null book?.let { if (curTextChapter == null) { - loadContent(durChapterIndex, upContent) + loadContent(durChapterIndex, upContent, false) } else if (upContent) { callBack?.upContent() } - loadContent(durChapterIndex.minus(1), upContent) + loadContent(durChapterIndex.minus(1), upContent, false) GlobalScope.launch(Dispatchers.IO) { for (i in -5..-2) { delay(100) @@ -184,21 +194,21 @@ object ReadBook { /** * 加载章节内容 */ - fun loadContent() { - loadContent(durChapterIndex) - loadContent(durChapterIndex + 1) - loadContent(durChapterIndex - 1) + fun loadContent(resetPageOffset: Boolean) { + loadContent(durChapterIndex, resetPageOffset = resetPageOffset) + loadContent(durChapterIndex + 1, resetPageOffset = resetPageOffset) + loadContent(durChapterIndex - 1, resetPageOffset = resetPageOffset) } - fun loadContent(index: Int, upContent: Boolean = true) { + fun loadContent(index: Int, upContent: Boolean = true, resetPageOffset: Boolean) { book?.let { book -> if (addLoading(index)) { Coroutine.async { App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter -> BookHelp.getContent(book, chapter)?.let { - contentLoadFinish(chapter, it, upContent) + contentLoadFinish(chapter, it, upContent, resetPageOffset) removeLoading(chapter.index) - } ?: download(chapter) + } ?: download(chapter, resetPageOffset = resetPageOffset) } ?: removeLoading(index) }.onError { removeLoading(index) @@ -216,7 +226,7 @@ object ReadBook { if (BookHelp.hasContent(book, chapter)) { removeLoading(chapter.index) } else { - download(chapter) + download(chapter, false) } } ?: removeLoading(index) }.onError { @@ -226,20 +236,28 @@ object ReadBook { } } - private fun download(chapter: BookChapter) { + private fun download(chapter: BookChapter, resetPageOffset: Boolean) { book?.let { book -> webBook?.getContent(book, chapter) ?.onSuccess(Dispatchers.IO) { content -> if (content.isNullOrEmpty()) { - contentLoadFinish(chapter, App.INSTANCE.getString(R.string.content_empty)) + contentLoadFinish( + chapter, + App.INSTANCE.getString(R.string.content_empty), + resetPageOffset = resetPageOffset + ) removeLoading(chapter.index) } else { BookHelp.saveContent(book, chapter, content) - contentLoadFinish(chapter, content) + contentLoadFinish(chapter, content, resetPageOffset = resetPageOffset) removeLoading(chapter.index) } }?.onError { - contentLoadFinish(chapter, it.localizedMessage ?: "未知错误") + contentLoadFinish( + chapter, + it.localizedMessage ?: "未知错误", + resetPageOffset = resetPageOffset + ) removeLoading(chapter.index) } } @@ -265,7 +283,8 @@ object ReadBook { private fun contentLoadFinish( chapter: BookChapter, content: String, - upContent: Boolean = true + upContent: Boolean = true, + resetPageOffset: Boolean ) { Coroutine.async { if (chapter.index in durChapterIndex - 1..durChapterIndex + 1) { @@ -279,18 +298,18 @@ object ReadBook { when (chapter.index) { durChapterIndex -> { curTextChapter = ChapterProvider.getTextChapter(chapter, c, chapterSize) - if (upContent) callBack?.upContent() + if (upContent) callBack?.upContent(resetPageOffset = resetPageOffset) callBack?.upView() curPageChanged() callBack?.contentLoadFinish() } durChapterIndex - 1 -> { prevTextChapter = ChapterProvider.getTextChapter(chapter, c, chapterSize) - if (upContent) callBack?.upContent(-1) + if (upContent) callBack?.upContent(-1, resetPageOffset) } durChapterIndex + 1 -> { nextTextChapter = ChapterProvider.getTextChapter(chapter, c, chapterSize) - if (upContent) callBack?.upContent(1) + if (upContent) callBack?.upContent(1, resetPageOffset) } } } @@ -316,7 +335,7 @@ object ReadBook { } interface CallBack { - fun upContent(relativePosition: Int = 0) + fun upContent(relativePosition: Int = 0, resetPageOffset: Boolean = true) fun upView() fun upPageProgress() fun contentLoadFinish() diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt index 1086f0416..8be9ed34f 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupManageDialog.kt @@ -33,6 +33,7 @@ import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.applyTint import io.legado.app.utils.getViewModel import io.legado.app.utils.requestInputMethod +import io.legado.app.utils.visible import kotlinx.android.synthetic.main.dialog_edit_text.view.* import kotlinx.android.synthetic.main.dialog_recycler_view.* import kotlinx.android.synthetic.main.item_group_manage.view.* @@ -74,6 +75,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter tv_ok.setTextColor(requireContext().accentColor) + tv_ok.visible() tv_ok.onClick { dismiss() } App.db.bookGroupDao().liveDataAll().observe(viewLifecycleOwner, Observer { val diffResult = 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 138d676be..8cd1915cc 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 @@ -25,6 +25,7 @@ import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp import io.legado.app.help.ReadBookConfig import io.legado.app.help.coroutine.Coroutine +import io.legado.app.help.storage.Backup import io.legado.app.help.storage.SyncBookProgress import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.noButton @@ -115,7 +116,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = false) } override fun onResume() { @@ -402,11 +403,10 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo */ override fun showTextActionMenu() { textActionMenu ?: let { - textActionMenu = TextActionMenu(this, this).apply { - contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) - } + textActionMenu = TextActionMenu(this, this) } textActionMenu?.let { popup -> + popup.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED) val popupHeight = popup.contentView.measuredHeight val x = text_menu_position.x.toInt() var y = text_menu_position.y.toInt() - popupHeight @@ -481,9 +481,9 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo /** * 更新内容 */ - override fun upContent(relativePosition: Int) { + override fun upContent(relativePosition: Int, resetPageOffset: Boolean) { launch { - page_view.upContent(relativePosition) + page_view.upContent(relativePosition, resetPageOffset) } } @@ -579,7 +579,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo override fun onReplaceRuleSave() { Coroutine.async { BookHelp.upReplaceRules() - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = false) } } @@ -684,6 +684,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo page_view.onDestroy() if (!BuildConfig.DEBUG) { SyncBookProgress.uploadBookProgress() + Backup.autoBack(this) } } @@ -707,9 +708,9 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo page_view.upBg() page_view.upStyle() if (it) { - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = false) } else { - page_view.upContent() + page_view.upContent(resetPageOffset = false) } } observeEvent(EventBus.ALOUD_STATE) { @@ -718,7 +719,7 @@ class ReadBookActivity : VMBaseActivity(R.layout.activity_boo val page = textChapter.page(ReadBook.durPageIndex) if (page != null) { page.removePageAloudSpan() - page_view.upContent() + page_view.upContent(resetPageOffset = false) } } } 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 2ebab7875..90d559f8d 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 @@ -39,7 +39,9 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { private fun initBook(book: Book) { if (ReadBook.book?.bookUrl != book.bookUrl) { - ReadBook.resetData(book) + ReadBook.resetData(book) { name, author -> + autoChangeSource(name, author) + } isInitFinish = true ReadBook.chapterSize = App.db.bookChapterDao().getChapterCount(book.bookUrl) if (ReadBook.chapterSize == 0) { @@ -52,7 +54,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { if (ReadBook.durChapterIndex > ReadBook.chapterSize - 1) { ReadBook.durChapterIndex = ReadBook.chapterSize - 1 } - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = true) } if (ReadBook.inBookshelf) { ReadBook.saveRead() @@ -60,7 +62,9 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { } else { isInitFinish = true ReadBook.titleDate.postValue(book.name) - ReadBook.upWebBook(book.origin) + ReadBook.upWebBook(book) { name, author -> + autoChangeSource(name, author) + } ReadBook.chapterSize = App.db.bookChapterDao().getChapterCount(book.bookUrl) if (ReadBook.chapterSize == 0) { if (book.tocUrl.isEmpty()) { @@ -70,7 +74,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { } } else { if (ReadBook.curTextChapter != null) { - ReadBook.callBack?.upContent() + ReadBook.callBack?.upContent(resetPageOffset = false) } } } @@ -103,7 +107,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { App.db.bookChapterDao().insert(*it.toTypedArray()) App.db.bookDao().update(book) ReadBook.chapterSize = it.size - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = true) } } else { ReadBook.webBook?.getChapterList(book, this) @@ -113,7 +117,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { App.db.bookChapterDao().insert(*cList.toTypedArray()) App.db.bookDao().update(book) ReadBook.chapterSize = cList.size - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = true) } else { changeDruChapterIndex(cList) } @@ -122,7 +126,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { } }?.onError { toast(R.string.error_load_toc) - } ?: autoChangeSource() + } } } } @@ -151,8 +155,28 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { } } - private fun autoChangeSource() { - + private fun autoChangeSource(name: String, author: String) { + execute { + App.db.bookSourceDao().allTextEnabled.forEach { source -> + try { + val searchBooks = WebBook(source).searchBookSuspend(name) + searchBooks.getOrNull(0)?.let { + if (it.name == name && (it.author == author || author == "")) { + changeTo(it.toBook()) + return@forEach + } + } + } catch (e: Exception) { + //nothing + } + } + }.onStart { + ReadBook.msg = "正在自动换源" + ReadBook.callBack?.upContent() + }.onFinally { + ReadBook.msg = null + ReadBook.callBack?.upContent() + } } private fun upChangeDurChapterIndex(book: Book, chapters: List) { @@ -167,7 +191,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { App.db.bookDao().update(book) App.db.bookChapterDao().insert(*chapters.toTypedArray()) ReadBook.chapterSize = chapters.size - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = true) } } @@ -181,7 +205,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { ReadBook.durPageIndex = pageIndex } ReadBook.saveRead() - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = true) } fun removeFromBookshelf(success: (() -> Unit)?) { @@ -208,9 +232,9 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { execute { App.db.bookChapterDao().getChapter(book.bookUrl, ReadBook.durChapterIndex) ?.let { chapter -> - BookHelp.delContent(book, chapter) - ReadBook.loadContent(ReadBook.durChapterIndex) - } + BookHelp.delContent(book, chapter) + ReadBook.loadContent(ReadBook.durChapterIndex, resetPageOffset = false) + } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt b/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt index 9d7046f6e..5c8d1d214 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt @@ -7,6 +7,7 @@ import android.content.Intent import android.content.pm.ResolveInfo import android.net.Uri import android.os.Build +import android.speech.tts.TextToSpeech import android.view.LayoutInflater import android.view.Menu import android.view.ViewGroup @@ -15,13 +16,12 @@ import androidx.annotation.RequiresApi import androidx.appcompat.view.SupportMenuInflater import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.view.menu.MenuItemImpl -import androidx.appcompat.widget.PopupMenu -import androidx.core.view.size -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView +import androidx.core.view.isVisible import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.SimpleRecyclerAdapter +import io.legado.app.service.BaseReadAloudService +import io.legado.app.utils.gone import io.legado.app.utils.isAbsUrl import io.legado.app.utils.sendToClip import io.legado.app.utils.visible @@ -30,10 +30,16 @@ import kotlinx.android.synthetic.main.popup_action_menu.view.* import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.share import org.jetbrains.anko.toast +import java.util.* @SuppressLint("RestrictedApi") class TextActionMenu(private val context: Context, private val callBack: CallBack) : - PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) { + PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT), + TextToSpeech.OnInitListener { + + private val adapter = Adapter(context) + private val menu = MenuBuilder(context) + private val moreMenu = MenuBuilder(context) init { @SuppressLint("InflateParams") @@ -44,33 +50,38 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac isFocusable = false initRecyclerView() + setOnDismissListener { + contentView.apply { + iv_menu_more.setImageResource(R.drawable.ic_more_vert) + recycler_view_more.gone() + adapter.setItems(menu.visibleItems) + recycler_view.visible() + } + } } private fun initRecyclerView() = with(contentView) { - val adapter = Adapter(context) - recycler_view.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) recycler_view.adapter = adapter - val menu = MenuBuilder(context) + recycler_view_more.adapter = adapter SupportMenuInflater(context).inflate(R.menu.content_select_action, menu) adapter.setItems(menu.visibleItems) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - val popupMenu = PopupMenu(context, iv_menu_more) - onInitializeMenu(popupMenu.menu) - if (popupMenu.menu.size > 0) { - iv_menu_more.visible() - popupMenu.setOnMenuItemClickListener { item -> - item.intent?.let { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - it.putExtra(Intent.EXTRA_PROCESS_TEXT, callBack.selectedText) - context.startActivity(it) - } - } - this@TextActionMenu.dismiss() - true - } - } - iv_menu_more.onClick { - popupMenu.show() + onInitializeMenu(moreMenu) + } + if (moreMenu.size() > 0) { + iv_menu_more.visible() + } + iv_menu_more.onClick { + if (recycler_view.isVisible) { + iv_menu_more.setImageResource(R.drawable.ic_arrow_back) + adapter.setItems(moreMenu.visibleItems) + recycler_view.gone() + recycler_view_more.visible() + } else { + iv_menu_more.setImageResource(R.drawable.ic_more_vert) + recycler_view_more.gone() + adapter.setItems(menu.visibleItems) + recycler_view.visible() } } } @@ -104,6 +115,13 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac when (item.itemId) { R.id.menu_copy -> context.sendToClip(callBack.selectedText) R.id.menu_share_str -> context.share(callBack.selectedText) + R.id.menu_aloud -> { + if (BaseReadAloudService.isRun) { + context.toast(R.string.alouding_disable) + return + } + readAloud(callBack.selectedText) + } R.id.menu_browser -> { try { val intent = if (callBack.selectedText.isAbsUrl()) { @@ -121,9 +139,41 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac context.toast(e.localizedMessage ?: "ERROR") } } + else -> item.intent?.let { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + it.putExtra(Intent.EXTRA_PROCESS_TEXT, callBack.selectedText) + context.startActivity(it) + } + } } } + private var textToSpeech: TextToSpeech? = null + private var ttsInitFinish = false + private var lastText: String = "" + + @SuppressLint("SetJavaScriptEnabled") + private fun readAloud(text: String) { + lastText = text + if (textToSpeech == null) { + textToSpeech = TextToSpeech(context, this) + return + } + if (!ttsInitFinish) return + if (text == "") return + if (textToSpeech?.isSpeaking == true) + textToSpeech?.stop() + textToSpeech?.speak(text, TextToSpeech.QUEUE_ADD, null, "select_text") + lastText = "" + } + + @Synchronized + override fun onInit(status: Int) { + textToSpeech?.language = Locale.CHINA + ttsInitFinish = true + readAloud(lastText) + } + @RequiresApi(Build.VERSION_CODES.M) private fun createProcessTextIntent(): Intent { return Intent() diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt index 6dc89f716..1cc006512 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt @@ -108,8 +108,10 @@ class ContentView(context: Context) : FrameLayout(context) { } } - fun setContent(textPage: TextPage) { + fun setContent(textPage: TextPage, resetPageOffset: Boolean = true) { setProgress(textPage) + if (resetPageOffset) + resetPageOffset() content_text_view.setContent(textPage) } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt b/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt index 4f7afa04f..3a128f969 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/DataSource.kt @@ -17,5 +17,5 @@ interface DataSource { fun hasPrevChapter(): Boolean - fun upContent(relativePosition: Int = 0) + fun upContent(relativePosition: Int = 0, resetPageOffset: Boolean = true) } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt index 1b7b71b07..dd19fdc0e 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt @@ -38,7 +38,7 @@ class PageView(context: Context, attrs: AttributeSet) : prevPage.x = -w.toFloat() pageDelegate?.setViewSize(w, h) if (oldw != 0 && oldh != 0) { - ReadBook.loadContent() + ReadBook.loadContent(resetPageOffset = false) } } @@ -93,9 +93,9 @@ class PageView(context: Context, attrs: AttributeSet) : upContent() } - override fun upContent(relativePosition: Int) { + override fun upContent(relativePosition: Int, resetPageOffset: Boolean) { if (ReadBookConfig.isScroll) { - curPage.setContent(pageFactory.currentPage) + curPage.setContent(pageFactory.currentPage, resetPageOffset) } else { when (relativePosition) { -1 -> prevPage.setContent(pageFactory.prevPage) diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt b/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt index a867daf3d..a38ed6e51 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/TextPageFactory.kt @@ -38,7 +38,7 @@ class TextPageFactory(dataSource: DataSource) : PageFactory(dataSource } else { ReadBook.setPageIndex(pageIndex.plus(1)) } - if (upContent) upContent() + if (upContent) upContent(resetPageOffset = false) true } else false @@ -51,7 +51,7 @@ class TextPageFactory(dataSource: DataSource) : PageFactory(dataSource } else { ReadBook.setPageIndex(pageIndex.minus(1)) } - if (upContent) upContent() + if (upContent) upContent(resetPageOffset = false) true } else false @@ -59,6 +59,9 @@ class TextPageFactory(dataSource: DataSource) : PageFactory(dataSource override val currentPage: TextPage get() = with(dataSource) { + ReadBook.msg?.let { + return@with TextPage(text = it).format() + } currentChapter?.let { return@with it.page(pageIndex) ?: TextPage(title = it.title).format() @@ -68,6 +71,9 @@ class TextPageFactory(dataSource: DataSource) : PageFactory(dataSource override val nextPage: TextPage get() = with(dataSource) { + ReadBook.msg?.let { + return@with TextPage(text = it).format() + } currentChapter?.let { if (pageIndex < it.pageSize() - 1) { return@with it.page(pageIndex + 1)?.removePageAloudSpan() @@ -86,6 +92,9 @@ class TextPageFactory(dataSource: DataSource) : PageFactory(dataSource override val prevPage: TextPage get() = with(dataSource) { + ReadBook.msg?.let { + return@with TextPage(text = it).format() + } if (pageIndex > 0) { currentChapter?.let { return@with it.page(pageIndex - 1)?.removePageAloudSpan() diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt index 2d1054859..8de6a489c 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt @@ -283,10 +283,12 @@ class SearchActivity : VMBaseActivity(R.layout.activity_book_se */ @Synchronized private fun upSearchItems(items: List, isMandatoryUpdate: Boolean) { + val searchItems = ArrayList(items) if (isMandatoryUpdate || System.currentTimeMillis() - refreshTime > 500) { refreshTime = System.currentTimeMillis() - val diffResult = DiffUtil.calculateDiff(DiffCallBack(adapter.getItems(), items)) - adapter.setItems(items, diffResult) + val diffResult = + DiffUtil.calculateDiff(DiffCallBack(adapter.getItems(), searchItems)) + adapter.setItems(searchItems, diffResult) } } diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt index 96424cc9b..0aa49ede7 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt @@ -15,7 +15,6 @@ import io.legado.app.base.VMBaseActivity 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.lib.theme.ATH import io.legado.app.service.BaseReadAloudService import io.legado.app.service.help.ReadAloud @@ -114,13 +113,6 @@ class MainActivity : VMBaseActivity(R.layout.activity_main), return super.onKeyUp(keyCode, event) } - override fun finish() { - if (!BuildConfig.DEBUG) { - Backup.autoBack(this) - } - super.finish() - } - override fun onDestroy() { super.onDestroy() ReadAloud.stop(this) diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt index d647afd3b..1438c4507 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt @@ -21,7 +21,6 @@ class BooksAdapterGrid(context: Context, private val callBack: CallBack) : if (bundle == null) { ATH.applyBackgroundTint(this) tv_name.text = item.name - bv_author.text = item.author iv_cover.load(item.getDisplayCover(), item.name, item.author) if (item.origin != BookType.local && callBack.isUpdate(item.bookUrl)) { bv_unread.invisible() @@ -35,7 +34,6 @@ class BooksAdapterGrid(context: Context, private val callBack: CallBack) : bundle.keySet().map { when (it) { "name" -> tv_name.text = item.name - "author" -> bv_author.text = item.author "cover" -> iv_cover.load(item.getDisplayCover(), item.name, item.author) "refresh" -> if (item.origin != BookType.local && callBack.isUpdate(item.bookUrl)) { bv_unread.invisible() diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt index 43375288e..d82480ca2 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.Observer import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseFragment @@ -26,6 +27,7 @@ import io.legado.app.utils.getViewModelOfActivity import io.legado.app.utils.observeEvent import kotlinx.android.synthetic.main.fragment_books.* import org.jetbrains.anko.startActivity +import kotlin.math.max class BooksFragment : BaseFragment(R.layout.fragment_books), @@ -71,9 +73,26 @@ class BooksFragment : BaseFragment(R.layout.fragment_books), booksAdapter = BooksAdapterList(requireContext(), this) } else { rv_bookshelf.layoutManager = GridLayoutManager(context, bookshelfLayout + 2) - booksAdapter = BooksAdapterGrid(requireContext(),this) + booksAdapter = BooksAdapterGrid(requireContext(), this) } rv_bookshelf.adapter = booksAdapter + booksAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + val layoutManager = rv_bookshelf.layoutManager + if (positionStart == 0 && layoutManager is LinearLayoutManager) { + val scrollTo = layoutManager.findFirstVisibleItemPosition() - itemCount + rv_bookshelf.scrollToPosition(max(0, scrollTo)) + } + } + + override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { + val layoutManager = rv_bookshelf.layoutManager + if (toPosition == 0 && layoutManager is LinearLayoutManager) { + val scrollTo = layoutManager.findFirstVisibleItemPosition() - itemCount + rv_bookshelf.scrollToPosition(max(0, scrollTo)) + } + } + }) } private fun upRecyclerData() { 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 3ceeca8b6..faf9cef8a 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 @@ -12,6 +12,7 @@ import io.legado.app.data.entities.BookSource import io.legado.app.help.coroutine.Coroutine import io.legado.app.lib.theme.accentColor import io.legado.app.utils.ACache +import io.legado.app.utils.dp import io.legado.app.utils.gone import io.legado.app.utils.visible import kotlinx.android.synthetic.main.item_fillet_text.view.* @@ -28,11 +29,16 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca override fun convert(holder: ItemViewHolder, item: BookSource, payloads: MutableList) { with(holder.itemView) { + if (holder.layoutPosition == getActualItemCount() - 1) { + setPadding(16.dp, 12.dp, 16.dp, 12.dp) + } else { + setPadding(16.dp, 12.dp, 16.dp, 0) + } if (payloads.isEmpty()) { tv_name.text = item.bookSourceName } if (exIndex == holder.layoutPosition) { - iv_status.setImageResource(R.drawable.ic_remove) + iv_status.setImageResource(R.drawable.ic_arrow_down) rotate_loading.loadingColor = context.accentColor rotate_loading.show() if (scrollTo >= 0) { @@ -68,7 +74,7 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca } } } else { - iv_status.setImageResource(R.drawable.ic_add) + iv_status.setImageResource(R.drawable.ic_arrow_right) rotate_loading.hide() gl_child.gone() } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt index ed09cec93..ce2313f5a 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/GroupManageDialog.kt @@ -24,10 +24,7 @@ import io.legado.app.lib.dialogs.noButton import io.legado.app.lib.dialogs.yesButton import io.legado.app.lib.theme.accentColor import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.applyTint -import io.legado.app.utils.getViewModelOfActivity -import io.legado.app.utils.requestInputMethod -import io.legado.app.utils.splitNotBlank +import io.legado.app.utils.* import kotlinx.android.synthetic.main.dialog_edit_text.view.* import kotlinx.android.synthetic.main.dialog_recycler_view.* import kotlinx.android.synthetic.main.item_group_manage.view.* @@ -68,6 +65,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { recycler_view.addItemDecoration(VerticalDivider(requireContext())) recycler_view.adapter = adapter tv_ok.setTextColor(requireContext().accentColor) + tv_ok.visible() tv_ok.onClick { dismiss() } App.db.rssSourceDao().liveGroup().observe(viewLifecycleOwner, Observer { val groups = linkedSetOf() diff --git a/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt b/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt index 08eb06a70..fdf77bc85 100644 --- a/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt +++ b/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt @@ -59,4 +59,6 @@ open class WelcomeActivity : BaseActivity(R.layout.activity_welcome) { class Launcher1 : WelcomeActivity() class Launcher2 : WelcomeActivity() class Launcher3 : WelcomeActivity() -class Launcher4 : WelcomeActivity() \ No newline at end of file +class Launcher4 : WelcomeActivity() +class Launcher5 : WelcomeActivity() +class Launcher6 : WelcomeActivity() \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/DocumentUtils.kt b/app/src/main/java/io/legado/app/utils/DocumentUtils.kt index f4fd0e8eb..b53cebb14 100644 --- a/app/src/main/java/io/legado/app/utils/DocumentUtils.kt +++ b/app/src/main/java/io/legado/app/utils/DocumentUtils.kt @@ -98,7 +98,7 @@ object DocumentUtils { DocumentsContract.Document.COLUMN_LAST_MODIFIED, DocumentsContract.Document.COLUMN_SIZE, DocumentsContract.Document.COLUMN_MIME_TYPE - ), null, null, null + ), null, null, DocumentsContract.Document.COLUMN_DISPLAY_NAME ) c?.let { val ici = c.getColumnIndex(DocumentsContract.Document.COLUMN_DOCUMENT_ID) diff --git a/app/src/main/res/drawable-v24/ic_launcher_2.xml b/app/src/main/res/drawable-v24/ic_launcher_2.xml deleted file mode 100644 index b4343492c..000000000 --- a/app/src/main/res/drawable-v24/ic_launcher_2.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/drawable-v24/ic_launcher_2b.xml b/app/src/main/res/drawable-v24/ic_launcher_2b.xml deleted file mode 100644 index be66fb2a7..000000000 --- a/app/src/main/res/drawable-v24/ic_launcher_2b.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/bg_find_book_group.xml b/app/src/main/res/drawable/bg_find_book_group.xml new file mode 100644 index 000000000..b00a89b22 --- /dev/null +++ b/app/src/main/res/drawable/bg_find_book_group.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_searchview.xml b/app/src/main/res/drawable/bg_searchview.xml new file mode 100644 index 000000000..beee4af1e --- /dev/null +++ b/app/src/main/res/drawable/bg_searchview.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_down.xml b/app/src/main/res/drawable/ic_arrow_down.xml new file mode 100644 index 000000000..19a41e8db --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_down.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_right.xml b/app/src/main/res/drawable/ic_arrow_right.xml new file mode 100644 index 000000000..72bcbdb79 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_right.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_bottom_books_e.xml b/app/src/main/res/drawable/ic_bottom_books_e.xml index d99a276ba..04d36c375 100644 --- a/app/src/main/res/drawable/ic_bottom_books_e.xml +++ b/app/src/main/res/drawable/ic_bottom_books_e.xml @@ -4,15 +4,9 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M23,3V2.5a0.5,0.5 0,0 0,-0.5 -0.5H5.69A4.63,4.63 0,0 0,1 6.06,4.51 4.51,0 0,0 5.5,11h17a0.5,0.5 0,0 0,0.5 -0.5V10a0.5,0.5 0,0 0,-0.41 -0.5,3 3,0 0,1 0,-5.94A0.5,0.5 0,0 0,23 3ZM2.56,5.9A3.09,3.09 0,0 1,5.62 3.5H19.67a4.43,4.43 0,0 0,0 6H5.5A3,3 0,0 1,2.56 5.9Z" + android:fillColor="#2f45a6" /> - - + android:pathData="M1,21v0.53a0.5,0.5 0,0 0,0.5 0.5H18.31A4.63,4.63 0,0 0,23 17.94,4.51 4.51,0 0,0 18.5,13H1.5a0.5,0.5 0,0 0,-0.5 0.5V14a0.5,0.5 0,0 0,0.41 0.5,3 3,0 0,1 0,5.94A0.5,0.5 0,0 0,1 21ZM21.44,18.1a3.09,3.09 0,0 1,-3.06 2.4h-14a4.43,4.43 0,0 0,0 -6H18.5A3,3 0,0 1,21.44 18.1Z" + android:fillColor="#2f45a6" /> diff --git a/app/src/main/res/drawable/ic_bottom_books_s.xml b/app/src/main/res/drawable/ic_bottom_books_s.xml index 7ab340659..8f5f72542 100644 --- a/app/src/main/res/drawable/ic_bottom_books_s.xml +++ b/app/src/main/res/drawable/ic_bottom_books_s.xml @@ -4,15 +4,9 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M20,6.5a3,3 0,0 1,2.59 -3A0.5,0.5 0,0 0,23 3V2.5a0.5,0.5 0,0 0,-0.5 -0.5H5.69A4.63,4.63 0,0 0,1 6.06,4.51 4.51,0 0,0 5.5,11h17a0.5,0.5 0,0 0,0.5 -0.5V10a0.5,0.5 0,0 0,-0.41 -0.5A3,3 0,0 1,20 6.5Z" + android:fillColor="#2f45a6" /> - + android:pathData="M4,17.5a3,3 0,0 1,-2.59 3A0.5,0.5 0,0 0,1 21v0.53a0.5,0.5 0,0 0,0.5 0.5H18.31A4.63,4.63 0,0 0,23 17.94,4.51 4.51,0 0,0 18.5,13H1.5a0.5,0.5 0,0 0,-0.5 0.5V14a0.5,0.5 0,0 0,0.41 0.5A3,3 0,0 1,4 17.5Z" + android:fillColor="#2f45a6" /> diff --git a/app/src/main/res/drawable/ic_bottom_explore_e.xml b/app/src/main/res/drawable/ic_bottom_explore_e.xml index 13db8dc28..47e4bde9d 100644 --- a/app/src/main/res/drawable/ic_bottom_explore_e.xml +++ b/app/src/main/res/drawable/ic_bottom_explore_e.xml @@ -4,9 +4,9 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M12,2.5A9.5,9.5 0,1 1,2.5 12,9.51 9.51,0 0,1 12,2.5M12,1A11,11 0,1 0,23 12,11 11,0 0,0 12,1Z" + android:fillColor="#2f45a6" /> + android:pathData="M13.93,10.07l-1.29,2.57 -2.57,1.29 1.29,-2.57 2.57,-1.29M16.85,7a0.18,0.18 0,0 0,-0.1 0l-6.51,3.26L7,16.75a0.2,0.2 0,0 0,0.17 0.29,0.18 0.18,0 0,0 0.1,0l6.51,-3.26L17,7.25A0.2,0.2 0,0 0,16.85 7Z" + android:fillColor="#2f45a6" /> diff --git a/app/src/main/res/drawable/ic_bottom_explore_s.xml b/app/src/main/res/drawable/ic_bottom_explore_s.xml index df805a464..6dc6e4322 100644 --- a/app/src/main/res/drawable/ic_bottom_explore_s.xml +++ b/app/src/main/res/drawable/ic_bottom_explore_s.xml @@ -4,7 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M12,1A11,11 0,1 0,23 12,11 11,0 0,0 12,1ZM17,7.25 L13.74,13.76L7.25,17A0.2,0.2 0,0 1,7 16.75l3.26,-6.51L16.75,7A0.2,0.2 0,0 1,17 7.25Z" + android:fillColor="#2f45a6" /> diff --git a/app/src/main/res/drawable/ic_bottom_person_e.xml b/app/src/main/res/drawable/ic_bottom_person_e.xml index 2ddd441dc..d01128391 100644 --- a/app/src/main/res/drawable/ic_bottom_person_e.xml +++ b/app/src/main/res/drawable/ic_bottom_person_e.xml @@ -4,9 +4,9 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M12,2.5A4.5,4.5 0,1 1,7.5 7,4.51 4.51,0 0,1 12,2.5M12,1a6,6 0,1 0,6 6,6 6,0 0,0 -6,-6Z" + android:fillColor="#2f45a6" /> + android:pathData="M3.5,21A4.49,4.49 0,0 1,8 16.5h8A4.49,4.49 0,0 1,20.5 21v2H21a1,1 0,0 0,1 -1V21a6,6 0,0 0,-6 -6H8a6,6 0,0 0,-6 6v1a1,1 0,0 0,1 1h0.5Z" + android:fillColor="#2f45a6" /> diff --git a/app/src/main/res/drawable/ic_bottom_person_s.xml b/app/src/main/res/drawable/ic_bottom_person_s.xml index d2a5d99d8..3ff7fc8c4 100644 --- a/app/src/main/res/drawable/ic_bottom_person_s.xml +++ b/app/src/main/res/drawable/ic_bottom_person_s.xml @@ -4,11 +4,9 @@ android:viewportWidth="24" android:viewportHeight="24"> + android:pathData="M12,7m-6,0a6,6 0,1 1,12 0a6,6 0,1 1,-12 0" + android:fillColor="#2f45a6" /> + android:pathData="M8,15h8a6,6 0,0 1,6 6v1a1,1 0,0 1,-1 1H3a1,1 0,0 1,-1 -1V21A6,6 0,0 1,8 15Z" + android:fillColor="#2f45a6" /> diff --git a/app/src/main/res/drawable/ic_bottom_rss_feed_e.xml b/app/src/main/res/drawable/ic_bottom_rss_feed_e.xml index 2575ba9d4..c1c4ba0e3 100644 --- a/app/src/main/res/drawable/ic_bottom_rss_feed_e.xml +++ b/app/src/main/res/drawable/ic_bottom_rss_feed_e.xml @@ -3,10 +3,10 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - - + + diff --git a/app/src/main/res/drawable/ic_bottom_rss_feed_s.xml b/app/src/main/res/drawable/ic_bottom_rss_feed_s.xml index 4105b0154..a73c01430 100644 --- a/app/src/main/res/drawable/ic_bottom_rss_feed_s.xml +++ b/app/src/main/res/drawable/ic_bottom_rss_feed_s.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - + diff --git a/app/src/main/res/drawable/ic_help.xml b/app/src/main/res/drawable/ic_help.xml new file mode 100644 index 000000000..931a86bf6 --- /dev/null +++ b/app/src/main/res/drawable/ic_help.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_launcher1.xml b/app/src/main/res/drawable/ic_launcher1.xml new file mode 100644 index 000000000..18c829634 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher1.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher1_b.xml b/app/src/main/res/drawable/ic_launcher1_b.xml new file mode 100644 index 000000000..559d07c34 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher1_b.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-v24/ic_launcher_1.xml b/app/src/main/res/drawable/ic_launcher2.xml similarity index 100% rename from app/src/main/res/drawable-v24/ic_launcher_1.xml rename to app/src/main/res/drawable/ic_launcher2.xml diff --git a/app/src/main/res/drawable-v24/ic_launcher_3.xml b/app/src/main/res/drawable/ic_launcher3.xml similarity index 100% rename from app/src/main/res/drawable-v24/ic_launcher_3.xml rename to app/src/main/res/drawable/ic_launcher3.xml diff --git a/app/src/main/res/drawable-v24/ic_launcher_4.xml b/app/src/main/res/drawable/ic_launcher4.xml similarity index 100% rename from app/src/main/res/drawable-v24/ic_launcher_4.xml rename to app/src/main/res/drawable/ic_launcher4.xml diff --git a/app/src/main/res/drawable/ic_launcher5.xml b/app/src/main/res/drawable/ic_launcher5.xml new file mode 100644 index 000000000..29435836b --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher5.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher5_b.xml b/app/src/main/res/drawable/ic_launcher5_b.xml new file mode 100644 index 000000000..9a5153369 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher5_b.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_launcher.xml b/app/src/main/res/drawable/ic_launcher6.xml similarity index 100% rename from app/src/main/res/drawable/ic_launcher.xml rename to app/src/main/res/drawable/ic_launcher6.xml diff --git a/app/src/main/res/drawable/ic_launcher7.xml b/app/src/main/res/drawable/ic_launcher7.xml new file mode 100644 index 000000000..983784aef --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher7.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher7_b.xml b/app/src/main/res/drawable/ic_launcher7_b.xml new file mode 100644 index 000000000..76214f1e4 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher7_b.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_live_help_black_24dp.xml b/app/src/main/res/drawable/ic_live_help_black_24dp.xml deleted file mode 100644 index 8b9c1ac46..000000000 --- a/app/src/main/res/drawable/ic_live_help_black_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/shape_fillet_btn.xml b/app/src/main/res/drawable/shape_fillet_btn.xml index 10dac7541..83ccf2776 100644 --- a/app/src/main/res/drawable/shape_fillet_btn.xml +++ b/app/src/main/res/drawable/shape_fillet_btn.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_fillet_btn_press.xml b/app/src/main/res/drawable/shape_fillet_btn_press.xml index b569081a4..b0c46f6f5 100644 --- a/app/src/main/res/drawable/shape_fillet_btn_press.xml +++ b/app/src/main/res/drawable/shape_fillet_btn_press.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9f2d2044e..77ed85415 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -10,7 +10,7 @@ android:layout_height="wrap_content" android:elevation="10dp" android:background="@color/background" - app:labelVisibilityMode="labeled" + app:labelVisibilityMode="unlabeled" app:menu="@menu/main_bnv" app:layout_constraintBottom_toBottomOf="parent" /> diff --git a/app/src/main/res/layout/dialog_read_aloud.xml b/app/src/main/res/layout/dialog_read_aloud.xml index 278117426..504865171 100644 --- a/app/src/main/res/layout/dialog_read_aloud.xml +++ b/app/src/main/res/layout/dialog_read_aloud.xml @@ -221,6 +221,7 @@ android:layout_gravity="center_horizontal" android:layout_marginTop="3dp" android:text="@string/chapter_list" + android:maxLines="1" android:textColor="@color/tv_text_default" android:textSize="12sp" /> @@ -256,6 +257,7 @@ android:layout_gravity="center_horizontal" android:layout_marginTop="3dp" android:text="@string/main_menu" + android:maxLines="1" android:textColor="@color/tv_text_default" android:textSize="12sp" /> @@ -291,6 +293,7 @@ android:layout_gravity="center_horizontal" android:layout_marginTop="3dp" android:text="@string/to_backstage" + android:maxLines="1" android:textColor="@color/tv_text_default" android:textSize="12sp" /> @@ -325,7 +328,8 @@ android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="3dp" - android:text="@string/aloud_config" + android:text="@string/setting" + android:maxLines="1" android:textColor="@color/tv_text_default" android:textSize="12sp" /> diff --git a/app/src/main/res/layout/dialog_recycler_view.xml b/app/src/main/res/layout/dialog_recycler_view.xml index 98f67043f..5b1d900a9 100644 --- a/app/src/main/res/layout/dialog_recycler_view.xml +++ b/app/src/main/res/layout/dialog_recycler_view.xml @@ -15,7 +15,7 @@ android:id="@+id/recycler_view" android:background="@color/background_card" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="0dp" android:layout_weight="1" /> diff --git a/app/src/main/res/layout/item_bookshelf_grid.xml b/app/src/main/res/layout/item_bookshelf_grid.xml index 666d67098..a038fa4fb 100644 --- a/app/src/main/res/layout/item_bookshelf_grid.xml +++ b/app/src/main/res/layout/item_bookshelf_grid.xml @@ -48,19 +48,6 @@ tools:ignore="RtlHardcoded" /> - - @@ -17,8 +15,7 @@ android:paddingRight="10dp" android:paddingTop="6dp" android:paddingBottom="6dp" - android:layout_margin="4dp" - android:background="@color/btn_bg_press" + android:background="@drawable/bg_find_book_group" android:orientation="horizontal" android:gravity="center_vertical"> @@ -28,11 +25,22 @@ android:layout_height="wrap_content" android:layout_weight="1" /> + + @@ -41,6 +49,8 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_text.xml b/app/src/main/res/layout/item_text.xml index e37188e47..357efdde3 100644 --- a/app/src/main/res/layout/item_text.xml +++ b/app/src/main/res/layout/item_text.xml @@ -9,6 +9,7 @@ android:gravity="center" android:padding="5dp" android:maxLines="1" + android:scrollbars="none" android:textColor="@color/tv_text_default" android:textSize="14sp" tools:ignore="UnusedAttribute" /> diff --git a/app/src/main/res/layout/popup_action_menu.xml b/app/src/main/res/layout/popup_action_menu.xml index 98cceb33c..0f6b6e0e5 100644 --- a/app/src/main/res/layout/popup_action_menu.xml +++ b/app/src/main/res/layout/popup_action_menu.xml @@ -1,27 +1,46 @@ - + android:orientation="vertical"> - + android:orientation="horizontal" + android:gravity="center_vertical"> + + + + + + - + android:orientation="vertical" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> - + diff --git a/app/src/main/res/layout/view_search.xml b/app/src/main/res/layout/view_search.xml index 5fd67be63..9b1d48efd 100644 --- a/app/src/main/res/layout/view_search.xml +++ b/app/src/main/res/layout/view_search.xml @@ -3,8 +3,13 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/search_view" - android:layout_width="match_parent" android:theme="?attr/actionBarStyle" - android:layout_height="wrap_content" + android:background="@drawable/bg_searchview" + android:layout_width="match_parent" + android:layout_height="34dp" + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp" android:imeOptions="actionSearch" + app:queryBackground="@null" + app:submitBackground="@null" app:defaultQueryHint="搜索"/> \ No newline at end of file diff --git a/app/src/main/res/menu/content_select_action.xml b/app/src/main/res/menu/content_select_action.xml index d11ee6154..ff83efd96 100644 --- a/app/src/main/res/menu/content_select_action.xml +++ b/app/src/main/res/menu/content_select_action.xml @@ -9,6 +9,10 @@ android:id="@+id/menu_copy" android:title="@android:string/copy" /> + + diff --git a/app/src/main/res/menu/main_bnv.xml b/app/src/main/res/menu/main_bnv.xml index 15b355b31..9197bec7b 100644 --- a/app/src/main/res/menu/main_bnv.xml +++ b/app/src/main/res/menu/main_bnv.xml @@ -4,20 +4,20 @@ tools:showIn="bottom_navigation_view"> + android:id="@+id/menu_bookshelf" + android:icon="@drawable/ic_bottom_books" + android:title="@string/bookshelf" /> + android:title="@string/find" /> + android:id="@+id/menu_rss" + android:icon="@drawable/ic_bottom_rss_feed" + android:title="@string/rss" /> + android:id="@+id/menu_my_config" + android:icon="@drawable/ic_bottom_person" + android:title="@string/my" /> diff --git a/app/src/main/res/menu/main_my.xml b/app/src/main/res/menu/main_my.xml index 74e555dff..02b6acbd0 100644 --- a/app/src/main/res/menu/main_my.xml +++ b/app/src/main/res/menu/main_my.xml @@ -6,7 +6,7 @@ diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 7f9b677b9..7a68d4392 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher1.xml b/app/src/main/res/mipmap-anydpi-v26/launcher1.xml index 57e845ad3..b3aa68018 100644 --- a/app/src/main/res/mipmap-anydpi-v26/launcher1.xml +++ b/app/src/main/res/mipmap-anydpi-v26/launcher1.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher2.xml b/app/src/main/res/mipmap-anydpi-v26/launcher2.xml index 409e0d965..5de236bd2 100644 --- a/app/src/main/res/mipmap-anydpi-v26/launcher2.xml +++ b/app/src/main/res/mipmap-anydpi-v26/launcher2.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher3.xml b/app/src/main/res/mipmap-anydpi-v26/launcher3.xml index 24428243f..9e7ef6711 100644 --- a/app/src/main/res/mipmap-anydpi-v26/launcher3.xml +++ b/app/src/main/res/mipmap-anydpi-v26/launcher3.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher4.xml b/app/src/main/res/mipmap-anydpi-v26/launcher4.xml index 22463230c..63e51b918 100644 --- a/app/src/main/res/mipmap-anydpi-v26/launcher4.xml +++ b/app/src/main/res/mipmap-anydpi-v26/launcher4.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher5.xml b/app/src/main/res/mipmap-anydpi-v26/launcher5.xml new file mode 100644 index 000000000..7a23c7c66 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/launcher5.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/launcher6.xml b/app/src/main/res/mipmap-anydpi-v26/launcher6.xml new file mode 100644 index 000000000..4ba689a93 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/launcher6.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index 66ab5d53d..0fe58e361 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index 24f2180fb..59526eefd 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index e7b02cc36..58b1e389a 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index b41e4253d..ea95882bd 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 5ec228901..fe1be3fde 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 18ab012e0..78d372bbd 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -10,6 +10,7 @@ #69000000 + #10ffffff #30ffffff #363636 diff --git a/app/src/main/res/values/array_values.xml b/app/src/main/res/values/array_values.xml index dd0842163..40bc6684e 100644 --- a/app/src/main/res/values/array_values.xml +++ b/app/src/main/res/values/array_values.xml @@ -7,6 +7,8 @@ launcher2 launcher3 launcher4 + launcher5 + launcher6 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index cb61d6daa..39c85cae3 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -80,6 +80,8 @@ icon2 icon3 icon4 + icon5 + icon6 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d6999a7ae..58f27cdec 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -18,6 +18,7 @@ @color/md_grey_200 #00000000 + #10000000 #30000000 #d3321b diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 6b7b8e2b1..f7ecf2030 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -6,7 +6,6 @@ 176dp 16dp - 14sp 16sp 18sp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a505fa785..558e90cbe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -225,7 +225,7 @@ 内容简介 简介:%s 打开外部书籍 - 来源:%s + 来源: %s 本地导入 导入在线规则 检查更新间隔 @@ -581,7 +581,7 @@ 类型: 文本 音频 - 转到后台 + 后台 正在导入 正在导出 自定义翻页按键 @@ -648,4 +648,5 @@ 主菜单 点击授予权限 阅读需要访问存储卡权限,请点击下方的"授予权限"按钮,或前往“设置”—“应用权限”—打开所需权限。如果授予权限后仍然不正常,请点击右上角的“选择文件夹”,使用系统文件夹选择器。 + 全文朗读中不能朗读选中文字