diff --git a/app/build.gradle b/app/build.gradle index 9ae2752a0..58ce975d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,13 +97,13 @@ android { compileOptions { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true - // Sets Java compatibility to Java 8 - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + // Sets Java compatibility to Java 11 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "11" } buildToolsVersion '30.0.3' tasks.withType(JavaCompile) { @@ -198,7 +198,7 @@ dependencies { implementation('org.nanohttpd:nanohttpd-apache-fileupload:2.3.1') //二维码 - implementation('com.github.jenly1314:zxing-lite:2.1.0') + implementation('com.github.jenly1314:zxing-lite:2.1.1') //颜色选择 implementation('com.jaredrummler:colorpicker:1.1.0') diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 7a0a16eeb..25069b073 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -2,7 +2,6 @@ * 关注公众号 **[开源阅读]** 菜单•软件下载 提前享受新版本。 * 关注合作公众号 **[小说拾遗]** 获取好看的小说。 -* 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 ## **必读** @@ -12,6 +11,15 @@ * 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则出现问题, 出现简体变化问题检查一下简繁转换是否关闭。 * 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源! +**2021/08/02** + +* 关于最近版本有时候界面没有数据的问题是因为把LiveData组件换成了谷歌推荐的Flow组件导致的问题,正在查找解决办法 + +1. 换源界面功能添加:置顶,置底,删除 by h11128 +2. Cronet:优化 by ag2s20150909 +3. 优化自动翻页 by jiuZhouWorlds +4. 封面设置移到主题里面,白天和夜间可分别设置 + **2021/08/01** 1. 为webService添加快捷操作 diff --git a/app/src/main/java/io/legado/app/base/BaseActivity.kt b/app/src/main/java/io/legado/app/base/BaseActivity.kt index 6406c18bf..8f4105882 100644 --- a/app/src/main/java/io/legado/app/base/BaseActivity.kt +++ b/app/src/main/java/io/legado/app/base/BaseActivity.kt @@ -2,6 +2,7 @@ package io.legado.app.base import android.content.Context import android.content.res.Configuration +import android.graphics.drawable.BitmapDrawable import android.os.Build import android.os.Bundle import android.util.AttributeSet @@ -174,8 +175,8 @@ abstract class BaseActivity( } if (imageBg) { try { - ThemeConfig.getBgImage(this)?.let { - window.decorView.background = it + ThemeConfig.getBgImage(this, windowSize)?.let { + window.decorView.background = BitmapDrawable(resources, it) } } catch (e: OutOfMemoryError) { toastOnUi(e.localizedMessage) diff --git a/app/src/main/java/io/legado/app/constant/AppPattern.kt b/app/src/main/java/io/legado/app/constant/AppPattern.kt index 006a4224f..884b2717d 100644 --- a/app/src/main/java/io/legado/app/constant/AppPattern.kt +++ b/app/src/main/java/io/legado/app/constant/AppPattern.kt @@ -5,7 +5,7 @@ import java.util.regex.Pattern @Suppress("RegExpRedundantEscape") object AppPattern { val JS_PATTERN: Pattern = - Pattern.compile("([\\w\\W]+?)|@js:([\\w\\W]*)", Pattern.CASE_INSENSITIVE) + Pattern.compile("([\\w\\W]*?)|@js:([\\w\\W]*)", Pattern.CASE_INSENSITIVE) val EXP_PATTERN: Pattern = Pattern.compile("\\{\\{([\\w\\W]*?)\\}\\}") //匹配格式化后的图片格式 diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt index 3baa9f98f..d2224a584 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -66,6 +66,7 @@ object PreferKey { const val transparentStatusBar = "transparentStatusBar" const val immNavigationBar = "immNavigationBar" const val defaultCover = "defaultCover" + const val defaultCoverDark = "defaultCoverDark" const val replaceEnableDefault = "replaceEnableDefault" const val showBrightnessView = "showBrightnessView" const val autoClearExpired = "autoClearExpired" @@ -90,11 +91,13 @@ object PreferKey { const val cBackground = "colorBackground" const val cBBackground = "colorBottomBackground" const val bgImage = "backgroundImage" + const val bgImageBlurring = "backgroundImageBlurring" const val cNPrimary = "colorPrimaryNight" const val cNAccent = "colorAccentNight" const val cNBackground = "colorBackgroundNight" const val cNBBackground = "colorBottomBackgroundNight" const val bgImageN = "backgroundImageNight" + const val bgImageNBlurring = "backgroundImageNightBlurring" } diff --git a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt index d76027909..2598e9c94 100644 --- a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt +++ b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt @@ -135,7 +135,7 @@ object ReadBookConfig { //配置写入读取 var readBodyToLh = appCtx.getPrefBoolean(PreferKey.readBodyToLh, true) - var autoReadSpeed = appCtx.getPrefInt(PreferKey.autoReadSpeed, 46) + var autoReadSpeed = appCtx.getPrefInt(PreferKey.autoReadSpeed, 10) set(value) { field = value appCtx.putPrefInt(PreferKey.autoReadSpeed, value) diff --git a/app/src/main/java/io/legado/app/help/ThemeConfig.kt b/app/src/main/java/io/legado/app/help/ThemeConfig.kt index e7a88d40f..8918a3596 100644 --- a/app/src/main/java/io/legado/app/help/ThemeConfig.kt +++ b/app/src/main/java/io/legado/app/help/ThemeConfig.kt @@ -1,9 +1,9 @@ package io.legado.app.help import android.content.Context +import android.graphics.Bitmap import android.graphics.Color -import android.graphics.drawable.BitmapDrawable -import android.graphics.drawable.Drawable +import android.util.DisplayMetrics import androidx.annotation.Keep import androidx.appcompat.app.AppCompatDelegate import io.legado.app.R @@ -11,6 +11,7 @@ import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey import io.legado.app.constant.Theme import io.legado.app.lib.theme.ThemeStore +import io.legado.app.ui.widget.image.CoverImageView import io.legado.app.utils.* import splitties.init.appCtx import java.io.File @@ -28,6 +29,7 @@ object ThemeConfig { ReadBookConfig.upBg() applyTheme(context) initNightMode() + CoverImageView.upDefaultCover() postEvent(EventBus.RECREATE, "") } @@ -41,14 +43,26 @@ object ThemeConfig { AppCompatDelegate.setDefaultNightMode(targetMode) } - fun getBgImage(context: Context): Drawable? { - val bgPath = when (Theme.getTheme()) { - Theme.Light -> context.getPrefString(PreferKey.bgImage) - Theme.Dark -> context.getPrefString(PreferKey.bgImageN) + fun getBgImage(context: Context, metrics: DisplayMetrics): Bitmap? { + val bgCfg = when (Theme.getTheme()) { + Theme.Light -> Pair( + context.getPrefString(PreferKey.bgImage), + context.getPrefInt(PreferKey.bgImageBlurring, 0) + ) + Theme.Dark -> Pair( + context.getPrefString(PreferKey.bgImageN), + context.getPrefInt(PreferKey.bgImageNBlurring, 0) + ) else -> null + } ?: return null + if (bgCfg.first.isNullOrBlank()) return null + val bgImage = BitmapUtils + .decodeBitmap(bgCfg.first!!, metrics.widthPixels, metrics.heightPixels) + ?: return null + if (bgCfg.second == 0) { + return bgImage } - if (bgPath.isNullOrBlank()) return null - return BitmapDrawable.createFromPath(bgPath) + return BitmapUtils.stackBlur(bgImage, bgCfg.second.toFloat()) } fun upConfig() { diff --git a/app/src/main/java/io/legado/app/help/http/HttpHelper.kt b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt index a77ebb17e..e67090fb3 100644 --- a/app/src/main/java/io/legado/app/help/http/HttpHelper.kt +++ b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt @@ -45,7 +45,8 @@ val okHttpClient: OkHttpClient by lazy { chain.proceed(request) }) if (AppConfig.isCronet && CronetLoader.install()) { - builder.addInterceptor(CronetInterceptor()) + //提供CookieJar 用于同步Cookie + builder.addInterceptor(CronetInterceptor(null)) } diff --git a/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt b/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt index 0a0efa358..4d01657d4 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt @@ -1,6 +1,6 @@ package io.legado.app.help.http.cronet -import io.legado.app.help.http.CookieStore +import android.util.Log import okhttp3.Headers import okhttp3.MediaType import okhttp3.Request @@ -9,29 +9,22 @@ import org.chromium.net.CronetEngine.Builder.HTTP_CACHE_DISK import org.chromium.net.ExperimentalCronetEngine import org.chromium.net.UploadDataProviders import org.chromium.net.UrlRequest -import org.chromium.net.urlconnection.CronetURLStreamHandlerFactory import splitties.init.appCtx -import java.net.URL import java.util.concurrent.Executor import java.util.concurrent.Executors -val executor: Executor by lazy { Executors.newSingleThreadExecutor() } +val executor: Executor by lazy { Executors.newCachedThreadPool() } val cronetEngine: ExperimentalCronetEngine by lazy { CronetLoader.preDownload() val builder = ExperimentalCronetEngine.Builder(appCtx) - //设置自定义so库加载 - .setLibraryLoader(CronetLoader) - //设置缓存路径 - .setStoragePath(appCtx.externalCacheDir?.absolutePath) - //设置缓存模式 - .enableHttpCache(HTTP_CACHE_DISK, (1024 * 1024 * 50)) - //设置支持http/3 - .enableQuic(true) - //设置支持http/2 - .enableHttp2(true) + .setLibraryLoader(CronetLoader)//设置自定义so库加载 + .setStoragePath(appCtx.externalCacheDir?.absolutePath)//设置缓存路径 + .enableHttpCache(HTTP_CACHE_DISK, (1024 * 1024 * 50))//设置缓存模式 + .enableQuic(true)//设置支持http/3 + .enableHttp2(true) //设置支持http/2 .enablePublicKeyPinningBypassForLocalTrustAnchors(true) //.enableNetworkQualityEstimator(true) @@ -39,7 +32,9 @@ val cronetEngine: ExperimentalCronetEngine by lazy { builder.enableBrotli(true) //builder.setExperimentalOptions("{\"quic_version\": \"h3-29\"}") val engine = builder.build() - URL.setURLStreamHandlerFactory(CronetURLStreamHandlerFactory(engine)) + Log.d("Cronet", "Cronet Version:" + engine.versionString) + //这会导致Jsoup的网络请求出现问题,暂时不接管系统URL + //URL.setURLStreamHandlerFactory(CronetURLStreamHandlerFactory(engine)) return@lazy engine } @@ -49,17 +44,10 @@ fun buildRequest(request: Request, callback: UrlRequest.Callback): UrlRequest { val url = request.url.toString() val requestBuilder = cronetEngine.newUrlRequestBuilder(url, callback, executor) requestBuilder.setHttpMethod(request.method) - val cookie = CookieStore.getCookie(url) - if (cookie.length > 1) { - requestBuilder.addHeader("Cookie", cookie) - } + val headers: Headers = request.headers headers.forEachIndexed { index, _ -> - val name = headers.name(index) - if (!name.equals("Keep-Alive", true)) { - requestBuilder.addHeader(name, headers.value(index)) - } - + requestBuilder.addHeader(headers.name(index), headers.value(index)) } val requestBody = request.body diff --git a/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt b/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt index 3c1c04b6e..0a0e955b3 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt @@ -1,23 +1,62 @@ package io.legado.app.help.http.cronet -import okhttp3.Call -import okhttp3.Interceptor -import okhttp3.Request -import okhttp3.Response +import io.legado.app.help.http.CookieStore +import okhttp3.* import java.io.IOException -class CronetInterceptor : Interceptor { +class CronetInterceptor(private val cookieJar: CookieJar?) : Interceptor { @Throws(IOException::class) override fun intercept(chain: Interceptor.Chain): Response { - return proceedWithCronet(chain.request(), chain.call()) + val original: Request = chain.request() + val builder: Request.Builder = original.newBuilder() + //Cronet未初始化 + return if (!CronetLoader.install()) { + chain.proceed(original) + } else try { + //移除Keep-Alive,手动设置会导致400 BadRequest + builder.removeHeader("Keep-Alive") + val cookieStr = getCookie(original.url) + //设置Cookie + if (cookieStr.length > 3) { + builder.header("Cookie", cookieStr) + } + val new = builder.build() + val response: Response = proceedWithCronet(new, chain.call()) + //从Response 中保存Cookie到CookieJar + cookieJar?.saveFromResponse(new.url, Cookie.parseAll(new.url, response.headers)) + response + } catch (e: Exception) { + //遇到Cronet处理有问题时的情况,如证书过期等等,回退到okhttp处理 + chain.proceed(original) + } + + } @Throws(IOException::class) private fun proceedWithCronet(request: Request, call: Call): Response { + val callback = CronetUrlRequestCallback(request, call) val urlRequest = buildRequest(request, callback) urlRequest.start() return callback.waitForDone() } + private fun getCookie(url: HttpUrl): String { + val sb = StringBuilder() + //处理从 Cookjar 获取到的Cookies + if (cookieJar != null) { + val cookies = cookieJar.loadForRequest(url) + for (cookie in cookies) { + sb.append(cookie.name).append("=").append(cookie.value).append("; ") + } + } + //处理自定义的Cookie + val cookie = CookieStore.getCookie(url.toString()) + if (cookie.length > 3) { + sb.append(cookie) + } + return sb.toString() + } + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt b/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt index bb17f88da..e7ea61ec1 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt @@ -142,9 +142,9 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() { @Suppress("SameParameterValue") private fun getUrlMd5(url: String): String? { //这样在下载成功后,遇到无网条件下,只要版本未发生变化也能获取md5 - if (md5 != null && md5!!.length == 32&& version==ImplVersion.getCronetVersion()) { - appCtx.putPrefString("soMd5",md5) - appCtx.putPrefString("soVersion",ImplVersion.getCronetVersion()) + if (md5 != null && md5!!.length == 32 && version == ImplVersion.getCronetVersion()) { + appCtx.putPrefString("soMd5", md5) + appCtx.putPrefString("soVersion", ImplVersion.getCronetVersion()) return md5 } val inputStream: InputStream @@ -159,11 +159,11 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() { outputStream.write(buffer, 0, read) outputStream.flush() } - val tmd5=outputStream.toString() + val tmd5 = outputStream.toString() //成功获取到md5后保存md5和版本 - if(tmd5.length==32){ - appCtx.putPrefString("soMd5",tmd5) - appCtx.putPrefString("soVersion",ImplVersion.getCronetVersion()) + if (tmd5.length == 32) { + appCtx.putPrefString("soMd5", tmd5) + appCtx.putPrefString("soVersion", ImplVersion.getCronetVersion()) } return tmd5 diff --git a/app/src/main/java/io/legado/app/help/http/cronet/CronetUrlRequestCallback.kt b/app/src/main/java/io/legado/app/help/http/cronet/CronetUrlRequestCallback.kt index e9e0e4260..41f6fab98 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/CronetUrlRequestCallback.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/CronetUrlRequestCallback.kt @@ -6,14 +6,13 @@ import io.legado.app.help.http.okHttpClient import okhttp3.* import okhttp3.EventListener import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.ResponseBody.Companion.toResponseBody +import okhttp3.ResponseBody.Companion.asResponseBody +import okio.Buffer import org.chromium.net.CronetException import org.chromium.net.UrlRequest import org.chromium.net.UrlResponseInfo -import java.io.ByteArrayOutputStream import java.io.IOException import java.nio.ByteBuffer -import java.nio.channels.Channels import java.util.* class CronetUrlRequestCallback @JvmOverloads internal constructor( @@ -29,8 +28,7 @@ class CronetUrlRequestCallback @JvmOverloads internal constructor( private var mResponse: Response private var mException: IOException? = null private val mResponseCondition = ConditionVariable() - private val mBytesReceived = ByteArrayOutputStream() - private val mReceiveChannel = Channels.newChannel(mBytesReceived) + private val mBuffer = Buffer() @Throws(IOException::class) fun waitForDone(): Response { @@ -64,6 +62,7 @@ class CronetUrlRequestCallback @JvmOverloads internal constructor( override fun onResponseStarted(request: UrlRequest, info: UrlResponseInfo) { this.mResponse = responseFromResponse(this.mResponse, info) +// 用于调试 // val sb: StringBuilder = StringBuilder(info.url).append("\r\n") // sb.append("[Cached:").append(info.wasCached()).append("][StatusCode:") // .append(info.httpStatusCode).append("][StatusText:").append(info.httpStatusText) @@ -74,6 +73,8 @@ class CronetUrlRequestCallback @JvmOverloads internal constructor( // sb.append("[").append(h.key).append("]").append(h.value).append("\r\n"); // } // Log.e("Cronet", sb.toString()) + //打印协议,用于调试 + Log.e("Cronet", info.negotiatedProtocol) if (eventListener != null) { eventListener.responseHeadersEnd(mCall, this.mResponse) eventListener.responseBodyStart(mCall) @@ -89,7 +90,8 @@ class CronetUrlRequestCallback @JvmOverloads internal constructor( ) { byteBuffer.flip() try { - mReceiveChannel.write(byteBuffer) + //mReceiveChannel.write(byteBuffer) + mBuffer.write(byteBuffer) } catch (e: IOException) { Log.i(TAG, "IOException during ByteBuffer read. Details: ", e) throw e @@ -102,8 +104,10 @@ class CronetUrlRequestCallback @JvmOverloads internal constructor( eventListener?.responseBodyEnd(mCall, info.receivedByteCount) val contentType: MediaType? = (this.mResponse.header("content-type") ?: "text/plain; charset=\"utf-8\"").toMediaTypeOrNull() +// val responseBody: ResponseBody = +// mBytesReceived.toByteArray().toResponseBody(contentType) val responseBody: ResponseBody = - mBytesReceived.toByteArray().toResponseBody(contentType) + mBuffer.asResponseBody(contentType) val newRequest = originalRequest.newBuilder().url(info.url).build() this.mResponse = this.mResponse.newBuilder().body(responseBody).request(newRequest).build() mResponseCondition.open() 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 f2be6b7b5..2d797472b 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 @@ -58,7 +58,8 @@ object Restore { //默认忽略keys private val ignorePrefKeys = arrayOf( - PreferKey.defaultCover + PreferKey.defaultCover, + PreferKey.defaultCoverDark ) private val readPrefKeys = arrayOf( PreferKey.readStyleSelect, diff --git a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt index 7775cbc0b..e3a096677 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceDialog.kt @@ -176,6 +176,7 @@ class ImportBookSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickList appDb.bookSourceDao.allGroup.forEach { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) } + textInputLayout.setHint(R.string.group_name) editView.setFilterValues(groups.toList()) editView.dropDownHeight = 180.dp } diff --git a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt index b139beb90..f2a8188dd 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceDialog.kt @@ -172,6 +172,7 @@ class ImportRssSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListe appDb.rssSourceDao.allGroup.forEach { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) } + textInputLayout.setHint(R.string.group_name) editView.setFilterValues(groups.toList()) editView.dropDownHeight = 180.dp } diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt index 55b482f72..9fed01921 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt @@ -298,6 +298,7 @@ class CacheActivity : VMBaseActivity() private fun alertExportFileName() { alert(R.string.export_file_name) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { + textInputLayout.hint = "file name js" editView.setText(AppConfig.bookExportFileName) } customView { alertBinding.root } @@ -317,6 +318,7 @@ class CacheActivity : VMBaseActivity() private fun showCharsetConfig() { alert(R.string.set_charset) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { + textInputLayout.hint = "charset name" editView.setFilterValues(charsets) editView.setText(AppConfig.exportCharset) } diff --git a/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverDialog.kt b/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverDialog.kt index 5558da7fc..2d3084173 100644 --- a/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverDialog.kt @@ -14,9 +14,8 @@ import io.legado.app.base.BaseDialogFragment import io.legado.app.databinding.DialogChangeCoverBinding import io.legado.app.lib.theme.primaryColor import io.legado.app.utils.applyTint -import io.legado.app.utils.getSize - import io.legado.app.utils.viewbindingdelegate.viewBinding +import io.legado.app.utils.windowSize class ChangeCoverDialog : BaseDialogFragment(), @@ -45,7 +44,7 @@ class ChangeCoverDialog : BaseDialogFragment(), override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) } diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt index acd00f18d..b5e3873b6 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceDialog.kt @@ -53,7 +53,7 @@ class ChangeSourceDialog : BaseDialogFragment(), override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) } diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupEdit.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupEdit.kt index c2a3610cf..79d66bd42 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupEdit.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupEdit.kt @@ -15,7 +15,7 @@ object GroupEdit { fun show(context: Context, layoutInflater: LayoutInflater, bookGroup: BookGroup) = context.run { alert(title = getString(R.string.group_edit)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { - editView.setHint(R.string.group_name) + textInputLayout.setHint(R.string.group_name) editView.setText(bookGroup.groupName) } if (bookGroup.groupId >= 0) { 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 ca6271a15..b3e7dfc66 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 @@ -28,10 +28,10 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.applyTint -import io.legado.app.utils.getSize import io.legado.app.utils.requestInputMethod import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.visible +import io.legado.app.utils.windowSize import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch @@ -43,7 +43,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) } @@ -103,7 +103,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener private fun addGroup() { alert(title = getString(R.string.add_group)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { - editView.setHint(R.string.group_name) + textInputLayout.setHint(R.string.group_name) } customView { alertBinding.root } yesButton { diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt index d202701ab..6beb2e626 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupSelectDialog.kt @@ -29,9 +29,9 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.applyTint -import io.legado.app.utils.getSize import io.legado.app.utils.requestInputMethod import io.legado.app.utils.viewbindingdelegate.viewBinding +import io.legado.app.utils.windowSize import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch @@ -61,7 +61,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) } @@ -125,7 +125,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener private fun addGroup() { alert(title = getString(R.string.add_group)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { - editView.setHint(R.string.group_name) + textInputLayout.setHint(R.string.group_name) } customView { alertBinding.root } yesButton { @@ -143,7 +143,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener private fun editGroup(bookGroup: BookGroup) { alert(title = getString(R.string.group_edit)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { - editView.setHint(R.string.group_name) + textInputLayout.setHint(R.string.group_name) editView.setText(bookGroup.groupName) } customView { alertBinding.root } diff --git a/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt index d9c5998ac..bea70bba4 100644 --- a/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/local/ImportBookActivity.kt @@ -280,6 +280,7 @@ class ImportBookActivity : VMBaseActivity screenHeight / 5) { 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 972c107f2..277335dd4 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 @@ -327,6 +327,7 @@ class BookSourceActivity : VMBaseActivity clearCache() - PreferKey.defaultCover -> if (getPrefString(PreferKey.defaultCover).isNullOrEmpty()) { - selectCoverImage.launch("image/*") - } else { - selector(items = arrayListOf("删除图片", "选择图片")) { _, i -> - if (i == 0) { - removePref(PreferKey.defaultCover) - } else { - selectCoverImage.launch("image/*") - } - } - } + } return super.onPreferenceTreeClick(preference) } @@ -134,9 +111,6 @@ class OtherConfigFragment : BasePreferenceFragment(), setProcessTextEnable(it.getBoolean(key, true)) } PreferKey.showDiscovery, PreferKey.showRss -> postEvent(EventBus.NOTIFY_MAIN, true) - PreferKey.defaultCover -> upPreferenceSummary( - key, getPrefString(PreferKey.defaultCover) - ) PreferKey.language -> listView.postDelayed({ LanguageUtils.setConfiguration(appCtx) val intent = Intent(appCtx, MainActivity::class.java) @@ -157,11 +131,6 @@ class OtherConfigFragment : BasePreferenceFragment(), getString(R.string.pre_download_s, value) PreferKey.threadCount -> preference.summary = getString(R.string.threads_num, value) PreferKey.webPort -> preference.summary = getString(R.string.web_port_summary, value) - PreferKey.defaultCover -> preference.summary = if (value.isNullOrBlank()) { - getString(R.string.select_image) - } else { - value - } else -> if (preference is ListPreference) { val index = preference.findIndexOfValue(value) // Set the summary to reflect the new value. @@ -175,8 +144,10 @@ class OtherConfigFragment : BasePreferenceFragment(), @SuppressLint("InflateParams") private fun showUserAgentDialog() { alert("UserAgent") { - val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - alertBinding.editView.setText(AppConfig.userAgent) + val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { + textInputLayout.hint = "UserAgent" + editView.setText(AppConfig.userAgent) + } customView { alertBinding.root } okButton { val userAgent = alertBinding.editView.text?.toString() @@ -222,41 +193,4 @@ class OtherConfigFragment : BasePreferenceFragment(), } } - private fun setCoverFromUri(uri: Uri) { - if (uri.isContentScheme()) { - val doc = DocumentFile.fromSingleUri(requireContext(), uri) - doc?.name?.let { - var file = requireContext().externalFiles - file = FileUtils.createFileIfNotExist(file, "covers", it) - kotlin.runCatching { - DocumentUtils.readBytes(requireContext(), doc.uri) - }.getOrNull()?.let { byteArray -> - file.writeBytes(byteArray) - putPrefString(PreferKey.defaultCover, file.absolutePath) - CoverImageView.upDefaultCover() - } ?: toastOnUi("获取文件出错") - } - } else { - PermissionsCompat.Builder(this) - .addPermissions( - Permissions.READ_EXTERNAL_STORAGE, - Permissions.WRITE_EXTERNAL_STORAGE - ) - .rationale(R.string.bg_image_per) - .onGranted { - RealPathUtil.getPath(requireContext(), uri)?.let { path -> - val imgFile = File(path) - if (imgFile.exists()) { - var file = requireContext().externalFiles - file = FileUtils.createFileIfNotExist(file, "covers", imgFile.name) - file.writeBytes(imgFile.readBytes()) - putPrefString(PreferKey.defaultCover, file.absolutePath) - CoverImageView.upDefaultCover() - } - } - } - .request() - } - } - } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt index 94eb8987b..510819f23 100644 --- a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt +++ b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt @@ -9,7 +9,7 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View -import androidx.activity.result.contract.ActivityResultContracts +import android.widget.SeekBar import androidx.documentfile.provider.DocumentFile import androidx.preference.Preference import io.legado.app.R @@ -18,6 +18,7 @@ import io.legado.app.constant.AppConst import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey import io.legado.app.databinding.DialogEditTextBinding +import io.legado.app.databinding.DialogImageBlurringBinding import io.legado.app.help.AppConfig import io.legado.app.help.LauncherIconHelp import io.legado.app.help.ThemeConfig @@ -26,8 +27,10 @@ import io.legado.app.lib.dialogs.selector import io.legado.app.lib.permission.Permissions import io.legado.app.lib.permission.PermissionsCompat import io.legado.app.lib.theme.ATH +import io.legado.app.ui.widget.image.CoverImageView import io.legado.app.ui.widget.number.NumberPickerDialog import io.legado.app.ui.widget.prefs.ColorPreference +import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.utils.* import java.io.File @@ -35,17 +38,21 @@ import java.io.File @Suppress("SameParameterValue") class ThemeConfigFragment : BasePreferenceFragment(), SharedPreferences.OnSharedPreferenceChangeListener { - - private val selectLightBg = registerForActivityResult(ActivityResultContracts.GetContent()) { - it ?: return@registerForActivityResult - setBgFromUri(it, PreferKey.bgImage) { - upTheme(false) - } - } - private val selectDarkBg = registerForActivityResult(ActivityResultContracts.GetContent()) { - it ?: return@registerForActivityResult - setBgFromUri(it, PreferKey.bgImageN) { - upTheme(true) + private val requestCodeCover = 111 + private val requestCodeCoverDark = 112 + private val requestCodeBgLight = 121 + private val requestCodeBgDark = 122 + private val selectImage = registerForActivityResult(ActivityResultContractUtils.SelectImage()) { + val uri = it?.second ?: return@registerForActivityResult + when (it.first) { + requestCodeCover -> setCoverFromUri(PreferKey.defaultCover, uri) + requestCodeCoverDark -> setCoverFromUri(PreferKey.defaultCoverDark, uri) + requestCodeBgLight -> setBgFromUri(uri, PreferKey.bgImage) { + upTheme(false) + } + requestCodeBgDark -> setBgFromUri(uri, PreferKey.bgImageN) { + upTheme(true) + } } } @@ -57,6 +64,8 @@ class ThemeConfigFragment : BasePreferenceFragment(), upPreferenceSummary(PreferKey.bgImage, getPrefString(PreferKey.bgImage)) upPreferenceSummary(PreferKey.bgImageN, getPrefString(PreferKey.bgImageN)) upPreferenceSummary(PreferKey.barElevation, AppConfig.elevation.toString()) + upPreferenceSummary(PreferKey.defaultCover, getPrefString(PreferKey.defaultCover)) + upPreferenceSummary(PreferKey.defaultCoverDark, getPrefString(PreferKey.defaultCoverDark)) findPreference(PreferKey.cBackground)?.let { it.onSaveColor = { color -> if (!ColorUtils.isColorLight(color)) { @@ -85,14 +94,14 @@ class ThemeConfigFragment : BasePreferenceFragment(), setHasOptionsMenu(true) } - override fun onResume() { - super.onResume() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this) } - override fun onPause() { + override fun onDestroy() { + super.onDestroy() preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this) - super.onPause() } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -128,6 +137,12 @@ class ThemeConfigFragment : BasePreferenceFragment(), PreferKey.cNBBackground -> { upTheme(true) } + PreferKey.bgImage, + PreferKey.bgImageN, + PreferKey.defaultCover, + PreferKey.defaultCoverDark -> { + upPreferenceSummary(key, getPrefString(key)) + } } } @@ -151,29 +166,58 @@ class ThemeConfigFragment : BasePreferenceFragment(), "themeList" -> ThemeListDialog().show(childFragmentManager, "themeList") "saveDayTheme", "saveNightTheme" -> saveThemeAlert(key) PreferKey.bgImage -> if (getPrefString(PreferKey.bgImage).isNullOrEmpty()) { - selectLightBg.launch("image/*") + selectImage.launch(requestCodeBgLight) } else { selector(items = arrayListOf("删除图片", "选择图片")) { _, i -> if (i == 0) { removePref(PreferKey.bgImage) upTheme(false) } else { - selectLightBg.launch("image/*") + selectImage.launch(requestCodeBgLight) } } } PreferKey.bgImageN -> if (getPrefString(PreferKey.bgImageN).isNullOrEmpty()) { - selectDarkBg.launch("image/*") + selectImage.launch(requestCodeBgDark) } else { selector(items = arrayListOf("删除图片", "选择图片")) { _, i -> if (i == 0) { removePref(PreferKey.bgImageN) upTheme(true) } else { - selectDarkBg.launch("image/*") + selectImage.launch(requestCodeBgDark) + } + } + } + PreferKey.bgImageBlurring -> alertImageBlurring(PreferKey.bgImageBlurring) { + upTheme(false) + } + PreferKey.bgImageNBlurring -> alertImageBlurring(PreferKey.bgImageNBlurring) { + upTheme(true) + } + PreferKey.defaultCover -> if (getPrefString(PreferKey.defaultCover).isNullOrEmpty()) { + selectImage.launch(requestCodeCover) + } else { + selector(items = arrayListOf("删除图片", "选择图片")) { _, i -> + if (i == 0) { + removePref(PreferKey.defaultCover) + } else { + selectImage.launch(requestCodeCover) } } } + PreferKey.defaultCoverDark -> + if (getPrefString(PreferKey.defaultCoverDark).isNullOrEmpty()) { + selectImage.launch(requestCodeCoverDark) + } else { + selector(items = arrayListOf("删除图片", "选择图片")) { _, i -> + if (i == 0) { + removePref(PreferKey.defaultCoverDark) + } else { + selectImage.launch(requestCodeCoverDark) + } + } + } } return super.onPreferenceTreeClick(preference) } @@ -181,7 +225,9 @@ class ThemeConfigFragment : BasePreferenceFragment(), @SuppressLint("InflateParams") private fun saveThemeAlert(key: String) { alert(R.string.theme_name) { - val alertBinding = DialogEditTextBinding.inflate(layoutInflater) + val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { + textInputLayout.hint = "name" + } customView { alertBinding.root } okButton { alertBinding.editView.text?.toString()?.let { themeName -> @@ -199,6 +245,34 @@ class ThemeConfigFragment : BasePreferenceFragment(), }.show() } + private fun alertImageBlurring(preferKey: String, success: () -> Unit) { + alert(R.string.background_image_blurring) { + val alertBinding = DialogImageBlurringBinding.inflate(layoutInflater).apply { + getPrefInt(preferKey, 0).let { + seekBar.progress = it + textViewValue.text = it.toString() + } + seekBar.setOnSeekBarChangeListener(object : SeekBarChangeListener { + override fun onProgressChanged( + seekBar: SeekBar, + progress: Int, + fromUser: Boolean + ) { + textViewValue.text = progress.toString() + } + }) + } + customView { alertBinding.root } + okButton { + alertBinding.seekBar.progress.let { + putPrefInt(preferKey, it) + success.invoke() + } + } + noButton() + }.show() + } + private fun upTheme(isNightTheme: Boolean) { if (AppConfig.isNightTheme == isNightTheme) { listView.post { @@ -217,6 +291,14 @@ class ThemeConfigFragment : BasePreferenceFragment(), when (preferenceKey) { PreferKey.barElevation -> preference.summary = getString(R.string.bar_elevation_s, value) + PreferKey.bgImage, + PreferKey.bgImageN, + PreferKey.defaultCover, + PreferKey.defaultCoverDark -> preference.summary = if (value.isNullOrBlank()) { + getString(R.string.select_image) + } else { + value + } else -> preference.summary = value } } @@ -232,7 +314,6 @@ class ThemeConfigFragment : BasePreferenceFragment(), }.getOrNull()?.let { byteArray -> file.writeBytes(byteArray) putPrefString(preferenceKey, file.absolutePath) - upPreferenceSummary(preferenceKey, file.absolutePath) success() } ?: toastOnUi("获取文件出错") } @@ -251,7 +332,6 @@ class ThemeConfigFragment : BasePreferenceFragment(), file = FileUtils.createFileIfNotExist(file, preferenceKey, imgFile.name) file.writeBytes(imgFile.readBytes()) putPrefString(preferenceKey, file.absolutePath) - upPreferenceSummary(preferenceKey, file.absolutePath) success() } } @@ -260,4 +340,41 @@ class ThemeConfigFragment : BasePreferenceFragment(), } } + private fun setCoverFromUri(preferenceKey: String, uri: Uri) { + if (uri.isContentScheme()) { + val doc = DocumentFile.fromSingleUri(requireContext(), uri) + doc?.name?.let { + var file = requireContext().externalFiles + file = FileUtils.createFileIfNotExist(file, "covers", it) + kotlin.runCatching { + DocumentUtils.readBytes(requireContext(), doc.uri) + }.getOrNull()?.let { byteArray -> + file.writeBytes(byteArray) + putPrefString(preferenceKey, file.absolutePath) + CoverImageView.upDefaultCover() + } ?: toastOnUi("获取文件出错") + } + } else { + PermissionsCompat.Builder(this) + .addPermissions( + Permissions.READ_EXTERNAL_STORAGE, + Permissions.WRITE_EXTERNAL_STORAGE + ) + .rationale(R.string.bg_image_per) + .onGranted { + RealPathUtil.getPath(requireContext(), uri)?.let { path -> + val imgFile = File(path) + if (imgFile.exists()) { + var file = requireContext().externalFiles + file = FileUtils.createFileIfNotExist(file, "covers", imgFile.name) + file.writeBytes(imgFile.readBytes()) + putPrefString(PreferKey.defaultCover, file.absolutePath) + CoverImageView.upDefaultCover() + } + } + } + .request() + } + } + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt b/app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt index be118d3de..b4275a7ae 100644 --- a/app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt +++ b/app/src/main/java/io/legado/app/ui/config/ThemeListDialog.kt @@ -26,7 +26,7 @@ class ThemeListDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) } diff --git a/app/src/main/java/io/legado/app/ui/dict/DictViewModel.kt b/app/src/main/java/io/legado/app/ui/dict/DictViewModel.kt index 473e424d6..27f2724a2 100644 --- a/app/src/main/java/io/legado/app/ui/dict/DictViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/dict/DictViewModel.kt @@ -16,7 +16,7 @@ class DictViewModel(application: Application) : BaseViewModel(application) { fun dict(word: String) { execute { val body = okHttpClient.newCallStrResponse { - get("http://apii.dict.cn/mini.php", mapOf(Pair("q", word))) + get("https://apii.dict.cn/mini.php", mapOf(Pair("q", word))) }.body val jsoup = Jsoup.parse(body!!) jsoup.body() diff --git a/app/src/main/java/io/legado/app/ui/document/FilePickerDialog.kt b/app/src/main/java/io/legado/app/ui/document/FilePickerDialog.kt index af573efb0..06964a969 100644 --- a/app/src/main/java/io/legado/app/ui/document/FilePickerDialog.kt +++ b/app/src/main/java/io/legado/app/ui/document/FilePickerDialog.kt @@ -76,7 +76,7 @@ class FilePickerDialog : DialogFragment(), override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.8).toInt()) } diff --git a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt index b5f4c0eaa..b78d15239 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt @@ -12,7 +12,6 @@ import io.legado.app.help.DefaultData import io.legado.app.help.LocalConfig import io.legado.app.model.webBook.WebBook import io.legado.app.service.help.CacheBook -import io.legado.app.utils.FileUtils import io.legado.app.utils.postEvent import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.delay @@ -143,7 +142,6 @@ class MainViewModel(application: Application) : BaseViewModel(application) { fun postLoad() { execute { - FileUtils.deleteFile(FileUtils.getPath(context.cacheDir, "Fonts")) if (appDb.httpTTSDao.count == 0) { DefaultData.httpTTS.let { appDb.httpTTSDao.insert(*it.toTypedArray()) diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BaseBookshelfFragment.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BaseBookshelfFragment.kt index d9a5acbfe..63942a048 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BaseBookshelfFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BaseBookshelfFragment.kt @@ -65,7 +65,9 @@ abstract class BaseBookshelfFragment(layoutId: Int) : VMBaseFragment(), OnScanResul override val binding by viewBinding(ActivityQrcodeCaptureBinding::inflate) private val selectQrImage = registerForActivityResult(ActivityResultContracts.GetContent()) { - it.readBytes(this)?.let { bytes -> + it?.readBytes(this)?.let { bytes -> val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) onScanResultCallback(QRCodeUtils.parseCodeResult(bitmap)) } diff --git a/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt index b108b918e..9572b2582 100644 --- a/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/replace/GroupManageDialog.kt @@ -36,7 +36,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) } @@ -88,12 +88,10 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener @SuppressLint("InflateParams") private fun addGroup() { alert(title = getString(R.string.add_group)) { - val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - customView { - alertBinding.apply { - editView.hint = "分组名称" - }.root + val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { + textInputLayout.setHint(R.string.group_name) } + customView { alertBinding.root } yesButton { alertBinding.editView.text?.toString()?.let { if (it.isNotBlank()) { @@ -109,7 +107,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener private fun editGroup(group: String) { alert(title = getString(R.string.group_edit)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { - editView.hint = "分组名称" + textInputLayout.setHint(R.string.group_name) editView.setText(group) } customView { alertBinding.root } diff --git a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt index 8a90440ff..09fc64473 100644 --- a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt +++ b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleActivity.kt @@ -255,6 +255,7 @@ class ReplaceRuleActivity : VMBaseActivity screenHeight / 5) { 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 1728f7320..a8ebdd2a3 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 @@ -43,6 +43,7 @@ class ReadRssActivity : VMBaseActivity private var customWebViewCallback: WebChromeClient.CustomViewCallback? = null private var webPic: String? = null private val saveImage = registerForActivityResult(FilePicker()) { + it ?: return@registerForActivityResult ACache.get(this).put(imagePathKey, it.toString()) viewModel.saveImage(webPic, it.toString()) } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt index cd941c206..f5eac52f4 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt @@ -256,7 +256,7 @@ class RssSourceEditActivity : val rect = Rect() // 获取当前页面窗口的显示范围 window.decorView.getWindowVisibleDisplayFrame(rect) - val screenHeight = this@RssSourceEditActivity.getSize().heightPixels + val screenHeight = this@RssSourceEditActivity.windowSize.heightPixels val keyboardHeight = screenHeight - rect.bottom // 输入法的高度 val preShowing = mIsSoftKeyBoardShowing if (abs(keyboardHeight) > screenHeight / 5) { 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 5fb2d2bad..7696f4b58 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 @@ -37,7 +37,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener override fun onStart() { super.onStart() - val dm = requireActivity().getSize() + val dm = requireActivity().windowSize dialog?.window?.setLayout((dm.widthPixels * 0.9).toInt(), (dm.heightPixels * 0.9).toInt()) } @@ -89,12 +89,10 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener @SuppressLint("InflateParams") private fun addGroup() { alert(title = getString(R.string.add_group)) { - val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - customView { - alertBinding.apply { - editView.setHint(R.string.group_name) - }.root + val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { + textInputLayout.setHint(R.string.group_name) } + customView { alertBinding.root } yesButton { alertBinding.editView.text?.toString()?.let { if (it.isNotBlank()) { @@ -109,13 +107,11 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener @SuppressLint("InflateParams") private fun editGroup(group: String) { alert(title = getString(R.string.group_edit)) { - val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - customView { - alertBinding.apply { - editView.setHint(R.string.group_name) - editView.setText(group) - }.root + val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { + textInputLayout.setHint(R.string.group_name) + editView.setText(group) } + customView { alertBinding.root } yesButton { viewModel.upGroup(group, alertBinding.editView.text?.toString()) } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt index cf3e97d96..1fc46da78 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceActivity.kt @@ -263,6 +263,7 @@ class RssSourceActivity : VMBaseActivity= Build.VERSION_CODES.R) { - val windowMetrics: WindowMetrics = windowManager.currentWindowMetrics - val insets = windowMetrics.windowInsets - .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()) - displayMetrics.widthPixels = windowMetrics.bounds.width() - insets.left - insets.right - displayMetrics.heightPixels = windowMetrics.bounds.height() - insets.top - insets.bottom - } else { - @Suppress("DEPRECATION") - windowManager.defaultDisplay.getMetrics(displayMetrics) +val Activity.windowSize: DisplayMetrics + get() { + val displayMetrics = DisplayMetrics() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val windowMetrics: WindowMetrics = windowManager.currentWindowMetrics + val insets = windowMetrics.windowInsets + .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()) + displayMetrics.widthPixels = windowMetrics.bounds.width() - insets.left - insets.right + displayMetrics.heightPixels = windowMetrics.bounds.height() - insets.top - insets.bottom + } else { + @Suppress("DEPRECATION") + windowManager.defaultDisplay.getMetrics(displayMetrics) + } + return displayMetrics } - return displayMetrics -} /** * 该方法需要在View完全被绘制出来之后调用,否则判断不了 diff --git a/app/src/main/java/io/legado/app/utils/ActivityResultContractUtils.kt b/app/src/main/java/io/legado/app/utils/ActivityResultContractUtils.kt new file mode 100644 index 000000000..3f0198023 --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/ActivityResultContractUtils.kt @@ -0,0 +1,32 @@ +package io.legado.app.utils + +import android.app.Activity.RESULT_OK +import android.content.Context +import android.content.Intent +import android.net.Uri +import androidx.activity.result.contract.ActivityResultContract + +object ActivityResultContractUtils { + + class SelectImage : ActivityResultContract?>() { + + var requestCode: Int? = null + + override fun createIntent(context: Context, input: Int?): Intent { + requestCode = input + return Intent(Intent.ACTION_GET_CONTENT) + .addCategory(Intent.CATEGORY_OPENABLE) + .setType("image/*") + } + + override fun parseResult(resultCode: Int, intent: Intent?): Pair? { + if (resultCode == RESULT_OK) { + return Pair(requestCode, intent?.data) + } + return null + } + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/BitmapUtils.kt b/app/src/main/java/io/legado/app/utils/BitmapUtils.kt index 2e7ae06ba..c200980c2 100644 --- a/app/src/main/java/io/legado/app/utils/BitmapUtils.kt +++ b/app/src/main/java/io/legado/app/utils/BitmapUtils.kt @@ -249,7 +249,7 @@ object BitmapUtils { /** * 高斯模糊 */ - fun stackBlur(srcBitmap: Bitmap?): Bitmap? { + fun stackBlur(srcBitmap: Bitmap?, radius: Float = 8f): Bitmap? { if (srcBitmap == null) return null val rs = RenderScript.create(appCtx) val blurredBitmap = srcBitmap.copy(Config.ARGB_8888, true) @@ -268,7 +268,7 @@ object BitmapUtils { script.setInput(input) //设置模糊半径 - script.setRadius(8f) + script.setRadius(radius) //启动 ScriptIntrinsicBlur script.forEach(output) diff --git a/app/src/main/java/io/legado/app/utils/MiscExtensions.kt b/app/src/main/java/io/legado/app/utils/JsonExtensions.kt similarity index 100% rename from app/src/main/java/io/legado/app/utils/MiscExtensions.kt rename to app/src/main/java/io/legado/app/utils/JsonExtensions.kt diff --git a/app/src/main/res/layout-land/activity_book_info.xml b/app/src/main/res/layout-land/activity_book_info.xml index 05a4b316a..036cdd05e 100644 --- a/app/src/main/res/layout-land/activity_book_info.xml +++ b/app/src/main/res/layout-land/activity_book_info.xml @@ -362,6 +362,7 @@ android:layout_marginTop="8dp" android:clickable="true" android:focusable="true" + android:minHeight="48dp" android:paddingLeft="8dp" android:paddingBottom="8dp" android:text="@string/book_intro" diff --git a/app/src/main/res/layout/activity_book_info.xml b/app/src/main/res/layout/activity_book_info.xml index e2d35458f..c34395d21 100644 --- a/app/src/main/res/layout/activity_book_info.xml +++ b/app/src/main/res/layout/activity_book_info.xml @@ -333,16 +333,17 @@ diff --git a/app/src/main/res/layout/activity_chapter_list.xml b/app/src/main/res/layout/activity_chapter_list.xml index c78973583..9bceaa108 100644 --- a/app/src/main/res/layout/activity_chapter_list.xml +++ b/app/src/main/res/layout/activity_chapter_list.xml @@ -1,6 +1,7 @@ @@ -15,6 +16,7 @@ + android:layout_height="match_parent" + tools:ignore="SpeakableTextPresentCheck" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_import_book.xml b/app/src/main/res/layout/activity_import_book.xml index 73635c2f4..7e3ee8997 100644 --- a/app/src/main/res/layout/activity_import_book.xml +++ b/app/src/main/res/layout/activity_import_book.xml @@ -69,7 +69,8 @@ + android:layout_height="match_parent" + tools:ignore="SpeakableTextPresentCheck" /> @@ -9,7 +10,8 @@ android:id="@+id/view_pager_main" android:layout_width="match_parent" android:layout_height="0dp" - android:layout_weight="1" /> + android:layout_weight="1" + tools:ignore="SpeakableTextPresentCheck" /> + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> + android:text="@string/use_regex" + tools:ignore="TouchTargetSizeCheck" /> @@ -94,7 +99,8 @@ + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> diff --git a/app/src/main/res/layout/activity_replace_rule.xml b/app/src/main/res/layout/activity_replace_rule.xml index b244fc3d9..eeb2a26f9 100644 --- a/app/src/main/res/layout/activity_replace_rule.xml +++ b/app/src/main/res/layout/activity_replace_rule.xml @@ -23,7 +23,8 @@ + android:layout_height="match_parent" + tools:ignore="SpeakableTextPresentCheck" /> diff --git a/app/src/main/res/layout/activity_rss_artivles.xml b/app/src/main/res/layout/activity_rss_artivles.xml index 50e503a9e..27a0dff9d 100644 --- a/app/src/main/res/layout/activity_rss_artivles.xml +++ b/app/src/main/res/layout/activity_rss_artivles.xml @@ -1,5 +1,6 @@ + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_rss_source_edit.xml b/app/src/main/res/layout/activity_rss_source_edit.xml index f576312db..aab498529 100644 --- a/app/src/main/res/layout/activity_rss_source_edit.xml +++ b/app/src/main/res/layout/activity_rss_source_edit.xml @@ -34,14 +34,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" - android:text="@string/is_enable" /> + android:text="@string/is_enable" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/single_url" + tools:ignore="TouchTargetSizeCheck" /> @@ -64,14 +66,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="false" - android:text="@string/enable_js" /> + android:text="@string/enable_js" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/load_with_base_url" + tools:ignore="TouchTargetSizeCheck" /> diff --git a/app/src/main/res/layout/activity_search_content.xml b/app/src/main/res/layout/activity_search_content.xml index e9bde053b..9a4a5da87 100644 --- a/app/src/main/res/layout/activity_search_content.xml +++ b/app/src/main/res/layout/activity_search_content.xml @@ -25,7 +25,8 @@ android:layout_height="0dp" android:overScrollMode="never" app:layout_constraintBottom_toTopOf="@+id/ll_search_base_info" - app:layout_constraintTop_toBottomOf="@id/refresh_progress_bar" /> + app:layout_constraintTop_toBottomOf="@id/refresh_progress_bar" + tools:ignore="SpeakableTextPresentCheck" /> diff --git a/app/src/main/res/layout/dialog_bookmark.xml b/app/src/main/res/layout/dialog_bookmark.xml index 231b945ca..c49654878 100644 --- a/app/src/main/res/layout/dialog_bookmark.xml +++ b/app/src/main/res/layout/dialog_bookmark.xml @@ -43,7 +43,8 @@ android:id="@+id/edit_book_text" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="@string/content" /> + android:hint="@string/content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> @@ -56,7 +57,8 @@ android:id="@+id/edit_content" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="@string/note_content" /> + android:hint="@string/note_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> diff --git a/app/src/main/res/layout/dialog_bookshelf_config.xml b/app/src/main/res/layout/dialog_bookshelf_config.xml index cbf550197..bb385cf3a 100644 --- a/app/src/main/res/layout/dialog_bookshelf_config.xml +++ b/app/src/main/res/layout/dialog_bookshelf_config.xml @@ -1,5 +1,6 @@ + app:theme="@style/Spinner" + tools:ignore="TouchTargetSizeCheck" /> @@ -51,27 +53,32 @@ + android:text="@string/layout_list" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/layout_grid3" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/layout_grid4" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/layout_grid5" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/layout_grid6" + tools:ignore="TouchTargetSizeCheck" /> @@ -84,8 +91,9 @@ android:padding="6dp" android:text="@string/show_unread" app:layout_constraintLeft_toRightOf="@+id/ll_layout" + app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" - app:layout_constraintRight_toRightOf="parent" /> + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/bookshelf_px_0" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/bookshelf_px_1" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/bookshelf_px_2" + tools:ignore="TouchTargetSizeCheck" /> + android:text="@string/bookshelf_px_3" + tools:ignore="TouchTargetSizeCheck" /> diff --git a/app/src/main/res/layout/dialog_download_choice.xml b/app/src/main/res/layout/dialog_download_choice.xml index 4548ac329..8e60ea030 100644 --- a/app/src/main/res/layout/dialog_download_choice.xml +++ b/app/src/main/res/layout/dialog_download_choice.xml @@ -4,10 +4,10 @@ android:id="@+id/ll_content" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="16dp" android:background="@color/background" android:gravity="center" - android:orientation="horizontal"> + android:orientation="horizontal" + android:padding="16dp"> + android:textSize="14sp" + tools:ignore="TouchTargetSizeCheck" /> + android:textSize="14sp" + tools:ignore="TouchTargetSizeCheck,SpeakableTextPresentCheck" /> - + + + android:layout_height="wrap_content"> - - \ No newline at end of file + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_image_blurring.xml b/app/src/main/res/layout/dialog_image_blurring.xml new file mode 100644 index 000000000..b9d20e55e --- /dev/null +++ b/app/src/main/res/layout/dialog_image_blurring.xml @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_recycler_view.xml b/app/src/main/res/layout/dialog_recycler_view.xml index 7f577dde3..82feaf44e 100644 --- a/app/src/main/res/layout/dialog_recycler_view.xml +++ b/app/src/main/res/layout/dialog_recycler_view.xml @@ -23,7 +23,8 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:scrollbars="none" /> + android:scrollbars="none" + tools:ignore="SpeakableTextPresentCheck" /> + + + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> @@ -27,7 +29,8 @@ + android:layout_height="wrap_content" + tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> diff --git a/app/src/main/res/layout/dialog_wait.xml b/app/src/main/res/layout/dialog_wait.xml index ccd7d4ccc..bc490a506 100644 --- a/app/src/main/res/layout/dialog_wait.xml +++ b/app/src/main/res/layout/dialog_wait.xml @@ -20,6 +20,6 @@ android:layout_height="wrap_content" android:padding="6dp" android:gravity="center" - android:text="执行中......" + android:text="@string/loading" android:textColor="@color/primaryText" /> \ No newline at end of file diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 7deb85506..ea85ec4e7 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -847,4 +847,5 @@ URL nula 字典 未知错误 + end diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 42cb3aa38..cc05056fd 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -847,4 +847,5 @@ url为空 字典 未知错误 + end diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index b3f2e2eb1..c804508f7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -847,4 +847,5 @@ Nenhuma url Dicionários 未知错误 + end diff --git a/app/src/main/res/values-zh-rHK/arrays.xml b/app/src/main/res/values-zh-rHK/arrays.xml index 6a0784ea8..a16e661f9 100644 --- a/app/src/main/res/values-zh-rHK/arrays.xml +++ b/app/src/main/res/values-zh-rHK/arrays.xml @@ -7,8 +7,8 @@ - 标签 - 文件夹 + 標籤 + 文件夾 @@ -76,4 +76,4 @@ 替換規則 - \ No newline at end of file + diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index b7c405f4f..2146ac4a7 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -343,7 +343,7 @@ 顯示所有發現 關閉則只顯示勾選源的發現 更新目錄 - Txt目錄正則 + TXT目錄正則 設置編碼 倒序-順序 排序 @@ -405,7 +405,7 @@ 書籍 URL 正則 (bookUrlPattern) 預處理規則 (bookInfoInit) 目錄 URL 規則 (tocUrl) - 允许修改书名作者(canReName) + 允許修改書名作者 (canReName) 目錄下一頁規則 (nextTocUrl) 目錄列表規則 (chapterList) 章節名稱規則 (ChapterName) @@ -414,7 +414,7 @@ 更新時間 (ChapterInfo) 正文規則 (content) 正文下一頁 URL 規則 (nextContentUrl) - WebViewJs(webJs) + WebViewJs (webJs) 資源正則 (sourceRegex) 圖標 (sourceIcon) 列表規則 (ruleArticles) @@ -672,10 +672,10 @@ 開發人員 聯繫我們 開源許可 - 關注公衆號 + 關注公眾號 WeChat 你的支持是我更新的動力 - 公众号[开源阅读] + 公眾號[开源阅读] 正在自動換源 點擊加入 @@ -716,46 +716,46 @@ 該書已在下載列表 點擊打開 關注[legado-top]點擊廣告支持我 - 微信赞赏码 + 微信讚賞碼 支付寶 支付寶紅包搜索碼 537954522 點擊複製 支付寶紅包二維碼 支付寶收款二維碼 QQ收款二維碼 - gedoor,Invinciblelee等,详情请在github中查看 + gedoor,Invinciblelee等,詳情請在github中查看 清除已下載書籍和字體緩存 默認封面 恢復忽略列表 恢復時忽略一些內容不恢復,方便不同手機配置不同 閱讀界面設置 - 图片样式(imageStyle) - 替换规则(replaceRegex) + 圖片樣式 (imageStyle) + 替換規則 (replaceRegex) 分組名稱 備註內容 - 默认启用替换净化 - 新加入书架的书是否启用替换净化 - 选择恢复文件 + 默認啟用替換淨化 + 新加入書架的書是否啟用替換淨化 + 選擇恢復文件 白天背景不能太暗 - 白天底栏不能太暗 - 夜间背景不能太亮 - 夜间底栏不能太亮 - 强调色不能和背景颜色相似 - 强调色不能和文字颜色相似 + 白天底欄不能太暗 + 夜間背景不能太亮 + 夜間底欄不能太亮 + 強調色不能和背景顏色相似 + 強調色不能和文字顏色相似 格式不對 錯誤 顯示亮度調節控制項 語言 匯入訂閱源 - 您嘅支援是我更新嘅動力 - 公众号[开源阅读软件] + 您嘅支援喺我更新嘅動力 + 公眾號[开源阅读软件] 閲讀記錄 閱讀時間記錄 本地TTS 線程數 總閲讀時間 全部唔要 - 删除所有 + 刪除所有 導入 導出 儲存主題配置 @@ -789,7 +789,7 @@ 無操作 正文標題 顯示/隱藏 - 页眉页脚 + 頁眉頁腳 規則訂閱 添加大佬們提供的規則匯入地址 添加後點擊可匯入規則 拉取雲端進度 @@ -804,6 +804,9 @@ 預先下載%s章正文 係咪啟用 背景圖片 + 背景圖片虛化 + 虛化半徑 + 0為停用,啓用範圍1~25\n半徑數值越大,虛化效果越高 導出資料夾 導出編碼 導出到WebDav @@ -836,14 +839,15 @@ 狀態欄顯示時隱藏 自訂源分組 輸入自訂源分組名稱 - 反转目录 - 显示发现 - 样式 - 分组样式 - 导出文件名 + 反轉目錄 + 顯示發現 + 樣式 + 分組樣式 + 導出文件名 重置 - url为空 + url為空 字典 - 未知错误 + 未知錯誤 + end diff --git a/app/src/main/res/values-zh-rTW/arrays.xml b/app/src/main/res/values-zh-rTW/arrays.xml index ff880fda3..d88800ca3 100644 --- a/app/src/main/res/values-zh-rTW/arrays.xml +++ b/app/src/main/res/values-zh-rTW/arrays.xml @@ -6,8 +6,8 @@ - 标签 - 文件夹 + 標籤 + 文件夾 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index e55d5cd04..4af6a2440 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -345,7 +345,7 @@ 顯示所有發現 關閉則只顯示勾選源的發現 更新目錄 - Txt目錄正則 + TXT目錄正則 設定編碼 倒序-順序 排序 @@ -807,6 +807,9 @@ 預先下載%s章正文 是否啟用 背景圖片 + 背景圖片虛化 + 虛化半徑 + 0為停用,啓用範圍1~25\n半徑數值越大,虛化效果越高 匯出資料夾 匯出編碼 匯出到WebDav @@ -843,8 +846,9 @@ 分組樣式 匯出檔案名 重設 - url为空 + url為空 字典 - 未知错误 + 未知錯誤 + end diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 910663504..fd844c95e 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -807,6 +807,9 @@ 预先下载%s章正文 是否启用 背景图片 + 背景图片虚化 + 虚化半径 + 0为停用,启用范围1~25\n半径数值越大,虚化效果越高 导出文件夹 导出编码 导出到WebDav @@ -847,5 +850,6 @@ 字典 未知错误 自动备份失败 + 结束 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 92954b0a0..a61943742 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -807,6 +807,9 @@ Download %s chapters in advance Is enabled Background image + Background image blurring + Blurring radius + Disabled when 0, enable range from 1 to 25\nThe greater the radius, the stronger the effect of blurring Copy book URL Copy chapters URL Export folder @@ -849,5 +852,6 @@ 字典 未知错误 Autobackup failed + end diff --git a/app/src/main/res/xml/pref_config_other.xml b/app/src/main/res/xml/pref_config_other.xml index 217fc4156..28360973f 100644 --- a/app/src/main/res/xml/pref_config_other.xml +++ b/app/src/main/res/xml/pref_config_other.xml @@ -40,20 +40,6 @@ android:defaultValue="true" android:key="showRss" android:title="@string/show_rss" - app:iconSpaceReserved="false" /> - - - - diff --git a/app/src/main/res/xml/pref_config_theme.xml b/app/src/main/res/xml/pref_config_theme.xml index ec131ec7a..564cb9811 100644 --- a/app/src/main/res/xml/pref_config_theme.xml +++ b/app/src/main/res/xml/pref_config_theme.xml @@ -33,6 +33,15 @@ android:title="@string/bar_elevation" app:iconSpaceReserved="false" /> + + + + + + + + + +