diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0f9f29bdb..ef2c71ab2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,6 +18,7 @@ + 【备份与恢复】,选择【导入旧版本数据】。 +**2020/09/15** +* 修复导入排版字体重复报错的bug +* 添加正文搜索 by [h11128](https://github.com/h11128) + **2020/09/12** * web看书同步最新章 * web写源增加图片样式等规则 diff --git a/app/src/main/java/io/legado/app/constant/EventBus.kt b/app/src/main/java/io/legado/app/constant/EventBus.kt index 6fe8b5cea..53ec7d778 100644 --- a/app/src/main/java/io/legado/app/constant/EventBus.kt +++ b/app/src/main/java/io/legado/app/constant/EventBus.kt @@ -20,4 +20,7 @@ object EventBus { const val WEB_SERVICE_STOP = "webServiceStop" const val UP_DOWNLOAD = "upDownload" const val SAVE_CONTENT = "saveContent" + const val CHECK_INIT = "checkInit" + const val CHECK_UP_PROGRESS = "checkProgress" + const val CHECK_DONE = "checkDone" } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/AppConfig.kt b/app/src/main/java/io/legado/app/help/AppConfig.kt index e2538e902..eddc4f428 100644 --- a/app/src/main/java/io/legado/app/help/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/AppConfig.kt @@ -58,6 +58,9 @@ object AppConfig { App.INSTANCE.putPrefBoolean(PreferKey.showRss, value) } + val backgroundVerification: Boolean + get() = App.INSTANCE.getPrefBoolean(R.string.pk_background_verification) + val autoRefreshBook: Boolean get() = App.INSTANCE.getPrefBoolean(R.string.pk_auto_refresh) diff --git a/app/src/main/java/io/legado/app/help/IntentHelp.kt b/app/src/main/java/io/legado/app/help/IntentHelp.kt index d02e13392..d7ed03af1 100644 --- a/app/src/main/java/io/legado/app/help/IntentHelp.kt +++ b/app/src/main/java/io/legado/app/help/IntentHelp.kt @@ -3,6 +3,7 @@ package io.legado.app.help import android.app.PendingIntent import android.content.Context import android.content.Intent +import android.os.Bundle import io.legado.app.R import org.jetbrains.anko.toast @@ -32,21 +33,29 @@ object IntentHelp { } } - inline fun servicePendingIntent(context: Context, action: String): PendingIntent? { - return PendingIntent.getService( - context, - 0, - Intent(context, T::class.java).apply { this.action = action }, - PendingIntent.FLAG_UPDATE_CURRENT - ) + inline fun servicePendingIntent( + context: Context, + action: String, + bundle: Bundle? = null + ): PendingIntent? { + val intent = Intent(context, T::class.java) + intent.action = action + bundle?.let { + intent.putExtras(bundle) + } + return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } - inline fun activityPendingIntent(context: Context, action: String): PendingIntent? { - return PendingIntent.getActivity( - context, - 0, - Intent(context, T::class.java).apply { this.action = action }, - PendingIntent.FLAG_UPDATE_CURRENT - ) + inline fun activityPendingIntent( + context: Context, + action: String, + bundle: Bundle? = null + ): PendingIntent? { + val intent = Intent(context, T::class.java) + intent.action = action + bundle?.let { + intent.putExtras(bundle) + } + return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt index d196e18fa..f9ed9230f 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt @@ -324,17 +324,37 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { */ private fun replaceRegex(result: String, rule: SourceRule): String { var vResult = result - if (rule.replaceRegex.isNotEmpty()) { + val stringBuffer = StringBuffer() + val evalMatcher = replacePattern.matcher(rule.replaceRegex) + while (evalMatcher.find()) { + val jsEval = evalMatcher.group().let { + if (it.startsWith("@get:", true)) { + get(it.substring(6, it.lastIndex)) + } else { + evalJS(it.substring(2, it.length - 2), result) + } + } ?: "" + if (jsEval is String) { + evalMatcher.appendReplacement(stringBuffer, jsEval) + } else if (jsEval is Double && jsEval % 1.0 == 0.0) { + evalMatcher.appendReplacement(stringBuffer, String.format("%.0f", jsEval)) + } else { + evalMatcher.appendReplacement(stringBuffer, jsEval.toString()) + } + } + evalMatcher.appendTail(stringBuffer) + val replaceRegex = stringBuffer.toString() + if (replaceRegex.isNotEmpty()) { vResult = if (rule.replaceFirst) { - val pattern = Pattern.compile(rule.replaceRegex) + val pattern = Pattern.compile(replaceRegex) val matcher = pattern.matcher(vResult) if (matcher.find()) { - matcher.group(0)!!.replaceFirst(rule.replaceRegex.toRegex(), rule.replacement) + matcher.group(0)!!.replaceFirst(replaceRegex.toRegex(), rule.replacement) } else { "" } } else { - vResult.replace(rule.replaceRegex.toRegex(), rule.replacement) + vResult.replace(replaceRegex.toRegex(), rule.replacement) } } return vResult @@ -644,6 +664,10 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions { "@get:\\{[^}]+?\\}|\\{\\{[\\w\\W]*?\\}\\}|\\$\\d{1,2}", Pattern.CASE_INSENSITIVE ) + private val replacePattern = Pattern.compile( + "@get:\\{[^}]+?\\}|\\{\\{[\\w\\W]*?\\}\\}", + Pattern.CASE_INSENSITIVE + ) } } diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt index 396df397e..067690afb 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt @@ -150,7 +150,7 @@ class AnalyzeUrl( //js if (ruleUrl.contains("{{") && ruleUrl.contains("}}")) { var jsEval: Any - val sb = StringBuffer(ruleUrl.length) + val sb = StringBuffer() val simpleBindings = SimpleBindings() simpleBindings["java"] = this simpleBindings["baseUrl"] = baseUrl diff --git a/app/src/main/java/io/legado/app/service/CheckSourceService.kt b/app/src/main/java/io/legado/app/service/CheckSourceService.kt index 09900d0d0..4ce08ff07 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -6,12 +6,15 @@ import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseService import io.legado.app.constant.AppConst +import io.legado.app.constant.EventBus import io.legado.app.constant.IntentAction import io.legado.app.help.AppConfig +import io.legado.app.help.AppConfig.backgroundVerification import io.legado.app.help.IntentHelp import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.service.help.CheckSource import io.legado.app.ui.book.source.manage.BookSourceActivity +import io.legado.app.utils.postEvent import kotlinx.coroutines.asCoroutineDispatcher import org.jetbrains.anko.toast import java.util.concurrent.Executors @@ -42,7 +45,9 @@ class CheckSourceService : BaseService() { override fun onCreate() { super.onCreate() - updateNotification(0, getString(R.string.start)) + if (backgroundVerification) { + updateNotification(0, getString(R.string.start)) + } } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -59,6 +64,7 @@ class CheckSourceService : BaseService() { super.onDestroy() tasks.clear() searchPool.close() + postEvent(EventBus.CHECK_DONE, 0) } private fun check(ids: List) { @@ -72,7 +78,11 @@ class CheckSourceService : BaseService() { allIds.addAll(ids) processIndex = 0 threadCount = min(allIds.size, threadCount) - updateNotification(0, getString(R.string.progress_show, 0, allIds.size)) + if (backgroundVerification) { + updateNotification(0, getString(R.string.progress_show, 0, allIds.size)) + } else { + postEvent(EventBus.CHECK_INIT, allIds.size) + } for (i in 0 until threadCount) { check() } @@ -106,10 +116,14 @@ class CheckSourceService : BaseService() { synchronized(this) { check() checkedIds.add(sourceUrl) - updateNotification( - checkedIds.size, - getString(R.string.progress_show, checkedIds.size, allIds.size) - ) + if (backgroundVerification) { + updateNotification( + checkedIds.size, + getString(R.string.progress_show, checkedIds.size, allIds.size) + ) + } else { + postEvent(EventBus.CHECK_UP_PROGRESS, checkedIds.size) + } if (processIndex >= allIds.size + threadCount - 1) { stopSelf() } diff --git a/app/src/main/java/io/legado/app/service/DownloadService.kt b/app/src/main/java/io/legado/app/service/DownloadService.kt index 7a77bb7a5..53868a977 100644 --- a/app/src/main/java/io/legado/app/service/DownloadService.kt +++ b/app/src/main/java/io/legado/app/service/DownloadService.kt @@ -1,46 +1,197 @@ package io.legado.app.service +import android.app.DownloadManager +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent +import android.content.IntentFilter +import android.net.Uri +import android.os.Build +import android.os.Handler import androidx.core.app.NotificationCompat +import androidx.core.content.FileProvider +import androidx.core.os.bundleOf +import io.legado.app.BuildConfig import io.legado.app.R import io.legado.app.base.BaseService import io.legado.app.constant.AppConst import io.legado.app.constant.IntentAction import io.legado.app.help.IntentHelp +import io.legado.app.utils.RealPathUtil +import io.legado.app.utils.msg +import org.jetbrains.anko.downloadManager +import org.jetbrains.anko.toast +import java.io.File + class DownloadService : BaseService() { - private val notificationBuilder by lazy { - val builder = NotificationCompat.Builder(this, AppConst.channelIdDownload) - .setSmallIcon(R.drawable.ic_download) - .setOngoing(true) - .setContentTitle(getString(R.string.action_download)) - builder.addAction( - R.drawable.ic_stop_black_24dp, - getString(R.string.cancel), - IntentHelp.servicePendingIntent(this, IntentAction.stop) - ) - builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + private val downloads = hashMapOf() + private val completeDownloads = hashSetOf() + private val handler = Handler() + private val runnable = Runnable { + checkDownloadState() + } + + private val downloadReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + queryState() + } } override fun onCreate() { super.onCreate() - updateNotification("准备下载") + registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) + } + + override fun onTaskRemoved(rootIntent: Intent?) { + super.onTaskRemoved(rootIntent) + stopSelf() + } + + override fun onDestroy() { + super.onDestroy() + unregisterReceiver(downloadReceiver) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { when (intent?.action) { - + IntentAction.start -> startDownload( + intent.getLongExtra("downloadId", 0), + intent.getStringExtra("fileName") ?: "未知文件" + ) + IntentAction.play -> { + val id = intent.getLongExtra("downloadId", 0) + if (downloads[id]?.endsWith(".apk") == true) { + installApk(id) + } + } + IntentAction.stop -> { + val downloadId = intent.getLongExtra("downloadId", 0) + downloads.remove(downloadId) + if (downloads.isEmpty()) { + stopSelf() + } + } } return super.onStartCommand(intent, flags, startId) } + private fun startDownload(downloadId: Long, fileName: String) { + if (downloadId > 0) { + downloads[downloadId] = fileName + queryState() + checkDownloadState() + } + } + + private fun checkDownloadState() { + handler.removeCallbacks(runnable) + queryState() + handler.postDelayed(runnable, 1000) + } + + //查询下载进度 + private fun queryState() { + val ids = downloads.keys + val query = DownloadManager.Query() + query.setFilterById(*ids.toLongArray()) + downloadManager.query(query).use { cursor -> + if (!cursor.moveToFirst()) return + val id = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID)) + val progress: Int = + cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)) + val max: Int = + cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)) + val status = + when (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))) { + DownloadManager.STATUS_PAUSED -> "暂停" + DownloadManager.STATUS_PENDING -> "待下载" + DownloadManager.STATUS_RUNNING -> "下载中" + DownloadManager.STATUS_SUCCESSFUL -> { + if (!completeDownloads.contains(id)) { + completeDownloads.add(id) + if (downloads[id]?.endsWith(".apk") == true) { + installApk(id) + } + } + "下载完成" + } + DownloadManager.STATUS_FAILED -> "下载失败" + else -> "未知状态" + } + updateNotification(id, "${downloads[id]} $status", max, progress) + } + } + + private fun installApk(downloadId: Long) { + downloadManager.getUriForDownloadedFile(downloadId)?.let { + val filePath = RealPathUtil.getPath(this, it) ?: return + val file = File(filePath) + //调用系统安装apk + val intent = Intent() + intent.action = Intent.ACTION_VIEW + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //7.0版本以上 + val uriForFile: Uri = + FileProvider.getUriForFile( + this, + "${BuildConfig.APPLICATION_ID}.fileProvider", + file + ) + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + intent.setDataAndType(uriForFile, "application/vnd.android.package-archive") + } else { + val uri: Uri = Uri.fromFile(file) + intent.setDataAndType(uri, "application/vnd.android.package-archive") + } + + try { + startActivity(intent) + } catch (e: Exception) { + toast(e.msg) + } + } + } + /** * 更新通知 */ - private fun updateNotification(content: String) { + private fun updateNotification(downloadId: Long, content: String, max: Int, progress: Int) { + val notificationBuilder = NotificationCompat.Builder(this, AppConst.channelIdDownload) + .setSmallIcon(R.drawable.ic_download) + .setOngoing(true) + .setContentTitle(getString(R.string.action_download)) + notificationBuilder.setContentIntent( + IntentHelp.servicePendingIntent( + this, + IntentAction.play, + bundleOf("downloadId" to downloadId) + ) + ) + notificationBuilder.addAction( + R.drawable.ic_stop_black_24dp, + getString(R.string.cancel), + IntentHelp.servicePendingIntent( + this, + IntentAction.stop, + bundleOf("downloadId" to downloadId) + ) + ) + notificationBuilder.setDeleteIntent( + IntentHelp.servicePendingIntent( + this, + IntentAction.stop, + bundleOf("downloadId" to downloadId) + ) + ) + notificationBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) notificationBuilder.setContentText(content) + notificationBuilder.setProgress(max, progress, false) + notificationBuilder.setAutoCancel(true) val notification = notificationBuilder.build() - startForeground(AppConst.notificationIdDownload, notification) + startForeground(downloadId.toInt(), notification) } + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/service/help/Download.kt b/app/src/main/java/io/legado/app/service/help/Download.kt new file mode 100644 index 000000000..cddbf59b6 --- /dev/null +++ b/app/src/main/java/io/legado/app/service/help/Download.kt @@ -0,0 +1,26 @@ +package io.legado.app.service.help + +import android.content.Context +import android.content.Intent +import io.legado.app.constant.IntentAction +import io.legado.app.service.DownloadService + +object Download { + + fun start(context: Context, downloadId: Long, fileName: String) { + Intent(context, DownloadService::class.java).let { + it.action = IntentAction.start + it.putExtra("downloadId", downloadId) + it.putExtra("fileName", fileName) + context.startService(it) + } + } + + fun stop(context: Context) { + Intent(context, DownloadService::class.java).let { + it.action = IntentAction.stop + context.startService(it) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt index 322e4a7a3..1118eb8cc 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowAdapter.kt @@ -26,7 +26,11 @@ class ExploreShowAdapter(context: Context, val callBack: CallBack) : tv_lasted.text = context.getString(R.string.lasted_show, item.latestChapterTitle) tv_lasted.visible() } - tv_introduce.text = context.getString(R.string.intro_show, item.intro) + if (item.intro.isNullOrEmpty()) { + tv_introduce.text = context.getString(R.string.intro_show_null) + } else { + tv_introduce.text = context.getString(R.string.intro_show, item.intro) + } val kinds = item.getKindList() if (kinds.isEmpty()) { ll_kind.gone() diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt index 26423e701..bef8898ee 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt @@ -65,6 +65,8 @@ class ReadMenu : FrameLayout { brightnessBackground.setColor(ColorUtils.adjustAlpha(bgColor, 0.5f)) ll_brightness.background = brightnessBackground ll_bottom_bg.setBackgroundColor(bgColor) + fabSearch.backgroundTintList = bottomBackgroundList + fabSearch.setColorFilter(textColor) fabAutoPage.backgroundTintList = bottomBackgroundList fabAutoPage.setColorFilter(textColor) fabReplaceRule.backgroundTintList = bottomBackgroundList @@ -170,6 +172,13 @@ class ReadMenu : FrameLayout { } }) + //搜索 + fabSearch.onClick { + runMenuOut { + callBack?.openSearchList() + } + } + //自动翻页 fabAutoPage.onClick { runMenuOut { @@ -200,12 +209,6 @@ class ReadMenu : FrameLayout { } } - ll_search.onClick { - runMenuOut { - callBack?.openSearchList() - } - } - //朗读 ll_read_aloud.onClick { runMenuOut { 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 841a5b9a9..b8d71b515 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 @@ -324,7 +324,9 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack { val fontName = FileUtils.getName(config.textFont) val fontPath = FileUtils.getPath(requireContext().externalFilesDir, "font", fontName) - FileUtils.getFile(configDir, fontName).copyTo(File(fontPath)) + if (!FileUtils.exist(fontPath)) { + FileUtils.getFile(configDir, fontName).copyTo(File(fontPath)) + } config.textFont = fontPath } if (config.bgType() == 2) { 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 a96244113..4370e9697 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 @@ -42,7 +42,13 @@ class SearchAdapter(context: Context, val callBack: CallBack) : tv_author.text = context.getString(R.string.author_show, searchBook.author) bv_originCount.setBadgeCount(searchBook.origins.size) upLasted(itemView, searchBook.latestChapterTitle) - tv_introduce.text = context.getString(R.string.intro_show, searchBook.intro) + if (searchBook.intro.isNullOrEmpty()) { + tv_introduce.text = + context.getString(R.string.intro_show_null) + } else { + tv_introduce.text = + context.getString(R.string.intro_show, searchBook.intro) + } upKind(itemView, searchBook.getKindList()) iv_cover.load(searchBook.coverUrl, searchBook.name, searchBook.author) @@ -58,8 +64,15 @@ class SearchAdapter(context: Context, val callBack: CallBack) : context.getString(R.string.author_show, searchBook.author) "origins" -> bv_originCount.setBadgeCount(searchBook.origins.size) "last" -> upLasted(itemView, searchBook.latestChapterTitle) - "intro" -> tv_introduce.text = - context.getString(R.string.intro_show, searchBook.intro) + "intro" -> { + if (searchBook.intro.isNullOrEmpty()) { + tv_introduce.text = + context.getString(R.string.intro_show_null) + } else { + tv_introduce.text = + context.getString(R.string.intro_show, searchBook.intro) + } + } "kind" -> upKind(itemView, searchBook.getKindList()) "cover" -> iv_cover.load( searchBook.coverUrl, diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt index d2c98b955..d68eb85ca 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchListAdapter.kt @@ -1,21 +1,12 @@ package io.legado.app.ui.book.searchContent import android.content.Context -import android.os.Build -import android.text.Html -import android.util.Log -import android.view.View -import androidx.annotation.RequiresApi -import androidx.core.text.HtmlCompat import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.SimpleRecyclerAdapter -import io.legado.app.data.entities.BookChapter -import io.legado.app.help.BookHelp import io.legado.app.lib.theme.accentColor import io.legado.app.utils.getCompatColor -import io.legado.app.utils.visible -import kotlinx.android.synthetic.main.item_bookmark.view.* +import io.legado.app.utils.hexString import kotlinx.android.synthetic.main.item_search_list.view.* import org.jetbrains.anko.sdk27.listeners.onClick @@ -23,15 +14,15 @@ class SearchListAdapter(context: Context, val callback: Callback) : SimpleRecyclerAdapter(context, R.layout.item_search_list) { val cacheFileNames = hashSetOf() + val textColor = context.getCompatColor(R.color.primaryText).hexString.substring(2) + val accentColor = context.accentColor.hexString.substring(2) override fun convert(holder: ItemViewHolder, item: SearchResult, payloads: MutableList) { with(holder.itemView) { val isDur = callback.durChapterIndex() == item.chapterIndex if (payloads.isEmpty()) { - tv_search_result.text = item.parseText(item.presentText) - if (isDur){ - tv_search_result.paint.isFakeBoldText = true - } + tv_search_result.text = item.getHtmlCompat(textColor, accentColor) + tv_search_result.paint.isFakeBoldText = isDur } } } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt index 6b0d9df5b..482afab30 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchResult.kt @@ -1,9 +1,7 @@ package io.legado.app.ui.book.searchContent import android.text.Spanned -import android.util.Log import androidx.core.text.HtmlCompat -import io.legado.app.ui.book.read.page.entities.TextPage data class SearchResult( var index: Int = 0, @@ -17,24 +15,25 @@ data class SearchResult( var newPosition: Int = 0, var contentPosition: Int =0 ) { - val presentText: String - get(){ - return colorPresentText(newPosition, query, text) + - "($chapterTitle)" - } - fun colorPresentText(position: Int, center: String, targetText: String): String{ - val sub1 = text.substring(0, position) - val sub2 = text.substring(position + center.length, targetText.length) - return "$sub1" + - "$center" + - "$sub2" + fun getHtmlCompat(textColor: String, accentColor: String): Spanned { + val html = colorPresentText(newPosition, query, text, textColor, accentColor) + + "($chapterTitle)" + return HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY) } - fun parseText(targetText: String): Spanned { - return HtmlCompat.fromHtml(targetText, HtmlCompat.FROM_HTML_MODE_LEGACY) + private fun colorPresentText( + position: Int, + center: String, + targetText: String, + textColor: String, + accentColor: String + ): String { + val sub1 = text.substring(0, position) + val sub2 = text.substring(position + center.length, targetText.length) + return "$sub1" + + "$center" + + "$sub2" } - - } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 07f959719..d6f1aab3f 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -21,6 +21,7 @@ import io.legado.app.BuildConfig import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppPattern +import io.legado.app.constant.EventBus import io.legado.app.data.entities.BookSource import io.legado.app.help.IntentDataHelp import io.legado.app.lib.dialogs.* @@ -65,6 +66,12 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity private var sort = 0 private var sortAscending = 0 + private val progressDialogBuilder by lazy { + progressDialog("校验书源") { + setCancelable(false) + } + } + override fun onActivityCreated(savedInstanceState: Bundle?) { initRecyclerView() initSearchView() @@ -263,6 +270,30 @@ class BookSourceActivity : VMBaseActivity(R.layout.activity } + override fun observeLiveBus() { + observeEvent(EventBus.CHECK_INIT) { max-> + progressDialogBuilder.max = max + progressDialogBuilder.show() + } + observeEvent(EventBus.CHECK_UP_PROGRESS) { progress-> + progressDialogBuilder.progress = progress + } + observeEvent(EventBus.CHECK_DONE) { + if (progressDialogBuilder.isShowing) { + progressDialogBuilder.progress = it + progressDialogBuilder.max = it + progressDialogBuilder.dismiss() + } + toast("校验完成!") + groups.map { group-> + if (group.contains("失效")) { + search_view.setQuery("失效", true) + toast("发现有失效书源,已为您自动筛选!") + } + } + } + } + override fun onMenuItemClick(item: MenuItem?): Boolean { when (item?.itemId) { R.id.menu_enable_selection -> viewModel.enableSelection(adapter.getSelection()) 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 ccfa5bf82..0fdfa373f 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 @@ -11,10 +11,7 @@ import io.legado.app.base.adapter.SimpleRecyclerAdapter 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 io.legado.app.utils.* import kotlinx.android.synthetic.main.item_fillet_text.view.* import kotlinx.android.synthetic.main.item_find_book.view.* import kotlinx.coroutines.CoroutineScope @@ -55,12 +52,12 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca .inflate(R.layout.item_fillet_text, gl_child, false) gl_child.addView(tv) tv.text_view.text = kind.title - tv.text_view.onClick { - kind.url?.let { kindUrl -> + if (!kind.url.isNullOrEmpty()) { + tv.text_view.onClick { callBack.openExplore( item.bookSourceUrl, kind.title, - kindUrl + kind.url.toString() ) } } diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt index e2834e456..c66cad69f 100644 --- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt @@ -15,12 +15,14 @@ import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.lib.theme.DrawableUtils import io.legado.app.lib.theme.primaryTextColor +import io.legado.app.service.help.Download import io.legado.app.ui.filechooser.FileChooserDialog import io.legado.app.ui.filechooser.FilePicker import io.legado.app.utils.* import kotlinx.android.synthetic.main.activity_rss_read.* import kotlinx.coroutines.launch import org.apache.commons.text.StringEscapeUtils +import org.jetbrains.anko.downloadManager import org.jetbrains.anko.share import org.jsoup.Jsoup @@ -160,13 +162,12 @@ class ReadRssActivity : VMBaseActivity(R.layout.activity_rss_r request.setAllowedOverRoaming(true) // 允许下载的网路类型 request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI) - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE) + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN) // 设置下载文件保存的路径和文件名 request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName) - val downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager // 添加一个下载任务 val downloadId = downloadManager.enqueue(request) - print(downloadId) + Download.start(this, downloadId, fileName) } } } diff --git a/app/src/main/res/layout/view_read_menu.xml b/app/src/main/res/layout/view_read_menu.xml index b63fba1ff..d48221169 100644 --- a/app/src/main/res/layout/view_read_menu.xml +++ b/app/src/main/res/layout/view_read_menu.xml @@ -92,6 +92,26 @@ android:paddingStart="32dp" android:paddingEnd="32dp"> + + + + - - - - - - - - - Version %s + 後臺校驗書源 + 打開后可以在校驗書源時自由操作 自動刷新 打開程式時自動更新書輯 自動下載最新章節 @@ -223,6 +225,7 @@ 載入失敗,點擊重試 內容簡介 簡介: %s + 簡介: 暫無簡介 打開外部書籍 來源: %s 本地導入 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 006b4ff45..17cc16af4 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -94,6 +94,8 @@ 閱讀3.0下載網址:\nhttps://play.google.com/store/apps/details?id=io.legado.play.release Version %s + 後臺校驗書源 + 打開后可以在校驗書源時自由操作 自動重新整理 打開軟體時自動更新書籍 自動下載最新章節 @@ -223,6 +225,7 @@ 載入失敗,點擊重試 內容簡介 簡介:%s + 簡介: 暫無簡介 打開外部書籍 來源: %s 本機匯入 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 78487a2be..2a5645ab8 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -96,6 +96,8 @@ 阅读3.0下载地址:\nhttps://www.coolapk.com/apk/256030 Version %s + 后台校验书源 + 打开后可以在校验书源时自由操作 自动刷新 打开软件时自动更新书籍 自动下载最新章节 @@ -225,6 +227,7 @@ 加载失败,点击重试 内容简介 简介:%s + 简介: 暂无简介 打开外部书籍 来源: %s 本地导入 diff --git a/app/src/main/res/values/pref_key_value.xml b/app/src/main/res/values/pref_key_value.xml index 42058ce0c..7ce2f7f13 100644 --- a/app/src/main/res/values/pref_key_value.xml +++ b/app/src/main/res/values/pref_key_value.xml @@ -1,5 +1,6 @@ + background_verification auto_refresh list_screen_direction full_screen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 893230b30..8ae687184 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -96,6 +96,8 @@ Legado (YueDu 3.0) download link:\n https://play.google.com/store/apps/details?id=io.legado.play.release Version %s + Background-verification + you can operate freely when verifying the book source Auto-refresh Update books automatically when opening the software Auto-download @@ -225,6 +227,7 @@ Load failed, tap to retry Book description Description:%s + Description: no introduction Open external book Origin: %s Import local rules diff --git a/app/src/main/res/xml/pref_config_other.xml b/app/src/main/res/xml/pref_config_other.xml index 0e3930546..f4f28ca94 100644 --- a/app/src/main/res/xml/pref_config_other.xml +++ b/app/src/main/res/xml/pref_config_other.xml @@ -51,6 +51,13 @@ app:iconSpaceReserved="false" app:layout="@layout/view_preference_category"> + +