diff --git a/app/build.gradle b/app/build.gradle index 51a57aef2..c01677c0c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -125,17 +125,26 @@ dependencies { implementation 'com.google.firebase:firebase-crashlytics-ktx:17.3.0' //androidX - implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.media:media:1.2.1' + implementation 'androidx.core:core-ktx:1.3.2' + implementation "androidx.activity:activity-ktx:1.1.0" + implementation "androidx.fragment:fragment-ktx:1.2.5" implementation 'androidx.preference:preference-ktx:1.1.1' + implementation "androidx.collection:collection-ktx:1.1.0" implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.viewpager2:viewpager2:1.0.0' + implementation 'androidx.media:media:1.2.1' implementation 'com.google.android.material:material:1.2.1' implementation 'com.google.android:flexbox:1.1.0' implementation 'com.google.code.gson:gson:2.8.6' + //Splitties + def splitties_version = '2.1.1' + implementation("com.louiscad.splitties:splitties-appctx:$splitties_version") + implementation("com.louiscad.splitties:splitties-systemservices:$splitties_version") + implementation("com.louiscad.splitties:splitties-views:$splitties_version") + //lifecycle def lifecycle_version = '2.2.0' implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" @@ -150,11 +159,6 @@ dependencies { //paging implementation 'androidx.paging:paging-runtime-ktx:2.1.2' - //anko - def anko_version = '0.10.8' - implementation "org.jetbrains.anko:anko-sdk27:$anko_version" - implementation "org.jetbrains.anko:anko-sdk27-listeners:$anko_version" - //liveEventBus implementation 'com.jeremyliao:live-event-bus-x:1.5.7' @@ -185,7 +189,7 @@ dependencies { implementation 'org.nanohttpd:nanohttpd-websocket:2.3.1' //二维码 - implementation 'cn.bingoogolapple:bga-qrcode-zxing:1.3.7' + implementation 'com.king.zxing:zxing-lite:2.0.2' //颜色选择 implementation 'com.jaredrummler:colorpicker:1.1.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4fe52b196..d14a6ef4e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -418,6 +418,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/assets/18PlusList.txt b/app/src/main/assets/18PlusList.txt index 52a5bb3cc..1428bccfd 100644 --- a/app/src/main/assets/18PlusList.txt +++ b/app/src/main/assets/18PlusList.txt @@ -80,3 +80,206 @@ cm5neHM= OTl3ZW5rdQ== bGFvc2lqaXhz ZnVzaHV6aGFpMQ== +cG8xOA== +czUyMTc= +czUyMTc= +c2FuaGFveHM= +NTJrc2h1 +NDhyeA== +ZWNub3ZlbA== +bGllaHVvenc= +eGlhb3FpYW5nd3g= +NTJrc2h1 +NDh3eA== +NTJrc2h1 +MDB1aQ== +MDFieg== +c2h1YmFvMQ== +ZG54aWFvc2h1b2E= +am5zaHViYQ== +MThzaHV3dQ== +bGV4cw== +MzM1eHM= +dXB1 +ZnVndW9kdQ== +ODB0eHQ= +YWFyZWFk +eWlkdWR1MQ== +YmFuemh1d2FuZw== +cWloYW9xaWhhbw== +OHhpYW54cw== +amluamlzaHV3dQ== +d21wOA== +ZXl1c2h1d3U= +NTB4c2Y= +aGF4d3g1 +cG93YW5qdWFu +d2luMTBjaXR5 +eWV5ZXhzdw== +bXlzaHVnZQ== +eGlhbmd0eHN3 +Y3Vpd2VpanV4 +MzY2eHN3 +aHVheXVld2Vua3U= +eW91ZGlhbmxlbg== +c291Nzg= +bGFucm91Mg== +cXFib29r +eW91d3V4cw== +cnVpbGlzYWxl +MzY1bXd3 +ZnV3ZW5o +bGVzYmw= +YXd1Ym9vaw== +bGl5dXhpYW5nMjAyMA== +OTJwb3Bv +ZnVzaHV0dWFu +ODhkYW5tZWk= +ZG14cw== +eXVsaW56aGFueWU= +M2hlYmFv +eGd1YWd1YXhz +ZGl5aWJhbnpodTY= +aXJlYWR4cw== +c2h1YmFvOTY= +ZGl5aWJhbnpodTU1NQ== +c2Fuaml1enc= +N3Fpbmc3 +NjZsZXdlbg== +a3l4czU= +MjIyMjJ4cw== +c2hhb3NodWdl +amlsaW41NQ== +bWt4czY= +amluc2h1bG91 +eGlhbndhbmdz +eWlkdWR1 +cWR0eHQ= +MTZib29rMQ== +am1zaHV3dQ== +MzY2eHN3 +ZHliejk= +c2hvdWRhOA== +ZnlxMTg= +eWlzaHVn +eXV6aGFpd3VsYQ== +MTFiYW56aHU= +MTIzeGlhb3FpYW5n +ZGl5aWJhbnpodTk= +ZGl5aWJhbnpodQ== +MzY2eHN3 +ODdzaHV3dQ== +NnF3eA== +emhlbmh1bnhpYW9zaHVv +bG9uZ3Rlbmc1Mg== +eGlueGluZ3hpYW5nemhpZmE= +ZHliejk= +ZHVvemhla2Fu +MTIzeGlhb3FpYW5n +MzM1eHM= +am1zaHV3dQ== +c2hhb3NodWdl +bGF3ZW54cw== +cnVzaHV3dQ== +MzY2eHN3 +NTB4c2Y= +bGV3ZW41NQ== +aGFpdGFuZzEyMw== +aGViYW81MjA= +bHVvcWl1enc= +c3NzeHN3 +c2h1c2h1d3V4cw== +cm5neHM= +cWR4aWFvc2h1bw== +dHl1ZQ== +Y2hlNDM= +bG9uZ3Rlbmcy +amZ5eHNo +aGV0dTI= +bGFvc2lqaXhz +bG9uZ3Rlbmd4cw== +bGllaHVvenc= +c2h1YmFvYW4= +eHNodW9zaHVv +NTIxZGFubWVp +YmFuemh1MjI= +cWtzaHU= +eWZ4aWFvc2h1b2U= +a3lnc28= +c2h1bG91YmE= +NXRucw== +N3Fpbmc3 +bWlhb2R1NQ== +eXVzaHV3ZW4= +YWFyZWFk +cXRzaHU= +MTdzaHV3dQ== +c2h1YmFvMnM= +YnowMDE= +ZGFtb2dl +MTMxdGI= +aXhpYW9z +bXlzaHVnZQ== +OXhpYW53ZW4= +ZHVvemhla2Fu +MTIwdw== +c2h1c2h1d3U1MjA= +c2h1YmFvMnM= +YWd4c3c= +OTR4c3c= +cG8xOA== +eWFvY2hpeHM= +eGlhb3FpYW5neHM= +Ym9va2Js +c2Fuaml1eHM= +d29kZXNodWJhbw== +em9uZ2NhaXhpYW9zaHVvMg== +OWI4OTEzOTRkZjVi +MThub3ZlbA== +YWFib29r +YjF0eHQ= +eXVjYWl6dw== +Yzl0eHQ= +ZGl5aWJhbnpodTU1NQ== +MzBtYw== +eGlueXVzaHV3dQ== +c2h1YmFvd2FuZzEyMw== +YWd4cw== +YmlxdWdlbmw= +c2hpcWlzaHV3dQ== +c2lsdWtl +ZGl5aWJhbnpodTg= +ZGl5aWJhbnpodTk= +aGV0dW54cw== +OTl3ZW5rdQ== +aGFpdGFuZ3NodXd1 +OTd5ZA== +eXV6aGFpd3UxMQ== +Y3Vpd2VpanV4cw== +Y2JpcXU= +NTIxZGFubWVp +c2h1YmFvMzM= +c2FuaGFvMQ== +dGlhbm1lbmd3ZW5rdQ== +eXVzaHV3dTUyMA== +c2h1YmFvMjIy +c2h1YmFvd2FuZzEyMw== +eXVib29r +Y2JpcXU= +MWxld2Vu +MTV4c3c= +eG5jd3h3 +c2h1YmFvd2FuZzEyMw== +c2FuaGFveHM= +eXV3YW5nc2hl +YmlxdXRz +bGFtZWl4cw== +eGJhbnpodQ== +cWR4aWFvc2h1bw== +bWh0bGE= +OTl3ZW5rdQ== +eGlhb3FpYW5nNTIw +dGlhbm1lbmd3ZW5rdQ== +YWlmdXNodQ== +bWlhb2R1NQ== +bWlmZW5neHM= \ No newline at end of file diff --git a/app/src/main/assets/help/replaceRuleHelp.md b/app/src/main/assets/help/replaceRuleHelp.md new file mode 100644 index 000000000..063c8d3a3 --- /dev/null +++ b/app/src/main/assets/help/replaceRuleHelp.md @@ -0,0 +1,6 @@ +# 替换管理界面帮助 + +* 替换规则是用来替换正文内容的一种规则 + * 菜单可以新建和导入规则 + * 可以拖动排序 + * 可以选择操作 \ No newline at end of file diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index c9abdb4bb..292f9f5ef 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -3,6 +3,16 @@ * 关注合作公众号 **[小说拾遗]** 获取好看的小说。 * 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 +**2021/02/03** +* 排版导出文件名修改为配置名称 +* 取消在线朗读下载文件检测,会导致朗读中断 +* 修复其它一些bug + +**2021/01/30** +* 优化阅读记录界面 +* 自定义分组可以隐藏,删除按钮移到编辑对话框 +* 修复其它一些bug + **2021/01/23** * 优化书源校验,从搜索到正文全部校验 * play版可以设置背景图片 @@ -264,27 +274,4 @@ getTxtInFolder(unzipPath: String): String **2020/09/10** * 修复自动换源的bug * 修复保存主题的bug -* 书源排序,分享,注释优化 by [h11128](https://github.com/h11128) - -**2020/09/09** -* 修复主题导入导出bug -* 优化分屏模式状态栏 -* 书源基本属性增加“书源注释” -* 页眉页脚跟随背景 -* 主题导入导出 -* 订阅源和替换规则添加滑动选择 -* 修复排版配置导入导出 -* 订阅界面添加下载文件功能 -* 优化翻页 -* EInk模式独立背景 -* 阅读排版配置导入导出,包括背景和字体,支持网络导入 -* 修复替换中的回车消失的bug -* 所有内容恢复htmlFormat, 在想其它办法解决丢失一些内容的问题 -* 图片(漫画)支持导出 -* 搜索url支持put,get,js里使用java.put,java.get -* 正文合并后替换规则支持所有规则写法,包括js -* 导入书源列表添加全不选 -* 详情页菜单添加清理缓存,清理当前书籍缓存 -* 修复滑动选择,选择数量不更新的bug -* 字体跟随背景,每个背景对应一个字体 -* 优化图片下载 \ No newline at end of file +* 书源排序,分享,注释优化 by [h11128](https://github.com/h11128) \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/App.kt b/app/src/main/java/io/legado/app/App.kt index 6b48a7499..6345cf1b1 100644 --- a/app/src/main/java/io/legado/app/App.kt +++ b/app/src/main/java/io/legado/app/App.kt @@ -5,58 +5,33 @@ import android.app.NotificationManager import android.content.Context import android.content.res.Configuration import android.os.Build -import android.provider.Settings -import androidx.appcompat.app.AppCompatDelegate import androidx.multidex.MultiDexApplication import com.jeremyliao.liveeventbus.LiveEventBus import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst.channelIdDownload import io.legado.app.constant.AppConst.channelIdReadAloud import io.legado.app.constant.AppConst.channelIdWeb -import io.legado.app.constant.EventBus -import io.legado.app.data.AppDatabase -import io.legado.app.help.* +import io.legado.app.help.ActivityHelp +import io.legado.app.help.AppConfig +import io.legado.app.help.CrashHandler +import io.legado.app.help.ThemeConfig.applyDayNight import io.legado.app.help.http.HttpHelper import io.legado.app.utils.LanguageUtils -import io.legado.app.utils.postEvent -import org.jetbrains.anko.defaultSharedPreferences +import io.legado.app.utils.defaultSharedPreferences import rxhttp.wrapper.param.RxHttp -@Suppress("DEPRECATION") class App : MultiDexApplication() { - companion object { - @JvmStatic - lateinit var INSTANCE: App - private set - - @JvmStatic - lateinit var db: AppDatabase - private set - - lateinit var androidId: String - var versionCode = 0 - var versionName = "" - var navigationBarHeight = 0 - } - override fun onCreate() { super.onCreate() - INSTANCE = this - androidId = Settings.System.getString(contentResolver, Settings.Secure.ANDROID_ID) CrashHandler(this) LanguageUtils.setConfiguration(this) - db = AppDatabase.createDatabase(INSTANCE) RxHttp.init(HttpHelper.client, BuildConfig.DEBUG) RxHttp.setOnParamAssembly { it.addHeader(AppConst.UA_NAME, AppConfig.userAgent) } - packageManager.getPackageInfo(packageName, 0)?.let { - versionCode = it.versionCode - versionName = it.versionName - } createNotificationChannels() - applyDayNight() + applyDayNight(this) LiveEventBus.config() .supportBroadcast(this) .lifecycleObserverAlwaysActive(true) @@ -69,27 +44,10 @@ class App : MultiDexApplication() { super.onConfigurationChanged(newConfig) when (newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK) { Configuration.UI_MODE_NIGHT_YES, - Configuration.UI_MODE_NIGHT_NO -> applyDayNight() + Configuration.UI_MODE_NIGHT_NO -> applyDayNight(this) } } - fun applyDayNight() { - ReadBookConfig.upBg() - ThemeConfig.applyTheme(this) - initNightMode() - postEvent(EventBus.RECREATE, "") - } - - private fun initNightMode() { - val targetMode = - if (AppConfig.isNightTheme) { - AppCompatDelegate.MODE_NIGHT_YES - } else { - AppCompatDelegate.MODE_NIGHT_NO - } - AppCompatDelegate.setDefaultNightMode(targetMode) - } - /** * 创建通知ID */ @@ -99,7 +57,7 @@ class App : MultiDexApplication() { val downloadChannel = NotificationChannel( channelIdDownload, getString(R.string.action_download), - NotificationManager.IMPORTANCE_LOW + NotificationManager.IMPORTANCE_DEFAULT ).apply { enableLights(false) enableVibration(false) @@ -109,7 +67,7 @@ class App : MultiDexApplication() { val readAloudChannel = NotificationChannel( channelIdReadAloud, getString(R.string.read_aloud), - NotificationManager.IMPORTANCE_LOW + NotificationManager.IMPORTANCE_DEFAULT ).apply { enableLights(false) enableVibration(false) @@ -119,7 +77,7 @@ class App : MultiDexApplication() { val webChannel = NotificationChannel( channelIdWeb, getString(R.string.web_service), - NotificationManager.IMPORTANCE_LOW + NotificationManager.IMPORTANCE_DEFAULT ).apply { enableLights(false) enableVibration(false) @@ -131,4 +89,8 @@ class App : MultiDexApplication() { } } + companion object { + var navigationBarHeight = 0 + } + } diff --git a/app/src/main/java/io/legado/app/api/controller/BookshelfController.kt b/app/src/main/java/io/legado/app/api/controller/BookshelfController.kt index c8e878f0f..82005aac2 100644 --- a/app/src/main/java/io/legado/app/api/controller/BookshelfController.kt +++ b/app/src/main/java/io/legado/app/api/controller/BookshelfController.kt @@ -1,8 +1,8 @@ package io.legado.app.api.controller -import io.legado.app.App import io.legado.app.api.ReturnData import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.help.BookHelp import io.legado.app.model.webBook.WebBook @@ -12,17 +12,18 @@ import io.legado.app.utils.cnCompare import io.legado.app.utils.fromJsonObject import io.legado.app.utils.getPrefInt import kotlinx.coroutines.runBlocking +import splitties.init.appCtx object BookshelfController { val bookshelf: ReturnData get() { - val books = App.db.bookDao.all + val books = appDb.bookDao.all val returnData = ReturnData() return if (books.isEmpty()) { returnData.setErrorMsg("还没有添加小说") } else { - val data = when (App.INSTANCE.getPrefInt(PreferKey.bookshelfSort)) { + val data = when (appCtx.getPrefInt(PreferKey.bookshelfSort)) { 1 -> books.sortedByDescending { it.latestChapterTime } 2 -> books.sortedWith { o1, o2 -> o1.name.cnCompare(o2.name) @@ -40,7 +41,7 @@ object BookshelfController { if (bookUrl.isNullOrEmpty()) { return returnData.setErrorMsg("参数url不能为空,请指定书籍地址") } - val chapterList = App.db.bookChapterDao.getChapterList(bookUrl) + val chapterList = appDb.bookChapterDao.getChapterList(bookUrl) return returnData.setData(chapterList) } @@ -54,8 +55,8 @@ object BookshelfController { if (index == null) { return returnData.setErrorMsg("参数index不能为空, 请指定目录序号") } - val book = App.db.bookDao.getBook(bookUrl) - val chapter = App.db.bookChapterDao.getChapter(bookUrl, index) + val book = appDb.bookDao.getBook(bookUrl) + val chapter = appDb.bookChapterDao.getChapter(bookUrl, index) if (book == null || chapter == null) { returnData.setErrorMsg("未找到") } else { @@ -64,7 +65,7 @@ object BookshelfController { saveBookReadIndex(book, index) returnData.setData(content) } else { - App.db.bookSourceDao.getBookSource(book.origin)?.let { source -> + appDb.bookSourceDao.getBookSource(book.origin)?.let { source -> runBlocking { WebBook(source).getContentAwait(this, book, chapter) }.let { @@ -81,7 +82,7 @@ object BookshelfController { val book = GSON.fromJsonObject(postData) val returnData = ReturnData() if (book != null) { - App.db.bookDao.insert(book) + appDb.bookDao.insert(book) if (ReadBook.book?.bookUrl == book.bookUrl) { ReadBook.book = book ReadBook.durChapterIndex = book.durChapterIndex @@ -95,10 +96,10 @@ object BookshelfController { if (index > book.durChapterIndex) { book.durChapterIndex = index book.durChapterTime = System.currentTimeMillis() - App.db.bookChapterDao.getChapter(book.bookUrl, index)?.let { + appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { book.durChapterTitle = it.title } - App.db.bookDao.update(book) + appDb.bookDao.update(book) if (ReadBook.book?.bookUrl == book.bookUrl) { ReadBook.book = book ReadBook.durChapterIndex = index diff --git a/app/src/main/java/io/legado/app/api/controller/SourceController.kt b/app/src/main/java/io/legado/app/api/controller/SourceController.kt index 6dc142804..3972295e5 100644 --- a/app/src/main/java/io/legado/app/api/controller/SourceController.kt +++ b/app/src/main/java/io/legado/app/api/controller/SourceController.kt @@ -2,8 +2,8 @@ package io.legado.app.api.controller import android.text.TextUtils -import io.legado.app.App import io.legado.app.api.ReturnData +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonArray @@ -14,7 +14,7 @@ object SourceController { val sources: ReturnData get() { - val bookSources = App.db.bookSourceDao.all + val bookSources = appDb.bookSourceDao.all val returnData = ReturnData() return if (bookSources.isEmpty()) { returnData.setErrorMsg("设备书源列表为空") @@ -29,7 +29,7 @@ object SourceController { if (TextUtils.isEmpty(bookSource.bookSourceName) || TextUtils.isEmpty(bookSource.bookSourceUrl)) { returnData.setErrorMsg("书源名称和URL不能为空") } else { - App.db.bookSourceDao.insert(bookSource) + appDb.bookSourceDao.insert(bookSource) returnData.setData("") } } else { @@ -50,7 +50,7 @@ object SourceController { if (bookSource.bookSourceName.isBlank() || bookSource.bookSourceUrl.isBlank()) { continue } - App.db.bookSourceDao.insert(bookSource) + appDb.bookSourceDao.insert(bookSource) okSources.add(bookSource) } } @@ -64,7 +64,7 @@ object SourceController { if (url.isNullOrEmpty()) { return returnData.setErrorMsg("参数url不能为空,请指定书源地址") } - val bookSource = App.db.bookSourceDao.getBookSource(url) + val bookSource = appDb.bookSourceDao.getBookSource(url) ?: return returnData.setErrorMsg("未找到书源,请检查书源地址") return returnData.setData(bookSource) } @@ -73,7 +73,7 @@ object SourceController { kotlin.runCatching { GSON.fromJsonArray(postData)?.let { it.forEach { source -> - App.db.bookSourceDao.delete(source) + appDb.bookSourceDao.delete(source) } } } diff --git a/app/src/main/java/io/legado/app/base/BaseViewModel.kt b/app/src/main/java/io/legado/app/base/BaseViewModel.kt index e5432e204..88ddc4b5e 100644 --- a/app/src/main/java/io/legado/app/base/BaseViewModel.kt +++ b/app/src/main/java/io/legado/app/base/BaseViewModel.kt @@ -6,15 +6,13 @@ import androidx.annotation.CallSuper import androidx.lifecycle.AndroidViewModel import io.legado.app.App import io.legado.app.help.coroutine.Coroutine +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.* -import org.jetbrains.anko.AnkoLogger -import org.jetbrains.anko.toast import kotlin.coroutines.CoroutineContext @Suppress("unused") open class BaseViewModel(application: Application) : AndroidViewModel(application), - CoroutineScope by MainScope(), - AnkoLogger { + CoroutineScope by MainScope() { val context: Context by lazy { this.getApplication() } @@ -40,27 +38,12 @@ open class BaseViewModel(application: Application) : AndroidViewModel(applicatio cancel() } - open fun toast(message: Int) { - launch { - context.toast(message) - } + open fun toastOnUi(message: Int) { + context.toastOnUi(message) } - open fun toast(message: CharSequence?) { - launch { - context.toast(message ?: toString()) - } + open fun toastOnUi(message: CharSequence?) { + context.toastOnUi(message ?: toString()) } - open fun longToast(message: Int) { - launch { - context.toast(message) - } - } - - open fun longToast(message: CharSequence?) { - launch { - context.toast(message ?: toString()) - } - } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/base/adapter/DiffRecyclerAdapter.kt b/app/src/main/java/io/legado/app/base/adapter/DiffRecyclerAdapter.kt index 60d3600ed..2575ea067 100644 --- a/app/src/main/java/io/legado/app/base/adapter/DiffRecyclerAdapter.kt +++ b/app/src/main/java/io/legado/app/base/adapter/DiffRecyclerAdapter.kt @@ -8,6 +8,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding +import splitties.views.onLongClick /** * Created by Invincible on 2017/12/15. @@ -130,10 +131,10 @@ abstract class DiffRecyclerAdapter(protected val context } if (itemLongClickListener != null) { - holder.itemView.setOnLongClickListener { + holder.itemView.onLongClick { getItem(holder.layoutPosition)?.let { - itemLongClickListener?.invoke(holder, it) ?: true - } ?: true + itemLongClickListener?.invoke(holder, it) + } } } diff --git a/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt b/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt index 0d6e3b668..11dd17f8c 100644 --- a/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt +++ b/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt @@ -8,6 +8,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding +import splitties.views.onLongClick import java.util.* /** @@ -351,10 +352,10 @@ abstract class RecyclerAdapter(protected val context: Co } if (itemLongClickListener != null) { - holder.itemView.setOnLongClickListener { + holder.itemView.onLongClick { getItem(holder.layoutPosition)?.let { - itemLongClickListener?.invoke(holder, it) ?: true - } ?: true + itemLongClickListener?.invoke(holder, it) + } } } diff --git a/app/src/main/java/io/legado/app/constant/AppConst.kt b/app/src/main/java/io/legado/app/constant/AppConst.kt index 07257a46c..69036d5d0 100644 --- a/app/src/main/java/io/legado/app/constant/AppConst.kt +++ b/app/src/main/java/io/legado/app/constant/AppConst.kt @@ -1,8 +1,8 @@ package io.legado.app.constant import android.annotation.SuppressLint -import io.legado.app.App import io.legado.app.R +import splitties.init.appCtx import java.text.SimpleDateFormat import javax.script.ScriptEngine import javax.script.ScriptEngineManager @@ -68,5 +68,12 @@ object AppConst { "androidx.appcompat.view.menu.ListMenuItemView" ) - val sysElevation = App.INSTANCE.resources.getDimension(R.dimen.design_appbar_elevation).toInt() + val sysElevation = appCtx.resources.getDimension(R.dimen.design_appbar_elevation).toInt() + + val darkWebViewJs by lazy { + """ + document.body.style.backgroundColor = "#222222"; + document.getElementsByTagName('body')[0].style.webkitTextFillColor = '#8a8a8a'; + """.trimIndent() + } } diff --git a/app/src/main/java/io/legado/app/constant/Const.kt b/app/src/main/java/io/legado/app/constant/Const.kt new file mode 100644 index 000000000..97e267f85 --- /dev/null +++ b/app/src/main/java/io/legado/app/constant/Const.kt @@ -0,0 +1,27 @@ +package io.legado.app.constant + +import android.provider.Settings +import splitties.init.appCtx + +val androidId: String by lazy { + Settings.System.getString(appCtx.contentResolver, Settings.Secure.ANDROID_ID) +} + +val appInfo: AppInfo by lazy { + val appInfo = AppInfo() + appCtx.packageManager.getPackageInfo(appCtx.packageName, 0)?.let { + appInfo.versionName = it.versionName + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + appInfo.versionCode = it.longVersionCode + } else { + @Suppress("DEPRECATION") + appInfo.versionCode = it.versionCode.toLong() + } + } + appInfo +} + +data class AppInfo( + var versionCode: Long = 0L, + var versionName: String = "" +) \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/data/AppDatabase.kt b/app/src/main/java/io/legado/app/data/AppDatabase.kt index 315793633..e679390c2 100644 --- a/app/src/main/java/io/legado/app/data/AppDatabase.kt +++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt @@ -6,12 +6,16 @@ import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase -import io.legado.app.App import io.legado.app.constant.AppConst +import io.legado.app.constant.androidId import io.legado.app.data.dao.* import io.legado.app.data.entities.* +import splitties.init.appCtx import java.util.* +val appDb by lazy { + AppDatabase.createDatabase(appCtx) +} @Database( entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class, @@ -151,7 +155,7 @@ abstract class AppDatabase : RoomDatabase() { """CREATE TABLE IF NOT EXISTS `readRecordNew` (`androidId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `readTime` INTEGER NOT NULL, PRIMARY KEY(`androidId`, `bookName`))""" ) - database.execSQL("INSERT INTO readRecordNew(androidId, bookName, readTime) select '${App.androidId}' as androidId, bookName, readTime from readRecord") + database.execSQL("INSERT INTO readRecordNew(androidId, bookName, readTime) select '${androidId}' as androidId, bookName, readTime from readRecord") database.execSQL("DROP TABLE readRecord") database.execSQL("ALTER TABLE readRecordNew RENAME TO readRecord") } diff --git a/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt b/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt index 6bf596905..34e6a3e88 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt @@ -19,7 +19,7 @@ interface BookGroupDao { @Query( """ - SELECT * FROM book_groups where groupId >= 0 + SELECT * FROM book_groups where (groupId >= 0 and show > 0) or (groupId = -4 and show > 0 and (select count(bookUrl) from books where type != ${BookType.audio} and origin != '${BookType.local}' and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0) > 0) or (groupId = -3 and show > 0 and (select count(bookUrl) from books where type = ${BookType.audio}) > 0) or (groupId = -2 and show > 0 and (select count(bookUrl) from books where origin = '${BookType.local}') > 0) diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt index 2b30a8538..8db3a77ff 100644 --- a/app/src/main/java/io/legado/app/data/entities/Book.kt +++ b/app/src/main/java/io/legado/app/data/entities/Book.kt @@ -2,9 +2,9 @@ package io.legado.app.data.entities import android.os.Parcelable import androidx.room.* -import io.legado.app.App import io.legado.app.constant.AppPattern import io.legado.app.constant.BookType +import io.legado.app.data.appDb import io.legado.app.help.AppConfig import io.legado.app.service.help.ReadBook import io.legado.app.utils.GSON @@ -182,14 +182,14 @@ data class Book( newBook.canUpdate = canUpdate newBook.readConfig = readConfig delete() - App.db.bookDao.insert(newBook) + appDb.bookDao.insert(newBook) } fun delete() { if (ReadBook.book?.bookUrl == bookUrl) { ReadBook.book = null } - App.db.bookDao.delete(this) + appDb.bookDao.delete(this) } fun upInfoFromOld(oldBook: Book?) { diff --git a/app/src/main/java/io/legado/app/data/entities/BookSource.kt b/app/src/main/java/io/legado/app/data/entities/BookSource.kt index b439fb367..88fbf53ed 100644 --- a/app/src/main/java/io/legado/app/data/entities/BookSource.kt +++ b/app/src/main/java/io/legado/app/data/entities/BookSource.kt @@ -3,7 +3,6 @@ package io.legado.app.data.entities import android.os.Parcelable import android.text.TextUtils import androidx.room.* -import io.legado.app.App import io.legado.app.constant.AppConst import io.legado.app.constant.BookType import io.legado.app.data.entities.rule.* @@ -16,6 +15,7 @@ import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonObject import io.legado.app.utils.splitNotBlank import kotlinx.parcelize.Parcelize +import splitties.init.appCtx import javax.script.SimpleBindings @Parcelize @@ -106,7 +106,7 @@ data class BookSource( if (a.isNotBlank()) { kotlin.runCatching { if (urlRule.startsWith("", false)) { - val aCache = ACache.get(App.INSTANCE, "explore") + val aCache = ACache.get(appCtx, "explore") a = aCache.getAsString(bookSourceUrl) ?: "" if (a.isBlank()) { val bindings = SimpleBindings() 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 1c5c10a72..08a1fa3df 100644 --- a/app/src/main/java/io/legado/app/help/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/AppConfig.kt @@ -2,15 +2,15 @@ package io.legado.app.help import android.content.Context import android.content.SharedPreferences -import io.legado.app.App import io.legado.app.R import io.legado.app.constant.AppConst import io.legado.app.constant.PreferKey import io.legado.app.utils.* +import splitties.init.appCtx @Suppress("MemberVisibilityCanBePrivate") object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { - private val context get() = App.INSTANCE + private val context get() = appCtx val isGooglePlay = context.channel == "google" var userAgent: String = getPrefUserAgent() var replaceEnableDefault = context.getPrefBoolean(PreferKey.replaceEnableDefault, true) diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt index c8fad6f6e..fbf05f538 100644 --- a/app/src/main/java/io/legado/app/help/BookHelp.kt +++ b/app/src/main/java/io/legado/app/help/BookHelp.kt @@ -1,8 +1,8 @@ package io.legado.app.help -import io.legado.app.App import io.legado.app.constant.AppPattern import io.legado.app.constant.EventBus +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.coroutine.Coroutine @@ -11,6 +11,7 @@ import io.legado.app.model.localBook.LocalBook import io.legado.app.utils.* import kotlinx.coroutines.delay import org.apache.commons.text.similarity.JaccardSimilarity +import splitties.init.appCtx import java.io.File import java.util.concurrent.CopyOnWriteArraySet import java.util.regex.Matcher @@ -22,7 +23,7 @@ import kotlin.math.min object BookHelp { private const val cacheFolderName = "book_cache" private const val cacheImageFolderName = "images" - private val downloadDir: File = App.INSTANCE.externalFilesDir + private val downloadDir: File = appCtx.externalFilesDir private val downloadImages = CopyOnWriteArraySet() fun clearCache() { @@ -42,7 +43,7 @@ object BookHelp { fun clearRemovedCache() { Coroutine.async { val bookFolderNames = arrayListOf() - App.db.bookDao.all.forEach { + appDb.bookDao.all.forEach { bookFolderNames.add(it.getFolderName()) } val file = FileUtils.getFile(downloadDir, cacheFolderName) diff --git a/app/src/main/java/io/legado/app/help/CacheManager.kt b/app/src/main/java/io/legado/app/help/CacheManager.kt index f7cb1ba5b..6194a6175 100644 --- a/app/src/main/java/io/legado/app/help/CacheManager.kt +++ b/app/src/main/java/io/legado/app/help/CacheManager.kt @@ -1,9 +1,10 @@ package io.legado.app.help -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.Cache import io.legado.app.model.analyzeRule.QueryTTF import io.legado.app.utils.ACache +import splitties.init.appCtx @Suppress("unused") object CacheManager { @@ -19,16 +20,16 @@ object CacheManager { if (saveTime == 0) 0 else System.currentTimeMillis() + saveTime * 1000 when (value) { is QueryTTF -> queryTTFMap[key] = Pair(deadline, value) - is ByteArray -> ACache.get(App.INSTANCE).put(key, value, saveTime) + is ByteArray -> ACache.get(appCtx).put(key, value, saveTime) else -> { val cache = Cache(key, value.toString(), deadline) - App.db.cacheDao.insert(cache) + appDb.cacheDao.insert(cache) } } } fun get(key: String): String? { - return App.db.cacheDao.get(key, System.currentTimeMillis()) + return appDb.cacheDao.get(key, System.currentTimeMillis()) } fun getInt(key: String): Int? { @@ -48,7 +49,7 @@ object CacheManager { } fun getByteArray(key: String): ByteArray? { - return ACache.get(App.INSTANCE).getAsBinary(key) + return ACache.get(appCtx).getAsBinary(key) } fun getQueryTTF(key: String): QueryTTF? { diff --git a/app/src/main/java/io/legado/app/help/ContentProcessor.kt b/app/src/main/java/io/legado/app/help/ContentProcessor.kt index c3fa8624d..17f6f6319 100644 --- a/app/src/main/java/io/legado/app/help/ContentProcessor.kt +++ b/app/src/main/java/io/legado/app/help/ContentProcessor.kt @@ -1,12 +1,13 @@ package io.legado.app.help import com.hankcs.hanlp.HanLP -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.ReplaceRule +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.jetbrains.anko.toast +import splitties.init.appCtx class ContentProcessor(private val bookName: String, private val bookOrigin: String) { @@ -19,7 +20,7 @@ class ContentProcessor(private val bookName: String, private val bookOrigin: Str @Synchronized fun upReplaceRules() { replaceRules.clear() - replaceRules.addAll(App.db.replaceRuleDao.findEnabledByScope(bookName, bookOrigin)) + replaceRules.addAll(appDb.replaceRuleDao.findEnabledByScope(bookName, bookOrigin)) } suspend fun getContent( @@ -40,7 +41,7 @@ class ContentProcessor(private val bookName: String, private val bookOrigin: Str } } catch (e: Exception) { withContext(Dispatchers.Main) { - App.INSTANCE.toast("${item.name}替换出错") + appCtx.toastOnUi("${item.name}替换出错") } } } @@ -57,7 +58,7 @@ class ContentProcessor(private val bookName: String, private val bookOrigin: Str } } catch (e: Exception) { withContext(Dispatchers.Main) { - App.INSTANCE.toast("简繁转换出错") + appCtx.toastOnUi("简繁转换出错") } } } diff --git a/app/src/main/java/io/legado/app/help/DefaultData.kt b/app/src/main/java/io/legado/app/help/DefaultData.kt index ba06316b9..d785be91e 100644 --- a/app/src/main/java/io/legado/app/help/DefaultData.kt +++ b/app/src/main/java/io/legado/app/help/DefaultData.kt @@ -1,11 +1,12 @@ package io.legado.app.help -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.HttpTTS import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.TxtTocRule import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonArray +import splitties.init.appCtx import java.io.File object DefaultData { @@ -16,7 +17,7 @@ object DefaultData { val httpTTS by lazy { val json = String( - App.INSTANCE.assets.open("defaultData${File.separator}$httpTtsFileName") + appCtx.assets.open("defaultData${File.separator}$httpTtsFileName") .readBytes() ) GSON.fromJsonArray(json)!! @@ -24,7 +25,7 @@ object DefaultData { val readConfigs by lazy { val json = String( - App.INSTANCE.assets.open("defaultData${File.separator}${ReadBookConfig.configFileName}") + appCtx.assets.open("defaultData${File.separator}${ReadBookConfig.configFileName}") .readBytes() ) GSON.fromJsonArray(json)!! @@ -32,7 +33,7 @@ object DefaultData { val txtTocRules by lazy { val json = String( - App.INSTANCE.assets.open("defaultData${File.separator}$txtTocRuleFileName") + appCtx.assets.open("defaultData${File.separator}$txtTocRuleFileName") .readBytes() ) GSON.fromJsonArray(json)!! @@ -40,7 +41,7 @@ object DefaultData { val themeConfigs by lazy { val json = String( - App.INSTANCE.assets.open("defaultData${File.separator}${ThemeConfig.configFileName}") + appCtx.assets.open("defaultData${File.separator}${ThemeConfig.configFileName}") .readBytes() ) GSON.fromJsonArray(json)!! @@ -48,23 +49,23 @@ object DefaultData { val rssSources by lazy { val json = String( - App.INSTANCE.assets.open("defaultData${File.separator}rssSources.json") + appCtx.assets.open("defaultData${File.separator}rssSources.json") .readBytes() ) GSON.fromJsonArray(json)!! } fun importDefaultHttpTTS() { - App.db.httpTTSDao.deleteDefault() - App.db.httpTTSDao.insert(*httpTTS.toTypedArray()) + appDb.httpTTSDao.deleteDefault() + appDb.httpTTSDao.insert(*httpTTS.toTypedArray()) } fun importDefaultTocRules() { - App.db.txtTocRule.deleteDefault() - App.db.txtTocRule.insert(*txtTocRules.toTypedArray()) + appDb.txtTocRule.deleteDefault() + appDb.txtTocRule.insert(*txtTocRules.toTypedArray()) } fun importDefaultRssSources() { - App.db.rssSourceDao.insert(*rssSources.toTypedArray()) + appDb.rssSourceDao.insert(*rssSources.toTypedArray()) } } \ No newline at end of file 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 7524bed78..10e1c53ac 100644 --- a/app/src/main/java/io/legado/app/help/IntentHelp.kt +++ b/app/src/main/java/io/legado/app/help/IntentHelp.kt @@ -5,7 +5,7 @@ import android.content.Context import android.content.Intent import android.os.Bundle import io.legado.app.R -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi @Suppress("unused") object IntentHelp { @@ -19,7 +19,7 @@ object IntentHelp { intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK context.startActivity(intent) }.onFailure { - context.toast(R.string.tip_cannot_jump_setting_page) + context.toastOnUi(R.string.tip_cannot_jump_setting_page) } } @@ -30,7 +30,7 @@ object IntentHelp { intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK context.startActivity(intent) }.onFailure { - context.toast("无法打开设置") + context.toastOnUi("无法打开设置") } } diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index bef4d0e4a..ed56073a1 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -3,7 +3,6 @@ package io.legado.app.help import android.net.Uri import android.util.Base64 import androidx.annotation.Keep -import io.legado.app.App import io.legado.app.constant.AppConst.dateFormat import io.legado.app.help.http.CookieStore import io.legado.app.help.http.SSLHelper @@ -16,6 +15,7 @@ import org.jsoup.Connection import org.jsoup.Jsoup import rxhttp.wrapper.param.RxHttp import rxhttp.wrapper.param.toByteArray +import splitties.init.appCtx import java.io.File import java.net.URLEncoder import java.util.* @@ -273,7 +273,7 @@ interface JsExtensions { } return@runBlocking x } - str.isContentScheme() -> Uri.parse(str).readBytes(App.INSTANCE) + str.isContentScheme() -> Uri.parse(str).readBytes(appCtx) str.startsWith("/storage") -> File(str).readBytes() else -> base64DecodeToByteArray(str) } diff --git a/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt b/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt index 04723c21a..3a226e071 100644 --- a/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt +++ b/app/src/main/java/io/legado/app/help/LauncherIconHelp.kt @@ -3,30 +3,30 @@ package io.legado.app.help import android.content.ComponentName import android.content.pm.PackageManager import android.os.Build -import io.legado.app.App import io.legado.app.R import io.legado.app.ui.welcome.* -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi +import splitties.init.appCtx /** * Created by GKF on 2018/2/27. * 更换图标 */ object LauncherIconHelp { - private val packageManager: PackageManager = App.INSTANCE.packageManager + private val packageManager: PackageManager = appCtx.packageManager private val componentNames = arrayListOf( - ComponentName(App.INSTANCE, Launcher1::class.java.name), - ComponentName(App.INSTANCE, Launcher2::class.java.name), - ComponentName(App.INSTANCE, Launcher3::class.java.name), - ComponentName(App.INSTANCE, Launcher4::class.java.name), - ComponentName(App.INSTANCE, Launcher5::class.java.name), - ComponentName(App.INSTANCE, Launcher6::class.java.name) + ComponentName(appCtx, Launcher1::class.java.name), + ComponentName(appCtx, Launcher2::class.java.name), + ComponentName(appCtx, Launcher3::class.java.name), + ComponentName(appCtx, Launcher4::class.java.name), + ComponentName(appCtx, Launcher5::class.java.name), + ComponentName(appCtx, Launcher6::class.java.name) ) fun changeIcon(icon: String?) { if (icon.isNullOrEmpty()) return if (Build.VERSION.SDK_INT < 26) { - App.INSTANCE.toast(R.string.change_icon_error) + appCtx.toastOnUi(R.string.change_icon_error) return } var hasEnabled = false @@ -50,13 +50,13 @@ object LauncherIconHelp { } if (hasEnabled) { packageManager.setComponentEnabledSetting( - ComponentName(App.INSTANCE, WelcomeActivity::class.java.name), + ComponentName(appCtx, WelcomeActivity::class.java.name), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP ) } else { packageManager.setComponentEnabledSetting( - ComponentName(App.INSTANCE, WelcomeActivity::class.java.name), + ComponentName(appCtx, WelcomeActivity::class.java.name), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP ) diff --git a/app/src/main/java/io/legado/app/help/LocalConfig.kt b/app/src/main/java/io/legado/app/help/LocalConfig.kt index 6278c0c55..ff86c7a47 100644 --- a/app/src/main/java/io/legado/app/help/LocalConfig.kt +++ b/app/src/main/java/io/legado/app/help/LocalConfig.kt @@ -2,19 +2,19 @@ package io.legado.app.help import android.content.Context import androidx.core.content.edit -import io.legado.app.App +import splitties.init.appCtx object LocalConfig { - private const val versionCodeKey = "versionCode" + private const val versionCodeKey = "appVersionCode" private val localConfig = - App.INSTANCE.getSharedPreferences("local", Context.MODE_PRIVATE) + appCtx.getSharedPreferences("local", Context.MODE_PRIVATE) var versionCode - get() = localConfig.getInt(versionCodeKey, 0) + get() = localConfig.getLong(versionCodeKey, 0) set(value) { localConfig.edit { - putInt(versionCodeKey, value) + putLong(versionCodeKey, value) } } 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 de8e0aaed..8ebc339fc 100644 --- a/app/src/main/java/io/legado/app/help/ReadBookConfig.kt +++ b/app/src/main/java/io/legado/app/help/ReadBookConfig.kt @@ -5,12 +5,12 @@ import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import androidx.annotation.Keep -import io.legado.app.App import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.help.coroutine.Coroutine import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.utils.* +import splitties.init.appCtx import java.io.File /** @@ -20,7 +20,7 @@ import java.io.File object ReadBookConfig { const val configFileName = "readConfig.json" const val shareConfigFileName = "shareReadConfig.json" - val context get() = App.INSTANCE + val context get() = appCtx val configFilePath = FileUtils.getPath(context.filesDir, configFileName) val shareConfigFilePath = FileUtils.getPath(context.filesDir, shareConfigFileName) val configList: ArrayList = arrayListOf() diff --git a/app/src/main/java/io/legado/app/help/ReadTipConfig.kt b/app/src/main/java/io/legado/app/help/ReadTipConfig.kt index c09876802..d962f64c0 100644 --- a/app/src/main/java/io/legado/app/help/ReadTipConfig.kt +++ b/app/src/main/java/io/legado/app/help/ReadTipConfig.kt @@ -1,11 +1,11 @@ package io.legado.app.help -import io.legado.app.App import io.legado.app.R +import splitties.init.appCtx object ReadTipConfig { val tips by lazy { - App.INSTANCE.resources.getStringArray(R.array.read_tip).toList() + appCtx.resources.getStringArray(R.array.read_tip).toList() } val headerModes by lazy { linkedMapOf(0 to "状态栏显示时隐藏", 1 to "显示", 2 to "隐藏") diff --git a/app/src/main/java/io/legado/app/help/SourceHelp.kt b/app/src/main/java/io/legado/app/help/SourceHelp.kt index 02b20bf52..be977ec87 100644 --- a/app/src/main/java/io/legado/app/help/SourceHelp.kt +++ b/app/src/main/java/io/legado/app/help/SourceHelp.kt @@ -2,20 +2,21 @@ package io.legado.app.help import android.os.Handler import android.os.Looper -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.RssSource import io.legado.app.utils.EncoderUtils import io.legado.app.utils.NetworkUtils import io.legado.app.utils.splitNotBlank -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi +import splitties.init.appCtx object SourceHelp { private val handler = Handler(Looper.getMainLooper()) private val list18Plus by lazy { try { - return@lazy String(App.INSTANCE.assets.open("18PlusList.txt").readBytes()) + return@lazy String(appCtx.assets.open("18PlusList.txt").readBytes()) .splitNotBlank("\n") } catch (e: Exception) { return@lazy arrayOf() @@ -26,10 +27,10 @@ object SourceHelp { rssSources.forEach { rssSource -> if (is18Plus(rssSource.sourceUrl)) { handler.post { - App.INSTANCE.toast("${rssSource.sourceName}是18+网址,禁止导入.") + appCtx.toastOnUi("${rssSource.sourceName}是18+网址,禁止导入.") } } else { - App.db.rssSourceDao.insert(rssSource) + appDb.rssSourceDao.insert(rssSource) } } } @@ -38,10 +39,10 @@ object SourceHelp { bookSources.forEach { bookSource -> if (is18Plus(bookSource.bookSourceUrl)) { handler.post { - App.INSTANCE.toast("${bookSource.bookSourceName}是18+网址,禁止导入.") + appCtx.toastOnUi("${bookSource.bookSourceName}是18+网址,禁止导入.") } } else { - App.db.bookSourceDao.insert(bookSource) + appDb.bookSourceDao.insert(bookSource) } } } 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 efaf72dc9..b7ecd3f03 100644 --- a/app/src/main/java/io/legado/app/help/ThemeConfig.kt +++ b/app/src/main/java/io/legado/app/help/ThemeConfig.kt @@ -5,24 +5,42 @@ import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import androidx.annotation.Keep -import io.legado.app.App +import androidx.appcompat.app.AppCompatDelegate import io.legado.app.R 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.utils.* +import splitties.init.appCtx import java.io.File object ThemeConfig { const val configFileName = "themeConfig.json" - val configFilePath = FileUtils.getPath(App.INSTANCE.filesDir, configFileName) + val configFilePath = FileUtils.getPath(appCtx.filesDir, configFileName) val configList: ArrayList by lazy { val cList = getConfigs() ?: DefaultData.themeConfigs ArrayList(cList) } + fun applyDayNight(context: Context) { + ReadBookConfig.upBg() + applyTheme(context) + initNightMode() + postEvent(EventBus.RECREATE, "") + } + + private fun initNightMode() { + val targetMode = + if (AppConfig.isNightTheme) { + AppCompatDelegate.MODE_NIGHT_YES + } else { + AppCompatDelegate.MODE_NIGHT_NO + } + AppCompatDelegate.setDefaultNightMode(targetMode) + } + fun getBgImage(context: Context): Drawable? { val bgPath = when (Theme.getTheme()) { Theme.Light -> context.getPrefString(PreferKey.bgImage) @@ -101,8 +119,7 @@ object ThemeConfig { context.putPrefInt(PreferKey.cBBackground, bBackground) } AppConfig.isNightTheme = config.isNightTheme - App.INSTANCE.applyDayNight() - postEvent(EventBus.RECREATE, "") + applyDayNight(context) } fun saveDayTheme(context: Context, name: String) { diff --git a/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt b/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt index 731e8ec9d..8bf30ba8d 100644 --- a/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt +++ b/app/src/main/java/io/legado/app/help/http/AjaxWebView.kt @@ -9,19 +9,15 @@ import android.webkit.CookieManager import android.webkit.WebSettings import android.webkit.WebView import android.webkit.WebViewClient -import io.legado.app.App import io.legado.app.constant.AppConst import org.apache.commons.text.StringEscapeUtils +import splitties.init.appCtx import java.lang.ref.WeakReference class AjaxWebView { var callback: Callback? = null - private var mHandler: AjaxHandler - - init { - mHandler = AjaxHandler(this) - } + private var mHandler: AjaxHandler = AjaxHandler(this) class AjaxHandler(private val ajaxWebView: AjaxWebView) : Handler(Looper.getMainLooper()) { @@ -51,7 +47,7 @@ class AjaxWebView { @SuppressLint("SetJavaScriptEnabled", "JavascriptInterface") fun createAjaxWebView(params: AjaxParams, handler: Handler): WebView { - val webView = WebView(App.INSTANCE) + val webView = WebView(appCtx) val settings = webView.settings settings.javaScriptEnabled = true settings.domStorageEnabled = true diff --git a/app/src/main/java/io/legado/app/help/http/CookieStore.kt b/app/src/main/java/io/legado/app/help/http/CookieStore.kt index 9aa344dbb..c8d516091 100644 --- a/app/src/main/java/io/legado/app/help/http/CookieStore.kt +++ b/app/src/main/java/io/legado/app/help/http/CookieStore.kt @@ -3,7 +3,7 @@ package io.legado.app.help.http import android.text.TextUtils -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.Cookie import io.legado.app.help.http.api.CookieManager import io.legado.app.utils.NetworkUtils @@ -12,7 +12,7 @@ object CookieStore : CookieManager { override fun setCookie(url: String, cookie: String?) { val cookieBean = Cookie(NetworkUtils.getSubDomain(url), cookie ?: "") - App.db.cookieDao.insert(cookieBean) + appDb.cookieDao.insert(cookieBean) } override fun replaceCookie(url: String, cookie: String) { @@ -31,12 +31,12 @@ object CookieStore : CookieManager { } override fun getCookie(url: String): String { - val cookieBean = App.db.cookieDao.get(NetworkUtils.getSubDomain(url)) + val cookieBean = appDb.cookieDao.get(NetworkUtils.getSubDomain(url)) return cookieBean?.cookie ?: "" } override fun removeCookie(url: String) { - App.db.cookieDao.delete(NetworkUtils.getSubDomain(url)) + appDb.cookieDao.delete(NetworkUtils.getSubDomain(url)) } override fun cookieToMap(cookie: String): MutableMap { @@ -77,7 +77,7 @@ object CookieStore : CookieManager { } fun clear() { - App.db.cookieDao.deleteOkHttp() + appDb.cookieDao.deleteOkHttp() } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt b/app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt index 04722997b..bd27e56e9 100644 --- a/app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt +++ b/app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt @@ -8,7 +8,7 @@ import android.view.KeyEvent import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import io.legado.app.R -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi class PermissionActivity : AppCompatActivity() { @@ -32,7 +32,7 @@ class PermissionActivity : AppCompatActivity() { settingIntent.data = Uri.fromParts("package", packageName, null) startActivityForResult(settingIntent, Request.TYPE_REQUEST_SETTING) } catch (e: Exception) { - toast(R.string.tip_cannot_jump_setting_page) + toastOnUi(R.string.tip_cannot_jump_setting_page) finish() } diff --git a/app/src/main/java/io/legado/app/help/permission/Request.kt b/app/src/main/java/io/legado/app/help/permission/Request.kt index f7ed0293a..7a26f521f 100644 --- a/app/src/main/java/io/legado/app/help/permission/Request.kt +++ b/app/src/main/java/io/legado/app/help/permission/Request.kt @@ -9,7 +9,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import io.legado.app.R -import org.jetbrains.anko.startActivity +import io.legado.app.utils.startActivity import java.util.* internal class Request : OnRequestPermissionsResultCallback { @@ -77,20 +77,26 @@ internal class Request : OnRequestPermissionsResultCallback { if (deniedPermissions == null) { onPermissionsGranted(requestCode) } else { - val rationale = if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale + val rationale = + if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale if (rationale != null) { - showSettingDialog(rationale) { onPermissionsDenied(requestCode, deniedPermissions) } + showSettingDialog(rationale) { + onPermissionsDenied( + requestCode, + deniedPermissions + ) + } } else { onPermissionsDenied(requestCode, deniedPermissions) } } } else { if (deniedPermissions != null) { - source?.context?.startActivity( - PermissionActivity.KEY_INPUT_REQUEST_TYPE to TYPE_REQUEST_PERMISSION, - PermissionActivity.KEY_INPUT_PERMISSIONS_CODE to requestCode, - PermissionActivity.KEY_INPUT_PERMISSIONS to deniedPermissions - ) + source?.context?.startActivity { + putExtra(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_PERMISSION) + putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode) + putExtra(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions) + } } else { onPermissionsGranted(requestCode) } @@ -132,9 +138,12 @@ internal class Request : OnRequestPermissionsResultCallback { .setTitle(R.string.dialog_title) .setMessage(rationale) .setPositiveButton(R.string.dialog_setting) { _, _ -> - it.startActivity( - PermissionActivity.KEY_INPUT_REQUEST_TYPE to TYPE_REQUEST_SETTING - ) + it.startActivity { + putExtra( + PermissionActivity.KEY_INPUT_REQUEST_TYPE, + TYPE_REQUEST_SETTING + ) + } } .setNegativeButton(R.string.dialog_cancel) { _, _ -> cancel() } .show() @@ -160,10 +169,15 @@ internal class Request : OnRequestPermissionsResultCallback { RequestPlugins.sResultCallback?.onPermissionsDenied(requestCode, deniedPermissions) } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { val deniedPermissions = getDeniedPermissions(permissions) if (deniedPermissions != null) { - val rationale = if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale + val rationale = + if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale if (rationale != null) { showSettingDialog(rationale) { onPermissionsDenied(requestCode, deniedPermissions) } } else { diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt index a26f5174f..abdb03cce 100644 --- a/app/src/main/java/io/legado/app/help/storage/Backup.kt +++ b/app/src/main/java/io/legado/app/help/storage/Backup.kt @@ -3,8 +3,8 @@ package io.legado.app.help.storage import android.content.Context import android.net.Uri import androidx.documentfile.provider.DocumentFile -import io.legado.app.App import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.help.DefaultData import io.legado.app.help.ReadBookConfig import io.legado.app.help.ThemeConfig @@ -12,7 +12,7 @@ import io.legado.app.help.coroutine.Coroutine import io.legado.app.utils.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.withContext -import org.jetbrains.anko.defaultSharedPreferences +import splitties.init.appCtx import java.io.File import java.util.concurrent.TimeUnit @@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit object Backup { val backupPath: String by lazy { - FileUtils.getFile(App.INSTANCE.filesDir, "backup").absolutePath + FileUtils.getFile(appCtx.filesDir, "backup").absolutePath } val backupFileNames by lazy { @@ -57,32 +57,33 @@ object Backup { context.putPrefLong(PreferKey.lastBackup, System.currentTimeMillis()) withContext(IO) { FileUtils.deleteFile(backupPath) - writeListToJson(App.db.bookDao.all, "bookshelf.json", backupPath) - writeListToJson(App.db.bookmarkDao.all, "bookmark.json", backupPath) - writeListToJson(App.db.bookGroupDao.all, "bookGroup.json", backupPath) - writeListToJson(App.db.bookSourceDao.all, "bookSource.json", backupPath) - writeListToJson(App.db.rssSourceDao.all, "rssSources.json", backupPath) - writeListToJson(App.db.rssStarDao.all, "rssStar.json", backupPath) - writeListToJson(App.db.replaceRuleDao.all, "replaceRule.json", backupPath) - writeListToJson(App.db.readRecordDao.all, "readRecord.json", backupPath) - writeListToJson(App.db.searchKeywordDao.all, "searchHistory.json", backupPath) - writeListToJson(App.db.ruleSubDao.all, "sourceSub.json", backupPath) - writeListToJson(App.db.txtTocRule.all, DefaultData.txtTocRuleFileName, backupPath) - writeListToJson(App.db.httpTTSDao.all, DefaultData.httpTtsFileName, backupPath) + writeListToJson(appDb.bookDao.all, "bookshelf.json", backupPath) + writeListToJson(appDb.bookmarkDao.all, "bookmark.json", backupPath) + writeListToJson(appDb.bookGroupDao.all, "bookGroup.json", backupPath) + writeListToJson(appDb.bookSourceDao.all, "bookSource.json", backupPath) + writeListToJson(appDb.rssSourceDao.all, "rssSources.json", backupPath) + writeListToJson(appDb.rssStarDao.all, "rssStar.json", backupPath) + writeListToJson(appDb.replaceRuleDao.all, "replaceRule.json", backupPath) + writeListToJson(appDb.readRecordDao.all, "readRecord.json", backupPath) + writeListToJson(appDb.searchKeywordDao.all, "searchHistory.json", backupPath) + writeListToJson(appDb.ruleSubDao.all, "sourceSub.json", backupPath) + writeListToJson(appDb.txtTocRule.all, DefaultData.txtTocRuleFileName, backupPath) + writeListToJson(appDb.httpTTSDao.all, DefaultData.httpTtsFileName, backupPath) GSON.toJson(ReadBookConfig.configList).let { FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.configFileName) .writeText(it) } GSON.toJson(ReadBookConfig.shareConfig).let { FileUtils.createFileIfNotExist(backupPath + File.separator + ReadBookConfig.shareConfigFileName) + .writeText(it) } GSON.toJson(ThemeConfig.configList).let { FileUtils.createFileIfNotExist(backupPath + File.separator + ThemeConfig.configFileName) .writeText(it) } - Preferences.getSharedPreferences(App.INSTANCE, backupPath, "config")?.let { sp -> + Preferences.getSharedPreferences(appCtx, backupPath, "config")?.let { sp -> val edit = sp.edit() - App.INSTANCE.defaultSharedPreferences.all.map { + appCtx.defaultSharedPreferences.all.map { when (val value = it.value) { is Int -> edit.putInt(it.key, value) is Boolean -> edit.putBoolean(it.key, value) diff --git a/app/src/main/java/io/legado/app/help/storage/BookWebDav.kt b/app/src/main/java/io/legado/app/help/storage/BookWebDav.kt index f3b7310b4..9a299512f 100644 --- a/app/src/main/java/io/legado/app/help/storage/BookWebDav.kt +++ b/app/src/main/java/io/legado/app/help/storage/BookWebDav.kt @@ -3,7 +3,6 @@ package io.legado.app.help.storage import android.content.Context import android.os.Handler import android.os.Looper -import io.legado.app.App import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.data.entities.Book @@ -16,7 +15,7 @@ import io.legado.app.utils.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.withContext -import org.jetbrains.anko.toast +import splitties.init.appCtx import java.io.File import java.text.SimpleDateFormat import java.util.* @@ -28,20 +27,20 @@ object BookWebDav { private val rootWebDavUrl: String get() { - var url = App.INSTANCE.getPrefString(PreferKey.webDavUrl) + var url = appCtx.getPrefString(PreferKey.webDavUrl) if (url.isNullOrEmpty()) { url = defaultWebDavUrl } if (!url.endsWith("/")) url = "${url}/" - if (App.INSTANCE.getPrefBoolean(PreferKey.webDavCreateDir, true)) { + if (appCtx.getPrefBoolean(PreferKey.webDavCreateDir, true)) { url = "${url}legado/" } return url } suspend fun initWebDav(): Boolean { - val account = App.INSTANCE.getPrefString(PreferKey.webDavAccount) - val password = App.INSTANCE.getPrefString(PreferKey.webDavPassword) + val account = appCtx.getPrefString(PreferKey.webDavAccount) + val password = appCtx.getPrefString(PreferKey.webDavPassword) if (!account.isNullOrBlank() && !password.isNullOrBlank()) { HttpAuth.auth = HttpAuth.Auth(account, password) WebDav(rootWebDavUrl).makeAsDir() @@ -80,7 +79,7 @@ object BookWebDav { Coroutine.async { restoreWebDav(names[index]) }.onError { - App.INSTANCE.toast("WebDavError:${it.localizedMessage}") + appCtx.toastOnUi("WebDavError:${it.localizedMessage}") } } } @@ -118,7 +117,7 @@ object BookWebDav { } } catch (e: Exception) { Handler(Looper.getMainLooper()).post { - App.INSTANCE.toast("WebDav\n${e.localizedMessage}") + appCtx.toastOnUi("WebDav\n${e.localizedMessage}") } } } @@ -139,7 +138,7 @@ object BookWebDav { } } catch (e: Exception) { Handler(Looper.getMainLooper()).post { - App.INSTANCE.toast("WebDav导出\n${e.localizedMessage}") + appCtx.toastOnUi("WebDav导出\n${e.localizedMessage}") } } } diff --git a/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt index 178f8369a..afaaa5e92 100644 --- a/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt +++ b/app/src/main/java/io/legado/app/help/storage/ImportOldData.kt @@ -3,12 +3,12 @@ package io.legado.app.help.storage import android.content.Context import android.net.Uri import androidx.documentfile.provider.DocumentFile -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.utils.DocumentUtils import io.legado.app.utils.FileUtils import io.legado.app.utils.isContentScheme -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi import java.io.File object ImportOldData { @@ -21,28 +21,28 @@ object ImportOldData { kotlin.runCatching { DocumentUtils.readText(context, doc.uri)?.let { json -> val importCount = importOldBookshelf(json) - context.toast("成功导入书籍${importCount}") + context.toastOnUi("成功导入书籍${importCount}") } }.onFailure { - context.toast("导入书籍失败\n${it.localizedMessage}") + context.toastOnUi("导入书籍失败\n${it.localizedMessage}") } "myBookSource.json" -> kotlin.runCatching { DocumentUtils.readText(context, doc.uri)?.let { json -> val importCount = importOldSource(json) - context.toast("成功导入书源${importCount}") + context.toastOnUi("成功导入书源${importCount}") } }.onFailure { - context.toast("导入源失败\n${it.localizedMessage}") + context.toastOnUi("导入源失败\n${it.localizedMessage}") } "myBookReplaceRule.json" -> kotlin.runCatching { DocumentUtils.readText(context, doc.uri)?.let { json -> val importCount = importOldReplaceRule(json) - context.toast("成功导入替换规则${importCount}") + context.toastOnUi("成功导入替换规则${importCount}") } }.onFailure { - context.toast("导入替换规则失败\n${it.localizedMessage}") + context.toastOnUi("导入替换规则失败\n${it.localizedMessage}") } } } @@ -54,9 +54,9 @@ object ImportOldData { FileUtils.createFileIfNotExist(file, "myBookShelf.json") val json = shelfFile.readText() val importCount = importOldBookshelf(json) - context.toast("成功导入书籍${importCount}") + context.toastOnUi("成功导入书籍${importCount}") }.onFailure { - context.toast("导入书籍失败\n${it.localizedMessage}") + context.toastOnUi("导入书籍失败\n${it.localizedMessage}") } kotlin.runCatching {// Book source @@ -64,9 +64,9 @@ object ImportOldData { FileUtils.getFile(file, "myBookSource.json") val json = sourceFile.readText() val importCount = importOldSource(json) - context.toast("成功导入书源${importCount}") + context.toastOnUi("成功导入书源${importCount}") }.onFailure { - context.toast("导入源失败\n${it.localizedMessage}") + context.toastOnUi("导入源失败\n${it.localizedMessage}") } kotlin.runCatching {// Replace rules @@ -74,12 +74,12 @@ object ImportOldData { if (ruleFile.exists()) { val json = ruleFile.readText() val importCount = importOldReplaceRule(json) - context.toast("成功导入替换规则${importCount}") + context.toastOnUi("成功导入替换规则${importCount}") } else { - context.toast("未找到替换规则") + context.toastOnUi("未找到替换规则") } }.onFailure { - context.toast("导入替换规则失败\n${it.localizedMessage}") + context.toastOnUi("导入替换规则失败\n${it.localizedMessage}") } } } @@ -87,7 +87,7 @@ object ImportOldData { private fun importOldBookshelf(json: String): Int { val books = OldBook.toNewBook(json) - App.db.bookDao.insert(*books.toTypedArray()) + appDb.bookDao.insert(*books.toTypedArray()) return books.size } @@ -100,13 +100,13 @@ object ImportOldData { bookSources.add(it) } } - App.db.bookSourceDao.insert(*bookSources.toTypedArray()) + appDb.bookSourceDao.insert(*bookSources.toTypedArray()) return bookSources.size } private fun importOldReplaceRule(json: String): Int { val rules = OldReplace.jsonToReplaceRules(json) - App.db.replaceRuleDao.insert(*rules.toTypedArray()) + appDb.replaceRuleDao.insert(*rules.toTypedArray()) return rules.size } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/storage/OldBook.kt b/app/src/main/java/io/legado/app/help/storage/OldBook.kt index b90bb2734..bc874d549 100644 --- a/app/src/main/java/io/legado/app/help/storage/OldBook.kt +++ b/app/src/main/java/io/legado/app/help/storage/OldBook.kt @@ -1,8 +1,8 @@ package io.legado.app.help.storage import android.util.Log -import io.legado.app.App import io.legado.app.constant.AppConst +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.utils.readBool import io.legado.app.utils.readInt @@ -14,7 +14,7 @@ object OldBook { fun toNewBook(json: String): List { val books = mutableListOf() val items: List> = Restore.jsonPath.parse(json).read("$") - val existingBooks = App.db.bookDao.allBookUrls.toSet() + val existingBooks = appDb.bookDao.allBookUrls.toSet() for (item in items) { val jsonItem = Restore.jsonPath.parse(item) val book = Book() 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 212152849..39ab91ba0 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 @@ -7,11 +7,12 @@ import com.jayway.jsonpath.Configuration import com.jayway.jsonpath.JsonPath import com.jayway.jsonpath.Option import com.jayway.jsonpath.ParseContext -import io.legado.app.App import io.legado.app.BuildConfig import io.legado.app.R import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.constant.androidId +import io.legado.app.data.appDb import io.legado.app.data.entities.* import io.legado.app.help.DefaultData import io.legado.app.help.LauncherIconHelp @@ -23,12 +24,11 @@ import io.legado.app.utils.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.withContext -import org.jetbrains.anko.defaultSharedPreferences -import org.jetbrains.anko.toast +import splitties.init.appCtx import java.io.File object Restore { - private val ignoreConfigPath = FileUtils.getPath(App.INSTANCE.filesDir, "restoreIgnore.json") + private val ignoreConfigPath = FileUtils.getPath(appCtx.filesDir, "restoreIgnore.json") val ignoreConfig: HashMap by lazy { val file = FileUtils.createFileIfNotExist(ignoreConfigPath) val json = file.readText() @@ -46,11 +46,11 @@ object Restore { //忽略标题 val ignoreTitle = arrayOf( - App.INSTANCE.getString(R.string.read_config), - App.INSTANCE.getString(R.string.theme_mode), - App.INSTANCE.getString(R.string.bookshelf_layout), - App.INSTANCE.getString(R.string.show_rss), - App.INSTANCE.getString(R.string.thread_count) + appCtx.getString(R.string.read_config), + appCtx.getString(R.string.theme_mode), + appCtx.getString(R.string.bookshelf_layout), + appCtx.getString(R.string.show_rss), + appCtx.getString(R.string.thread_count) ) //默认忽略keys @@ -111,48 +111,48 @@ object Restore { suspend fun restoreDatabase(path: String = Backup.backupPath) { withContext(IO) { fileToListT(path, "bookshelf.json")?.let { - App.db.bookDao.insert(*it.toTypedArray()) + appDb.bookDao.insert(*it.toTypedArray()) } fileToListT(path, "bookmark.json")?.let { - App.db.bookmarkDao.insert(*it.toTypedArray()) + appDb.bookmarkDao.insert(*it.toTypedArray()) } fileToListT(path, "bookGroup.json")?.let { - App.db.bookGroupDao.insert(*it.toTypedArray()) + appDb.bookGroupDao.insert(*it.toTypedArray()) } fileToListT(path, "bookSource.json")?.let { - App.db.bookSourceDao.insert(*it.toTypedArray()) + appDb.bookSourceDao.insert(*it.toTypedArray()) } fileToListT(path, "rssSources.json")?.let { - App.db.rssSourceDao.insert(*it.toTypedArray()) + appDb.rssSourceDao.insert(*it.toTypedArray()) } fileToListT(path, "rssStar.json")?.let { - App.db.rssStarDao.insert(*it.toTypedArray()) + appDb.rssStarDao.insert(*it.toTypedArray()) } fileToListT(path, "replaceRule.json")?.let { - App.db.replaceRuleDao.insert(*it.toTypedArray()) + appDb.replaceRuleDao.insert(*it.toTypedArray()) } fileToListT(path, "searchHistory.json")?.let { - App.db.searchKeywordDao.insert(*it.toTypedArray()) + appDb.searchKeywordDao.insert(*it.toTypedArray()) } fileToListT(path, "sourceSub.json")?.let { - App.db.ruleSubDao.insert(*it.toTypedArray()) + appDb.ruleSubDao.insert(*it.toTypedArray()) } fileToListT(path, DefaultData.txtTocRuleFileName)?.let { - App.db.txtTocRule.insert(*it.toTypedArray()) + appDb.txtTocRule.insert(*it.toTypedArray()) } fileToListT(path, DefaultData.httpTtsFileName)?.let { - App.db.httpTTSDao.insert(*it.toTypedArray()) + appDb.httpTTSDao.insert(*it.toTypedArray()) } fileToListT(path, "readRecord.json")?.let { it.forEach { readRecord -> //判断是不是本机记录 - if (readRecord.androidId != App.androidId) { - App.db.readRecordDao.insert(readRecord) + if (readRecord.androidId != androidId) { + appDb.readRecordDao.insert(readRecord) } else { - val time = App.db.readRecordDao + val time = appDb.readRecordDao .getReadTime(readRecord.androidId, readRecord.bookName) if (time == null || time < readRecord.readTime) { - App.db.readRecordDao.insert(readRecord) + appDb.readRecordDao.insert(readRecord) } } } @@ -197,8 +197,8 @@ object Restore { e.printStackTrace() } } - Preferences.getSharedPreferences(App.INSTANCE, path, "config")?.all?.let { map -> - val edit = App.INSTANCE.defaultSharedPreferences.edit() + Preferences.getSharedPreferences(appCtx, path, "config")?.all?.let { map -> + val edit = appCtx.defaultSharedPreferences.edit() map.forEach { if (keyIsNotIgnore(it.key)) { when (val value = it.value) { @@ -214,22 +214,22 @@ object Restore { edit.apply() } ReadBookConfig.apply { - styleSelect = App.INSTANCE.getPrefInt(PreferKey.readStyleSelect) - shareLayout = App.INSTANCE.getPrefBoolean(PreferKey.shareLayout) - hideStatusBar = App.INSTANCE.getPrefBoolean(PreferKey.hideStatusBar) - hideNavigationBar = App.INSTANCE.getPrefBoolean(PreferKey.hideNavigationBar) - autoReadSpeed = App.INSTANCE.getPrefInt(PreferKey.autoReadSpeed, 46) + styleSelect = appCtx.getPrefInt(PreferKey.readStyleSelect) + shareLayout = appCtx.getPrefBoolean(PreferKey.shareLayout) + hideStatusBar = appCtx.getPrefBoolean(PreferKey.hideStatusBar) + hideNavigationBar = appCtx.getPrefBoolean(PreferKey.hideNavigationBar) + autoReadSpeed = appCtx.getPrefInt(PreferKey.autoReadSpeed, 46) } ChapterProvider.upStyle() ReadBook.loadContent(resetPageOffset = false) } withContext(Main) { - App.INSTANCE.toast(R.string.restore_success) + appCtx.toastOnUi(R.string.restore_success) if (!BuildConfig.DEBUG) { - LauncherIconHelp.changeIcon(App.INSTANCE.getPrefString(PreferKey.launcherIcon)) + LauncherIconHelp.changeIcon(appCtx.getPrefString(PreferKey.launcherIcon)) } - LanguageUtils.setConfiguration(App.INSTANCE) - App.INSTANCE.applyDayNight() + LanguageUtils.setConfiguration(appCtx) + ThemeConfig.applyDayNight(appCtx) postEvent(EventBus.SHOW_RSS, "") } } diff --git a/app/src/main/java/io/legado/app/lib/dialogs/AlertBuilder.kt b/app/src/main/java/io/legado/app/lib/dialogs/AlertBuilder.kt index 6a245e5fb..5dab676bb 100644 --- a/app/src/main/java/io/legado/app/lib/dialogs/AlertBuilder.kt +++ b/app/src/main/java/io/legado/app/lib/dialogs/AlertBuilder.kt @@ -11,40 +11,28 @@ import android.view.View import androidx.annotation.DrawableRes import androidx.annotation.StringRes import io.legado.app.R -import org.jetbrains.anko.internals.AnkoInternals.NO_GETTER -import kotlin.DeprecationLevel.ERROR @SuppressLint("SupportAnnotationUsage") interface AlertBuilder { val ctx: Context - var title: CharSequence - @Deprecated(NO_GETTER, level = ERROR) get + fun setTitle(title: CharSequence) - var titleResource: Int - @Deprecated(NO_GETTER, level = ERROR) get + fun setTitle(titleResource: Int) - var message: CharSequence - @Deprecated(NO_GETTER, level = ERROR) get + fun setMessage(message: CharSequence) - var messageResource: Int - @Deprecated(NO_GETTER, level = ERROR) get + fun setMessage(messageResource: Int) - var icon: Drawable - @Deprecated(NO_GETTER, level = ERROR) get + fun setIcon(icon: Drawable) - @setparam:DrawableRes - var iconResource: Int - @Deprecated(NO_GETTER, level = ERROR) get + fun setIcon(@DrawableRes iconResource: Int) - var customTitle: View - @Deprecated(NO_GETTER, level = ERROR) get + fun setCustomTitle(customTitle: View) - var customView: View - @Deprecated(NO_GETTER, level = ERROR) get + fun setCustomView(customView: View) - var isCancelable: Boolean - @Deprecated(NO_GETTER, level = ERROR) get + fun setCancelable(isCancelable: Boolean) fun positiveButton(buttonText: String, onClicked: ((dialog: DialogInterface) -> Unit)? = null) fun positiveButton( @@ -97,11 +85,11 @@ interface AlertBuilder { fun customTitle(view: () -> View) { - customTitle = view() + setCustomTitle(view()) } fun customView(view: () -> View) { - customView = view() + setCustomView(view()) } fun okButton(handler: ((dialog: DialogInterface) -> Unit)? = null) = diff --git a/app/src/main/java/io/legado/app/lib/dialogs/AndroidAlertBuilder.kt b/app/src/main/java/io/legado/app/lib/dialogs/AndroidAlertBuilder.kt index cf53eac12..47cb3432b 100644 --- a/app/src/main/java/io/legado/app/lib/dialogs/AndroidAlertBuilder.kt +++ b/app/src/main/java/io/legado/app/lib/dialogs/AndroidAlertBuilder.kt @@ -7,48 +7,45 @@ import android.view.KeyEvent import android.view.View import androidx.appcompat.app.AlertDialog import io.legado.app.utils.applyTint -import org.jetbrains.anko.internals.AnkoInternals -import org.jetbrains.anko.internals.AnkoInternals.NO_GETTER -import kotlin.DeprecationLevel.ERROR internal class AndroidAlertBuilder(override val ctx: Context) : AlertBuilder { private val builder = AlertDialog.Builder(ctx) - override var title: CharSequence - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setTitle(value) } + override fun setTitle(title: CharSequence) { + builder.setTitle(title) + } - override var titleResource: Int - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setTitle(value) } + override fun setTitle(titleResource: Int) { + builder.setTitle(titleResource) + } - override var message: CharSequence - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setMessage(value) } + override fun setMessage(message: CharSequence) { + builder.setMessage(message) + } - override var messageResource: Int - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setMessage(value) } + override fun setMessage(messageResource: Int) { + builder.setMessage(messageResource) + } - override var icon: Drawable - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setIcon(value) } + override fun setIcon(icon: Drawable) { + builder.setIcon(icon) + } - override var iconResource: Int - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setIcon(value) } + override fun setIcon(iconResource: Int) { + builder.setIcon(iconResource) + } - override var customTitle: View - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setCustomTitle(value) } + override fun setCustomTitle(customTitle: View) { + builder.setCustomTitle(customTitle) + } - override var customView: View - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setView(value) } + override fun setCustomView(customView: View) { + builder.setView(customView) + } - override var isCancelable: Boolean - @Deprecated(NO_GETTER, level = ERROR) get() = AnkoInternals.noGetter() - set(value) { builder.setCancelable(value) } + override fun setCancelable(isCancelable: Boolean) { + builder.setCancelable(isCancelable) + } override fun onCancelled(handler: (DialogInterface) -> Unit) { builder.setOnCancelListener(handler) @@ -58,7 +55,10 @@ internal class AndroidAlertBuilder(override val ctx: Context) : AlertBuilder Unit)?) { + override fun positiveButton( + buttonText: String, + onClicked: ((dialog: DialogInterface) -> Unit)? + ) { builder.setPositiveButton(buttonText) { dialog, _ -> onClicked?.invoke(dialog) } } diff --git a/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt b/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt index 233bbfe7d..d99ec1e7b 100644 --- a/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt +++ b/app/src/main/java/io/legado/app/lib/dialogs/AndroidDialogs.kt @@ -7,7 +7,6 @@ import android.content.Context import android.content.DialogInterface import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment -import org.jetbrains.anko.AnkoContext inline fun Fragment.alert( title: CharSequence? = null, @@ -22,10 +21,10 @@ fun Context.alert( ): AlertBuilder { return AndroidAlertBuilder(this).apply { if (title != null) { - this.title = title + this.setTitle(title) } if (message != null) { - this.message = message + this.setMessage(message) } if (init != null) init() } @@ -44,17 +43,16 @@ fun Context.alert( ): AlertBuilder { return AndroidAlertBuilder(this).apply { if (titleResource != null) { - this.titleResource = titleResource + this.setTitle(titleResource) } if (messageResource != null) { - this.messageResource = messageResource + this.setMessage(messageResource) } if (init != null) init() } } -inline fun AnkoContext<*>.alert(noinline init: AlertBuilder.() -> Unit) = ctx.alert(init) inline fun Fragment.alert(noinline init: AlertBuilder.() -> Unit) = requireContext().alert(init) fun Context.alert(init: AlertBuilder.() -> Unit): AlertBuilder = diff --git a/app/src/main/java/io/legado/app/lib/dialogs/AndroidSelectors.kt b/app/src/main/java/io/legado/app/lib/dialogs/AndroidSelectors.kt index fd6570240..6033879de 100644 --- a/app/src/main/java/io/legado/app/lib/dialogs/AndroidSelectors.kt +++ b/app/src/main/java/io/legado/app/lib/dialogs/AndroidSelectors.kt @@ -35,7 +35,7 @@ fun Context.selector( ) { with(AndroidAlertBuilder(this)) { if (title != null) { - this.title = title + this.setTitle(title) } items(items, onClick) show() @@ -49,7 +49,7 @@ fun Context.selector( ) { with(AndroidAlertBuilder(this)) { if (titleSource != null) { - this.title = getString(titleSource) + this.setTitle(titleSource) } items(items, onClick) show() diff --git a/app/src/main/java/io/legado/app/lib/dialogs/Dialogs.kt b/app/src/main/java/io/legado/app/lib/dialogs/Dialogs.kt index fb3729465..0abcc36c0 100644 --- a/app/src/main/java/io/legado/app/lib/dialogs/Dialogs.kt +++ b/app/src/main/java/io/legado/app/lib/dialogs/Dialogs.kt @@ -23,10 +23,10 @@ fun Context.alert( ): AlertBuilder { return factory(this).apply { if (title != null) { - this.title = title + this.setTitle(title) } if (message != null) { - this.message = message + this.setMessage(message) } if (init != null) init() } @@ -47,10 +47,10 @@ fun Context.alert( ): AlertBuilder { return factory(this).apply { if (titleResource != null) { - this.titleResource = titleResource + this.setTitle(titleResource) } if (messageResource != null) { - this.messageResource = messageResource + this.setMessage(messageResource) } if (init != null) init() } diff --git a/app/src/main/java/io/legado/app/lib/dialogs/Selectors.kt b/app/src/main/java/io/legado/app/lib/dialogs/Selectors.kt index 87a35cf76..c74535955 100644 --- a/app/src/main/java/io/legado/app/lib/dialogs/Selectors.kt +++ b/app/src/main/java/io/legado/app/lib/dialogs/Selectors.kt @@ -21,7 +21,7 @@ fun Context.selector( ) { with(factory(this)) { if (title != null) { - this.title = title + this.setTitle(title) } items(items, onClick) show() diff --git a/app/src/main/java/io/legado/app/lib/theme/ATH.kt b/app/src/main/java/io/legado/app/lib/theme/ATH.kt index f5274d09a..cbe1c2ebb 100644 --- a/app/src/main/java/io/legado/app/lib/theme/ATH.kt +++ b/app/src/main/java/io/legado/app/lib/theme/ATH.kt @@ -18,14 +18,12 @@ import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.RecyclerView import androidx.viewpager.widget.ViewPager import com.google.android.material.bottomnavigation.BottomNavigationView -import io.legado.app.App import io.legado.app.R import io.legado.app.help.AppConfig import io.legado.app.utils.ColorUtils import io.legado.app.utils.dp import io.legado.app.utils.getCompatColor -import org.jetbrains.anko.backgroundColor - +import splitties.init.appCtx /** * @author Karim Abou Zeid (kabouzeid) @@ -272,7 +270,7 @@ object ATH { fun applyBackgroundTint(view: View?) { view?.apply { if (background == null) { - backgroundColor = context.backgroundColor + setBackgroundColor(context.backgroundColor) } else { setBackgroundTint(this, context.backgroundColor) } @@ -290,7 +288,7 @@ object ATH { fun getDialogBackground(): GradientDrawable { val background = GradientDrawable() background.cornerRadius = 3F.dp - background.setColor(App.INSTANCE.backgroundColor) + background.setColor(appCtx.backgroundColor) return background } diff --git a/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt b/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt index 182db2d40..ab88e798f 100644 --- a/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt +++ b/app/src/main/java/io/legado/app/lib/theme/ThemeStore.kt @@ -9,9 +9,9 @@ import androidx.annotation.CheckResult import androidx.annotation.ColorInt import androidx.annotation.ColorRes import androidx.core.content.ContextCompat -import io.legado.app.App import io.legado.app.R import io.legado.app.utils.ColorUtils +import splitties.init.appCtx /** * @author Aidan Follestad (afollestad), Karim Abou Zeid (kabouzeid) @@ -200,7 +200,7 @@ private constructor(private val mContext: Context) : ThemeStoreInterface { @CheckResult @ColorInt - fun primaryColor(context: Context = App.INSTANCE): Int { + fun primaryColor(context: Context = appCtx): Int { return prefs(context).getInt( ThemeStorePrefKeys.KEY_PRIMARY_COLOR, ATHUtils.resolveColor(context, R.attr.colorPrimary, Color.parseColor("#455A64")) @@ -218,7 +218,7 @@ private constructor(private val mContext: Context) : ThemeStoreInterface { @CheckResult @ColorInt - fun accentColor(context: Context = App.INSTANCE): Int { + fun accentColor(context: Context = appCtx): Int { return prefs(context).getInt( ThemeStorePrefKeys.KEY_ACCENT_COLOR, ATHUtils.resolveColor(context, R.attr.colorAccent, Color.parseColor("#263238")) @@ -292,7 +292,7 @@ private constructor(private val mContext: Context) : ThemeStoreInterface { @CheckResult @ColorInt - fun backgroundColor(context: Context = App.INSTANCE): Int { + fun backgroundColor(context: Context = appCtx): Int { return prefs(context).getInt( ThemeStorePrefKeys.KEY_BACKGROUND_COLOR, ATHUtils.resolveColor(context, android.R.attr.colorBackground) @@ -314,7 +314,7 @@ private constructor(private val mContext: Context) : ThemeStoreInterface { @CheckResult @ColorInt - fun bottomBackground(context: Context = App.INSTANCE): Int { + fun bottomBackground(context: Context = appCtx): Int { return prefs(context).getInt( ThemeStorePrefKeys.KEY_BOTTOM_BACKGROUND, ATHUtils.resolveColor(context, android.R.attr.colorBackground) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.java b/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.java new file mode 100644 index 000000000..72b614f97 --- /dev/null +++ b/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.java @@ -0,0 +1,600 @@ +package io.legado.app.model.analyzeRule; + +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class QueryTTF { + private static class Header { + public int majorVersion; + public int minorVersion; + public int numOfTables; + public int searchRange; + public int entrySelector; + public int rangeShift; + } + + private static class Directory { + public String tag; // table name + public int checkSum; // Check sum + public int offset; // Offset from beginning of file + public int length; // length of the table in bytes + } + + private static class NameLayout { + public int format; + public int count; + public int stringOffset; + public List records = new LinkedList<>(); + } + + private static class NameRecord { + public int platformID; // 平台标识符<0:Unicode, 1:Mac, 2:ISO, 3:Windows, 4:Custom> + public int encodingID; // 编码标识符 + public int languageID; // 语言标识符 + public int nameID; // 名称标识符 + public int length; // 名称字符串的长度 + public int offset; // 名称字符串相对于stringOffset的字节偏移量 + } + + private static class HeadLayout { + public int majorVersion; + public int minorVersion; + public int fontRevision; + public int checkSumAdjustment; + public int magicNumber; + public int flags; + public int unitsPerEm; + public long created; + public long modified; + public short xMin; + public short yMin; + public short xMax; + public short yMax; + public int macStyle; + public int lowestRecPPEM; + public short fontDirectionHint; + public short indexToLocFormat; // <0:loca是2字节数组, 1:loca是4字节数组> + public short glyphDataFormat; + } + + private static class MaxpLayout { + public int majorVersion; + public int minorVersion; + public int numGlyphs; // 字体中的字形数量 + public int maxPoints; + public int maxContours; + public int maxCompositePoints; + public int maxCompositeContours; + public int maxZones; + public int maxTwilightPoints; + public int maxStorage; + public int maxFunctionDefs; + public int maxInstructionDefs; + public int maxStackElements; + public int maxSizeOfInstructions; + public int maxComponentElements; + public int maxComponentDepth; + } + + private class CmapLayout { + public int version; + public int numTables; + public List records = new LinkedList<>(); + public Map tables = new HashMap<>(); + } + + private static class CmapRecord { + public int platformID; + public int encodingID; + public int offset; + } + + private static class CmapFormat { + public int format; + public int length; + public int language; + public byte[] glyphIdArray; + } + + private static class CmapFormat4 extends CmapFormat { + public int segCountX2; + public int searchRange; + public int entrySelector; + public int rangeShift; + public int[] endCode; + public int reservedPad; + public int[] startCode; + public short[] idDelta; + public int[] idRangeOffset; + public int[] glyphIdArray; + } + + private static class CmapFormat6 extends CmapFormat { + public int firstCode; + public int entryCount; + public int[] glyphIdArray; + } + + private static class CmapFormat12 extends CmapFormat { + public int reserved; + public int length; + public int language; + public int numGroups; + public List> groups; + } + + private static class GlyfLayout { + public short numberOfContours; // 非负值为简单字型,负值为符合字型 + public short xMin; + public short yMin; + public short xMax; + public short yMax; + public int[] endPtsOfContours; // length=numberOfContours + public int instructionLength; + public byte[] instructions; // length=instructionLength + public byte[] flags; + public short[] xCoordinates; // length = flags.length + public short[] yCoordinates; // length = flags.length + } + + private static class ByteArrayReader { + public int Index; + public byte[] Buffer; + + public ByteArrayReader(byte[] buffer, int index) { + Buffer = buffer; + Index = index; + } + + public long ReadUIntX(long len) { + long result = 0; + for (long i = 0; i < len; ++i) { + result <<= 8; + result |= Buffer[Index++] & 0xFF; + } + return result; + } + + public long ReadUInt64() { + return ReadUIntX(8); + } + + public int ReadUInt32() { + return (int) ReadUIntX(4); + } + + public int ReadUInt16() { + return (int) ReadUIntX(2); + } + + public short ReadInt16() { + return (short) ReadUIntX(2); + } + + public short ReadUInt8() { + return (short) ReadUIntX(1); + } + + + public String ReadStrings(int len, Charset charset) { + byte[] result = len > 0 ? new byte[len] : null; + for (int i = 0; i < len; ++i) result[i] = Buffer[Index++]; + return new String(result, charset); + } + + public byte GetByte() { + return Buffer[Index++]; + } + + public byte[] GetBytes(int len) { + byte[] result = len > 0 ? new byte[len] : null; + for (int i = 0; i < len; ++i) result[i] = Buffer[Index++]; + return result; + } + + public int[] GetUInt16Array(int len) { + int[] result = len > 0 ? new int[len] : null; + for (int i = 0; i < len; ++i) result[i] = ReadUInt16(); + return result; + } + + public short[] GetInt16Array(int len) { + short[] result = len > 0 ? new short[len] : null; + for (int i = 0; i < len; ++i) result[i] = ReadInt16(); + return result; + } + } + + private final ByteArrayReader FontReader; + private final Header fileHeader = new Header(); + private final List Directorys = new LinkedList<>(); + private final NameLayout Name = new NameLayout(); + private final HeadLayout head = new HeadLayout(); + private final MaxpLayout maxp = new MaxpLayout(); + private final List loca = new LinkedList<>(); + private final CmapLayout Cmap = new CmapLayout(); + private final List glyf = new LinkedList<>(); + private final Pair[] pps = new Pair[]{ + Pair.of(3, 10), + Pair.of(0, 4), + Pair.of(3, 1), + Pair.of(1, 0), + Pair.of(0, 3), + Pair.of(0, 1) + }; + + public final Map CodeToGlyph = new HashMap<>(); + public final Map GlyphToCode = new HashMap<>(); + private int LimitMix = 0; + private int LimitMax = 0; + + /** + * 构造函数 + * + * @param buffer 传入TTF字体二进制数组 + */ + public QueryTTF(byte[] buffer) { + FontReader = new ByteArrayReader(buffer, 0); + // 获取文件头 + fileHeader.majorVersion = FontReader.ReadUInt16(); + fileHeader.minorVersion = FontReader.ReadUInt16(); + fileHeader.numOfTables = FontReader.ReadUInt16(); + fileHeader.searchRange = FontReader.ReadUInt16(); + fileHeader.entrySelector = FontReader.ReadUInt16(); + fileHeader.rangeShift = FontReader.ReadUInt16(); + // 获取目录 + for (int i = 0; i < fileHeader.numOfTables; ++i) { + Directory d = new Directory(); + d.tag = FontReader.ReadStrings(4, StandardCharsets.US_ASCII); + d.checkSum = FontReader.ReadUInt32(); + d.offset = FontReader.ReadUInt32(); + d.length = FontReader.ReadUInt32(); + Directorys.add(d); + } + // 解析表 name (字体信息,包含版权、名称、作者等...) + for (Directory Temp : Directorys) { + if (Temp.tag.equals("name")) { + FontReader.Index = Temp.offset; + Name.format = FontReader.ReadUInt16(); + Name.count = FontReader.ReadUInt16(); + Name.stringOffset = FontReader.ReadUInt16(); + for (int i = 0; i < Name.count; ++i) { + NameRecord record = new NameRecord(); + record.platformID = FontReader.ReadUInt16(); + record.encodingID = FontReader.ReadUInt16(); + record.languageID = FontReader.ReadUInt16(); + record.nameID = FontReader.ReadUInt16(); + record.length = FontReader.ReadUInt16(); + record.offset = FontReader.ReadUInt16(); + Name.records.add(record); + } + } + } + // 解析表 head (获取 head.indexToLocFormat) + for (Directory Temp : Directorys) { + if (Temp.tag.equals("head")) { + FontReader.Index = Temp.offset; + head.majorVersion = FontReader.ReadUInt16(); + head.minorVersion = FontReader.ReadUInt16(); + head.fontRevision = FontReader.ReadUInt32(); + head.checkSumAdjustment = FontReader.ReadUInt32(); + head.magicNumber = FontReader.ReadUInt32(); + head.flags = FontReader.ReadUInt16(); + head.unitsPerEm = FontReader.ReadUInt16(); + head.created = FontReader.ReadUInt64(); + head.modified = FontReader.ReadUInt64(); + head.xMin = FontReader.ReadInt16(); + head.yMin = FontReader.ReadInt16(); + head.xMax = FontReader.ReadInt16(); + head.yMax = FontReader.ReadInt16(); + head.macStyle = FontReader.ReadUInt16(); + head.lowestRecPPEM = FontReader.ReadUInt16(); + head.fontDirectionHint = FontReader.ReadInt16(); + head.indexToLocFormat = FontReader.ReadInt16(); + head.glyphDataFormat = FontReader.ReadInt16(); + } + } + // 解析表 maxp (获取 maxp.numGlyphs) + for (Directory Temp : Directorys) { + if (Temp.tag.equals("maxp")) { + FontReader.Index = Temp.offset; + maxp.majorVersion = FontReader.ReadUInt16(); + maxp.minorVersion = FontReader.ReadUInt16(); + maxp.numGlyphs = FontReader.ReadUInt16(); + maxp.maxPoints = FontReader.ReadUInt16(); + maxp.maxContours = FontReader.ReadUInt16(); + maxp.maxCompositePoints = FontReader.ReadUInt16(); + maxp.maxCompositeContours = FontReader.ReadUInt16(); + maxp.maxZones = FontReader.ReadUInt16(); + maxp.maxTwilightPoints = FontReader.ReadUInt16(); + maxp.maxStorage = FontReader.ReadUInt16(); + maxp.maxFunctionDefs = FontReader.ReadUInt16(); + maxp.maxInstructionDefs = FontReader.ReadUInt16(); + maxp.maxStackElements = FontReader.ReadUInt16(); + maxp.maxSizeOfInstructions = FontReader.ReadUInt16(); + maxp.maxComponentElements = FontReader.ReadUInt16(); + maxp.maxComponentDepth = FontReader.ReadUInt16(); + } + } + // 解析表 loca (轮廓数据偏移地址表) + for (Directory Temp : Directorys) { + if (Temp.tag.equals("loca")) { + FontReader.Index = Temp.offset; + int offset = head.indexToLocFormat == 0 ? 2 : 4; + for (long i = 0; i < Temp.length; i += offset) { + loca.add(offset == 2 ? FontReader.ReadUInt16() << 1 : FontReader.ReadUInt32()); + } + } + } + // 解析表 cmap (Unicode编码轮廓索引对照表) + for (Directory Temp : Directorys) { + if (Temp.tag.equals("cmap")) { + FontReader.Index = Temp.offset; + Cmap.version = FontReader.ReadUInt16(); + Cmap.numTables = FontReader.ReadUInt16(); + + for (int i = 0; i < Cmap.numTables; ++i) { + CmapRecord record = new CmapRecord(); + record.platformID = FontReader.ReadUInt16(); + record.encodingID = FontReader.ReadUInt16(); + record.offset = FontReader.ReadUInt32(); + Cmap.records.add(record); + } + for (int i = 0; i < Cmap.numTables; ++i) { + int fmtOffset = Cmap.records.get(i).offset; + FontReader.Index = Temp.offset + fmtOffset; + int EndIndex = FontReader.Index; + + int format = FontReader.ReadUInt16(); + if (Cmap.tables.containsKey(fmtOffset)) continue; + if (format == 0) { + CmapFormat f = new CmapFormat(); + f.format = format; + f.length = FontReader.ReadUInt16(); + f.language = FontReader.ReadUInt16(); + f.glyphIdArray = FontReader.GetBytes(f.length - 6); + Cmap.tables.put(fmtOffset, f); + } else if (format == 4) { + CmapFormat4 f = new CmapFormat4(); + f.format = format; + f.length = FontReader.ReadUInt16(); + f.language = FontReader.ReadUInt16(); + f.segCountX2 = FontReader.ReadUInt16(); + int segCount = f.segCountX2 >> 1; + f.searchRange = FontReader.ReadUInt16(); + f.entrySelector = FontReader.ReadUInt16(); + f.rangeShift = FontReader.ReadUInt16(); + f.endCode = FontReader.GetUInt16Array(segCount); + f.reservedPad = FontReader.ReadUInt16(); + f.startCode = FontReader.GetUInt16Array(segCount); + f.idDelta = FontReader.GetInt16Array(segCount); + f.idRangeOffset = FontReader.GetUInt16Array(segCount); + f.glyphIdArray = FontReader.GetUInt16Array((EndIndex + f.length - FontReader.Index) >> 1); + Cmap.tables.put(fmtOffset, f); + } else if (format == 6) { + CmapFormat6 f = new CmapFormat6(); + f.format = format; + f.length = FontReader.ReadUInt16(); + f.language = FontReader.ReadUInt16(); + f.firstCode = FontReader.ReadUInt16(); + f.entryCount = FontReader.ReadUInt16(); + f.glyphIdArray = FontReader.GetUInt16Array(f.entryCount); + Cmap.tables.put(fmtOffset, f); + } else if (format == 12) { + CmapFormat12 f = new CmapFormat12(); + f.format = format; + f.reserved = FontReader.ReadUInt16(); + f.length = FontReader.ReadUInt32(); + f.language = FontReader.ReadUInt32(); + f.numGroups = FontReader.ReadUInt32(); + f.groups = new ArrayList<>(f.numGroups); + for (int n = 0; n < f.numGroups; ++n) { + f.groups.add(Triple.of(FontReader.ReadUInt32(), FontReader.ReadUInt32(), FontReader.ReadUInt32())); + } + Cmap.tables.put(fmtOffset, f); + } + } + } + } + // 解析表 glyf (字体轮廓数据表) + for (Directory Temp : Directorys) { + if (Temp.tag.equals("glyf")) { + FontReader.Index = Temp.offset; + for (int i = 0; i < maxp.numGlyphs; ++i) { + FontReader.Index = Temp.offset + loca.get(i); + + short numberOfContours = FontReader.ReadInt16(); + if (numberOfContours > 0) { + GlyfLayout g = new GlyfLayout(); + g.numberOfContours = numberOfContours; + g.xMin = FontReader.ReadInt16(); + g.yMin = FontReader.ReadInt16(); + g.xMax = FontReader.ReadInt16(); + g.yMax = FontReader.ReadInt16(); + g.endPtsOfContours = FontReader.GetUInt16Array(numberOfContours); + g.instructionLength = FontReader.ReadUInt16(); + g.instructions = FontReader.GetBytes(g.instructionLength); + int flagLength = g.endPtsOfContours[g.endPtsOfContours.length - 1] + 1; + // 获取轮廓点描述标志 + g.flags = new byte[flagLength]; + for (int n = 0; n < flagLength; ++n) { + g.flags[n] = FontReader.GetByte(); + if ((g.flags[n] & 0x08) != 0x00) { + for (int m = FontReader.ReadUInt8(); m > 0; --m) { + g.flags[++n] = g.flags[n - 1]; + } + } + } + // 获取轮廓点描述x轴相对值 + g.xCoordinates = new short[flagLength]; + for (int n = 0; n < flagLength; ++n) { + short same = (short) ((g.flags[n] & 0x10) != 0 ? 1 : -1); + if ((g.flags[n] & 0x02) != 0) { + g.xCoordinates[n] = (short) (same * FontReader.ReadUInt8()); + } else { + g.xCoordinates[n] = same == 1 ? (short) 0 : FontReader.ReadInt16(); + } + } + // 获取轮廓点描述y轴相对值 + g.yCoordinates = new short[flagLength]; + for (int n = 0; n < flagLength; ++n) { + short same = (short) ((g.flags[n] & 0x20) != 0 ? 1 : -1); + if ((g.flags[n] & 0x04) != 0) { + g.yCoordinates[n] = (short) (same * FontReader.ReadUInt8()); + } else { + g.yCoordinates[n] = same == 1 ? (short) 0 : FontReader.ReadInt16(); + } + } + // 相对坐标转绝对坐标 +// for (int n = 1; n < flagLength; ++n) { +// xCoordinates[n] += xCoordinates[n - 1]; +// yCoordinates[n] += yCoordinates[n - 1]; +// } + + glyf.add(g); + } else { + // 复合字体暂未使用 + } + } + } + } + + // 建立Unicode&Glyph双向表 + for (int key = 0; key < 130000; ++key) { + if (key == 0xFF) key = 0x3400; + int gid = getGlyfIndex(key); + if (gid == 0) continue; + StringBuilder sb = new StringBuilder(); + // 字型数据转String,方便存HashMap + for (short b : glyf.get(gid).xCoordinates) sb.append(b); + for (short b : glyf.get(gid).yCoordinates) sb.append(b); + String val = sb.toString(); + if (LimitMix == 0) LimitMix = key; + LimitMax = key; + CodeToGlyph.put(key, val); + if (GlyphToCode.containsKey(val)) continue; + GlyphToCode.put(val, key); + } + } + + /** + * 获取字体信息 (1=字体名称) + * + * @param nameId 传入十进制字体信息索引 + * @return 返回查询结果字符串 + */ + public String getNameById(int nameId) { + for (Directory Temp : Directorys) { + if (!Temp.tag.equals("name")) continue; + FontReader.Index = Temp.offset; + break; + } + for (NameRecord record : Name.records) { + if (record.nameID != nameId) continue; + FontReader.Index += Name.stringOffset + record.offset; + return FontReader.ReadStrings(record.length, record.platformID == 1 ? StandardCharsets.UTF_8 : StandardCharsets.UTF_16BE); + } + return "error"; + } + + /** + * 使用Unicode值查找轮廓索引 + * + * @param code 传入Unicode十进制值 + * @return 返回十进制轮廓索引 + */ + private int getGlyfIndex(int code) { + if (code == 0) return 0; + int fmtKey = 0; + for (@SuppressWarnings("unchecked") Pair item : pps) { + for (CmapRecord record : Cmap.records) { + if ((item.getLeft() == record.platformID) && (item.getRight() == record.encodingID)) { + fmtKey = record.offset; + break; + } + } + if (fmtKey > 0) break; + } + if (fmtKey == 0) return 0; + + int glyfID = 0; + CmapFormat table = Cmap.tables.get(fmtKey); + int fmt = table.format; + if (fmt == 0) { + if (code < table.glyphIdArray.length) glyfID = table.glyphIdArray[code] & 0xFF; + } else if (fmt == 4) { + CmapFormat4 tab = (CmapFormat4) table; + if (code > tab.endCode[tab.endCode.length - 1]) return 0; + // 二分法查找数值索引 + int start = 0, middle, end = tab.endCode.length - 1; + while (start + 1 < end) { + middle = (start + end) / 2; + if (tab.endCode[middle] <= code) start = middle; + else end = middle; + } + if (tab.endCode[start] < code) ++start; + if (code < tab.startCode[start]) return 0; + if (tab.idRangeOffset[start] != 0) { + glyfID = tab.glyphIdArray[code - tab.startCode[start] + (tab.idRangeOffset[start] >> 1) - (tab.idRangeOffset.length - start)]; + } else glyfID = code + tab.idDelta[start]; + glyfID &= 0xFFFF; + } else if (fmt == 6) { + CmapFormat6 tab = (CmapFormat6) table; + int index = code - tab.firstCode; + if (index < 0 || index >= tab.glyphIdArray.length) glyfID = 0; + else glyfID = tab.glyphIdArray[index]; + } else if (fmt == 12) { + CmapFormat12 tab = (CmapFormat12) table; + if (code > tab.groups.get(tab.numGroups - 1).getMiddle()) return 0; + // 二分法查找数值索引 + int start = 0, middle, end = tab.numGroups - 1; + while (start + 1 < end) { + middle = (start + end) / 2; + if (tab.groups.get(middle).getLeft() <= code) start = middle; + else end = middle; + } + if (tab.groups.get(start).getLeft() <= code && code <= tab.groups.get(start).getMiddle()) { + glyfID = tab.groups.get(start).getRight() + code - tab.groups.get(start).getLeft(); + } + } + return glyfID; + } + + /** + * 判断Unicode值是否在字体范围内 + * + * @param code 传入Unicode十进制值 + * @return 返回bool查询结果 + */ + public boolean inLimit(char code) { + return (LimitMix <= code) && (code < LimitMax); + } + + /** + * 使用Unicode值获取轮廓数据 + * + * @param key 传入Unicode十进制值 + * @return 返回轮廓数组的String值 + */ + public String getGlyfByCode(int key) { + return CodeToGlyph.getOrDefault(key, ""); + } + + /** + * 使用轮廓数据获取Unicode值 + * + * @param val 传入轮廓数组的String值 + * @return 返回Unicode十进制值 + */ + public int getCodeByGlyf(String val) { + return GlyphToCode.getOrDefault(val, 0); + } +} diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt b/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt deleted file mode 100644 index 0f7af2c52..000000000 --- a/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt +++ /dev/null @@ -1,633 +0,0 @@ -package io.legado.app.model.analyzeRule - -import org.apache.commons.lang3.tuple.Pair -import org.apache.commons.lang3.tuple.Triple -import java.nio.charset.Charset -import java.nio.charset.StandardCharsets -import java.util.* -import kotlin.experimental.and - -class QueryTTF(buffer: ByteArray) { - private class Header( - var majorVersion: Int = 0, - var minorVersion: Int = 0, - var numOfTables: Int = 0, - var searchRange: Int = 0, - var entrySelector: Int = 0, - var rangeShift: Int = 0, - ) - - private class Directory { - lateinit var tag: String // table name - var checkSum: Int = 0 // Check sum - var offset: Int = 0 // Offset from beginning of file - var length: Int = 0 // length of the table in bytes - } - - private class NameLayout( - var format: Int = 0, - var count: Int = 0, - var stringOffset: Int = 0, - var records: MutableList = LinkedList(), - ) - - private class NameRecord( - var platformID: Int = 0, // 平台标识符<0:Unicode, 1:Mac, 2:ISO, 3:Windows, 4:Custom> - var encodingID: Int = 0, // 编码标识符 - var languageID: Int = 0, // 语言标识符 - var nameID: Int = 0, // 名称标识符 - var length: Int = 0,// 名称字符串的长度 - var offset: Int = 0, // 名称字符串相对于stringOffset的字节偏移量 - ) - - private class HeadLayout( - var majorVersion: Int = 0, - var minorVersion: Int = 0, - var fontRevision: Int = 0, - var checkSumAdjustment: Int = 0, - var magicNumber: Int = 0, - var flags: Int = 0, - var unitsPerEm: Int = 0, - var created: Long = 0, - var modified: Long = 0, - var xMin: Short = 0, - var yMin: Short = 0, - var xMax: Short = 0, - var yMax: Short = 0, - var macStyle: Int = 0, - var lowestRecPPEM: Int = 0, - var fontDirectionHint: Short = 0, - var indexToLocFormat: Short = 0, // <0:loca是2字节数组, 1:loca是4字节数组> - var glyphDataFormat: Short = 0, - ) - - private class MaxpLayout( - var majorVersion: Int = 0, - var minorVersion: Int = 0, - var numGlyphs: Int = 0, // 字体中的字形数量 - var maxPoints: Int = 0, - var maxContours: Int = 0, - var maxCompositePoints: Int = 0, - var maxCompositeContours: Int = 0, - var maxZones: Int = 0, - var maxTwilightPoints: Int = 0, - var maxStorage: Int = 0, - var maxFunctionDefs: Int = 0, - var maxInstructionDefs: Int = 0, - var maxStackElements: Int = 0, - var maxSizeOfInstructions: Int = 0, - var maxComponentElements: Int = 0, - var maxComponentDepth: Int = 0, - ) - - private class CmapLayout( - var version: Int = 0, - var numTables: Int = 0, - var records: MutableList = LinkedList(), - var tables: MutableMap = HashMap(), - ) - - private class CmapRecord( - var platformID: Int = 0, - var encodingID: Int = 0, - var offset: Int = 0, - ) - - private open class CmapFormat { - var format: Int = 0 - open var length: Int = 0 - open var language: Int = 0 - lateinit var glyphIdArray: IntArray - } - - private class CmapFormat4 : CmapFormat() { - var segCountX2: Int = 0 - var searchRange: Int = 0 - var entrySelector: Int = 0 - var rangeShift: Int = 0 - lateinit var endCode: IntArray - var reservedPad: Int = 0 - lateinit var startCode: IntArray - lateinit var idDelta: ShortArray - lateinit var idRangeOffset: IntArray -// override lateinit var glyphIdArray: IntArray - } - - private class CmapFormat6( - var firstCode: Int = 0, - var entryCount: Int = 0, - ) : CmapFormat() - - private class CmapFormat12( - var reserved: Int = 0, - override var length: Int = 0, - override var language: Int = 0, - var numGroups: Int = 0, - var groups: MutableList> - ) : CmapFormat() - - private class GlyfLayout( - var numberOfContours: Short = 0, // 非负值为简单字型,负值为符合字型 - var xMin: Short = 0, - var yMin: Short = 0, - var xMax: Short = 0, - var yMax: Short = 0, - var instructionLength: Int = 0 - ) { - lateinit var endPtsOfContours: IntArray // length=numberOfContours - lateinit var instructions: IntArray // length=instructionLength - lateinit var flags: ByteArray - lateinit var xCoordinates: ShortArray // length = flags.length - lateinit var yCoordinates: ShortArray // length = flags.length - } - - private class ByteArrayReader(var buffer: ByteArray, var index: Int) { - fun readUIntX(len: Long): Long { - var result: Long = 0 - for (i in 0 until len) { - result = result shl 8 - result = result or ((buffer[index++] and 0xFF.toByte()).toLong()) - } - return result - } - - fun readUInt64(): Long = readUIntX(8) - - fun readUInt32(): Int = readUIntX(4).toInt() - - fun readUInt16(): Int = readUIntX(2).toInt() - - fun readInt16(): Short = readUIntX(2).toShort() - - fun readUInt8(): Short = readUIntX(1).toShort() - - fun readStrings(len: Int, charset: Charset): String { - val result = ByteArray(len) - for (i in 0 until len) { - result[i] = buffer[index++] - } - return String(result, charset) - } - - fun getByte() = buffer[index++] - - fun getBytes(len: Int): IntArray { - val result = IntArray(len) - for (i in 0 until len) { - result[i] = buffer[index++].toInt() - } - return result - } - - fun getUInt16Array(len: Int): IntArray { - val result = IntArray(len) - for (i in 0 until len) { - result[i] = readUInt16() - } - return result - } - - fun getInt16Array(len: Int): ShortArray { - val result = ShortArray(len) - for (i in 0 until len) { - result[i] = readInt16() - } - return result - } - } - - private val fontReader: ByteArrayReader = ByteArrayReader(buffer, 0) - private val directories: MutableList = LinkedList() - private val name = NameLayout() - private val cmap = CmapLayout() - private val pps: Array> = arrayOf( - Pair.of(3, 10), - Pair.of(0, 4), - Pair.of(3, 1), - Pair.of(1, 0), - Pair.of(0, 3), - Pair.of(0, 1) - ) - private val codeToGlyph: MutableMap = HashMap() - private val glyphToCode: MutableMap = HashMap() - private var limitMix = 0 - private var limitMax = 0 - - /** - * 获取字体信息 (1=字体名称) - * - * @param nameId 传入十进制字体信息索引 - * @return 返回查询结果字符串 - */ - fun getNameById(nameId: Int): String { - for (temp in directories) { - if ("name" != temp.tag) { - continue - } - fontReader.index = temp.offset - break - } - for (record in name.records) { - if (record.nameID != nameId) { - continue - } - fontReader.index += name.stringOffset + record.offset - return fontReader.readStrings(record.length, if (record.platformID == 1) StandardCharsets.UTF_8 else StandardCharsets.UTF_16BE) - } - return "error" - } - - /** - * 使用Unicode值查找轮廓索引 - * - * @param code 传入Unicode十进制值 - * @return 返回十进制轮廓索引 - */ - private fun getGlyfIndex(code: Int): Int { - if (code == 0) { - return 0 - } - var fmtKey = 0 - for (item in pps) { - for (record in cmap.records) { - if (item.left == record.platformID && item.right == record.encodingID) { - fmtKey = record.offset - break - } - } - if (fmtKey > 0) { - break - } - } - if (fmtKey == 0) { - return 0 - } - var glyfID = 0 - val table = cmap.tables[fmtKey] - when (table?.format) { - 0 -> { - if (code < table.glyphIdArray.size) { - glyfID = table.glyphIdArray[code] and 0xFF - } - } - 4 -> { - val tab = table as CmapFormat4 - if (code > tab.endCode[tab.endCode.size - 1]) { - return 0 - } - // 二分法查找数值索引 - var start = 0 - var middle: Int - var end = tab.endCode.size - 1 - while (start + 1 < end) { - middle = (start + end) / 2 - if (tab.endCode[middle] <= code) { - start = middle - } else { - end = middle - } - } - if (tab.endCode[start] < code) { - ++start - } - if (code < tab.startCode[start]) { - return 0 - } - glyfID = if (tab.idRangeOffset[start] != 0) { - tab.glyphIdArray[code - tab.startCode[start] + (tab.idRangeOffset[start] shr 1) - (tab.idRangeOffset.size - start)] - } else { - code + tab.idDelta[start] - } - glyfID = glyfID and 0xFFFF - } - 6 -> { - val tab = table as CmapFormat6 - val index = code - tab.firstCode - glyfID = if (index < 0 || index >= tab.glyphIdArray.size) { - 0 - } else { - tab.glyphIdArray[index] - } - } - 12 -> { - val tab = table as CmapFormat12 - if (code > tab.groups[tab.numGroups - 1].middle) { - return 0 - } - // 二分法查找数值索引 - var start = 0 - var middle: Int - var end = tab.numGroups - 1 - while (start + 1 < end) { - middle = (start + end) / 2 - if (tab.groups[middle].left <= code) { - start = middle - } else { - end = middle - } - } - if (tab.groups[start].left <= code && code <= tab.groups[start].middle) { - glyfID = tab.groups[start].right + code - tab.groups[start].left - } - } - } - return glyfID - } - - /** - * 判断Unicode值是否在字体范围内 - * @param code 传入Unicode十进制值 - * @return 返回bool查询结果 - */ - fun inLimit(code: Char): Boolean = code.toInt() in limitMix until limitMax - - /** - * 使用Unicode值获取轮廓数据 - * - * @param key 传入Unicode十进制值 - * @return 返回轮廓数组的String值 - */ - fun getGlyfByCode(key: Int): String = codeToGlyph.getOrDefault(key, "") - - /** - * 使用轮廓数据获取Unicode值 - * - * @param val 传入轮廓数组的String值 - * @return 返回Unicode十进制值 - */ - fun getCodeByGlyf(`val`: String): Int = glyphToCode.getOrDefault(`val`, 0) - - /** - * 构造函数 buffer 传入TTF字体二进制数组 - */ - init { - // 获取文件头 - val fileHeader = Header() - fileHeader.majorVersion = fontReader.readUInt16() - fileHeader.minorVersion = fontReader.readUInt16() - fileHeader.numOfTables = fontReader.readUInt16() - fileHeader.searchRange = fontReader.readUInt16() - fileHeader.entrySelector = fontReader.readUInt16() - fileHeader.rangeShift = fontReader.readUInt16() - // 获取目录 - for (i in 0 until fileHeader.numOfTables) { - val d = Directory() - d.tag = fontReader.readStrings(4, StandardCharsets.US_ASCII) - d.checkSum = fontReader.readUInt32() - d.offset = fontReader.readUInt32() - d.length = fontReader.readUInt32() - directories.add(d) - } - // 解析表 name (字体信息,包含版权、名称、作者等...) - for (temp in directories) { - if ("name" == temp.tag) { - fontReader.index = temp.offset - name.format = fontReader.readUInt16() - name.count = fontReader.readUInt16() - name.stringOffset = fontReader.readUInt16() - for (i in 0 until name.count) { - val record = NameRecord() - record.platformID = fontReader.readUInt16() - record.encodingID = fontReader.readUInt16() - record.languageID = fontReader.readUInt16() - record.nameID = fontReader.readUInt16() - record.length = fontReader.readUInt16() - record.offset = fontReader.readUInt16() - name.records.add(record) - } - } - } - // 解析表 head (获取 head.indexToLocFormat) - val head = HeadLayout() - for (temp in directories) { - if ("head" == temp.tag) { - fontReader.index = temp.offset - head.majorVersion = fontReader.readUInt16() - head.minorVersion = fontReader.readUInt16() - head.fontRevision = fontReader.readUInt32() - head.checkSumAdjustment = fontReader.readUInt32() - head.magicNumber = fontReader.readUInt32() - head.flags = fontReader.readUInt16() - head.unitsPerEm = fontReader.readUInt16() - head.created = fontReader.readUInt64() - head.modified = fontReader.readUInt64() - head.xMin = fontReader.readInt16() - head.yMin = fontReader.readInt16() - head.xMax = fontReader.readInt16() - head.yMax = fontReader.readInt16() - head.macStyle = fontReader.readUInt16() - head.lowestRecPPEM = fontReader.readUInt16() - head.fontDirectionHint = fontReader.readInt16() - head.indexToLocFormat = fontReader.readInt16() - head.glyphDataFormat = fontReader.readInt16() - } - } - // 解析表 maxp (获取 maxp.numGlyphs) - val maxp = MaxpLayout() - for (temp in directories) { - if ("maxp" == temp.tag) { - fontReader.index = temp.offset - maxp.majorVersion = fontReader.readUInt16() - maxp.minorVersion = fontReader.readUInt16() - maxp.numGlyphs = fontReader.readUInt16() - maxp.maxPoints = fontReader.readUInt16() - maxp.maxContours = fontReader.readUInt16() - maxp.maxCompositePoints = fontReader.readUInt16() - maxp.maxCompositeContours = fontReader.readUInt16() - maxp.maxZones = fontReader.readUInt16() - maxp.maxTwilightPoints = fontReader.readUInt16() - maxp.maxStorage = fontReader.readUInt16() - maxp.maxFunctionDefs = fontReader.readUInt16() - maxp.maxInstructionDefs = fontReader.readUInt16() - maxp.maxStackElements = fontReader.readUInt16() - maxp.maxSizeOfInstructions = fontReader.readUInt16() - maxp.maxComponentElements = fontReader.readUInt16() - maxp.maxComponentDepth = fontReader.readUInt16() - } - } - // 解析表 loca (轮廓数据偏移地址表) - val loca: MutableList = LinkedList() - for (temp in directories) { - if ("loca" == temp.tag) { - fontReader.index = temp.offset - val offset = if (head.indexToLocFormat == 0.toShort()) 2 else 4 - var i: Long = 0 - while (i < temp.length) { - loca.add(if (offset == 2) fontReader.readUInt16() shl 1 else fontReader.readUInt32()) - i += offset - } - } - } - // 解析表 cmap (Unicode编码轮廓索引对照表) - for (temp in directories) { - if ("cmap" == temp.tag) { - fontReader.index = temp.offset - cmap.version = fontReader.readUInt16() - cmap.numTables = fontReader.readUInt16() - for (i in 0 until cmap.numTables) { - val record = CmapRecord() - record.platformID = fontReader.readUInt16() - record.encodingID = fontReader.readUInt16() - record.offset = fontReader.readUInt32() - cmap.records.add(record) - } - for (i in 0 until cmap.numTables) { - val fmtOffset = cmap.records[i].offset - fontReader.index = temp.offset + fmtOffset - val endIndex = fontReader.index - val format = fontReader.readUInt16() - if (cmap.tables.containsKey(fmtOffset)) { - continue - } - when (format) { - 0 -> { - val f = CmapFormat() - f.format = format - f.length = fontReader.readUInt16() - f.language = fontReader.readUInt16() - f.glyphIdArray = fontReader.getBytes(f.length - 6) - cmap.tables[fmtOffset] = f - } - 4 -> { - val f = CmapFormat4() - f.format = format - f.length = fontReader.readUInt16() - f.language = fontReader.readUInt16() - f.segCountX2 = fontReader.readUInt16() - val segCount = f.segCountX2 shr 1 - f.searchRange = fontReader.readUInt16() - f.entrySelector = fontReader.readUInt16() - f.rangeShift = fontReader.readUInt16() - f.endCode = fontReader.getUInt16Array(segCount) - f.reservedPad = fontReader.readUInt16() - f.startCode = fontReader.getUInt16Array(segCount) - f.idDelta = fontReader.getInt16Array(segCount) - f.idRangeOffset = fontReader.getUInt16Array(segCount) - f.glyphIdArray = fontReader.getUInt16Array(endIndex + f.length - fontReader.index shr 1) - cmap.tables[fmtOffset] = f - } - 6 -> { - val f = CmapFormat6() - f.format = format - f.length = fontReader.readUInt16() - f.language = fontReader.readUInt16() - f.firstCode = fontReader.readUInt16() - f.entryCount = fontReader.readUInt16() - f.glyphIdArray = fontReader.getUInt16Array(f.entryCount) - cmap.tables[fmtOffset] = f - } - 12 -> { - val f = CmapFormat12( - reserved = fontReader.readUInt16(), - length = fontReader.readUInt32(), - language = fontReader.readUInt32(), - numGroups = fontReader.readUInt32(), - groups = ArrayList(fontReader.readUInt32()) - ) - f.format = format - for (n in 0 until f.numGroups) { - (f.groups as ArrayList>).add(Triple.of(fontReader.readUInt32(), fontReader.readUInt32(), fontReader.readUInt32())) - } - cmap.tables[fmtOffset] = f - } - } - } - } - } - // 解析表 glyf (字体轮廓数据表) - val glyf: MutableList = LinkedList() - for (temp in directories) { - if ("glyf" == temp.tag) { - fontReader.index = temp.offset - for (i in 0 until maxp.numGlyphs) { - fontReader.index = temp.offset + loca[i] - val numberOfContours = fontReader.readInt16() - if (numberOfContours > 0) { - val g = GlyfLayout() - g.numberOfContours = numberOfContours - g.xMin = fontReader.readInt16() - g.yMin = fontReader.readInt16() - g.xMax = fontReader.readInt16() - g.yMax = fontReader.readInt16() - g.endPtsOfContours = fontReader.getUInt16Array(numberOfContours.toInt()) - g.instructionLength = fontReader.readUInt16() - g.instructions = fontReader.getBytes(g.instructionLength) - val flagLength = g.endPtsOfContours[g.endPtsOfContours.size - 1] + 1 - // 获取轮廓点描述标志 - g.flags = ByteArray(flagLength).apply { - var n = 0 - while (n < flagLength) { - this[n] = fontReader.getByte() - if ((this[n] and 0x08) != 0x00.toByte()) { - for (m in fontReader.readUInt8() downTo 1) { - this[++n] = this[n - 1] - } - } - ++n - } - } - // 获取轮廓点描述x轴相对值 - g.xCoordinates = ShortArray(flagLength) - for (n in 0 until flagLength) { - val same = (if (g.flags[n] and 0x10 != 0.toByte()) 1 else -1).toShort() - if (g.flags[n] and 0x02 != 0.toByte()) { - g.xCoordinates[n] = (same * fontReader.readUInt8()).toShort() - } else { - g.xCoordinates[n] = if (same.toInt() == 1) 0.toShort() else fontReader.readInt16() - } - } - // 获取轮廓点描述y轴相对值 - g.yCoordinates = ShortArray(flagLength) - for (n in 0 until flagLength) { - val same = (if (g.flags[n] and 0x20 != 0.toByte()) 1 else -1).toShort() - if (g.flags[n] and 0x04 != 0.toByte()) { - g.yCoordinates[n] = (same * fontReader.readUInt8()).toShort() - } else { - g.yCoordinates[n] = if (same.toInt() == 1) 0.toShort() else fontReader.readInt16() - } - } - // 相对坐标转绝对坐标 -// for (int n = 1; n < flagLength; ++n) { -// xCoordinates[n] += xCoordinates[n - 1]; -// yCoordinates[n] += yCoordinates[n - 1]; -// } - glyf.add(g) - } //else情况:复合字体暂未使用 - } - } - } - - // 建立Unicode&Glyph双向表 - var key = 0 - while (key < 130000) { - if (key == 0xFF) { - key = 0x3400 - } - val gid = getGlyfIndex(key) - if (gid == 0) { - ++key - continue - } - val sb = StringBuilder() - // 字型数据转String,方便存HashMap - for (b in glyf[gid].xCoordinates) { - sb.append(b.toInt()) - } - for (b in glyf[gid].yCoordinates) { - sb.append(b.toInt()) - } - val `val` = sb.toString() - if (limitMix == 0) { - limitMix = key - } - limitMax = key - codeToGlyph[key] = `val` - if (glyphToCode.containsKey(`val`)) { - ++key - continue - } - glyphToCode[`val`] = key - ++key - } - } -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt b/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt index a6f952e66..da80c1275 100644 --- a/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt +++ b/app/src/main/java/io/legado/app/model/localBook/AnalyzeTxtFile.kt @@ -1,12 +1,13 @@ package io.legado.app.model.localBook import android.net.Uri -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.TxtTocRule import io.legado.app.help.DefaultData import io.legado.app.utils.* +import splitties.init.appCtx import java.io.File import java.io.RandomAccessFile import java.nio.charset.Charset @@ -266,7 +267,7 @@ class AnalyzeTxtFile { val bookFile = FileUtils.getFile(LocalBook.cacheFolder, book.originName) if (!bookFile.exists()) { bookFile.createNewFile() - DocumentUtils.readBytes(App.INSTANCE, uri)?.let { + DocumentUtils.readBytes(appCtx, uri)?.let { bookFile.writeBytes(it) } } @@ -276,10 +277,10 @@ class AnalyzeTxtFile { } private fun getTocRules(): List { - var rules = App.db.txtTocRule.enabled + var rules = appDb.txtTocRule.enabled if (rules.isEmpty()) { rules = DefaultData.txtTocRules.apply { - App.db.txtTocRule.insert(*this.toTypedArray()) + appDb.txtTocRule.insert(*this.toTypedArray()) }.filter { it.enable } diff --git a/app/src/main/java/io/legado/app/model/localBook/EPUBFile.kt b/app/src/main/java/io/legado/app/model/localBook/EPUBFile.kt index 2cc0b4340..c7fceafad 100644 --- a/app/src/main/java/io/legado/app/model/localBook/EPUBFile.kt +++ b/app/src/main/java/io/legado/app/model/localBook/EPUBFile.kt @@ -4,13 +4,13 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri import android.text.TextUtils -import io.legado.app.App import io.legado.app.data.entities.BookChapter import io.legado.app.utils.* import nl.siegmann.epublib.domain.Book import nl.siegmann.epublib.domain.TOCReference import nl.siegmann.epublib.epub.EpubReader import org.jsoup.Jsoup +import splitties.init.appCtx import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -59,14 +59,14 @@ class EPUBFile(val book: io.legado.app.data.entities.Book) { val epubReader = EpubReader() val inputStream = if (book.bookUrl.isContentScheme()) { val uri = Uri.parse(book.bookUrl) - App.INSTANCE.contentResolver.openInputStream(uri) + appCtx.contentResolver.openInputStream(uri) } else { File(book.bookUrl).inputStream() } epubBook = epubReader.readEpub(inputStream) if (book.coverUrl.isNullOrEmpty()) { book.coverUrl = FileUtils.getPath( - App.INSTANCE.externalFilesDir, + appCtx.externalFilesDir, "covers", "${MD5Utils.md5Encode16(book.bookUrl)}.jpg" ) diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index ff96cb519..219f47310 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -2,20 +2,21 @@ package io.legado.app.model.localBook import android.net.Uri import androidx.documentfile.provider.DocumentFile -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp import io.legado.app.utils.* +import splitties.init.appCtx import java.io.File object LocalBook { private const val folderName = "bookTxt" val cacheFolder: File by lazy { - val rootFile = App.INSTANCE.getExternalFilesDir(null) - ?: App.INSTANCE.externalCacheDir - ?: App.INSTANCE.cacheDir + val rootFile = appCtx.getExternalFilesDir(null) + ?: appCtx.externalCacheDir + ?: appCtx.cacheDir FileUtils.createFolderIfNotExist(rootFile, folderName) } @@ -39,12 +40,12 @@ object LocalBook { val path: String val fileName = if (uri.isContentScheme()) { path = uri.toString() - val doc = DocumentFile.fromSingleUri(App.INSTANCE, uri) + val doc = DocumentFile.fromSingleUri(appCtx, uri) doc?.let { val bookFile = FileUtils.getFile(cacheFolder, it.name!!) if (!bookFile.exists()) { bookFile.createNewFile() - doc.readBytes(App.INSTANCE)?.let { bytes -> + doc.readBytes(appCtx)?.let { bytes -> bookFile.writeBytes(bytes) } } @@ -77,12 +78,12 @@ object LocalBook { author = author, originName = fileName, coverUrl = FileUtils.getPath( - App.INSTANCE.externalFilesDir, + appCtx.externalFilesDir, "covers", "${MD5Utils.md5Encode16(path)}.jpg" ) ) - App.db.bookDao.insert(book) + appDb.bookDao.insert(book) return book } @@ -96,7 +97,7 @@ object LocalBook { if (deleteOriginal) { if (book.bookUrl.isContentScheme()) { val uri = Uri.parse(book.bookUrl) - DocumentFile.fromSingleUri(App.INSTANCE, uri)?.delete() + DocumentFile.fromSingleUri(appCtx, uri)?.delete() } else { FileUtils.deleteFile(book.bookUrl) } diff --git a/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt b/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt index 18d05c022..b162f37e1 100644 --- a/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt +++ b/app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt @@ -1,7 +1,6 @@ package io.legado.app.model.rss import androidx.annotation.Keep -import io.legado.app.App import io.legado.app.R import io.legado.app.data.entities.RssArticle import io.legado.app.data.entities.RssSource @@ -10,6 +9,7 @@ import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.RuleDataInterface import io.legado.app.utils.GSON import io.legado.app.utils.NetworkUtils +import splitties.init.appCtx import java.util.* @Keep @@ -27,7 +27,7 @@ object RssParserByRule { var nextUrl: String? = null if (body.isNullOrBlank()) { throw Exception( - App.INSTANCE.getString(R.string.error_get_web_content, rssSource.sourceUrl) + appCtx.getString(R.string.error_get_web_content, rssSource.sourceUrl) ) } Debug.log(sourceUrl, "≡获取成功:$sourceUrl") diff --git a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt index 1bdf1ca05..008ad3d6c 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt @@ -1,7 +1,6 @@ package io.legado.app.model.webBook import android.text.TextUtils -import io.legado.app.App import io.legado.app.R import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter @@ -14,6 +13,7 @@ import io.legado.app.model.analyzeRule.AnalyzeUrl import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ensureActive import kotlinx.coroutines.suspendCancellableCoroutine +import splitties.init.appCtx import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -29,7 +29,7 @@ object BookChapterList { kotlin.runCatching { val chapterList = ArrayList() body ?: throw Exception( - App.INSTANCE.getString(R.string.error_get_web_content, baseUrl) + appCtx.getString(R.string.error_get_web_content, baseUrl) ) Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}") diff --git a/app/src/main/java/io/legado/app/model/webBook/BookContent.kt b/app/src/main/java/io/legado/app/model/webBook/BookContent.kt index 25fcfa512..77069b178 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookContent.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookContent.kt @@ -1,7 +1,7 @@ package io.legado.app.model.webBook -import io.legado.app.App import io.legado.app.R +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource @@ -14,6 +14,7 @@ import io.legado.app.utils.NetworkUtils import io.legado.app.utils.htmlFormat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.withContext +import splitties.init.appCtx object BookContent { @@ -28,7 +29,7 @@ object BookContent { nextChapterUrlF: String? = null ): String { body ?: throw Exception( - App.INSTANCE.getString(R.string.error_get_web_content, baseUrl) + appCtx.getString(R.string.error_get_web_content, baseUrl) ) Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}") val content = StringBuilder() @@ -45,7 +46,7 @@ object BookContent { val nextChapterUrl = if (!nextChapterUrlF.isNullOrEmpty()) nextChapterUrlF else - App.db.bookChapterDao.getChapter(book.bookUrl, bookChapter.index + 1)?.url + appDb.bookChapterDao.getChapter(book.bookUrl, bookChapter.index + 1)?.url while (nextUrl.isNotEmpty() && !nextUrlList.contains(nextUrl)) { if (!nextChapterUrl.isNullOrEmpty() && NetworkUtils.getAbsoluteURL(baseUrl, nextUrl) diff --git a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt index d4eb8b9d9..c8bf93e71 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookInfo.kt @@ -1,6 +1,5 @@ package io.legado.app.model.webBook -import io.legado.app.App import io.legado.app.R import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookSource @@ -12,6 +11,7 @@ import io.legado.app.utils.StringUtils.wordCountFormat import io.legado.app.utils.htmlFormat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ensureActive +import splitties.init.appCtx object BookInfo { @@ -25,7 +25,7 @@ object BookInfo { canReName: Boolean, ) { body ?: throw Exception( - App.INSTANCE.getString(R.string.error_get_web_content, baseUrl) + appCtx.getString(R.string.error_get_web_content, baseUrl) ) Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}") val infoRule = bookSource.getBookInfoRule() diff --git a/app/src/main/java/io/legado/app/model/webBook/BookList.kt b/app/src/main/java/io/legado/app/model/webBook/BookList.kt index 25ab215e6..0dbde453e 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookList.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookList.kt @@ -1,6 +1,5 @@ package io.legado.app.model.webBook -import io.legado.app.App import io.legado.app.R import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook @@ -14,6 +13,7 @@ import io.legado.app.utils.StringUtils.wordCountFormat import io.legado.app.utils.htmlFormat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ensureActive +import splitties.init.appCtx object BookList { @@ -29,7 +29,7 @@ object BookList { ): ArrayList { val bookList = ArrayList() body ?: throw Exception( - App.INSTANCE.getString( + appCtx.getString( R.string.error_get_web_content, analyzeUrl.ruleUrl ) diff --git a/app/src/main/java/io/legado/app/model/webBook/SearchBookModel.kt b/app/src/main/java/io/legado/app/model/webBook/SearchBookModel.kt index 95aa3a95e..2cdc53f43 100644 --- a/app/src/main/java/io/legado/app/model/webBook/SearchBookModel.kt +++ b/app/src/main/java/io/legado/app/model/webBook/SearchBookModel.kt @@ -1,6 +1,6 @@ package io.legado.app.model.webBook -import io.legado.app.App +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.help.AppConfig @@ -10,6 +10,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.ExecutorCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher +import splitties.init.appCtx import java.util.concurrent.Executors import kotlin.math.min @@ -44,12 +45,12 @@ class SearchBookModel(private val scope: CoroutineScope, private val callBack: C initSearchPool() mSearchId = searchId searchPage = 1 - val searchGroup = App.INSTANCE.getPrefString("searchGroup") ?: "" + val searchGroup = appCtx.getPrefString("searchGroup") ?: "" bookSourceList.clear() if (searchGroup.isBlank()) { - bookSourceList.addAll(App.db.bookSourceDao.allEnabled) + bookSourceList.addAll(appDb.bookSourceDao.allEnabled) } else { - bookSourceList.addAll(App.db.bookSourceDao.getEnabledByGroup(searchGroup)) + bookSourceList.addAll(appDb.bookSourceDao.getEnabledByGroup(searchGroup)) } } else { searchPage++ diff --git a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt index ddd065570..92a4b9320 100644 --- a/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt +++ b/app/src/main/java/io/legado/app/receiver/MediaButtonReceiver.kt @@ -4,8 +4,8 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.view.KeyEvent -import io.legado.app.App import io.legado.app.constant.EventBus +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.help.ActivityHelp import io.legado.app.service.AudioPlayService @@ -76,7 +76,7 @@ class MediaButtonReceiver : BroadcastReceiver() { else -> if (context.getPrefBoolean("mediaButtonOnExit", true)) { GlobalScope.launch(Main) { val lastBook: Book? = withContext(IO) { - App.db.bookDao.lastReadBook + appDb.bookDao.lastReadBook } lastBook?.let { if (!ActivityHelp.isExist(MainActivity::class.java)) { diff --git a/app/src/main/java/io/legado/app/receiver/SharedReceiverActivity.kt b/app/src/main/java/io/legado/app/receiver/SharedReceiverActivity.kt index e6b78f0f5..6d76736d5 100644 --- a/app/src/main/java/io/legado/app/receiver/SharedReceiverActivity.kt +++ b/app/src/main/java/io/legado/app/receiver/SharedReceiverActivity.kt @@ -6,7 +6,7 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.main.MainActivity -import org.jetbrains.anko.startActivity +import io.legado.app.utils.startActivity class SharedReceiverActivity : AppCompatActivity() { @@ -22,7 +22,9 @@ class SharedReceiverActivity : AppCompatActivity() { if (Intent.ACTION_SEND == intent.action && intent.type == receivingType) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { if (openUrl(it)) { - startActivity(Pair("key", it)) + startActivity { + putExtra("key", it) + } } } } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M @@ -31,7 +33,9 @@ class SharedReceiverActivity : AppCompatActivity() { ) { intent.getStringExtra(Intent.EXTRA_PROCESS_TEXT)?.let { if (openUrl(it)) { - startActivity(Pair("key", it)) + startActivity { + putExtra("key", it) + } } } } diff --git a/app/src/main/java/io/legado/app/service/AudioPlayService.kt b/app/src/main/java/io/legado/app/service/AudioPlayService.kt index 805fdfc14..c2659337f 100644 --- a/app/src/main/java/io/legado/app/service/AudioPlayService.kt +++ b/app/src/main/java/io/legado/app/service/AudioPlayService.kt @@ -16,13 +16,13 @@ import android.os.Looper import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.PlaybackStateCompat import androidx.core.app.NotificationCompat -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.constant.Status +import io.legado.app.data.appDb import io.legado.app.data.entities.BookChapter import io.legado.app.help.IntentHelp import io.legado.app.help.MediaHelp @@ -31,10 +31,11 @@ import io.legado.app.receiver.MediaButtonReceiver import io.legado.app.service.help.AudioPlay import io.legado.app.ui.audio.AudioPlayActivity import io.legado.app.utils.postEvent +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.jetbrains.anko.toast +import splitties.init.appCtx class AudioPlayService : BaseService(), @@ -133,7 +134,7 @@ class AudioPlayService : BaseService(), }.onFailure { it.printStackTrace() launch { - toast("$url ${it.localizedMessage}") + toastOnUi("$url ${it.localizedMessage}") stopSelf() } } @@ -219,7 +220,7 @@ class AudioPlayService : BaseService(), if (!mediaPlayer.isPlaying) { AudioPlay.status = Status.STOP postEvent(EventBus.AUDIO_STATE, Status.STOP) - launch { toast("error: $what $extra $url") } + launch { toastOnUi("error: $what $extra $url") } } return true } @@ -274,7 +275,7 @@ class AudioPlayService : BaseService(), .onSuccess { content -> if (content.isEmpty()) { withContext(Main) { - toast("未获取到资源链接") + toastOnUi("未获取到资源链接") } } else { contentLoadFinish(chapter, content) @@ -286,7 +287,7 @@ class AudioPlayService : BaseService(), } } else { removeLoading(chapter.index) - toast("book or source is null") + toastOnUi("book or source is null") } } } @@ -321,7 +322,7 @@ class AudioPlayService : BaseService(), execute { AudioPlay.book?.let { AudioPlay.durChapterPos = mediaPlayer.currentPosition - App.db.bookDao.upProgress(it.bookUrl, AudioPlay.durChapterPos) + appDb.bookDao.upProgress(it.bookUrl, AudioPlay.durChapterPos) } } } @@ -370,7 +371,7 @@ class AudioPlayService : BaseService(), Intent( Intent.ACTION_MEDIA_BUTTON, null, - App.INSTANCE, + appCtx, MediaButtonReceiver::class.java ), PendingIntent.FLAG_CANCEL_CURRENT diff --git a/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt b/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt index 9e60ac6b2..541a2d99e 100644 --- a/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt +++ b/app/src/main/java/io/legado/app/service/BaseReadAloudService.kt @@ -14,7 +14,6 @@ import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.PlaybackStateCompat import androidx.annotation.CallSuper import androidx.core.app.NotificationCompat -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseService import io.legado.app.constant.* @@ -27,6 +26,7 @@ import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.read.page.entities.TextChapter import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.postEvent +import splitties.init.appCtx abstract class BaseReadAloudService : BaseService(), AudioManager.OnAudioFocusChangeListener { @@ -233,7 +233,7 @@ abstract class BaseReadAloudService : BaseService(), Intent( Intent.ACTION_MEDIA_BUTTON, null, - App.INSTANCE, + appCtx, MediaButtonReceiver::class.java ), PendingIntent.FLAG_CANCEL_CURRENT diff --git a/app/src/main/java/io/legado/app/service/CacheBookService.kt b/app/src/main/java/io/legado/app/service/CacheBookService.kt index 06a6dea35..963dc534c 100644 --- a/app/src/main/java/io/legado/app/service/CacheBookService.kt +++ b/app/src/main/java/io/legado/app/service/CacheBookService.kt @@ -4,12 +4,12 @@ import android.content.Intent import android.os.Handler import android.os.Looper import androidx.core.app.NotificationCompat -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.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.AppConfig @@ -20,9 +20,10 @@ import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.webBook.WebBook import io.legado.app.service.help.CacheBook import io.legado.app.utils.postEvent +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.isActive -import org.jetbrains.anko.toast +import splitties.init.appCtx import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.Executors @@ -43,7 +44,7 @@ class CacheBookService : BaseService() { @Volatile private var downloadingCount = 0 - private var notificationContent = App.INSTANCE.getString(R.string.starting_download) + private var notificationContent = appCtx.getString(R.string.starting_download) private val notificationBuilder by lazy { val builder = NotificationCompat.Builder(this, AppConst.channelIdDownload) @@ -95,7 +96,7 @@ class CacheBookService : BaseService() { synchronized(this) { book = bookMap[bookUrl] if (book == null) { - book = App.db.bookDao.getBook(bookUrl) + book = appDb.bookDao.getBook(bookUrl) if (book == null) { removeDownload(bookUrl) } @@ -111,7 +112,7 @@ class CacheBookService : BaseService() { synchronized(this) { webBook = webBookMap[origin] if (webBook == null) { - App.db.bookSourceDao.getBookSource(origin)?.let { + appDb.bookSourceDao.getBookSource(origin)?.let { webBook = WebBook(it) } if (webBook == null) { @@ -128,12 +129,12 @@ class CacheBookService : BaseService() { if (downloadMap.containsKey(bookUrl)) { notificationContent = getString(R.string.already_in_download) upNotification() - toast(notificationContent) + toastOnUi(notificationContent) return } downloadCount[bookUrl] = DownloadCount() execute { - App.db.bookChapterDao.getChapterList(bookUrl, start, end).let { + appDb.bookChapterDao.getChapterList(bookUrl, start, end).let { if (it.isNotEmpty()) { val chapters = CopyOnWriteArraySet() chapters.addAll(it) 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 a803a2aa2..6c66be641 100644 --- a/app/src/main/java/io/legado/app/service/CheckSourceService.kt +++ b/app/src/main/java/io/legado/app/service/CheckSourceService.kt @@ -2,12 +2,12 @@ package io.legado.app.service import android.content.Intent import androidx.core.app.NotificationCompat -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.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.help.AppConfig import io.legado.app.help.IntentHelp @@ -16,8 +16,8 @@ import io.legado.app.model.webBook.WebBook import io.legado.app.service.help.CheckSource import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.utils.postEvent +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.asCoroutineDispatcher -import org.jetbrains.anko.toast import java.util.concurrent.Executors import kotlin.math.min @@ -70,7 +70,7 @@ class CheckSourceService : BaseService() { private fun check(ids: List) { if (allIds.isNotEmpty()) { - toast("已有书源在校验,等完成后再试") + toastOnUi("已有书源在校验,等完成后再试") return } tasks.clear() @@ -97,7 +97,7 @@ class CheckSourceService : BaseService() { execute { if (index < allIds.size) { val sourceUrl = allIds[index] - App.db.bookSourceDao.getBookSource(sourceUrl)?.let { source -> + appDb.bookSourceDao.getBookSource(sourceUrl)?.let { source -> check(source) } ?: onNext(sourceUrl, "") } @@ -133,10 +133,10 @@ class CheckSourceService : BaseService() { source.addGroup("失效") source.bookSourceComment = "error:${it.localizedMessage}\n${source.bookSourceComment}" - App.db.bookSourceDao.update(source) + appDb.bookSourceDao.update(source) }.onSuccess { source.removeGroup("失效") - App.db.bookSourceDao.update(source) + appDb.bookSourceDao.update(source) }.onFinally { onNext(source.bookSourceUrl, source.bookSourceName) } 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 fd21a079b..134ca55eb 100644 --- a/app/src/main/java/io/legado/app/service/DownloadService.kt +++ b/app/src/main/java/io/legado/app/service/DownloadService.kt @@ -20,8 +20,8 @@ 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 io.legado.app.utils.toastOnUi +import splitties.systemservices.downloadManager import java.io.File @@ -149,7 +149,7 @@ class DownloadService : BaseService() { try { startActivity(intent) } catch (e: Exception) { - toast(e.msg) + toastOnUi(e.msg) } } } diff --git a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt index 6cefb4e4c..8ad7b1420 100644 --- a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt +++ b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt @@ -10,15 +10,9 @@ import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.service.help.ReadAloud import io.legado.app.service.help.ReadBook -import io.legado.app.utils.FileUtils -import io.legado.app.utils.LogUtils -import io.legado.app.utils.MD5Utils -import io.legado.app.utils.postEvent +import io.legado.app.utils.* import kotlinx.coroutines.ensureActive import kotlinx.coroutines.isActive -import org.jetbrains.anko.collections.forEachWithIndex -import org.jetbrains.anko.runOnUiThread -import org.jetbrains.anko.toast import java.io.File import java.io.FileDescriptor import java.io.FileInputStream @@ -84,10 +78,10 @@ class HttpReadAloudService : BaseReadAloudService(), task = execute { removeCacheFile() ReadAloud.httpTTS?.let { - contentList.forEachWithIndex { index, item -> + contentList.forEachIndexed { index, item -> if (isActive) { val fileName = - md5SpeakFileName(it.url, AppConfig.ttsSpeechRate.toString(), item) + md5SpeakFileName(it.url, AppConfig.ttsSpeechRate.toString(), item) if (hasSpeakFile(fileName)) { //已经下载好的语音缓存 if (index == nowSpeak) { @@ -116,12 +110,6 @@ class HttpReadAloudService : BaseReadAloudService(), val fis = FileInputStream(file) - // 用来检测下载的文件是否为可正常播放的音频 (如果不是的话抛出异常,没找到更秒的办法,先这么着吧) - MediaPlayer().apply { - setDataSource(fis.fd) - prepare() - release() - } if (index == nowSpeak) { @Suppress("BlockingMethodInNonBlockingContext") playAudio(fis.fd) @@ -129,17 +117,17 @@ class HttpReadAloudService : BaseReadAloudService(), } } catch (e: SocketTimeoutException) { removeSpeakCacheFile(fileName) - runOnUiThread { toast("tts接口超时,尝试重新获取") } + toastOnUi("tts接口超时,尝试重新获取") downloadAudio() } catch (e: ConnectException) { removeSpeakCacheFile(fileName) - runOnUiThread { toast("网络错误") } + toastOnUi("网络错误") } catch (e: IOException) { val file = getSpeakFileAsMd5(fileName) if (file.exists()) { FileUtils.deleteFile(file.absolutePath) } - runOnUiThread { toast("tts文件解析错误") } + toastOnUi("tts文件解析错误") } catch (e: Exception) { removeSpeakCacheFile(fileName) } diff --git a/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt b/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt index d1341a4c3..60cb11bdf 100644 --- a/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt +++ b/app/src/main/java/io/legado/app/service/TTSReadAloudService.kt @@ -13,8 +13,8 @@ import io.legado.app.help.MediaHelp import io.legado.app.service.help.ReadBook import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.postEvent +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.launch -import org.jetbrains.anko.toast import java.util.* class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener { @@ -64,7 +64,7 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener } } else { launch { - toast(R.string.tts_init_failed) + toastOnUi(R.string.tts_init_failed) } } } diff --git a/app/src/main/java/io/legado/app/service/WebService.kt b/app/src/main/java/io/legado/app/service/WebService.kt index 03bddff2c..da350a90a 100644 --- a/app/src/main/java/io/legado/app/service/WebService.kt +++ b/app/src/main/java/io/legado/app/service/WebService.kt @@ -10,14 +10,9 @@ import io.legado.app.constant.EventBus import io.legado.app.constant.IntentAction import io.legado.app.constant.PreferKey import io.legado.app.help.IntentHelp -import io.legado.app.utils.NetworkUtils -import io.legado.app.utils.getPrefInt -import io.legado.app.utils.postEvent +import io.legado.app.utils.* import io.legado.app.web.HttpServer import io.legado.app.web.WebSocketServer -import kotlinx.coroutines.launch -import org.jetbrains.anko.startService -import org.jetbrains.anko.toast import java.io.IOException class WebService : BaseService() { @@ -92,10 +87,8 @@ class WebService : BaseService() { notificationContent = hostAddress upNotification() } catch (e: IOException) { - launch { - toast(e.localizedMessage ?: "") - stopSelf() - } + toastOnUi(e.localizedMessage ?: "") + stopSelf() } } else { stopSelf() diff --git a/app/src/main/java/io/legado/app/service/help/AudioPlay.kt b/app/src/main/java/io/legado/app/service/help/AudioPlay.kt index 65f6e7f0d..7a599a190 100644 --- a/app/src/main/java/io/legado/app/service/help/AudioPlay.kt +++ b/app/src/main/java/io/legado/app/service/help/AudioPlay.kt @@ -3,10 +3,10 @@ package io.legado.app.service.help import android.content.Context import android.content.Intent import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.constant.EventBus import io.legado.app.constant.IntentAction import io.legado.app.constant.Status +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.coroutine.Coroutine @@ -44,7 +44,7 @@ object AudioPlay { } fun upDurChapter(book: Book) { - durChapter = App.db.bookChapterDao.getChapter(book.bookUrl, durChapterIndex) + durChapter = appDb.bookChapterDao.getChapter(book.bookUrl, durChapterIndex) postEvent(EventBus.AUDIO_SUB_TITLE, durChapter?.title ?: "") postEvent(EventBus.AUDIO_SIZE, durChapter?.end?.toInt() ?: 0) postEvent(EventBus.AUDIO_PROGRESS, durChapterPos) @@ -153,10 +153,10 @@ object AudioPlay { book.durChapterTime = System.currentTimeMillis() book.durChapterIndex = durChapterIndex book.durChapterPos = durChapterPos - App.db.bookChapterDao.getChapter(book.bookUrl, book.durChapterIndex)?.let { + appDb.bookChapterDao.getChapter(book.bookUrl, book.durChapterIndex)?.let { book.durChapterTitle = it.title } - App.db.bookDao.update(book) + appDb.bookDao.update(book) } } } @@ -165,7 +165,7 @@ object AudioPlay { Coroutine.async { durChapter?.let { it.end = audioSize - App.db.bookChapterDao.insert(it) + appDb.bookChapterDao.insert(it) } } } diff --git a/app/src/main/java/io/legado/app/service/help/CacheBook.kt b/app/src/main/java/io/legado/app/service/help/CacheBook.kt index 782ab3bf8..3a8a5d0ce 100644 --- a/app/src/main/java/io/legado/app/service/help/CacheBook.kt +++ b/app/src/main/java/io/legado/app/service/help/CacheBook.kt @@ -2,7 +2,6 @@ package io.legado.app.service.help import android.content.Context import android.content.Intent -import io.legado.app.App import io.legado.app.R import io.legado.app.constant.IntentAction import io.legado.app.data.entities.Book @@ -11,6 +10,7 @@ import io.legado.app.model.webBook.WebBook import io.legado.app.service.CacheBookService import io.legado.app.utils.msg import kotlinx.coroutines.CoroutineScope +import splitties.init.appCtx import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArraySet @@ -81,7 +81,7 @@ object CacheBook { ReadBook.contentLoadFinish( book, chapter, - content.ifBlank { App.INSTANCE.getString(R.string.content_empty) }, + content.ifBlank { appCtx.getString(R.string.content_empty) }, resetPageOffset = resetPageOffset ) } diff --git a/app/src/main/java/io/legado/app/service/help/CheckSource.kt b/app/src/main/java/io/legado/app/service/help/CheckSource.kt index d38e6c225..725c303e7 100644 --- a/app/src/main/java/io/legado/app/service/help/CheckSource.kt +++ b/app/src/main/java/io/legado/app/service/help/CheckSource.kt @@ -6,14 +6,14 @@ import io.legado.app.R import io.legado.app.constant.IntentAction import io.legado.app.data.entities.BookSource import io.legado.app.service.CheckSourceService -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi object CheckSource { var keyword = "我的" fun start(context: Context, sources: List) { if (sources.isEmpty()) { - context.toast(R.string.non_select) + context.toastOnUi(R.string.non_select) return } val selectedIds: ArrayList = arrayListOf() diff --git a/app/src/main/java/io/legado/app/service/help/ReadAloud.kt b/app/src/main/java/io/legado/app/service/help/ReadAloud.kt index 1bcdae796..fb0b71804 100644 --- a/app/src/main/java/io/legado/app/service/help/ReadAloud.kt +++ b/app/src/main/java/io/legado/app/service/help/ReadAloud.kt @@ -2,22 +2,23 @@ package io.legado.app.service.help import android.content.Context import android.content.Intent -import io.legado.app.App import io.legado.app.constant.IntentAction import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.HttpTTS import io.legado.app.service.BaseReadAloudService import io.legado.app.service.HttpReadAloudService import io.legado.app.service.TTSReadAloudService import io.legado.app.utils.getPrefLong +import splitties.init.appCtx object ReadAloud { private var aloudClass: Class<*> = getReadAloudClass() var httpTTS: HttpTTS? = null private fun getReadAloudClass(): Class<*> { - val spId = App.INSTANCE.getPrefLong(PreferKey.speakEngine) - httpTTS = App.db.httpTTSDao.get(spId) + val spId = appCtx.getPrefLong(PreferKey.speakEngine) + httpTTS = appDb.httpTTSDao.get(spId) return if (httpTTS != null) { HttpReadAloudService::class.java } else { @@ -26,7 +27,7 @@ object ReadAloud { } fun upReadAloudClass() { - stop(App.INSTANCE) + stop(appCtx) aloudClass = getReadAloudClass() } diff --git a/app/src/main/java/io/legado/app/service/help/ReadBook.kt b/app/src/main/java/io/legado/app/service/help/ReadBook.kt index 1a2d7b340..5b6f33b6e 100644 --- a/app/src/main/java/io/legado/app/service/help/ReadBook.kt +++ b/app/src/main/java/io/legado/app/service/help/ReadBook.kt @@ -2,8 +2,8 @@ package io.legado.app.service.help import androidx.lifecycle.MutableLiveData import com.hankcs.hanlp.HanLP -import io.legado.app.App import io.legado.app.constant.BookType +import io.legado.app.data.appDb import io.legado.app.data.entities.* import io.legado.app.help.* import io.legado.app.help.coroutine.Coroutine @@ -14,12 +14,13 @@ import io.legado.app.ui.book.read.page.entities.TextChapter import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ImageProvider +import io.legado.app.utils.msg +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import org.jetbrains.anko.getStackTraceString -import org.jetbrains.anko.toast +import splitties.init.appCtx @Suppress("MemberVisibilityCanBePrivate") @@ -47,7 +48,7 @@ object ReadBook { this.book = book contentProcessor = ContentProcessor(book.name, book.origin) readRecord.bookName = book.name - readRecord.readTime = App.db.readRecordDao.getReadTime(book.name) ?: 0 + readRecord.readTime = appDb.readRecordDao.getReadTime(book.name) ?: 0 durChapterIndex = book.durChapterIndex durChapterPos = book.durChapterPos isLocalBook = book.origin == BookType.local @@ -67,7 +68,7 @@ object ReadBook { bookSource = null webBook = null } else { - App.db.bookSourceDao.getBookSource(book.origin)?.let { + appDb.bookSourceDao.getBookSource(book.origin)?.let { bookSource = it webBook = WebBook(it) } ?: let { @@ -102,7 +103,7 @@ object ReadBook { Coroutine.async { readRecord.readTime = readRecord.readTime + System.currentTimeMillis() - readStartTime readStartTime = System.currentTimeMillis() - App.db.readRecordDao.insert(readRecord) + appDb.readRecordDao.insert(readRecord) } } @@ -215,7 +216,7 @@ object ReadBook { if (book != null && textChapter != null) { val key = IntentDataHelp.putData(textChapter) ReadAloud.play( - App.INSTANCE, book.name, textChapter.title, durPageIndex(), key, play + appCtx, book.name, textChapter.title, durPageIndex(), key, play ) } } @@ -259,7 +260,7 @@ object ReadBook { book?.let { book -> if (addLoading(index)) { Coroutine.async { - App.db.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter -> + appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter -> BookHelp.getContent(book, chapter)?.let { contentLoadFinish(book, chapter, it, upContent, resetPageOffset) { success?.invoke() @@ -279,7 +280,7 @@ object ReadBook { if (book.isLocalBook()) return if (addLoading(index)) { Coroutine.async { - App.db.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter -> + appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter -> if (BookHelp.hasContent(book, chapter)) { removeLoading(chapter.index) } else { @@ -437,7 +438,7 @@ object ReadBook { } }.onError { it.printStackTrace() - App.INSTANCE.toast("ChapterProvider ERROR:\n${it.getStackTraceString()}") + appCtx.toastOnUi("ChapterProvider ERROR:\n${it.msg}") }.onSuccess { success?.invoke() } @@ -470,10 +471,10 @@ object ReadBook { book.durChapterTime = System.currentTimeMillis() book.durChapterIndex = durChapterIndex book.durChapterPos = durChapterPos - App.db.bookChapterDao.getChapter(book.bookUrl, durChapterIndex)?.let { + appDb.bookChapterDao.getChapter(book.bookUrl, durChapterIndex)?.let { book.durChapterTitle = it.title } - App.db.bookDao.update(book) + appDb.bookDao.update(book) } } } diff --git a/app/src/main/java/io/legado/app/ui/about/AboutActivity.kt b/app/src/main/java/io/legado/app/ui/about/AboutActivity.kt index f6c9088de..2c669aacd 100644 --- a/app/src/main/java/io/legado/app/ui/about/AboutActivity.kt +++ b/app/src/main/java/io/legado/app/ui/about/AboutActivity.kt @@ -12,7 +12,7 @@ import io.legado.app.databinding.ActivityAboutBinding import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.accentColor import io.legado.app.utils.openUrl -import org.jetbrains.anko.share +import io.legado.app.utils.share class AboutActivity : BaseActivity() { diff --git a/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt b/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt index 321ba268b..96297729f 100644 --- a/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt +++ b/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt @@ -7,15 +7,15 @@ import android.view.View import androidx.annotation.StringRes import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat -import io.legado.app.App import io.legado.app.R +import io.legado.app.constant.appInfo import io.legado.app.help.AppConfig import io.legado.app.lib.dialogs.alert import io.legado.app.ui.widget.dialog.TextDialog import io.legado.app.utils.openUrl import io.legado.app.utils.sendMail import io.legado.app.utils.sendToClip -import io.legado.app.utils.toast +import io.legado.app.utils.toastOnUi class AboutFragment : PreferenceFragmentCompat() { @@ -39,7 +39,7 @@ class AboutFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.about) findPreference("update_log")?.summary = - "${getString(R.string.version)} ${App.versionName}" + "${getString(R.string.version)} ${appInfo.versionName}" if (AppConfig.isGooglePlay) { preferenceScreen.removePreferenceRecursively("check_update") } @@ -105,7 +105,7 @@ class AboutFragment : PreferenceFragmentCompat() { startActivity(intent) return true }.onFailure { - toast("添加失败,请手动添加") + toastOnUi("添加失败,请手动添加") } return false } diff --git a/app/src/main/java/io/legado/app/ui/about/DonateFragment.kt b/app/src/main/java/io/legado/app/ui/about/DonateFragment.kt index b716c8f05..29da08d54 100644 --- a/app/src/main/java/io/legado/app/ui/about/DonateFragment.kt +++ b/app/src/main/java/io/legado/app/ui/about/DonateFragment.kt @@ -8,9 +8,9 @@ import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import io.legado.app.R import io.legado.app.utils.ACache +import io.legado.app.utils.longToastOnUi import io.legado.app.utils.openUrl import io.legado.app.utils.sendToClip -import org.jetbrains.anko.longToast class DonateFragment : PreferenceFragmentCompat() { @@ -42,7 +42,7 @@ class DonateFragment : PreferenceFragmentCompat() { private fun getZfbHb(context: Context) { requireContext().sendToClip("537954522") - context.longToast("高级功能已开启\n红包码已复制\n支付宝首页搜索“537954522” 立即领红包") + context.longToastOnUi("高级功能已开启\n红包码已复制\n支付宝首页搜索“537954522” 立即领红包") try { val packageManager = context.applicationContext.packageManager val intent = packageManager.getLaunchIntentForPackage("com.eg.android.AlipayGphone")!! diff --git a/app/src/main/java/io/legado/app/ui/about/ReadRecordActivity.kt b/app/src/main/java/io/legado/app/ui/about/ReadRecordActivity.kt index ea467af80..8d3295299 100644 --- a/app/src/main/java/io/legado/app/ui/about/ReadRecordActivity.kt +++ b/app/src/main/java/io/legado/app/ui/about/ReadRecordActivity.kt @@ -5,11 +5,11 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.ViewGroup -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseActivity import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.appDb import io.legado.app.data.entities.ReadRecordShow import io.legado.app.databinding.ActivityReadRecordBinding import io.legado.app.databinding.ItemReadRecordBinding @@ -19,7 +19,6 @@ import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.jetbrains.anko.sdk27.listeners.onClick import java.util.* class ReadRecordActivity : BaseActivity() { @@ -59,10 +58,10 @@ class ReadRecordActivity : BaseActivity() { readRecord.tvBookName.setText(R.string.all_read_time) adapter = RecordAdapter(this@ReadRecordActivity) recyclerView.adapter = adapter - readRecord.ivRemove.onClick { + readRecord.tvRemove.setOnClickListener { alert(R.string.delete, R.string.sure_del) { okButton { - App.db.readRecordDao.clear() + appDb.readRecordDao.clear() initData() } noButton() @@ -72,11 +71,11 @@ class ReadRecordActivity : BaseActivity() { private fun initData() { launch(IO) { - val allTime = App.db.readRecordDao.allTime + val allTime = appDb.readRecordDao.allTime withContext(Main) { binding.readRecord.tvReadTime.text = formatDuring(allTime) } - var readRecords = App.db.readRecordDao.allShow + var readRecords = appDb.readRecordDao.allShow readRecords = when (sortMode) { 1 -> readRecords.sortedBy { it.readTime } else -> { @@ -112,7 +111,7 @@ class ReadRecordActivity : BaseActivity() { override fun registerListener(holder: ItemViewHolder, binding: ItemReadRecordBinding) { binding.apply { - ivRemove.onClick { + tvRemove.setOnClickListener { getItem(holder.layoutPosition)?.let { item -> sureDelAlert(item) } @@ -122,9 +121,9 @@ class ReadRecordActivity : BaseActivity() { private fun sureDelAlert(item: ReadRecordShow) { alert(R.string.delete) { - message = getString(R.string.sure_del_any, item.bookName) + setMessage(getString(R.string.sure_del_any, item.bookName)) okButton { - App.db.readRecordDao.deleteByName(item.bookName) + appDb.readRecordDao.deleteByName(item.bookName) initData() } noButton() @@ -142,7 +141,11 @@ class ReadRecordActivity : BaseActivity() { val h = if (hours > 0) "${hours}小时" else "" val m = if (minutes > 0) "${minutes}分钟" else "" val s = if (seconds > 0) "${seconds}秒" else "" - return "$d$h$m$s" + var time = "$d$h$m$s" + if (time.isBlank()) { + time = "0秒" + } + return time } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt b/app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt index a9f79def1..67aec440f 100644 --- a/app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt +++ b/app/src/main/java/io/legado/app/ui/association/FileAssociationActivity.kt @@ -2,14 +2,14 @@ package io.legado.app.ui.association import android.content.Intent import android.os.Bundle +import androidx.activity.viewModels import io.legado.app.base.VMBaseActivity import io.legado.app.constant.Theme import io.legado.app.databinding.ActivityTranslucenceBinding import io.legado.app.ui.main.MainActivity -import io.legado.app.utils.getViewModel -import org.jetbrains.anko.startActivity -import org.jetbrains.anko.toast +import io.legado.app.utils.startActivity +import io.legado.app.utils.toastOnUi class FileAssociationActivity : VMBaseActivity( @@ -20,14 +20,13 @@ class FileAssociationActivity : return ActivityTranslucenceBinding.inflate(layoutInflater) } - override val viewModel: FileAssociationViewModel - get() = getViewModel(FileAssociationViewModel::class.java) + override val viewModel: FileAssociationViewModel by viewModels() override fun onActivityCreated(savedInstanceState: Bundle?) { binding.rotateLoading.show() viewModel.errorLiveData.observe(this, { binding.rotateLoading.hide() - toast(it) + toastOnUi(it) finish() }) viewModel.successLiveData.observe(this, { diff --git a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceActivity.kt index f6e11de63..09007b795 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceActivity.kt @@ -1,14 +1,15 @@ package io.legado.app.ui.association import android.os.Bundle +import androidx.activity.viewModels import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.Theme import io.legado.app.databinding.ActivityTranslucenceBinding import io.legado.app.help.IntentDataHelp import io.legado.app.lib.dialogs.alert -import io.legado.app.utils.getViewModel -import org.jetbrains.anko.toast + +import io.legado.app.utils.toastOnUi class ImportBookSourceActivity : @@ -21,7 +22,7 @@ class ImportBookSourceActivity : } override val viewModel: ImportBookSourceViewModel - get() = getViewModel(ImportBookSourceViewModel::class.java) + by viewModels() override fun onActivityCreated(savedInstanceState: Bundle?) { binding.rotateLoading.show() @@ -66,7 +67,7 @@ class ImportBookSourceActivity : } else -> { binding.rotateLoading.hide() - toast(R.string.wrong_format) + toastOnUi(R.string.wrong_format) finish() } } 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 0f3e6008f..2b5c2fea6 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 @@ -9,23 +9,27 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogRecyclerViewBinding import io.legado.app.databinding.ItemSourceImportBinding import io.legado.app.help.AppConfig import io.legado.app.lib.dialogs.alert -import io.legado.app.utils.* +import io.legado.app.utils.dp +import io.legado.app.utils.putPrefBoolean +import io.legado.app.utils.splitNotBlank import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick +import io.legado.app.utils.visible + /** * 导入书源弹出窗口 @@ -34,8 +38,7 @@ class ImportBookSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickList private val binding by viewBinding(DialogRecyclerViewBinding::bind) - val viewModel: ImportBookSourceViewModel - get() = getViewModelOfActivity(ImportBookSourceViewModel::class.java) + val viewModel: ImportBookSourceViewModel by viewModels() lateinit var adapter: SourcesAdapter override fun onStart() { @@ -62,11 +65,11 @@ class ImportBookSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickList binding.recyclerView.adapter = adapter adapter.setItems(viewModel.allSources) binding.tvCancel.visible() - binding.tvCancel.onClick { + binding.tvCancel.setOnClickListener { dismiss() } binding.tvOk.visible() - binding.tvOk.onClick { + binding.tvOk.setOnClickListener { viewModel.importSelect { dismiss() } @@ -87,13 +90,15 @@ class ImportBookSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickList alert(R.string.diy_edit_source_group) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { val groups = linkedSetOf() - App.db.bookSourceDao.allGroup.forEach { group -> + appDb.bookSourceDao.allGroup.forEach { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) } editView.setFilterValues(groups.toList()) editView.dropDownHeight = 180.dp } - customView = alertBinding.root + customView { + alertBinding.root + } okButton { alertBinding.editView.text?.toString()?.let { group -> viewModel.groupName = group diff --git a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt index 8b3397a0c..35a7031b9 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt @@ -5,9 +5,9 @@ import android.net.Uri import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.MutableLiveData import com.jayway.jsonpath.JsonPath -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.help.AppConfig import io.legado.app.help.SourceHelp @@ -134,7 +134,7 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) { private fun comparisonSource() { execute { allSources.forEach { - val has = App.db.bookSourceDao.getBookSource(it.bookSourceUrl) + val has = appDb.bookSourceDao.getBookSource(it.bookSourceUrl) checkSources.add(has) selectStatus.add(has == null) } diff --git a/app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleActivity.kt b/app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleActivity.kt index 19e90b540..d048b1264 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleActivity.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportReplaceRuleActivity.kt @@ -1,15 +1,15 @@ package io.legado.app.ui.association import android.os.Bundle -import io.legado.app.App +import androidx.activity.viewModels import io.legado.app.base.VMBaseActivity import io.legado.app.constant.Theme +import io.legado.app.data.appDb import io.legado.app.data.entities.ReplaceRule import io.legado.app.databinding.ActivityTranslucenceBinding import io.legado.app.help.IntentDataHelp import io.legado.app.lib.dialogs.alert -import io.legado.app.utils.getViewModel -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi class ImportReplaceRuleActivity : VMBaseActivity( @@ -21,7 +21,7 @@ class ImportReplaceRuleActivity : } override val viewModel: ImportReplaceRuleViewModel - get() = getViewModel(ImportReplaceRuleViewModel::class.java) + by viewModels() override fun onActivityCreated(savedInstanceState: Bundle?) { binding.rotateLoading.show() @@ -66,7 +66,7 @@ class ImportReplaceRuleActivity : } else -> { binding.rotateLoading.hide() - toast("格式不对") + toastOnUi("格式不对") finish() } } @@ -85,7 +85,7 @@ class ImportReplaceRuleActivity : private fun successDialog(allSource: ArrayList) { alert("解析结果", "共${allSource.size}个替换规则,是否确认导入?") { okButton { - App.db.replaceRuleDao.insert(*allSource.toTypedArray()) + appDb.replaceRuleDao.insert(*allSource.toTypedArray()) } noButton() onDismiss { diff --git a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceActivity.kt b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceActivity.kt index 76e7bb2c7..3a8efd37b 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceActivity.kt @@ -1,14 +1,15 @@ package io.legado.app.ui.association import android.os.Bundle +import androidx.activity.viewModels import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.Theme import io.legado.app.databinding.ActivityTranslucenceBinding import io.legado.app.help.IntentDataHelp import io.legado.app.lib.dialogs.alert -import io.legado.app.utils.getViewModel -import org.jetbrains.anko.toast + +import io.legado.app.utils.toastOnUi class ImportRssSourceActivity : VMBaseActivity( @@ -20,7 +21,7 @@ class ImportRssSourceActivity : } override val viewModel: ImportRssSourceViewModel - get() = getViewModel(ImportRssSourceViewModel::class.java) + by viewModels() override fun onActivityCreated(savedInstanceState: Bundle?) { binding.rotateLoading.show() @@ -65,7 +66,7 @@ class ImportRssSourceActivity : } else -> { binding.rotateLoading.hide() - toast(R.string.wrong_format) + toastOnUi(R.string.wrong_format) finish() } } 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 5ad9aeee7..265d10a18 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 @@ -9,23 +9,26 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.RssSource import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogRecyclerViewBinding import io.legado.app.databinding.ItemSourceImportBinding import io.legado.app.help.AppConfig import io.legado.app.lib.dialogs.alert -import io.legado.app.utils.* +import io.legado.app.utils.dp +import io.legado.app.utils.putPrefBoolean +import io.legado.app.utils.splitNotBlank import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick +import io.legado.app.utils.visible /** * 导入rss源弹出窗口 @@ -35,7 +38,7 @@ class ImportRssSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListe private val binding by viewBinding(DialogRecyclerViewBinding::bind) val viewModel: ImportRssSourceViewModel - get() = getViewModelOfActivity(ImportRssSourceViewModel::class.java) + by activityViewModels() lateinit var adapter: SourcesAdapter override fun onStart() { @@ -62,11 +65,11 @@ class ImportRssSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListe binding.recyclerView.adapter = adapter adapter.setItems(viewModel.allSources) binding.tvCancel.visible() - binding.tvCancel.onClick { + binding.tvCancel.setOnClickListener { dismiss() } binding.tvOk.visible() - binding.tvOk.onClick { + binding.tvOk.setOnClickListener { viewModel.importSelect { dismiss() } @@ -87,13 +90,15 @@ class ImportRssSourceDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListe alert(R.string.diy_edit_source_group) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { val groups = linkedSetOf() - App.db.rssSourceDao.allGroup.forEach { group -> + appDb.rssSourceDao.allGroup.forEach { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) } editView.setFilterValues(groups.toList()) editView.dropDownHeight = 180.dp } - customView = alertBinding.root + customView { + alertBinding.root + } okButton { alertBinding.editView.text?.toString()?.let { group -> viewModel.groupName = group diff --git a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt index 35aad7c27..1a972ec46 100644 --- a/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/association/ImportRssSourceViewModel.kt @@ -5,9 +5,9 @@ import android.net.Uri import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.MutableLiveData import com.jayway.jsonpath.JsonPath -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.RssSource import io.legado.app.help.AppConfig import io.legado.app.help.SourceHelp @@ -129,7 +129,7 @@ class ImportRssSourceViewModel(app: Application) : BaseViewModel(app) { private fun comparisonSource() { execute { allSources.forEach { - val has = App.db.rssSourceDao.getByKey(it.sourceUrl) + val has = appDb.rssSourceDao.getByKey(it.sourceUrl) checkSources.add(has) selectStatus.add(has == null) } diff --git a/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt b/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt index aa8a95a83..a210aeb99 100644 --- a/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt +++ b/app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt @@ -9,6 +9,7 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.widget.SeekBar +import androidx.activity.viewModels import com.bumptech.glide.RequestBuilder import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.request.RequestOptions.bitmapTransform @@ -28,9 +29,7 @@ import io.legado.app.ui.book.toc.ChapterListActivity import io.legado.app.ui.widget.image.CoverImageView import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.utils.* -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick -import org.jetbrains.anko.startActivityForResult +import splitties.views.onLongClick import java.util.* /** @@ -41,7 +40,7 @@ class AudioPlayActivity : ChangeSourceDialog.CallBack { override val viewModel: AudioPlayViewModel - get() = getViewModel(AudioPlayViewModel::class.java) + by viewModels() private var requestCodeChapter = 8461 private var adjustProgress = false @@ -80,18 +79,17 @@ class AudioPlayActivity : } private fun initView() { - binding.fabPlayStop.onClick { + binding.fabPlayStop.setOnClickListener { playButton() } binding.fabPlayStop.onLongClick { - AudioPlay.stop(this) - true + AudioPlay.stop(this@AudioPlayActivity) } - binding.ivSkipNext.onClick { - AudioPlay.next(this) + binding.ivSkipNext.setOnClickListener { + AudioPlay.next(this@AudioPlayActivity) } - binding.ivSkipPrevious.onClick { - AudioPlay.prev(this) + binding.ivSkipPrevious.setOnClickListener { + AudioPlay.prev(this@AudioPlayActivity) } binding.playerProgress.setOnSeekBarChangeListener(object : SeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { @@ -107,26 +105,25 @@ class AudioPlayActivity : AudioPlay.adjustProgress(this@AudioPlayActivity, seekBar.progress) } }) - binding.ivChapter.onClick { + binding.ivChapter.setOnClickListener { AudioPlay.book?.let { - startActivityForResult( - requestCodeChapter, - Pair("bookUrl", it.bookUrl) - ) + startActivityForResult(requestCodeChapter) { + putExtra("bookUrl", it.bookUrl) + } } } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { binding.ivFastRewind.invisible() binding.ivFastForward.invisible() } - binding.ivFastForward.onClick { - AudioPlay.adjustSpeed(this, 0.1f) + binding.ivFastForward.setOnClickListener { + AudioPlay.adjustSpeed(this@AudioPlayActivity, 0.1f) } - binding.ivFastRewind.onClick { - AudioPlay.adjustSpeed(this, -0.1f) + binding.ivFastRewind.setOnClickListener { + AudioPlay.adjustSpeed(this@AudioPlayActivity, -0.1f) } - binding.ivTimer.onClick { - AudioPlay.addTimer(this) + binding.ivTimer.setOnClickListener { + AudioPlay.addTimer(this@AudioPlayActivity) } } @@ -166,7 +163,7 @@ class AudioPlayActivity : AudioPlay.book?.let { if (!AudioPlay.inBookshelf) { alert(title = getString(R.string.add_to_shelf)) { - message = getString(R.string.check_add_bookshelf, it.name) + setMessage(getString(R.string.check_add_bookshelf, it.name)) okButton { AudioPlay.inBookshelf = true setResult(Activity.RESULT_OK) diff --git a/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt b/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt index 184663f3d..c5cd330ef 100644 --- a/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt @@ -2,9 +2,9 @@ package io.legado.app.ui.audio import android.app.Application import android.content.Intent -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp @@ -21,18 +21,18 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) stop(context) inBookshelf = intent.getBooleanExtra("inBookshelf", true) book = if (!bookUrl.isNullOrEmpty()) { - App.db.bookDao.getBook(bookUrl) + appDb.bookDao.getBook(bookUrl) } else { - App.db.bookDao.lastReadBook + appDb.bookDao.lastReadBook } book?.let { book -> titleData.postValue(book.name) coverData.postValue(book.getDisplayCover()) durChapterIndex = book.durChapterIndex durChapterPos = book.durChapterPos - durChapter = App.db.bookChapterDao.getChapter(book.bookUrl, durChapterIndex) + durChapter = appDb.bookChapterDao.getChapter(book.bookUrl, durChapterIndex) upDurChapter(book) - App.db.bookSourceDao.getBookSource(book.origin)?.let { + appDb.bookSourceDao.getBookSource(book.origin)?.let { webBook = WebBook(it) } if (durChapter == null) { @@ -69,16 +69,16 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) ?.onSuccess(Dispatchers.IO) { cList -> if (cList.isNotEmpty()) { if (changeDruChapterIndex == null) { - App.db.bookChapterDao.insert(*cList.toTypedArray()) + appDb.bookChapterDao.insert(*cList.toTypedArray()) } else { changeDruChapterIndex(cList) } AudioPlay.upDurChapter(book) } else { - toast(R.string.error_load_toc) + toastOnUi(R.string.error_load_toc) } }?.onError { - toast(R.string.error_load_toc) + toastOnUi(R.string.error_load_toc) } } } @@ -89,11 +89,11 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) AudioPlay.book?.let { oldTocSize = it.totalChapterNum book1.order = it.order - App.db.bookDao.delete(it) + appDb.bookDao.delete(it) } - App.db.bookDao.insert(book1) + appDb.bookDao.insert(book1) AudioPlay.book = book1 - App.db.bookSourceDao.getBookSource(book1.origin)?.let { + appDb.bookSourceDao.getBookSource(book1.origin)?.let { AudioPlay.webBook = WebBook(it) } if (book1.tocUrl.isEmpty()) { @@ -118,15 +118,15 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application) ) book.durChapterIndex = AudioPlay.durChapterIndex book.durChapterTitle = chapters[AudioPlay.durChapterIndex].title - App.db.bookDao.update(book) - App.db.bookChapterDao.insert(*chapters.toTypedArray()) + appDb.bookDao.update(book) + appDb.bookChapterDao.insert(*chapters.toTypedArray()) } } fun removeFromBookshelf(success: (() -> Unit)?) { execute { AudioPlay.book?.let { - App.db.bookDao.delete(it) + appDb.bookDao.delete(it) } }.onSuccess { success?.invoke() diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt index 216fc076a..d75e13828 100644 --- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookActivity.kt @@ -3,15 +3,16 @@ package io.legado.app.ui.book.arrange import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.lifecycle.LiveData import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppConst import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookGroup import io.legado.app.databinding.ActivityArrangeBookBinding @@ -25,7 +26,6 @@ import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.cnCompare import io.legado.app.utils.getPrefInt -import io.legado.app.utils.getViewModel class ArrangeBookActivity : VMBaseActivity(), @@ -34,7 +34,7 @@ class ArrangeBookActivity : VMBaseActivity = arrayListOf() private val groupRequestCode = 22 private val addToGroupRequestCode = 34 @@ -102,7 +102,7 @@ class ArrangeBookActivity : VMBaseActivity App.db.bookDao.observeAll() - AppConst.bookGroupLocalId -> App.db.bookDao.observeLocal() - AppConst.bookGroupAudioId -> App.db.bookDao.observeAudio() - AppConst.bookGroupNoneId -> App.db.bookDao.observeNoGroup() - else -> App.db.bookDao.observeByGroup(groupId) + AppConst.bookGroupAllId -> appDb.bookDao.observeAll() + AppConst.bookGroupLocalId -> appDb.bookDao.observeLocal() + AppConst.bookGroupAudioId -> appDb.bookDao.observeAudio() + AppConst.bookGroupNoneId -> appDb.bookDao.observeNoGroup() + else -> appDb.bookDao.observeByGroup(groupId) } booksLiveData?.observe(this, { list -> val books = when (getPrefInt(PreferKey.bookshelfSort)) { @@ -140,7 +140,7 @@ class ArrangeBookActivity : VMBaseActivity if (item.groupId == R.id.menu_group) { binding.titleBar.subtitle = item.title - groupId = App.db.bookGroupDao.getByName(item.title.toString())?.groupId ?: 0 + groupId = appDb.bookGroupDao.getByName(item.title.toString())?.groupId ?: 0 initBookData() } } diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt index d2423de01..00474109f 100644 --- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookAdapter.kt @@ -13,8 +13,6 @@ import io.legado.app.databinding.ItemArrangeBookBinding import io.legado.app.lib.theme.backgroundColor import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback -import org.jetbrains.anko.backgroundColor -import org.jetbrains.anko.sdk27.listeners.onClick import java.util.* class ArrangeBookAdapter(context: Context, val callBack: CallBack) : @@ -40,7 +38,7 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) : payloads: MutableList ) { binding.apply { - root.backgroundColor = context.backgroundColor + root.setBackgroundColor(context.backgroundColor) tvName.text = item.name tvAuthor.text = item.author tvAuthor.visibility = if (item.author.isEmpty()) View.GONE else View.VISIBLE @@ -65,7 +63,7 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) : } } } - root.onClick { + root.setOnClickListener { getItem(holder.layoutPosition)?.let { checkbox.isChecked = !checkbox.isChecked if (checkbox.isChecked) { @@ -76,12 +74,12 @@ class ArrangeBookAdapter(context: Context, val callBack: CallBack) : callBack.upSelectCount() } } - tvDelete.onClick { + tvDelete.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.deleteBook(it) } } - tvGroup.onClick { + tvGroup.setOnClickListener { getItem(holder.layoutPosition)?.let { actionItem = it callBack.selectGroup(groupRequestCode, it.group) diff --git a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookViewModel.kt index 890fcf8bb..c6d389997 100644 --- a/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/arrange/ArrangeBookViewModel.kt @@ -1,8 +1,8 @@ package io.legado.app.ui.book.arrange import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book @@ -13,19 +13,19 @@ class ArrangeBookViewModel(application: Application) : BaseViewModel(application books.forEach { it.canUpdate = canUpdate } - App.db.bookDao.update(*books) + appDb.bookDao.update(*books) } } fun updateBook(vararg book: Book) { execute { - App.db.bookDao.update(*book) + appDb.bookDao.update(*book) } } fun deleteBook(vararg book: Book) { execute { - App.db.bookDao.delete(*book) + appDb.bookDao.delete(*book) } } 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 1e417a1a0..f77daa7d2 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 @@ -5,15 +5,16 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.activity.viewModels import androidx.lifecycle.LiveData import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.snackbar.Snackbar -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppConst import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookGroup @@ -46,7 +47,7 @@ class CacheActivity : VMBaseActivity() private var groupId: Long = -1 override val viewModel: CacheViewModel - get() = getViewModel(CacheViewModel::class.java) + by viewModels() override fun getViewBinding(): ActivityCacheBookBinding { return ActivityCacheBookBinding.inflate(layoutInflater) @@ -101,7 +102,7 @@ class CacheActivity : VMBaseActivity() } else -> if (item.groupId == R.id.menu_group) { binding.titleBar.subtitle = item.title - groupId = App.db.bookGroupDao.getByName(item.title.toString())?.groupId ?: 0 + groupId = appDb.bookGroupDao.getByName(item.title.toString())?.groupId ?: 0 initBookData() } } @@ -117,11 +118,11 @@ class CacheActivity : VMBaseActivity() private fun initBookData() { booksLiveData?.removeObservers(this) booksLiveData = when (groupId) { - AppConst.bookGroupAllId -> App.db.bookDao.observeAll() - AppConst.bookGroupLocalId -> App.db.bookDao.observeLocal() - AppConst.bookGroupAudioId -> App.db.bookDao.observeAudio() - AppConst.bookGroupNoneId -> App.db.bookDao.observeNoGroup() - else -> App.db.bookDao.observeByGroup(groupId) + AppConst.bookGroupAllId -> appDb.bookDao.observeAll() + AppConst.bookGroupLocalId -> appDb.bookDao.observeLocal() + AppConst.bookGroupAudioId -> appDb.bookDao.observeAudio() + AppConst.bookGroupNoneId -> appDb.bookDao.observeNoGroup() + else -> appDb.bookDao.observeByGroup(groupId) } booksLiveData?.observe(this, { list -> val booksDownload = list.filter { @@ -142,7 +143,7 @@ class CacheActivity : VMBaseActivity() private fun initGroupData() { groupLiveData?.removeObservers(this) - groupLiveData = App.db.bookGroupDao.liveDataAll() + groupLiveData = appDb.bookGroupDao.liveDataAll() groupLiveData?.observe(this, { groupList.clear() groupList.addAll(it) @@ -156,7 +157,7 @@ class CacheActivity : VMBaseActivity() books.forEach { book -> val chapterCaches = hashSetOf() val cacheNames = BookHelp.getChapterFiles(book) - App.db.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> + appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> if (cacheNames.contains(chapter.getFileName())) { chapterCaches.add(chapter.url) } diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt index c7e3209b8..96d20d3df 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt @@ -10,7 +10,7 @@ import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.databinding.ItemDownloadBinding import io.legado.app.service.help.CacheBook -import org.jetbrains.anko.sdk27.listeners.onClick + import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArraySet @@ -54,7 +54,7 @@ class CacheAdapter(context: Context, private val callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemDownloadBinding) { with(binding) { - ivDownload.onClick { + ivDownload.setOnClickListener { getItem(holder.layoutPosition)?.let { if (downloadMap?.containsKey(it.bookUrl) == true) { CacheBook.remove(context, it.bookUrl) @@ -63,7 +63,7 @@ class CacheAdapter(context: Context, private val callBack: CallBack) : } } } - tvExport.onClick { + tvExport.setOnClickListener { callBack.export(holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt index 2df117411..9737b618a 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt @@ -3,16 +3,17 @@ package io.legado.app.ui.book.cache import android.app.Application import android.net.Uri import androidx.documentfile.provider.DocumentFile -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.help.BookHelp import io.legado.app.help.ContentProcessor import io.legado.app.help.storage.BookWebDav import io.legado.app.utils.* +import splitties.init.appCtx import java.io.File @@ -41,7 +42,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val content = getAllContents(book) DocumentUtils.createFileIfNotExist(doc, filename) ?.writeText(context, content) - if (App.INSTANCE.getPrefBoolean(PreferKey.webDavCacheBackup, false)) { + if (appCtx.getPrefBoolean(PreferKey.webDavCacheBackup, false)) { FileUtils.createFileIfNotExist( File(FileUtils.getCachePath()), filename @@ -67,7 +68,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val filename = "${book.name} by ${book.author}.txt" FileUtils.createFileIfNotExist(file, filename) .writeText(getAllContents(book)) - if (App.INSTANCE.getPrefBoolean(PreferKey.webDavCacheBackup, false)) { + if (appCtx.getPrefBoolean(PreferKey.webDavCacheBackup, false)) { BookWebDav.exportWebDav(file.absolutePath, filename) // 导出到webdav } getSrcList(book).forEach { @@ -90,7 +91,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { stringBuilder.append(book.name) .append("\n") .append(context.getString(R.string.author_show, book.author)) - App.db.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> + appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> BookHelp.getContent(book, chapter).let { content -> val content1 = contentProcessor .getContent(book, chapter.title, content ?: "null", false) @@ -104,7 +105,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { private fun getSrcList(book: Book): ArrayList> { val srcList = arrayListOf>() - App.db.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> + appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> BookHelp.getContent(book, chapter)?.let { content -> content.split("\n").forEachIndexed { index, text -> val matcher = AppPattern.imgPattern.matcher(text) 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 483fbbb75..cf3eb8d1f 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 @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.GridLayoutManager import io.legado.app.R import io.legado.app.base.BaseDialogFragment @@ -14,7 +15,7 @@ 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.getViewModel + import io.legado.app.utils.viewbindingdelegate.viewBinding @@ -39,7 +40,7 @@ class ChangeCoverDialog : BaseDialogFragment(), private val binding by viewBinding(DialogChangeCoverBinding::bind) private var callBack: CallBack? = null - private lateinit var viewModel: ChangeCoverViewModel + private val viewModel: ChangeCoverViewModel by viewModels() lateinit var adapter: CoverAdapter override fun onStart() { @@ -54,7 +55,6 @@ class ChangeCoverDialog : BaseDialogFragment(), savedInstanceState: Bundle? ): View? { callBack = activity as? CallBack - viewModel = getViewModel(ChangeCoverViewModel::class.java) return inflater.inflate(R.layout.dialog_change_cover, container) } diff --git a/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt index 2bfcffdaa..64ec67578 100644 --- a/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt @@ -5,9 +5,9 @@ import android.os.Bundle import android.os.Handler import android.os.Looper import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.help.AppConfig @@ -55,7 +55,7 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application fun loadDbSearchBook() { execute { - App.db.searchBookDao.getEnableHasCover(name, author).let { + appDb.searchBookDao.getEnableHasCover(name, author).let { searchBooks.addAll(it) searchBooksLiveData.postValue(searchBooks.toList()) if (it.size <= 1) { @@ -81,7 +81,7 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application private fun startSearch() { execute { bookSourceList.clear() - bookSourceList.addAll(App.db.bookSourceDao.allEnabled) + bookSourceList.addAll(appDb.bookSourceDao.allEnabled) searchStateData.postValue(true) initSearchPool() for (i in 0 until threadCount) { @@ -106,7 +106,7 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application if (searchBook.name == name && searchBook.author == author && !searchBook.coverUrl.isNullOrEmpty() ) { - App.db.searchBookDao.insert(searchBook) + appDb.searchBookDao.insert(searchBook) if (!searchBooks.contains(searchBook)) { searchBooks.add(searchBook) upAdapter() diff --git a/app/src/main/java/io/legado/app/ui/book/changecover/CoverAdapter.kt b/app/src/main/java/io/legado/app/ui/book/changecover/CoverAdapter.kt index 2d181d28c..0f75ed99f 100644 --- a/app/src/main/java/io/legado/app/ui/book/changecover/CoverAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/changecover/CoverAdapter.kt @@ -7,7 +7,7 @@ import io.legado.app.base.adapter.DiffRecyclerAdapter import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.ItemCoverBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class CoverAdapter(context: Context, val callBack: CallBack) : DiffRecyclerAdapter(context) { @@ -41,7 +41,7 @@ class CoverAdapter(context: Context, val callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemCoverBinding) { holder.itemView.apply { - onClick { + setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.changeTo(it.coverUrl ?: "") } diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceAdapter.kt index 2db9cb239..70196a543 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceAdapter.kt @@ -13,8 +13,7 @@ import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.ItemChangeSourceBinding import io.legado.app.utils.invisible import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick +import splitties.views.onLongClick class ChangeSourceAdapter(context: Context, val callBack: CallBack) : @@ -65,14 +64,13 @@ class ChangeSourceAdapter(context: Context, val callBack: CallBack) : } override fun registerListener(holder: ItemViewHolder, binding: ItemChangeSourceBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.changeTo(it) } } holder.itemView.onLongClick { showMenu(holder.itemView, getItem(holder.layoutPosition)) - true } } 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 fe26451fb..289aa4b9a 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 @@ -5,13 +5,14 @@ import android.view.* import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.Toolbar import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.DialogChangeSourceBinding @@ -45,7 +46,7 @@ class ChangeSourceDialog : BaseDialogFragment(), private val binding by viewBinding(DialogChangeSourceBinding::bind) private val groups = linkedSetOf() private var callBack: CallBack? = null - private lateinit var viewModel: ChangeSourceViewModel + private val viewModel: ChangeSourceViewModel by viewModels() lateinit var adapter: ChangeSourceAdapter override fun onStart() { @@ -60,7 +61,6 @@ class ChangeSourceDialog : BaseDialogFragment(), savedInstanceState: Bundle? ): View? { callBack = activity as? CallBack - viewModel = getViewModel(ChangeSourceViewModel::class.java) return inflater.inflate(R.layout.dialog_change_source, container) } @@ -146,7 +146,7 @@ class ChangeSourceDialog : BaseDialogFragment(), viewModel.searchBooksLiveData.observe(viewLifecycleOwner, { adapter.setItems(it) }) - App.db.bookSourceDao.liveGroupEnabled().observe(this, { + appDb.bookSourceDao.liveGroupEnabled().observe(this, { groups.clear() it.map { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt index 0c738d93e..ae3114e04 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt @@ -5,11 +5,10 @@ import android.os.Bundle import android.os.Handler import android.os.Looper import androidx.lifecycle.MutableLiveData -import io.legado.app.App -import io.legado.app.R import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook @@ -21,7 +20,7 @@ import io.legado.app.utils.getPrefString import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.ExecutorCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher -import org.jetbrains.anko.debug +import splitties.init.appCtx import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.Executors @@ -39,7 +38,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio private val searchBooks = CopyOnWriteArraySet() private var postTime = 0L private val sendRunnable = Runnable { upAdapter() } - private val searchGroup get() = App.INSTANCE.getPrefString("searchGroup") ?: "" + private val searchGroup get() = appCtx.getPrefString("searchGroup") ?: "" @Volatile private var searchIndex = -1 @@ -64,7 +63,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio execute { searchBooks.clear() upAdapter() - App.db.searchBookDao.getChangeSourceSearch(name, author, searchGroup).let { + appDb.searchBookDao.getChangeSourceSearch(name, author, searchGroup).let { searchBooks.addAll(it) searchBooksLiveData.postValue(searchBooks.toList()) if (it.size <= 1) { @@ -89,7 +88,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio private fun searchFinish(searchBook: SearchBook) { if (searchBooks.contains(searchBook)) return - App.db.searchBookDao.insert(searchBook) + appDb.searchBookDao.insert(searchBook) if (screenKey.isEmpty()) { searchBooks.add(searchBook) } else if (searchBook.name.contains(screenKey)) { @@ -100,14 +99,14 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio private fun startSearch() { execute { - App.db.searchBookDao.clear(name, author) + appDb.searchBookDao.clear(name, author) searchBooks.clear() upAdapter() bookSourceList.clear() if (searchGroup.isBlank()) { - bookSourceList.addAll(App.db.bookSourceDao.allEnabled) + bookSourceList.addAll(appDb.bookSourceDao.allEnabled) } else { - bookSourceList.addAll(App.db.bookSourceDao.getEnabledByGroup(searchGroup)) + bookSourceList.addAll(appDb.bookSourceDao.getEnabledByGroup(searchGroup)) } searchStateData.postValue(true) initSearchPool() @@ -173,7 +172,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio searchFinish(searchBook) } }.onError { - debug { context.getString(R.string.error_get_book_info) } + it.printStackTrace() } } @@ -186,7 +185,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio searchFinish(searchBook) } }.onError { - debug { context.getString(R.string.error_get_chapter_list) } + it.printStackTrace() } } @@ -200,7 +199,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio loadDbSearchBook() } else { val items = - App.db.searchBookDao.getChangeSourceSearch(name, author, screenKey, searchGroup) + appDb.searchBookDao.getChangeSourceSearch(name, author, screenKey, searchGroup) searchBooks.clear() searchBooks.addAll(items) upAdapter() @@ -225,9 +224,9 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio fun disableSource(searchBook: SearchBook) { execute { - App.db.bookSourceDao.getBookSource(searchBook.origin)?.let { source -> + appDb.bookSourceDao.getBookSource(searchBook.origin)?.let { source -> source.enabled = false - App.db.bookSourceDao.update(source) + appDb.bookSourceDao.update(source) } searchBooks.remove(searchBook) upAdapter() diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt index 136717903..95f1a12bc 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowActivity.kt @@ -1,6 +1,7 @@ package io.legado.app.ui.book.explore import android.os.Bundle +import androidx.activity.viewModels import androidx.recyclerview.widget.RecyclerView import io.legado.app.R import io.legado.app.base.VMBaseActivity @@ -11,13 +12,12 @@ import io.legado.app.databinding.ViewLoadMoreBinding import io.legado.app.ui.book.info.BookInfoActivity import io.legado.app.ui.widget.recycler.LoadMoreView import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.getViewModel -import org.jetbrains.anko.startActivity +import io.legado.app.utils.startActivity class ExploreShowActivity : VMBaseActivity(), ExploreShowAdapter.CallBack { override val viewModel: ExploreShowViewModel - get() = getViewModel(ExploreShowViewModel::class.java) + by viewModels() private lateinit var adapter: ExploreShowAdapter private lateinit var loadMoreView: LoadMoreView @@ -87,9 +87,9 @@ class ExploreShowActivity : VMBaseActivity( - Pair("name", book.name), - Pair("author", book.author) - ) + startActivity { + putExtra("name", book.name) + putExtra("author", book.author) + } } } 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 77b15300a..9c0e521b7 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 @@ -10,7 +10,7 @@ import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.ItemSearchBinding import io.legado.app.utils.gone import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick + class ExploreShowAdapter(context: Context, val callBack: CallBack) : RecyclerAdapter(context) { @@ -51,7 +51,7 @@ class ExploreShowAdapter(context: Context, val callBack: CallBack) : } override fun registerListener(holder: ItemViewHolder, binding: ItemSearchBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.showBookInfo(it.toBook()) } diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt index 502fdefa5..9fedbd613 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt @@ -3,8 +3,8 @@ package io.legado.app.ui.book.explore import android.app.Application import android.content.Intent import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.model.webBook.WebBook @@ -24,7 +24,7 @@ class ExploreShowViewModel(application: Application) : BaseViewModel(application val sourceUrl = intent.getStringExtra("sourceUrl") exploreUrl = intent.getStringExtra("exploreUrl") if (bookSource == null && sourceUrl != null) { - bookSource = App.db.bookSourceDao.getBookSource(sourceUrl) + bookSource = appDb.bookSourceDao.getBookSource(sourceUrl) } explore() } @@ -38,7 +38,7 @@ class ExploreShowViewModel(application: Application) : BaseViewModel(application .timeout(30000L) .onSuccess(IO) { searchBooks -> booksData.postValue(searchBooks) - App.db.searchBookDao.insert(*searchBooks.toTypedArray()) + appDb.searchBookDao.insert(*searchBooks.toTypedArray()) page++ }.onError { it.printStackTrace() 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 4eda999ce..0f87783db 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 @@ -8,31 +8,34 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar -import androidx.core.view.isGone +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.appDb import io.legado.app.data.entities.BookGroup import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogRecyclerViewBinding -import io.legado.app.databinding.ItemGroupManageBinding +import io.legado.app.databinding.ItemBookGroupManageBinding import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.backgroundColor 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.* +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 org.jetbrains.anko.sdk27.listeners.onClick +import io.legado.app.utils.visible + class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { - private lateinit var viewModel: GroupViewModel + private val viewModel: GroupViewModel by viewModels() private lateinit var adapter: GroupAdapter private val binding by viewBinding(DialogRecyclerViewBinding::bind) @@ -47,7 +50,6 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener container: ViewGroup?, savedInstanceState: Bundle? ): View? { - viewModel = getViewModel(GroupViewModel::class.java) return inflater.inflate(R.layout.dialog_recycler_view, container) } @@ -69,11 +71,11 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView) binding.tvOk.setTextColor(requireContext().accentColor) binding.tvOk.visible() - binding.tvOk.onClick { dismiss() } + binding.tvOk.setOnClickListener { dismiss() } } private fun initData() { - App.db.bookGroupDao.liveDataAll().observe(viewLifecycleOwner, { + appDb.bookGroupDao.liveDataAll().observe(viewLifecycleOwner, { adapter.setItems(it) }) } @@ -97,7 +99,7 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { editView.setHint(R.string.group_name) } - customView = alertBinding.root + customView { alertBinding.root } yesButton { alertBinding.editView.text?.toString()?.let { if (it.isNotBlank()) { @@ -116,7 +118,12 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener editView.setHint(R.string.group_name) editView.setText(bookGroup.groupName) } - customView = alertBinding.root + if (bookGroup.groupId >= 0) { + neutralButton(R.string.delete) { + deleteGroup(bookGroup) + } + } + customView { alertBinding.root } yesButton { alertBinding.editView.text?.toString()?.let { viewModel.upGroup(bookGroup.copy(groupName = it)) @@ -136,18 +143,18 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener } private inner class GroupAdapter(context: Context) : - RecyclerAdapter(context), + RecyclerAdapter(context), ItemTouchCallback.Callback { private var isMoved = false - override fun getViewBinding(parent: ViewGroup): ItemGroupManageBinding { - return ItemGroupManageBinding.inflate(inflater, parent, false) + override fun getViewBinding(parent: ViewGroup): ItemBookGroupManageBinding { + return ItemBookGroupManageBinding.inflate(inflater, parent, false) } override fun convert( holder: ItemViewHolder, - binding: ItemGroupManageBinding, + binding: ItemBookGroupManageBinding, item: BookGroup, payloads: MutableList ) { @@ -155,15 +162,12 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener root.setBackgroundColor(context.backgroundColor) tvGroup.text = item.getManageName(context) swShow.isChecked = item.show - tvDel.isGone = item.groupId < 0 - swShow.isGone = item.groupId >= 0 } } - override fun registerListener(holder: ItemViewHolder, binding: ItemGroupManageBinding) { + override fun registerListener(holder: ItemViewHolder, binding: ItemBookGroupManageBinding) { with(binding) { - tvEdit.onClick { getItem(holder.layoutPosition)?.let { editGroup(it) } } - tvDel.onClick { getItem(holder.layoutPosition)?.let { deleteGroup(it) } } + tvEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { editGroup(it) } } swShow.setOnCheckedChangeListener { buttonView, isChecked -> if (buttonView.isPressed) { getItem(holder.layoutPosition)?.let { 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 0aaac8ce4..42a4ab229 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 @@ -9,14 +9,15 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.appDb import io.legado.app.data.entities.BookGroup import io.legado.app.databinding.DialogBookGroupPickerBinding import io.legado.app.databinding.DialogEditTextBinding @@ -29,10 +30,9 @@ 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.getViewModel import io.legado.app.utils.requestInputMethod import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { @@ -52,7 +52,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener private val binding by viewBinding(DialogBookGroupPickerBinding::bind) private var requestCode: Int = -1 - private lateinit var viewModel: GroupViewModel + private val viewModel: GroupViewModel by viewModels() private lateinit var adapter: GroupAdapter private var callBack: CallBack? = null private var groupId: Long = 0 @@ -68,7 +68,6 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener container: ViewGroup?, savedInstanceState: Bundle? ): View? { - viewModel = getViewModel(GroupViewModel::class.java) return inflater.inflate(R.layout.dialog_book_group_picker, container) } @@ -95,16 +94,16 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener val itemTouchCallback = ItemTouchCallback(adapter) itemTouchCallback.isCanDrag = true ItemTouchHelper(itemTouchCallback).attachToRecyclerView(binding.recyclerView) - binding.tvCancel.onClick { dismiss() } + binding.tvCancel.setOnClickListener { dismiss() } binding.tvOk.setTextColor(requireContext().accentColor) - binding.tvOk.onClick { + binding.tvOk.setOnClickListener { callBack?.upGroup(requestCode, groupId) dismiss() } } private fun initData() { - App.db.bookGroupDao.liveDataSelect().observe(viewLifecycleOwner, { + appDb.bookGroupDao.liveDataSelect().observe(viewLifecycleOwner, { adapter.setItems(it) }) } @@ -122,7 +121,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { editView.setHint(R.string.group_name) } - customView = alertBinding.root + customView { alertBinding.root } yesButton { alertBinding.editView.text?.toString()?.let { if (it.isNotBlank()) { @@ -141,7 +140,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener editView.setHint(R.string.group_name) editView.setText(bookGroup.groupName) } - customView = alertBinding.root + customView { alertBinding.root } yesButton { alertBinding.editView.text?.toString()?.let { viewModel.upGroup(bookGroup.copy(groupName = it)) @@ -187,7 +186,7 @@ class GroupSelectDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener } } } - tvEdit.onClick { getItem(holder.layoutPosition)?.let { editGroup(it) } } + tvEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { editGroup(it) } } } } diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupViewModel.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupViewModel.kt index 80fbac639..3b78e45f8 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupViewModel.kt @@ -1,8 +1,8 @@ package io.legado.app.ui.book.group import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.BookGroup class GroupViewModel(application: Application) : BaseViewModel(application) { @@ -10,34 +10,34 @@ class GroupViewModel(application: Application) : BaseViewModel(application) { fun addGroup(groupName: String) { execute { var id = 1L - val idsSum = App.db.bookGroupDao.idsSum + val idsSum = appDb.bookGroupDao.idsSum while (id and idsSum != 0L) { id = id.shl(1) } val bookGroup = BookGroup( groupId = id, groupName = groupName, - order = App.db.bookGroupDao.maxOrder.plus(1) + order = appDb.bookGroupDao.maxOrder.plus(1) ) - App.db.bookGroupDao.insert(bookGroup) + appDb.bookGroupDao.insert(bookGroup) } } fun upGroup(vararg bookGroup: BookGroup) { execute { - App.db.bookGroupDao.update(*bookGroup) + appDb.bookGroupDao.update(*bookGroup) } } fun delGroup(vararg bookGroup: BookGroup) { execute { - App.db.bookGroupDao.delete(*bookGroup) + appDb.bookGroupDao.delete(*bookGroup) bookGroup.forEach { group -> - val books = App.db.bookDao.getBooksByGroup(group.groupId) + val books = appDb.bookDao.getBooksByGroup(group.groupId) books.forEach { it.group = it.group - group.groupId } - App.db.bookDao.update(*books.toTypedArray()) + appDb.bookDao.update(*books.toTypedArray()) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt index 3314f8aa9..f5e4c9ff8 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt @@ -9,6 +9,7 @@ import android.view.Menu import android.view.MenuItem import android.widget.CheckBox import android.widget.LinearLayout +import androidx.activity.viewModels import com.bumptech.glide.RequestBuilder import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.request.RequestOptions.bitmapTransform @@ -37,10 +38,6 @@ import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.book.toc.ChapterListActivity import io.legado.app.ui.widget.image.CoverImageView import io.legado.app.utils.* -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.startActivity -import org.jetbrains.anko.startActivityForResult -import org.jetbrains.anko.toast class BookInfoActivity : @@ -55,7 +52,7 @@ class BookInfoActivity : private val requestCodeRead = 432 override val viewModel: BookInfoViewModel - get() = getViewModel(BookInfoViewModel::class.java) + by viewModels() override fun getViewBinding(): ActivityBookInfoBinding { return ActivityBookInfoBinding.inflate(layoutInflater) @@ -87,12 +84,13 @@ class BookInfoActivity : if (viewModel.inBookshelf) { viewModel.bookData.value?.let { startActivityForResult( - requestCodeInfoEdit, - Pair("bookUrl", it.bookUrl) - ) + requestCodeInfoEdit + ) { + putExtra("bookUrl", it.bookUrl) + } } } else { - toast(R.string.after_add_bookshelf) + toastOnUi(R.string.after_add_bookshelf) } } R.id.menu_share_it -> { @@ -113,7 +111,7 @@ class BookInfoActivity : } R.id.menu_copy_url -> viewModel.bookData.value?.bookUrl?.let { sendToClip(it) - } ?: toast(R.string.no_book) + } ?: toastOnUi(R.string.no_book) R.id.menu_can_update -> { if (viewModel.inBookshelf) { viewModel.bookData.value?.let { @@ -121,7 +119,7 @@ class BookInfoActivity : viewModel.saveBook() } } else { - toast(R.string.after_add_bookshelf) + toastOnUi(R.string.after_add_bookshelf) } } R.id.menu_clear_cache -> viewModel.clearCache() @@ -207,17 +205,17 @@ class BookInfoActivity : } private fun initOnClick() = with(binding) { - ivCover.onClick { + ivCover.setOnClickListener { viewModel.bookData.value?.let { ChangeCoverDialog.show(supportFragmentManager, it.name, it.author) } } - tvRead.onClick { + tvRead.setOnClickListener { viewModel.bookData.value?.let { readBook(it) } } - tvShelf.onClick { + tvShelf.setOnClickListener { if (viewModel.inBookshelf) { deleteBook() } else { @@ -226,17 +224,19 @@ class BookInfoActivity : } } } - tvOrigin.onClick { + tvOrigin.setOnClickListener { viewModel.bookData.value?.let { - startActivity(Pair("data", it.origin)) + startActivity { + putExtra("data", it.origin) + } } } - tvChangeSource.onClick { + tvChangeSource.setOnClickListener { viewModel.bookData.value?.let { ChangeSourceDialog.show(supportFragmentManager, it.name, it.author) } } - tvTocView.onClick { + tvTocView.setOnClickListener { if (!viewModel.inBookshelf) { viewModel.saveBook { viewModel.saveChapterList { @@ -247,16 +247,20 @@ class BookInfoActivity : openChapterList() } } - tvChangeGroup.onClick { + tvChangeGroup.setOnClickListener { viewModel.bookData.value?.let { GroupSelectDialog.show(supportFragmentManager, it.group) } } - tvAuthor.onClick { - startActivity(Pair("key", viewModel.bookData.value?.author)) + tvAuthor.setOnClickListener { + startActivity { + putExtra("key", viewModel.bookData.value?.author) + } } - tvName.onClick { - startActivity(Pair("key", viewModel.bookData.value?.name)) + tvName.setOnClickListener { + startActivity { + putExtra("key", viewModel.bookData.value?.name) + } } } @@ -275,7 +279,7 @@ class BookInfoActivity : setPadding(16.dp, 0, 16.dp, 0) addView(checkBox) } - customView = view + customView { view } positiveButton(R.string.yes) { viewModel.delBook(checkBox.isChecked) { finish() @@ -293,14 +297,15 @@ class BookInfoActivity : private fun openChapterList() { if (viewModel.chapterListData.value.isNullOrEmpty()) { - toast(R.string.chapter_list_empty) + toastOnUi(R.string.chapter_list_empty) return } viewModel.bookData.value?.let { startActivityForResult( - requestCodeChapterList, - Pair("bookUrl", it.bookUrl) - ) + requestCodeChapterList + ) { + putExtra("bookUrl", it.bookUrl) + } } } @@ -321,16 +326,18 @@ class BookInfoActivity : private fun startReadActivity(book: Book) { when (book.type) { BookType.audio -> startActivityForResult( - requestCodeRead, - Pair("bookUrl", book.bookUrl), - Pair("inBookshelf", viewModel.inBookshelf) - ) + requestCodeRead + ) { + putExtra("bookUrl", book.bookUrl) + putExtra("inBookshelf", viewModel.inBookshelf) + } else -> startActivityForResult( - requestCodeRead, - Pair("bookUrl", book.bookUrl), - Pair("inBookshelf", viewModel.inBookshelf), - Pair("key", IntentDataHelp.putData(book)) - ) + requestCodeRead + ) { + putExtra("bookUrl", book.bookUrl) + putExtra("inBookshelf", viewModel.inBookshelf) + putExtra("key", IntentDataHelp.putData(book)) + } } } diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index 21f2dd157..8348dca02 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -3,9 +3,9 @@ package io.legado.app.ui.book.info import android.app.Application import android.content.Intent import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.help.BookHelp @@ -24,10 +24,10 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { execute { val name = intent.getStringExtra("name") ?: "" val author = intent.getStringExtra("author") ?: "" - App.db.bookDao.getBook(name, author)?.let { book -> + appDb.bookDao.getBook(name, author)?.let { book -> inBookshelf = true setBook(book) - } ?: App.db.searchBookDao.getFirstByNameAuthor(name, author)?.toBook()?.let { book -> + } ?: appDb.searchBookDao.getFirstByNameAuthor(name, author)?.toBook()?.let { book -> setBook(book) } } @@ -39,7 +39,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { if (book.tocUrl.isEmpty()) { loadBookInfo(book) } else { - val chapterList = App.db.bookChapterDao.getChapterList(book.bookUrl) + val chapterList = appDb.bookChapterDao.getChapterList(book.bookUrl) if (chapterList.isNotEmpty()) { chapterListData.postValue(chapterList) } else { @@ -56,20 +56,20 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { if (book.isLocalBook()) { loadChapter(book, changeDruChapterIndex) } else { - App.db.bookSourceDao.getBookSource(book.origin)?.let { bookSource -> + appDb.bookSourceDao.getBookSource(book.origin)?.let { bookSource -> WebBook(bookSource).getBookInfo(this, book, canReName = canReName) .onSuccess(IO) { bookData.postValue(book) if (inBookshelf) { - App.db.bookDao.update(book) + appDb.bookDao.update(book) } loadChapter(it, changeDruChapterIndex) }.onError { - toast(R.string.error_get_book_info) + toastOnUi(R.string.error_get_book_info) } } ?: let { chapterListData.postValue(null) - toast(R.string.error_no_source) + toastOnUi(R.string.error_no_source) } } } @@ -82,18 +82,18 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { execute { if (book.isLocalBook()) { LocalBook.getChapterList(book).let { - App.db.bookDao.update(book) - App.db.bookChapterDao.insert(*it.toTypedArray()) + appDb.bookDao.update(book) + appDb.bookChapterDao.insert(*it.toTypedArray()) chapterListData.postValue(it) } } else { - App.db.bookSourceDao.getBookSource(book.origin)?.let { bookSource -> + appDb.bookSourceDao.getBookSource(book.origin)?.let { bookSource -> WebBook(bookSource).getChapterList(this, book) .onSuccess(IO) { if (it.isNotEmpty()) { if (inBookshelf) { - App.db.bookDao.update(book) - App.db.bookChapterDao.insert(*it.toTypedArray()) + appDb.bookDao.update(book) + appDb.bookChapterDao.insert(*it.toTypedArray()) } if (changeDruChapterIndex == null) { chapterListData.postValue(it) @@ -101,25 +101,25 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { changeDruChapterIndex(it) } } else { - toast(R.string.chapter_list_empty) + toastOnUi(R.string.chapter_list_empty) } }.onError { chapterListData.postValue(null) - toast(R.string.error_get_chapter_list) + toastOnUi(R.string.error_get_chapter_list) } } ?: let { chapterListData.postValue(null) - toast(R.string.error_no_source) + toastOnUi(R.string.error_no_source) } } }.onError { - toast("LoadTocError:${it.localizedMessage}") + toastOnUi("LoadTocError:${it.localizedMessage}") } } fun loadGroup(groupId: Long, success: ((groupNames: String?) -> Unit)) { execute { - App.db.bookGroupDao.getGroupNames(groupId).joinToString(",") + appDb.bookGroupDao.getGroupNames(groupId).joinToString(",") }.onSuccess { success.invoke(it) } @@ -161,8 +161,8 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { ) book.durChapterTitle = chapters[book.durChapterIndex].title if (inBookshelf) { - App.db.bookDao.update(book) - App.db.bookChapterDao.insert(*chapters.toTypedArray()) + appDb.bookDao.update(book) + appDb.bookChapterDao.insert(*chapters.toTypedArray()) } bookData.postValue(book) chapterListData.postValue(chapters) @@ -173,13 +173,13 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { execute { bookData.value?.let { book -> if (book.order == 0) { - book.order = App.db.bookDao.maxOrder + 1 + book.order = appDb.bookDao.maxOrder + 1 } - App.db.bookDao.getBook(book.name, book.author)?.let { + appDb.bookDao.getBook(book.name, book.author)?.let { book.durChapterPos = it.durChapterPos book.durChapterTitle = it.durChapterTitle } - App.db.bookDao.insert(book) + appDb.bookDao.insert(book) if (ReadBook.book?.name == book.name && ReadBook.book?.author == book.author) { ReadBook.book = book } @@ -192,7 +192,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { fun saveChapterList(success: (() -> Unit)?) { execute { chapterListData.value?.let { - App.db.bookChapterDao.insert(*it.toTypedArray()) + appDb.bookChapterDao.insert(*it.toTypedArray()) } }.onSuccess { success?.invoke() @@ -203,16 +203,16 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { execute { bookData.value?.let { book -> if (book.order == 0) { - book.order = App.db.bookDao.maxOrder + 1 + book.order = appDb.bookDao.maxOrder + 1 } - App.db.bookDao.getBook(book.name, book.author)?.let { + appDb.bookDao.getBook(book.name, book.author)?.let { book.durChapterPos = it.durChapterPos book.durChapterTitle = it.durChapterTitle } - App.db.bookDao.insert(book) + appDb.bookDao.insert(book) } chapterListData.value?.let { - App.db.bookChapterDao.insert(*it.toTypedArray()) + appDb.bookChapterDao.insert(*it.toTypedArray()) } inBookshelf = true }.onSuccess { @@ -238,15 +238,15 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { execute { BookHelp.clearCache(bookData.value!!) }.onSuccess { - toast(R.string.clear_cache_success) + toastOnUi(R.string.clear_cache_success) }.onError { - toast(it.stackTraceToString()) + toastOnUi(it.stackTraceToString()) } } fun upEditBook() { bookData.value?.let { - App.db.bookDao.getBook(it.bookUrl)?.let { book -> + appDb.bookDao.getBook(it.bookUrl)?.let { book -> bookData.postValue(book) } } diff --git a/app/src/main/java/io/legado/app/ui/book/info/ChapterListAdapter.kt b/app/src/main/java/io/legado/app/ui/book/info/ChapterListAdapter.kt index dab2525ec..dde20e3e8 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/ChapterListAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/ChapterListAdapter.kt @@ -8,8 +8,8 @@ import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.data.entities.BookChapter import io.legado.app.databinding.ItemChapterListBinding import io.legado.app.lib.theme.accentColor -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.textColorResource +import io.legado.app.utils.getCompatColor + class ChapterListAdapter(context: Context, var callBack: CallBack) : RecyclerAdapter(context) { @@ -29,7 +29,7 @@ class ChapterListAdapter(context: Context, var callBack: CallBack) : if (item.index == callBack.durChapterIndex()) { tvChapterName.setTextColor(context.accentColor) } else { - tvChapterName.textColorResource = R.color.secondaryText + tvChapterName.setTextColor(context.getCompatColor(R.color.secondaryText)) } } @@ -37,7 +37,7 @@ class ChapterListAdapter(context: Context, var callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemChapterListBinding) { holder.itemView.apply { - this.onClick { + this.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.openChapter(it) } diff --git a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt index f5e4e9f38..4d16ba6bd 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt @@ -6,6 +6,7 @@ import android.net.Uri import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.activity.viewModels import androidx.documentfile.provider.DocumentFile import io.legado.app.R import io.legado.app.base.VMBaseActivity @@ -15,8 +16,6 @@ import io.legado.app.help.permission.Permissions import io.legado.app.help.permission.PermissionsCompat import io.legado.app.ui.book.changecover.ChangeCoverDialog import io.legado.app.utils.* -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.toast import java.io.File class BookInfoEditActivity : @@ -26,7 +25,7 @@ class BookInfoEditActivity : private val resultSelectCover = 132 override val viewModel: BookInfoEditViewModel - get() = getViewModel(BookInfoEditViewModel::class.java) + by viewModels() override fun getViewBinding(): ActivityBookInfoEditBinding { return ActivityBookInfoEditBinding.inflate(layoutInflater) @@ -55,15 +54,15 @@ class BookInfoEditActivity : } private fun initEvent() = with(binding) { - tvChangeCover.onClick { + tvChangeCover.setOnClickListener { viewModel.bookData.value?.let { ChangeCoverDialog.show(supportFragmentManager, it.name, it.author) } } - tvSelectCover.onClick { + tvSelectCover.setOnClickListener { selectImage() } - tvRefreshCover.onClick { + tvRefreshCover.setOnClickListener { viewModel.book?.customCoverUrl = tieCoverUrl.text?.toString() upCover() } @@ -121,7 +120,7 @@ class BookInfoEditActivity : }.getOrNull()?.let { byteArray -> file.writeBytes(byteArray) coverChangeTo(file.absolutePath) - } ?: toast("获取文件出错") + } ?: toastOnUi("获取文件出错") } } else { PermissionsCompat.Builder(this) diff --git a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditViewModel.kt index 357360763..1265d9b4d 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditViewModel.kt @@ -2,8 +2,8 @@ package io.legado.app.ui.book.info.edit import android.app.Application import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.service.help.ReadBook @@ -13,7 +13,7 @@ class BookInfoEditViewModel(application: Application) : BaseViewModel(applicatio fun loadBook(bookUrl: String) { execute { - book = App.db.bookDao.getBook(bookUrl) + book = appDb.bookDao.getBook(bookUrl) book?.let { bookData.postValue(it) } @@ -25,7 +25,7 @@ class BookInfoEditViewModel(application: Application) : BaseViewModel(applicatio if (ReadBook.book?.bookUrl == book.bookUrl) { ReadBook.book = book } - App.db.bookDao.update(book) + appDb.bookDao.update(book) }.onSuccess { success?.invoke() } 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 f87a0817e..776d980c5 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 @@ -8,13 +8,14 @@ import android.os.Bundle import android.provider.DocumentsContract import android.view.Menu import android.view.MenuItem +import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.LiveData import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity +import io.legado.app.data.appDb import io.legado.app.databinding.ActivityImportBookBinding import io.legado.app.help.AppConfig import io.legado.app.help.permission.Permissions @@ -28,8 +29,6 @@ import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.toast import java.io.File import java.util.* @@ -50,7 +49,7 @@ class ImportBookActivity : VMBaseActivity ReadBook.book?.let { - startActivity(Pair("name", it.name), Pair("author", it.author)) + startActivity { + putExtra("name", it.name) + putExtra("author", it.author) + } } R.id.menu_toc_regex -> TocRegexDialog.show( supportFragmentManager, @@ -347,7 +348,7 @@ class ReadBookActivity : ReadBookBaseActivity(), ) { if (BaseReadAloudService.isPlay()) { ReadAloud.pause(this) - toast(R.string.read_aloud_pause) + toastOnUi(R.string.read_aloud_pause) return true } if (isAutoPage) { @@ -453,7 +454,7 @@ class ReadBookActivity : ReadBookBaseActivity(), R.id.menu_bookmark -> binding.readView.curPage.let { val bookmark = it.createBookmark() if (bookmark == null) { - toast(R.string.create_bookmark_error) + toastOnUi(R.string.create_bookmark_error) } else { showBookMark(bookmark) } @@ -658,9 +659,10 @@ class ReadBookActivity : ReadBookBaseActivity(), override fun openSourceEditActivity() { ReadBook.webBook?.let { startActivityForResult( - requestCodeEditSource, - Pair("data", it.bookSource.bookSourceUrl) - ) + requestCodeEditSource + ) { + putExtra("data", it.bookSource.bookSourceUrl) + } } } @@ -677,9 +679,10 @@ class ReadBookActivity : ReadBookBaseActivity(), override fun openChapterList() { ReadBook.book?.let { startActivityForResult( - requestCodeChapterList, - Pair("bookUrl", it.bookUrl) - ) + requestCodeChapterList + ) { + putExtra("bookUrl", it.bookUrl) + } } } @@ -689,10 +692,11 @@ class ReadBookActivity : ReadBookBaseActivity(), override fun openSearchActivity(searchWord: String?) { ReadBook.book?.let { startActivityForResult( - requestCodeSearchResult, - Pair("bookUrl", it.bookUrl), - Pair("searchWord", searchWord ?: viewModel.searchContentQuery) - ) + requestCodeSearchResult + ) { + putExtra("bookUrl", it.bookUrl) + putExtra("searchWord", searchWord ?: viewModel.searchContentQuery) + } } } @@ -720,10 +724,11 @@ class ReadBookActivity : ReadBookBaseActivity(), override fun showLogin() { ReadBook.webBook?.bookSource?.let { - startActivity( - Pair("sourceUrl", it.bookSourceUrl), - Pair("loginUrl", it.loginUrl) - ) + startActivity { + putExtra("sourceUrl", it.bookSourceUrl) + putExtra("loginUrl", it.loginUrl) + putExtra("userAgent", it.getHeaderMap()[AppConst.UA_NAME]) + } } } @@ -775,7 +780,7 @@ class ReadBookActivity : ReadBookBaseActivity(), private fun sureSyncProgress(progress: BookProgress) { alert(R.string.get_book_progress) { - message = getString(R.string.current_progress_exceeds_cloud) + setMessage(R.string.current_progress_exceeds_cloud) okButton { ReadBook.setProgress(progress) } @@ -846,7 +851,7 @@ class ReadBookActivity : ReadBookBaseActivity(), ReadBook.book?.let { if (!ReadBook.inBookshelf) { alert(title = getString(R.string.add_to_shelf)) { - message = getString(R.string.check_add_bookshelf, it.name) + setMessage(getString(R.string.check_add_bookshelf, it.name)) okButton { ReadBook.inBookshelf = true setResult(Activity.RESULT_OK) diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookBaseActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookBaseActivity.kt index 6a305f928..eb256ae8a 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookBaseActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookBaseActivity.kt @@ -6,11 +6,12 @@ import android.graphics.Color import android.os.Build import android.os.Bundle import android.view.* +import androidx.activity.viewModels import androidx.core.view.isVisible -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Bookmark import io.legado.app.databinding.ActivityBookReadBinding import io.legado.app.databinding.DialogBookmarkBinding @@ -31,7 +32,6 @@ import io.legado.app.ui.book.read.config.BgTextConfigDialog import io.legado.app.ui.book.read.config.ClickActionConfigDialog import io.legado.app.ui.book.read.config.PaddingConfigDialog import io.legado.app.utils.getPrefString -import io.legado.app.utils.getViewModel import io.legado.app.utils.requestInputMethod /** @@ -41,7 +41,7 @@ abstract class ReadBookBaseActivity : VMBaseActivity() { override val viewModel: ReadBookViewModel - get() = getViewModel(ReadBookViewModel::class.java) + by viewModels() var bottomDialog = 0 override fun getViewBinding(): ActivityBookReadBinding { @@ -186,7 +186,7 @@ abstract class ReadBookBaseActivity : editStart.setText((book.durChapterIndex + 1).toString()) editEnd.setText(book.totalChapterNum.toString()) } - customView = alertBinding.root + customView { alertBinding.root } yesButton { alertBinding.run { val start = editStart.text?.toString()?.toInt() ?: 0 @@ -202,18 +202,18 @@ abstract class ReadBookBaseActivity : @SuppressLint("InflateParams") fun showBookMark(bookmark: Bookmark) { alert(title = getString(R.string.bookmark_add)) { - message = bookmark.chapterName + setMessage(bookmark.chapterName) val alertBinding = DialogBookmarkBinding.inflate(layoutInflater).apply { editBookText.setText(bookmark.bookText) editView.setText(bookmark.content) } - customView = alertBinding.root + customView { alertBinding.root } yesButton { alertBinding.apply { Coroutine.async { bookmark.bookText = editBookText.text.toString() bookmark.content = editView.text.toString() - App.db.bookmarkDao.insert(bookmark) + appDb.bookmarkDao.insert(bookmark) } } } @@ -230,7 +230,7 @@ abstract class ReadBookBaseActivity : editView.setFilterValues(charsets) editView.setText(ReadBook.book?.charset) } - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.editView.text?.toString()?.let { ReadBook.setCharset(it) diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt index d73f96658..5fff40d5c 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt @@ -2,9 +2,9 @@ package io.legado.app.ui.book.read import android.app.Application import android.content.Intent -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookProgress @@ -33,10 +33,10 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { IntentDataHelp.getData(intent.getStringExtra("key"))?.let { initBook(it) } ?: intent.getStringExtra("bookUrl")?.let { - App.db.bookDao.getBook(it)?.let { book -> + appDb.bookDao.getBook(it)?.let { book -> initBook(book) } - } ?: App.db.bookDao.lastReadBook?.let { + } ?: appDb.bookDao.lastReadBook?.let { initBook(it) } }.onFinally { @@ -54,7 +54,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { autoChangeSource(book.name, book.author) return } - ReadBook.chapterSize = App.db.bookChapterDao.getChapterCount(book.bookUrl) + ReadBook.chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl) if (ReadBook.chapterSize == 0) { if (book.tocUrl.isEmpty()) { loadBookInfo(book) @@ -84,7 +84,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { autoChangeSource(book.name, book.author) return } - ReadBook.chapterSize = App.db.bookChapterDao.getChapterCount(book.bookUrl) + ReadBook.chapterSize = appDb.bookChapterDao.getChapterCount(book.bookUrl) if (ReadBook.chapterSize == 0) { if (book.tocUrl.isEmpty()) { loadBookInfo(book) @@ -125,9 +125,9 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { if (book.isLocalBook()) { execute { LocalBook.getChapterList(book).let { - App.db.bookChapterDao.delByBook(book.bookUrl) - App.db.bookChapterDao.insert(*it.toTypedArray()) - App.db.bookDao.update(book) + appDb.bookChapterDao.delByBook(book.bookUrl) + appDb.bookChapterDao.insert(*it.toTypedArray()) + appDb.bookDao.update(book) ReadBook.chapterSize = it.size if (it.isEmpty()) { ReadBook.upMsg(context.getString(R.string.error_load_toc)) @@ -144,8 +144,8 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { ?.onSuccess(IO) { cList -> if (cList.isNotEmpty()) { if (changeDruChapterIndex == null) { - App.db.bookChapterDao.insert(*cList.toTypedArray()) - App.db.bookDao.update(book) + appDb.bookChapterDao.insert(*cList.toTypedArray()) + appDb.bookDao.update(book) ReadBook.chapterSize = cList.size ReadBook.upMsg(null) ReadBook.loadContent(resetPageOffset = true) @@ -191,7 +191,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { it.changeTo(newBook) } ReadBook.book = newBook - App.db.bookSourceDao.getBookSource(newBook.origin)?.let { + appDb.bookSourceDao.getBookSource(newBook.origin)?.let { ReadBook.webBook = WebBook(it) } ReadBook.prevTextChapter = null @@ -215,7 +215,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { private fun autoChangeSource(name: String, author: String) { if (!AppConfig.autoChangeSource) return execute { - val sources = App.db.bookSourceDao.allTextEnabled + val sources = appDb.bookSourceDao.allTextEnabled val book = PreciseSearch.searchFirstBook(this, sources, name, author) if (book != null) { book.upInfoFromOld(ReadBook.book) @@ -226,7 +226,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { }.onStart { ReadBook.upMsg(context.getString(R.string.source_auto_changing)) }.onError { - toast(it.msg) + toastOnUi(it.msg) }.onFinally { ReadBook.upMsg(null) } @@ -242,8 +242,8 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { ) book.durChapterIndex = ReadBook.durChapterIndex book.durChapterTitle = chapters[ReadBook.durChapterIndex].title - App.db.bookDao.update(book) - App.db.bookChapterDao.insert(*chapters.toTypedArray()) + appDb.bookDao.update(book) + appDb.bookChapterDao.insert(*chapters.toTypedArray()) ReadBook.chapterSize = chapters.size ReadBook.upMsg(null) ReadBook.loadContent(resetPageOffset = true) @@ -276,7 +276,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { fun upBookSource(success: (() -> Unit)?) { execute { ReadBook.book?.let { book -> - App.db.bookSourceDao.getBookSource(book.origin)?.let { + appDb.bookSourceDao.getBookSource(book.origin)?.let { ReadBook.webBook = WebBook(it) } } @@ -287,7 +287,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) { fun refreshContent(book: Book) { execute { - App.db.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex) + appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex) ?.let { chapter -> BookHelp.delContent(book, chapter) ReadBook.loadContent(ReadBook.durChapterIndex, resetPageOffset = false) 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 63fa5c0f1..60a90b56e 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 @@ -11,18 +11,17 @@ import android.widget.FrameLayout import android.widget.SeekBar import androidx.core.view.isGone import androidx.core.view.isVisible -import io.legado.app.App import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.databinding.ViewReadMenuBinding import io.legado.app.help.AppConfig import io.legado.app.help.LocalConfig +import io.legado.app.help.ThemeConfig import io.legado.app.lib.theme.* import io.legado.app.service.help.ReadBook import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.utils.* -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick +import splitties.views.onLongClick /** * 阅读界面菜单 @@ -83,8 +82,8 @@ class ReadMenu @JvmOverloads constructor( tvFont.setTextColor(textColor) ivSetting.setColorFilter(textColor) tvSetting.setTextColor(textColor) - vwBg.onClick { } - vwNavigationBar.onClick { } + vwBg.setOnClickListener { } + vwNavigationBar.setOnClickListener { } seekBrightness.progress = context.getPrefInt("brightness", 100) } @@ -135,16 +134,16 @@ class ReadMenu @JvmOverloads constructor( } private fun bindEvent() = with(binding) { - tvChapterName.onClick { + tvChapterName.setOnClickListener { callBack.openSourceEditActivity() } - tvChapterUrl.onClick { + tvChapterUrl.setOnClickListener { context.openUrl(binding.tvChapterUrl.text.toString()) } - tvLogin.onClick { + tvLogin.setOnClickListener { callBack.showLogin() } - ivBrightnessAuto.onClick { + ivBrightnessAuto.setOnClickListener { context.putPrefBoolean("brightnessAuto", !brightnessAuto()) upBrightnessState() } @@ -171,60 +170,59 @@ class ReadMenu @JvmOverloads constructor( }) //搜索 - fabSearch.onClick { + fabSearch.setOnClickListener { runMenuOut { callBack.openSearchActivity(null) } } //自动翻页 - fabAutoPage.onClick { + fabAutoPage.setOnClickListener { runMenuOut { callBack.autoPage() } } //替换 - fabReplaceRule.onClick { callBack.openReplaceRule() } + fabReplaceRule.setOnClickListener { callBack.openReplaceRule() } //夜间模式 - fabNightTheme.onClick { + fabNightTheme.setOnClickListener { AppConfig.isNightTheme = !AppConfig.isNightTheme - App.INSTANCE.applyDayNight() + ThemeConfig.applyDayNight(context) } //上一章 - tvPre.onClick { ReadBook.moveToPrevChapter(upContent = true, toLast = false) } + tvPre.setOnClickListener { ReadBook.moveToPrevChapter(upContent = true, toLast = false) } //下一章 - tvNext.onClick { ReadBook.moveToNextChapter(true) } + tvNext.setOnClickListener { ReadBook.moveToNextChapter(true) } //目录 - llCatalog.onClick { + llCatalog.setOnClickListener { runMenuOut { callBack.openChapterList() } } //朗读 - llReadAloud.onClick { + llReadAloud.setOnClickListener { runMenuOut { callBack.onClickReadAloud() } } llReadAloud.onLongClick { runMenuOut { callBack.showReadAloudDialog() } - true } //界面 - llFont.onClick { + llFont.setOnClickListener { runMenuOut { callBack.showReadStyle() } } //设置 - llSetting.onClick { + llSetting.setOnClickListener { runMenuOut { callBack.showMoreSetting() } @@ -242,7 +240,7 @@ class ReadMenu @JvmOverloads constructor( } override fun onAnimationEnd(animation: Animation) { - binding.vwMenuBg.onClick { runMenuOut() } + binding.vwMenuBg.setOnClickListener { runMenuOut() } binding.vwNavigationBar.layoutParams = binding.vwNavigationBar.layoutParams.apply { height = activity!!.navigationBarHeight } diff --git a/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt b/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt index 4a75e05c0..29373ae37 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/TextActionMenu.kt @@ -24,13 +24,7 @@ import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.databinding.ItemTextBinding import io.legado.app.databinding.PopupActionMenuBinding import io.legado.app.service.BaseReadAloudService -import io.legado.app.utils.gone -import io.legado.app.utils.isAbsUrl -import io.legado.app.utils.sendToClip -import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.share -import org.jetbrains.anko.toast +import io.legado.app.utils.* import java.util.* @SuppressLint("RestrictedApi") @@ -73,7 +67,7 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac if (moreMenu.size() > 0) { ivMenuMore.visible() } - ivMenuMore.onClick { + ivMenuMore.setOnClickListener { if (recyclerView.isVisible) { ivMenuMore.setImageResource(R.drawable.ic_arrow_back) adapter.setItems(moreMenu.visibleItems) @@ -107,7 +101,7 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac } override fun registerListener(holder: ItemViewHolder, binding: ItemTextBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { if (!callBack.onMenuItemSelected(it.itemId)) { onMenuItemSelected(it) @@ -124,7 +118,7 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac R.id.menu_share_str -> context.share(callBack.selectedText) R.id.menu_aloud -> { if (BaseReadAloudService.isRun) { - context.toast(R.string.alouding_disable) + context.toastOnUi(R.string.alouding_disable) return } readAloud(callBack.selectedText) @@ -143,7 +137,7 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac context.startActivity(intent) }.onFailure { it.printStackTrace() - context.toast(it.localizedMessage ?: "ERROR") + context.toastOnUi(it.localizedMessage ?: "ERROR") } } else -> item.intent?.let { @@ -219,7 +213,7 @@ class TextActionMenu(private val context: Context, private val callBack: CallBac ).intent = createProcessTextIntentForResolveInfo(resolveInfo) } }.onFailure { - context.toast("获取文字操作菜单出错:${it.localizedMessage}") + context.toastOnUi("获取文字操作菜单出错:${it.localizedMessage}") } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/AutoReadDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/AutoReadDialog.kt index 67656c57e..a3b8db620 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/AutoReadDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/AutoReadDialog.kt @@ -16,7 +16,7 @@ import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.utils.ColorUtils import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class AutoReadDialog : BaseDialogFragment() { var callBack: CallBack? = null @@ -94,12 +94,12 @@ class AutoReadDialog : BaseDialogFragment() { } private fun initEvent() { - binding.llMainMenu.onClick { callBack?.showMenuBar(); dismiss() } - binding.llSetting.onClick { + binding.llMainMenu.setOnClickListener { callBack?.showMenuBar(); dismiss() } + binding.llSetting.setOnClickListener { ReadAloudConfigDialog().show(childFragmentManager, "readAloudConfigDialog") } - binding.llCatalog.onClick { callBack?.openChapterList() } - binding.llAutoPageStop.onClick { + binding.llCatalog.setOnClickListener { callBack?.openChapterList() } + binding.llAutoPageStop.setOnClickListener { callBack?.autoPageStop() dismiss() } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt b/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt index 826a701f2..fd0d390e9 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/BgAdapter.kt @@ -9,7 +9,7 @@ import io.legado.app.databinding.ItemBgImageBinding import io.legado.app.help.ImageLoader import io.legado.app.help.ReadBookConfig import io.legado.app.utils.postEvent -import org.jetbrains.anko.sdk27.listeners.onClick + import java.io.File class BgAdapter(context: Context, val textColor: Int) : @@ -39,7 +39,7 @@ class BgAdapter(context: Context, val textColor: Int) : override fun registerListener(holder: ItemViewHolder, binding: ItemBgImageBinding) { holder.itemView.apply { - this.onClick { + this.setOnClickListener { getItemByLayoutPosition(holder.layoutPosition)?.let { ReadBookConfig.durConfig.setCurBg(1, it) ReadBookConfig.upBg() 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 99d9285ea..771ae2873 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 @@ -28,8 +28,6 @@ import io.legado.app.ui.filepicker.FilePicker import io.legado.app.ui.filepicker.FilePickerDialog import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onCheckedChange -import org.jetbrains.anko.sdk27.listeners.onClick import rxhttp.wrapper.param.RxHttp import rxhttp.wrapper.param.toByteArray import java.io.File @@ -110,7 +108,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { tvName.text = getString(R.string.select_image) ivBg.setImageResource(R.drawable.ic_image) ivBg.setColorFilter(primaryTextColor) - root.onClick { selectImage() } + root.setOnClickListener { selectImage() } } } requireContext().assets.list("bg")?.let { @@ -120,12 +118,12 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { @SuppressLint("InflateParams") private fun initEvent() = with(ReadBookConfig.durConfig) { - binding.ivEdit.onClick { + binding.ivEdit.setOnClickListener { alert(R.string.style_name) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { editView.setText(ReadBookConfig.durConfig.name) } - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.editView.text?.toString()?.let { binding.tvName.text = it @@ -135,13 +133,13 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { cancelButton() }.show() } - binding.swDarkStatusIcon.onCheckedChange { buttonView, isChecked -> + binding.swDarkStatusIcon.setOnCheckedChangeListener { buttonView, isChecked -> if (buttonView?.isPressed == true) { setCurStatusIconDark(isChecked) (activity as? ReadBookActivity)?.upSystemUiVisibility() } } - binding.tvTextColor.onClick { + binding.tvTextColor.setOnClickListener { ColorPickerDialog.newBuilder() .setColor(curTextColor()) .setShowAlphaSlider(false) @@ -149,7 +147,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { .setDialogId(TEXT_COLOR) .show(requireActivity()) } - binding.tvBgColor.onClick { + binding.tvBgColor.setOnClickListener { val bgColor = if (curBgType() == 0) Color.parseColor(curBgStr()) else Color.parseColor("#015A86") @@ -160,7 +158,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { .setDialogId(BG_COLOR) .show(requireActivity()) } - binding.ivImport.onClick { + binding.ivImport.setOnClickListener { val importFormNet = "网络导入" val otherActions = arrayListOf(importFormNet) FilePicker.selectFile( @@ -175,19 +173,19 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { } } } - binding.ivExport.onClick { + binding.ivExport.setOnClickListener { FilePicker.selectFolder( this@BgTextConfigDialog, requestCodeExport, title = getString(R.string.export_str) ) } - binding.ivDelete.onClick { + binding.ivDelete.setOnClickListener { if (ReadBookConfig.deleteDur()) { postEvent(EventBus.UP_CONFIG, true) dismiss() } else { - toast("数量已是最少,不能删除.") + toastOnUi("数量已是最少,不能删除.") } } } @@ -201,6 +199,11 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { @Suppress("BlockingMethodInNonBlockingContext") private fun exportConfig(uri: Uri) { + val exportFileName = if (ReadBookConfig.config.name.isBlank()) { + configFileName + } else { + "${ReadBookConfig.config.name}.zip" + } execute { val exportFiles = arrayListOf() val configDirPath = FileUtils.getPath(requireContext().eCacheDir, "readConfig") @@ -252,19 +255,19 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { if (ZipUtils.zipFiles(exportFiles, File(configZipPath))) { if (uri.isContentScheme()) { DocumentFile.fromTreeUri(requireContext(), uri)?.let { treeDoc -> - treeDoc.findFile(configFileName)?.delete() - treeDoc.createFile("", configFileName) + treeDoc.findFile(exportFileName)?.delete() + treeDoc.createFile("", exportFileName) ?.writeBytes(requireContext(), File(configZipPath).readBytes()) } } else { - val exportPath = FileUtils.getPath(File(uri.path!!), configFileName) + val exportPath = FileUtils.getPath(File(uri.path!!), exportFileName) FileUtils.deleteFile(exportPath) FileUtils.createFileIfNotExist(exportPath) .writeBytes(File(configZipPath).readBytes()) } } }.onSuccess { - toast("导出成功, 文件名为 $configFileName") + toastOnUi("导出成功, 文件名为 $exportFileName") }.onError { it.printStackTrace() longToast("导出失败:${it.localizedMessage}") @@ -275,7 +278,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { private fun importNetConfigAlert() { alert("输入地址") { val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.editView.text?.toString()?.let { url -> importNetConfig(url) @@ -360,7 +363,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { ReadBookConfig.durConfig = config postEvent(EventBus.UP_CONFIG, true) }.onSuccess { - toast("导入成功") + toastOnUi("导入成功") }.onError { it.printStackTrace() longToast("导入失败:${it.localizedMessage}") @@ -401,7 +404,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack { ReadBookConfig.durConfig.setCurBg(2, file.absolutePath) ReadBookConfig.upBg() postEvent(EventBus.UP_CONFIG, false) - } ?: toast("获取文件出错") + } ?: toastOnUi("获取文件出错") } } else { PermissionsCompat.Builder(this) diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ChineseConverter.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ChineseConverter.kt index dc8f36d67..514e0a350 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ChineseConverter.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ChineseConverter.kt @@ -10,7 +10,7 @@ import io.legado.app.help.AppConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.accentColor import io.legado.app.ui.widget.text.StrokeTextView -import org.jetbrains.anko.sdk27.listeners.onClick + class ChineseConverter(context: Context, attrs: AttributeSet?) : StrokeTextView(context, attrs) { @@ -23,7 +23,7 @@ class ChineseConverter(context: Context, attrs: AttributeSet?) : StrokeTextView( if (!isInEditMode) { upUi(AppConfig.chineseConverterType) } - onClick { + setOnClickListener { selectType() } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ClickActionConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ClickActionConfigDialog.kt index cc4a3157b..e9f79e26c 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ClickActionConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ClickActionConfigDialog.kt @@ -16,7 +16,7 @@ import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.utils.getCompatColor import io.legado.app.utils.putPrefInt import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class ClickActionConfigDialog : BaseDialogFragment() { private val binding by viewBinding(DialogClickActionConfigBinding::bind) @@ -68,52 +68,52 @@ class ClickActionConfigDialog : BaseDialogFragment() { } private fun initViewEvent() { - binding.ivClose.onClick { + binding.ivClose.setOnClickListener { dismiss() } - binding.tvTopLeft.onClick { + binding.tvTopLeft.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionTL, action) (it as? TextView)?.text = actions[action] } } - binding.tvTopCenter.onClick { + binding.tvTopCenter.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionTC, action) (it as? TextView)?.text = actions[action] } } - binding.tvTopRight.onClick { + binding.tvTopRight.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionTR, action) (it as? TextView)?.text = actions[action] } } - binding.tvMiddleLeft.onClick { + binding.tvMiddleLeft.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionML, action) (it as? TextView)?.text = actions[action] } } - binding.tvMiddleRight.onClick { + binding.tvMiddleRight.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionMR, action) (it as? TextView)?.text = actions[action] } } - binding.tvBottomLeft.onClick { + binding.tvBottomLeft.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionBL, action) (it as? TextView)?.text = actions[action] } } - binding.tvBottomCenter.onClick { + binding.tvBottomCenter.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionBC, action) (it as? TextView)?.text = actions[action] } } - binding.tvBottomRight.onClick { + binding.tvBottomRight.setOnClickListener { selectAction { action -> putPrefInt(PreferKey.clickActionBR, action) (it as? TextView)?.text = actions[action] diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/PageKeyDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/PageKeyDialog.kt index 85ec5d31a..092134e77 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/PageKeyDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/PageKeyDialog.kt @@ -10,7 +10,6 @@ import io.legado.app.lib.theme.backgroundColor import io.legado.app.utils.getPrefString import io.legado.app.utils.hideSoftInput import io.legado.app.utils.putPrefString -import org.jetbrains.anko.sdk27.listeners.onClick class PageKeyDialog(context: Context) : Dialog(context, R.style.AppTheme_AlertDialog) { @@ -22,7 +21,7 @@ class PageKeyDialog(context: Context) : Dialog(context, R.style.AppTheme_AlertDi binding.contentView.setBackgroundColor(context.backgroundColor) binding.etPrev.setText(context.getPrefString(PreferKey.prevKeys)) binding.etNext.setText(context.getPrefString(PreferKey.nextKeys)) - binding.tvOk.onClick { + binding.tvOk.setOnClickListener { context.putPrefString(PreferKey.prevKeys, binding.etPrev.text?.toString()) context.putPrefString(PreferKey.nextKeys, binding.etNext.text?.toString()) dismiss() diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudConfigDialog.kt index fe4379dbd..189b7df26 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudConfigDialog.kt @@ -9,11 +9,11 @@ import android.widget.LinearLayout import androidx.fragment.app.DialogFragment import androidx.preference.ListPreference import androidx.preference.Preference -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BasePreferenceFragment import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.backgroundColor import io.legado.app.service.BaseReadAloudService @@ -21,6 +21,7 @@ import io.legado.app.service.help.ReadAloud import io.legado.app.utils.getPrefLong import io.legado.app.utils.getSize import io.legado.app.utils.postEvent +import splitties.init.appCtx class ReadAloudConfigDialog : DialogFragment() { private val readAloudPreferTag = "readAloudPreferTag" @@ -60,8 +61,8 @@ class ReadAloudConfigDialog : DialogFragment() { private val speakEngineSummary: String get() { - val eid = App.INSTANCE.getPrefLong(PreferKey.speakEngine) - val ht = App.db.httpTTSDao.get(eid) + val eid = appCtx.getPrefLong(PreferKey.speakEngine) + val ht = appDb.httpTTSDao.get(eid) return ht?.name ?: getString(R.string.local_tts) } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt index 8fb2bbcea..6b0391738 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt @@ -21,7 +21,7 @@ import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.observeEvent import io.legado.app.utils.putPrefBoolean import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class ReadAloudDialog : BaseDialogFragment() { private var callBack: CallBack? = null @@ -122,18 +122,18 @@ class ReadAloudDialog : BaseDialogFragment() { } private fun initEvent() = with(binding) { - llMainMenu.onClick { callBack?.showMenuBar(); dismiss() } - llSetting.onClick { + llMainMenu.setOnClickListener { callBack?.showMenuBar(); dismiss() } + llSetting.setOnClickListener { ReadAloudConfigDialog().show(childFragmentManager, "readAloudConfigDialog") } - tvPre.onClick { ReadBook.moveToPrevChapter(upContent = true, toLast = false) } - tvNext.onClick { ReadBook.moveToNextChapter(true) } - ivStop.onClick { ReadAloud.stop(requireContext()); dismiss() } - ivPlayPause.onClick { callBack?.onClickReadAloud() } - ivPlayPrev.onClick { ReadAloud.prevParagraph(requireContext()) } - ivPlayNext.onClick { ReadAloud.nextParagraph(requireContext()) } - llCatalog.onClick { callBack?.openChapterList() } - llToBackstage.onClick { callBack?.finish() } + tvPre.setOnClickListener { ReadBook.moveToPrevChapter(upContent = true, toLast = false) } + tvNext.setOnClickListener { ReadBook.moveToNextChapter(true) } + ivStop.setOnClickListener { ReadAloud.stop(requireContext()); dismiss() } + ivPlayPause.setOnClickListener { callBack?.onClickReadAloud() } + ivPlayPrev.setOnClickListener { ReadAloud.prevParagraph(requireContext()) } + ivPlayNext.setOnClickListener { ReadAloud.nextParagraph(requireContext()) } + llCatalog.setOnClickListener { callBack?.openChapterList() } + llToBackstage.setOnClickListener { callBack?.finish() } } private fun upPlayState() { diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt index 556545e95..d92394e14 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt @@ -24,9 +24,7 @@ import io.legado.app.utils.dp import io.legado.app.utils.getIndexById import io.legado.app.utils.postEvent import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onCheckedChange -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick +import splitties.views.onLongClick class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack { private val binding by viewBinding(DialogReadBookStyleBinding::bind) @@ -93,7 +91,7 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack { ivStyle.setColorFilter(textColor) ivStyle.borderColor = textColor ivStyle.setImageResource(R.drawable.ic_add) - root.onClick { + root.setOnClickListener { ReadBookConfig.configList.add(ReadBookConfig.Config()) showBgTextConfig(ReadBookConfig.configList.lastIndex) } @@ -114,10 +112,10 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack { textFontWeightConverter.onChanged { postEvent(EventBus.UP_CONFIG, true) } - tvTextFont.onClick { + tvTextFont.setOnClickListener { FontSelectDialog().show(childFragmentManager, "fontSelectDialog") } - tvTextIndent.onClick { + tvTextIndent.setOnClickListener { selector( title = getString(R.string.text_indent), items = resources.getStringArray(R.array.indent).toList() @@ -126,14 +124,14 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack { postEvent(EventBus.UP_CONFIG, true) } } - tvPadding.onClick { + tvPadding.setOnClickListener { dismiss() callBack?.showPaddingConfig() } - tvTip.onClick { + tvTip.setOnClickListener { TipConfigDialog().show(childFragmentManager, "tipConfigDialog") } - rgPageAnim.onCheckedChange { _, checkedId -> + rgPageAnim.setOnCheckedChangeListener { _, checkedId -> ReadBook.book?.setPageAnim(-1) ReadBookConfig.pageAnim = binding.rgPageAnim.getIndexById(checkedId) callBack?.upPageAnim() @@ -235,16 +233,14 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack { override fun registerListener(holder: ItemViewHolder, binding: ItemReadStyleBinding) { binding.apply { - ivStyle.onClick { + ivStyle.setOnClickListener { if (ivStyle.isInView) { changeBg(holder.layoutPosition) } } - ivStyle.onLongClick { + ivStyle.onLongClick(ivStyle.isInView) { if (ivStyle.isInView) { showBgTextConfig(holder.layoutPosition) - } else { - false } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt index 2c807a279..0277a566e 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt @@ -8,14 +8,15 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.HttpTTS import io.legado.app.databinding.DialogHttpTtsEditBinding import io.legado.app.databinding.DialogRecyclerViewBinding @@ -27,14 +28,15 @@ import io.legado.app.service.help.ReadAloud import io.legado.app.ui.widget.dialog.TextDialog import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick +import splitties.init.appCtx + class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { private val binding by viewBinding(DialogRecyclerViewBinding::bind) lateinit var adapter: Adapter - lateinit var viewModel: SpeakEngineViewModel + private val viewModel: SpeakEngineViewModel by viewModels() private var httpTTSData: LiveData>? = null - var engineId = App.INSTANCE.getPrefLong(PreferKey.speakEngine) + var engineId = appCtx.getPrefLong(PreferKey.speakEngine) override fun onStart() { super.onStart() @@ -47,7 +49,6 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener container: ViewGroup?, savedInstanceState: Bundle? ): View? { - viewModel = getViewModel(SpeakEngineViewModel::class.java) return inflater.inflate(R.layout.dialog_recycler_view, container) } @@ -66,17 +67,17 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener recyclerView.adapter = adapter tvFooterLeft.setText(R.string.local_tts) tvFooterLeft.visible() - tvFooterLeft.onClick { + tvFooterLeft.setOnClickListener { removePref(PreferKey.speakEngine) dismiss() } tvOk.visible() - tvOk.onClick { + tvOk.setOnClickListener { putPrefLong(PreferKey.speakEngine, engineId) dismiss() } tvCancel.visible() - tvCancel.onClick { + tvCancel.setOnClickListener { dismiss() } } @@ -89,7 +90,7 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener private fun initData() { httpTTSData?.removeObservers(this) - httpTTSData = App.db.httpTTSDao.observeAll() + httpTTSData = appDb.httpTTSDao.observeAll() httpTTSData?.observe(this, { adapter.setItems(it) }) @@ -110,13 +111,13 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener val alertBinding = DialogHttpTtsEditBinding.inflate(layoutInflater) alertBinding.tvName.setText(httpTTS.name) alertBinding.tvUrl.setText(httpTTS.url) - customView = alertBinding.root + customView { alertBinding.root } cancelButton() okButton { alertBinding.apply { httpTTS.name = tvName.text.toString() httpTTS.url = tvUrl.text.toString() - App.db.httpTTSDao.insert(httpTTS) + appDb.httpTTSDao.insert(httpTTS) ReadAloud.upReadAloudClass() } } @@ -150,18 +151,18 @@ class SpeakEngineDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener override fun registerListener(holder: ItemViewHolder, binding: ItemHttpTtsBinding) { binding.apply { - cbName.onClick { + cbName.setOnClickListener { getItem(holder.layoutPosition)?.let { httpTTS -> engineId = httpTTS.id notifyItemRangeChanged(0, itemCount) } } - ivEdit.onClick { + ivEdit.setOnClickListener { editHttpTTS(getItem(holder.layoutPosition)) } - ivMenuDelete.onClick { + ivMenuDelete.setOnClickListener { getItem(holder.layoutPosition)?.let { httpTTS -> - App.db.httpTTSDao.delete(httpTTS) + appDb.httpTTSDao.delete(httpTTS) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineViewModel.kt index bfcb8ae2b..3ebaa228d 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineViewModel.kt @@ -1,8 +1,8 @@ package io.legado.app.ui.book.read.config import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.HttpTTS import io.legado.app.help.DefaultData import io.legado.app.utils.GSON @@ -22,7 +22,7 @@ class SpeakEngineViewModel(application: Application) : BaseViewModel(application execute { RxHttp.get(url).toText("utf-8").await().let { json -> GSON.fromJsonArray(json)?.let { - App.db.httpTTSDao.insert(*it.toTypedArray()) + appDb.httpTTSDao.insert(*it.toTypedArray()) } } }.onSuccess { diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/TextFontWeightConverter.kt b/app/src/main/java/io/legado/app/ui/book/read/config/TextFontWeightConverter.kt index ae240846d..832cff925 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/TextFontWeightConverter.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/TextFontWeightConverter.kt @@ -10,7 +10,7 @@ import io.legado.app.help.ReadBookConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.accentColor import io.legado.app.ui.widget.text.StrokeTextView -import org.jetbrains.anko.sdk27.listeners.onClick + class TextFontWeightConverter(context: Context, attrs: AttributeSet?) : StrokeTextView(context, attrs) { @@ -23,7 +23,7 @@ class TextFontWeightConverter(context: Context, attrs: AttributeSet?) : StrokeTe if (!isInEditMode) { upUi(ReadBookConfig.textBold) } - onClick { + setOnClickListener { selectType() } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt index 7f20e8879..8e0d74b74 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/TipConfigDialog.kt @@ -14,8 +14,7 @@ import io.legado.app.help.ReadTipConfig import io.legado.app.lib.dialogs.selector import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onCheckedChange -import org.jetbrains.anko.sdk27.listeners.onClick + class TipConfigDialog : BaseDialogFragment() { @@ -76,7 +75,7 @@ class TipConfigDialog : BaseDialogFragment() { } private fun initEvent() = with(binding) { - rgTitleMode.onCheckedChange { _, checkedId -> + rgTitleMode.setOnCheckedChangeListener { _, checkedId -> ReadBookConfig.titleMode = rgTitleMode.getIndexById(checkedId) postEvent(EventBus.UP_CONFIG, true) } @@ -92,21 +91,21 @@ class TipConfigDialog : BaseDialogFragment() { ReadBookConfig.titleBottomSpacing = it postEvent(EventBus.UP_CONFIG, true) } - llHeaderShow.onClick { + llHeaderShow.setOnClickListener { selector(items = ReadTipConfig.headerModes.values.toList()) { _, i -> ReadTipConfig.headerMode = ReadTipConfig.headerModes.keys.toList()[i] tvHeaderShow.text = ReadTipConfig.headerModes[ReadTipConfig.headerMode] postEvent(EventBus.UP_CONFIG, true) } } - llFooterShow.onClick { + llFooterShow.setOnClickListener { selector(items = ReadTipConfig.footerModes.values.toList()) { _, i -> ReadTipConfig.footerMode = ReadTipConfig.footerModes.keys.toList()[i] tvFooterShow.text = ReadTipConfig.footerModes[ReadTipConfig.footerMode] postEvent(EventBus.UP_CONFIG, true) } } - llHeaderLeft.onClick { + llHeaderLeft.setOnClickListener { selector(items = ReadTipConfig.tips) { _, i -> clearRepeat(i) ReadTipConfig.tipHeaderLeft = i @@ -114,7 +113,7 @@ class TipConfigDialog : BaseDialogFragment() { postEvent(EventBus.UP_CONFIG, true) } } - llHeaderMiddle.onClick { + llHeaderMiddle.setOnClickListener { selector(items = ReadTipConfig.tips) { _, i -> clearRepeat(i) ReadTipConfig.tipHeaderMiddle = i @@ -122,7 +121,7 @@ class TipConfigDialog : BaseDialogFragment() { postEvent(EventBus.UP_CONFIG, true) } } - llHeaderRight.onClick { + llHeaderRight.setOnClickListener { selector(items = ReadTipConfig.tips) { _, i -> clearRepeat(i) ReadTipConfig.tipHeaderRight = i @@ -130,7 +129,7 @@ class TipConfigDialog : BaseDialogFragment() { postEvent(EventBus.UP_CONFIG, true) } } - llFooterLeft.onClick { + llFooterLeft.setOnClickListener { selector(items = ReadTipConfig.tips) { _, i -> clearRepeat(i) ReadTipConfig.tipFooterLeft = i @@ -138,7 +137,7 @@ class TipConfigDialog : BaseDialogFragment() { postEvent(EventBus.UP_CONFIG, true) } } - llFooterMiddle.onClick { + llFooterMiddle.setOnClickListener { selector(items = ReadTipConfig.tips) { _, i -> clearRepeat(i) ReadTipConfig.tipFooterMiddle = i @@ -146,7 +145,7 @@ class TipConfigDialog : BaseDialogFragment() { postEvent(EventBus.UP_CONFIG, true) } } - llFooterRight.onClick { + llFooterRight.setOnClickListener { selector(items = ReadTipConfig.tips) { _, i -> clearRepeat(i) ReadTipConfig.tipFooterRight = i @@ -154,7 +153,7 @@ class TipConfigDialog : BaseDialogFragment() { postEvent(EventBus.UP_CONFIG, true) } } - llTipColor.onClick { + llTipColor.setOnClickListener { selector(items = arrayListOf("跟随正文", "自定义")) { _, i -> when (i) { 0 -> { diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt index 11ee46f6c..eb8c8bdf0 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexDialog.kt @@ -9,16 +9,17 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.Snackbar -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.appDb import io.legado.app.data.entities.TxtTocRule import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogTocRegexBinding @@ -33,17 +34,15 @@ import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.launch -import org.jetbrains.anko.sdk27.listeners.onClick import java.util.* - class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { private val importTocRuleKey = "tocRuleUrl" private lateinit var adapter: TocRegexAdapter private var tocRegexLiveData: LiveData>? = null var selectedName: String? = null private var durRegex: String? = null - lateinit var viewModel: TocRegexViewModel + private val viewModel: TocRegexViewModel by viewModels() private val binding by viewBinding(DialogTocRegexBinding::bind) override fun onStart() { @@ -57,7 +56,6 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { container: ViewGroup?, savedInstanceState: Bundle? ): View? { - viewModel = getViewModel(TocRegexViewModel::class.java) return inflater.inflate(R.layout.dialog_toc_regex, container) } @@ -80,16 +78,16 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { val itemTouchCallback = ItemTouchCallback(adapter) itemTouchCallback.isCanDrag = true ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recyclerView) - tvCancel.onClick { + tvCancel.setOnClickListener { dismiss() } - tvOk.onClick { + tvOk.setOnClickListener { adapter.getItems().forEach { tocRule -> if (selectedName == tocRule.name) { val callBack = activity as? CallBack callBack?.onTocRegexDialogResult(tocRule.rule) dismiss() - return@onClick + return@setOnClickListener } } } @@ -97,7 +95,7 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { private fun initData() { tocRegexLiveData?.removeObservers(viewLifecycleOwner) - tocRegexLiveData = App.db.txtTocRule.observeAll() + tocRegexLiveData = appDb.txtTocRule.observeAll() tocRegexLiveData?.observe(viewLifecycleOwner, { tocRules -> initSelectedName(tocRules) adapter.setItems(tocRules) @@ -148,7 +146,7 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { aCache.put(importTocRuleKey, cacheUrls.joinToString(",")) } } - customView = alertBinding.root + customView { alertBinding.root } okButton { val text = alertBinding.editView.text?.toString() text?.let { @@ -176,7 +174,7 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { tvRuleName.setText(tocRule.name) tvRuleRegex.setText(tocRule.rule) } - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.apply { tocRule.name = tvRuleName.text.toString() @@ -227,18 +225,18 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { getItem(holder.layoutPosition)?.let { it.enable = isChecked launch(IO) { - App.db.txtTocRule.update(it) + appDb.txtTocRule.update(it) } } } } - ivEdit.onClick { + ivEdit.setOnClickListener { editRule(getItem(holder.layoutPosition)) } - ivDelete.onClick { + ivDelete.setOnClickListener { getItem(holder.layoutPosition)?.let { item -> launch(IO) { - App.db.txtTocRule.delete(item) + appDb.txtTocRule.delete(item) } } } @@ -260,7 +258,7 @@ class TocRegexDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { item.serialNumber = index + 1 } launch(IO) { - App.db.txtTocRule.update(*getItems().toTypedArray()) + appDb.txtTocRule.update(*getItems().toTypedArray()) } } isMoved = false diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexViewModel.kt index aa8ee25fb..cbf7983e9 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/TocRegexViewModel.kt @@ -1,8 +1,8 @@ package io.legado.app.ui.book.read.config import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.TxtTocRule import io.legado.app.help.DefaultData import io.legado.app.utils.GSON @@ -15,9 +15,9 @@ class TocRegexViewModel(application: Application) : BaseViewModel(application) { fun saveRule(rule: TxtTocRule) { execute { if (rule.serialNumber < 0) { - rule.serialNumber = App.db.txtTocRule.lastOrderNum + 1 + rule.serialNumber = appDb.txtTocRule.lastOrderNum + 1 } - App.db.txtTocRule.insert(rule) + appDb.txtTocRule.insert(rule) } } @@ -31,7 +31,7 @@ class TocRegexViewModel(application: Application) : BaseViewModel(application) { execute { RxHttp.get(url).toText("utf-8").await().let { json -> GSON.fromJsonArray(json)?.let { - App.db.txtTocRule.insert(*it.toTypedArray()) + appDb.txtTocRule.insert(*it.toTypedArray()) } } }.onSuccess { diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt index dbecc4b82..7b621735f 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt @@ -20,7 +20,6 @@ import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.widget.BatteryView import io.legado.app.utils.* -import org.jetbrains.anko.topPadding import java.util.* /** @@ -97,9 +96,9 @@ class PageView(context: Context) : FrameLayout(context) { /** * 显示状态栏时隐藏header */ - fun upStatusBar() { - binding.vwStatusBar.topPadding = context.statusBarHeight - binding.vwStatusBar.isGone = + fun upStatusBar() = with(binding.vwStatusBar) { + setPadding(paddingLeft, context.statusBarHeight, paddingRight, paddingBottom) + isGone = ReadBookConfig.hideStatusBar || (activity as? BaseActivity<*>)?.isInMultiWindow == true } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt index ba57dbc48..0c90a541e 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextPage.kt @@ -2,18 +2,18 @@ package io.legado.app.ui.book.read.page.entities import android.text.Layout import android.text.StaticLayout -import io.legado.app.App import io.legado.app.R import io.legado.app.help.ReadBookConfig import io.legado.app.service.help.ReadBook import io.legado.app.ui.book.read.page.provider.ChapterProvider +import splitties.init.appCtx import java.text.DecimalFormat import kotlin.math.min @Suppress("unused") data class TextPage( var index: Int = 0, - var text: String = App.INSTANCE.getString(R.string.data_loading), + var text: String = appCtx.getString(R.string.data_loading), var title: String = "", val textLines: ArrayList = arrayListOf(), var pageSize: Int = 0, diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt index af7f8ecd8..abffa17fc 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt @@ -6,7 +6,6 @@ import android.os.Build import android.text.Layout import android.text.StaticLayout import android.text.TextPaint -import io.legado.app.App import io.legado.app.constant.AppPattern import io.legado.app.constant.EventBus import io.legado.app.data.entities.Book @@ -19,6 +18,7 @@ import io.legado.app.ui.book.read.page.entities.TextChar import io.legado.app.ui.book.read.page.entities.TextLine import io.legado.app.ui.book.read.page.entities.TextPage import io.legado.app.utils.* +import splitties.init.appCtx import java.util.* @@ -355,13 +355,13 @@ object ChapterProvider { return kotlin.runCatching { when { fontPath.isContentScheme() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> { - val fd = App.INSTANCE.contentResolver + val fd = appCtx.contentResolver .openFileDescriptor(Uri.parse(fontPath), "r")!! .fileDescriptor Typeface.Builder(fd).build() } fontPath.isContentScheme() -> { - Typeface.createFromFile(RealPathUtil.getPath(App.INSTANCE, Uri.parse(fontPath))) + Typeface.createFromFile(RealPathUtil.getPath(appCtx, Uri.parse(fontPath))) } fontPath.isNotEmpty() -> Typeface.createFromFile(fontPath) else -> when (AppConfig.systemTypefaces) { diff --git a/app/src/main/java/io/legado/app/ui/book/search/BookAdapter.kt b/app/src/main/java/io/legado/app/ui/book/search/BookAdapter.kt index 3f27b52c6..40bcd0ed3 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/BookAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/BookAdapter.kt @@ -6,7 +6,7 @@ import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.data.entities.Book import io.legado.app.databinding.ItemFilletTextBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class BookAdapter(context: Context, val callBack: CallBack) : RecyclerAdapter(context) { @@ -28,7 +28,7 @@ class BookAdapter(context: Context, val callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemFilletTextBinding) { holder.itemView.apply { - onClick { + setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.showBookInfo(it) } diff --git a/app/src/main/java/io/legado/app/ui/book/search/HistoryKeyAdapter.kt b/app/src/main/java/io/legado/app/ui/book/search/HistoryKeyAdapter.kt index 15c0695c9..6b377c0ca 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/HistoryKeyAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/HistoryKeyAdapter.kt @@ -1,18 +1,16 @@ package io.legado.app.ui.book.search import android.view.ViewGroup -import io.legado.app.App import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.appDb import io.legado.app.data.entities.SearchKeyword import io.legado.app.databinding.ItemFilletTextBinding import io.legado.app.ui.widget.anima.explosion_field.ExplosionField import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick - +import splitties.views.onLongClick class HistoryKeyAdapter(activity: SearchActivity, val callBack: CallBack) : RecyclerAdapter(activity) { @@ -36,21 +34,18 @@ class HistoryKeyAdapter(activity: SearchActivity, val callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemFilletTextBinding) { holder.itemView.apply { - onClick { + setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.searchHistory(it.word) } } onLongClick { - it?.let { - explosionField.explode(it, true) - } + explosionField.explode(this, true) getItem(holder.layoutPosition)?.let { GlobalScope.launch(IO) { - App.db.searchKeywordDao.delete(it) + appDb.searchKeywordDao.delete(it) } } - true } } } diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt index 3f1d377bb..fcaa0d1fe 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchActivity.kt @@ -6,16 +6,17 @@ import android.view.Menu import android.view.MenuItem import android.view.View.GONE import android.view.View.VISIBLE +import androidx.activity.viewModels import androidx.appcompat.widget.SearchView import androidx.lifecycle.LiveData import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.flexbox.FlexboxLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppPattern import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchKeyword @@ -28,9 +29,6 @@ import io.legado.app.utils.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.startActivity - class SearchActivity : VMBaseActivity(), BookAdapter.CallBack, @@ -38,7 +36,7 @@ class SearchActivity : VMBaseActivity groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) @@ -274,7 +272,7 @@ class SearchActivity : VMBaseActivity searchBook?.let { - startActivity( - Pair("name", it.name), - Pair("author", it.author) - ) + startActivity { + putExtra("name", it.name) + putExtra("author", it.author) + } } } } @@ -345,10 +343,10 @@ class SearchActivity : VMBaseActivity( - Pair("name", book.name), - Pair("author", book.author) - ) + startActivity { + putExtra("name", book.name) + putExtra("author", book.author) + } } /** @@ -360,7 +358,7 @@ class SearchActivity : VMBaseActivity { searchView.setQuery(key, true) } - withContext(IO) { App.db.bookDao.findByName(key).isEmpty() } -> { + withContext(IO) { appDb.bookDao.findByName(key).isEmpty() } -> { searchView.setQuery(key, true) } else -> { 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 7ad9d35e0..70de12ac1 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 @@ -11,7 +11,7 @@ import io.legado.app.data.entities.SearchBook import io.legado.app.databinding.ItemSearchBinding import io.legado.app.utils.gone import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick + class SearchAdapter(context: Context, val callBack: CallBack) : DiffRecyclerAdapter(context) { @@ -66,7 +66,7 @@ class SearchAdapter(context: Context, val callBack: CallBack) : } override fun registerListener(holder: ItemViewHolder, binding: ItemSearchBinding) { - binding.root.onClick { + binding.root.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.showBookInfo(it.name, it.author) } diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt index c6b003613..2eee0dbeb 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchViewModel.kt @@ -4,9 +4,9 @@ import android.app.Application import android.os.Handler import android.os.Looper import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.base.BaseViewModel import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchKeyword import io.legado.app.model.webBook.SearchBookModel @@ -63,7 +63,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application), override fun onSearchSuccess(searchBooks: ArrayList) { val precision = context.getPrefBoolean(PreferKey.precisionSearch) - App.db.searchBookDao.insert(*searchBooks.toTypedArray()) + appDb.searchBookDao.insert(*searchBooks.toTypedArray()) mergeItems(this, searchBooks, precision) } @@ -146,7 +146,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application), */ fun getSearchBook(name: String, author: String, success: ((searchBook: SearchBook?) -> Unit)?) { execute { - val searchBook = App.db.searchBookDao.getFirstByNameAuthor(name, author) + val searchBook = appDb.searchBookDao.getFirstByNameAuthor(name, author) success?.invoke(searchBook) } } @@ -156,10 +156,10 @@ class SearchViewModel(application: Application) : BaseViewModel(application), */ fun saveSearchKey(key: String) { execute { - App.db.searchKeywordDao.get(key)?.let { + appDb.searchKeywordDao.get(key)?.let { it.usage = it.usage + 1 - App.db.searchKeywordDao.update(it) - } ?: App.db.searchKeywordDao.insert(SearchKeyword(key, 1)) + appDb.searchKeywordDao.update(it) + } ?: appDb.searchKeywordDao.insert(SearchKeyword(key, 1)) } } @@ -168,7 +168,7 @@ class SearchViewModel(application: Application) : BaseViewModel(application), */ fun clearHistory() { execute { - App.db.searchKeywordDao.deleteAll() + appDb.searchKeywordDao.deleteAll() } } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt index a111a8cf2..aa433c6c8 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentActivity.kt @@ -3,12 +3,13 @@ package io.legado.app.ui.book.searchContent import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle +import androidx.activity.viewModels import androidx.appcompat.widget.SearchView import com.hankcs.hanlp.HanLP -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.EventBus +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.databinding.ActivitySearchContentBinding @@ -21,12 +22,10 @@ import io.legado.app.lib.theme.primaryTextColor import io.legado.app.ui.widget.recycler.UpLinearLayoutManager import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.ColorUtils -import io.legado.app.utils.getViewModel import io.legado.app.utils.observeEvent import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.jetbrains.anko.sdk27.listeners.onClick class SearchContentActivity : @@ -34,7 +33,7 @@ class SearchContentActivity : SearchContentAdapter.Callback { override val viewModel: SearchContentViewModel - get() = getViewModel(SearchContentViewModel::class.java) + by viewModels() lateinit var adapter: SearchContentAdapter private lateinit var mLayoutManager: UpLinearLayoutManager private lateinit var searchView: SearchView @@ -93,8 +92,13 @@ class SearchContentActivity : } private fun initView() { - binding.ivSearchContentTop.onClick { mLayoutManager.scrollToPositionWithOffset(0, 0) } - binding.ivSearchContentBottom.onClick { + binding.ivSearchContentTop.setOnClickListener { + mLayoutManager.scrollToPositionWithOffset( + 0, + 0 + ) + } + binding.ivSearchContentBottom.setOnClickListener { if (adapter.itemCount > 0) { mLayoutManager.scrollToPositionWithOffset(adapter.itemCount - 1, 0) } @@ -144,7 +148,7 @@ class SearchContentActivity : viewModel.lastQuery = newText var searchResults = listOf() launch(Dispatchers.Main) { - App.db.bookChapterDao.getChapterList(viewModel.bookUrl).map { chapter -> + appDb.bookChapterDao.getChapterList(viewModel.bookUrl).map { chapter -> withContext(Dispatchers.IO) { if (isLocalBook || adapter.cacheFileNames.contains(chapter.getFileName()) diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentAdapter.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentAdapter.kt index f65042827..10a3502df 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentAdapter.kt @@ -9,7 +9,7 @@ import io.legado.app.databinding.ItemSearchListBinding import io.legado.app.lib.theme.accentColor import io.legado.app.utils.getCompatColor import io.legado.app.utils.hexString -import org.jetbrains.anko.sdk27.listeners.onClick + class SearchContentAdapter(context: Context, val callback: Callback) : RecyclerAdapter(context) { @@ -38,7 +38,7 @@ class SearchContentAdapter(context: Context, val callback: Callback) : } override fun registerListener(holder: ItemViewHolder, binding: ItemSearchListBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callback.openSearchResult(it) } diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt index a3b996470..94cb50d51 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt @@ -2,8 +2,8 @@ package io.legado.app.ui.book.searchContent import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.help.ContentProcessor @@ -16,7 +16,7 @@ class SearchContentViewModel(application: Application) : BaseViewModel(applicati fun initBook(bookUrl: String, success: () -> Unit) { this.bookUrl = bookUrl execute { - book = App.db.bookDao.getBook(bookUrl) + book = appDb.bookDao.getBook(bookUrl) book?.let { contentProcessor = ContentProcessor(it.name, it.origin) } diff --git a/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugActivity.kt index 42b2e2ccd..fb11c3cfd 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugActivity.kt @@ -4,6 +4,7 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.activity.viewModels import androidx.appcompat.widget.SearchView import io.legado.app.R import io.legado.app.base.VMBaseActivity @@ -13,15 +14,15 @@ import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.accentColor import io.legado.app.ui.qrcode.QrCodeActivity import io.legado.app.ui.widget.dialog.TextDialog -import io.legado.app.utils.getViewModel +import io.legado.app.utils.startActivityForResult + +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.launch -import org.jetbrains.anko.startActivityForResult -import org.jetbrains.anko.toast class BookSourceDebugActivity : VMBaseActivity() { override val viewModel: BookSourceDebugModel - get() = getViewModel(BookSourceDebugModel::class.java) + by viewModels() private lateinit var adapter: BookSourceDebugAdapter private lateinit var searchView: SearchView @@ -83,7 +84,7 @@ class BookSourceDebugActivity : VMBaseActivity getSource().let { source -> if (checkSource(source)) { viewModel.save(source) { - startActivity(Pair("key", source.bookSourceUrl)) + startActivity { + putExtra("key", source.bookSourceUrl) + } } } } @@ -105,12 +108,13 @@ class BookSourceEditActivity : R.id.menu_login -> getSource().let { if (checkSource(it)) { if (it.loginUrl.isNullOrEmpty()) { - toast(R.string.source_no_login) + toastOnUi(R.string.source_no_login) } else { - startActivity( - Pair("sourceUrl", it.bookSourceUrl), - Pair("loginUrl", it.loginUrl) - ) + startActivity { + putExtra("sourceUrl", it.bookSourceUrl) + putExtra("loginUrl", it.loginUrl) + putExtra("userAgent", it.getHeaderMap()[AppConst.UA_NAME]) + } } } } @@ -144,7 +148,7 @@ class BookSourceEditActivity : val source = getSource() if (!source.equal(viewModel.bookSource ?: BookSource())) { alert(R.string.exit) { - messageResource = R.string.exit_no_save + setMessage(R.string.exit_no_save) positiveButton(R.string.yes) negativeButton(R.string.no) { super.finish() @@ -357,7 +361,7 @@ class BookSourceEditActivity : private fun checkSource(source: BookSource): Boolean { if (source.bookSourceUrl.isBlank() || source.bookSourceName.isBlank()) { - toast(R.string.non_null_name_url) + toastOnUi(R.string.non_null_name_url) return false } return true @@ -448,7 +452,7 @@ class BookSourceEditActivity : val rect = Rect() // 获取当前页面窗口的显示范围 window.decorView.getWindowVisibleDisplayFrame(rect) - val screenHeight = this@BookSourceEditActivity.displayMetrics.heightPixels + val screenHeight = this@BookSourceEditActivity.getSize().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/book/source/edit/BookSourceEditViewModel.kt b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt index e1c7d4d2c..add5b83c7 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt @@ -2,8 +2,8 @@ package io.legado.app.ui.book.source.edit import android.app.Application import android.content.Intent -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.help.storage.OldRule import io.legado.app.utils.GSON @@ -21,7 +21,7 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat val key = intent.getStringExtra("data") var source: BookSource? = null if (key != null) { - source = App.db.bookSourceDao.getBookSource(key) + source = appDb.bookSourceDao.getBookSource(key) } source?.let { oldSourceUrl = it.bookSourceUrl @@ -36,16 +36,16 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat execute { oldSourceUrl?.let { if (oldSourceUrl != source.bookSourceUrl) { - App.db.bookSourceDao.delete(it) + appDb.bookSourceDao.delete(it) } } oldSourceUrl = source.bookSourceUrl - App.db.bookSourceDao.insert(source) + appDb.bookSourceDao.insert(source) bookSource = source }.onSuccess { success?.invoke() }.onError { - toast(it.localizedMessage) + toastOnUi(it.localizedMessage) it.printStackTrace() } } @@ -58,13 +58,13 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat } source }.onError { - toast(it.localizedMessage) + toastOnUi(it.localizedMessage) it.printStackTrace() }.onSuccess { if (it != null) { onSuccess(it) } else { - toast("格式不对") + toastOnUi("格式不对") } } } @@ -76,7 +76,7 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat finally.invoke(it) } }.onError { - toast(it.localizedMessage ?: "Error") + toastOnUi(it.localizedMessage ?: "Error") } } } \ 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 aa78e4a5b..34c8a4ceb 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 @@ -7,17 +7,18 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.SubMenu +import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.LiveData import androidx.recyclerview.widget.ItemTouchHelper import com.google.android.material.snackbar.Snackbar -import io.legado.app.App 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.appDb import io.legado.app.data.entities.BookSource import io.legado.app.databinding.ActivityBookSourceBinding import io.legado.app.databinding.DialogEditTextBinding @@ -38,9 +39,6 @@ import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* -import org.jetbrains.anko.startActivity -import org.jetbrains.anko.startActivityForResult -import org.jetbrains.anko.toast import java.io.File class BookSourceActivity : VMBaseActivity(), @@ -50,7 +48,7 @@ class BookSourceActivity : VMBaseActivity { - App.db.bookSourceDao.liveDataAll() + appDb.bookSourceDao.liveDataAll() } searchKey == getString(R.string.enabled) -> { - App.db.bookSourceDao.liveDataEnabled() + appDb.bookSourceDao.liveDataEnabled() } searchKey == getString(R.string.disabled) -> { - App.db.bookSourceDao.liveDataDisabled() + appDb.bookSourceDao.liveDataDisabled() } searchKey.startsWith("group:") -> { val key = searchKey.substringAfter("group:") - App.db.bookSourceDao.liveDataGroupSearch("%$key%") + appDb.bookSourceDao.liveDataGroupSearch("%$key%") } else -> { - App.db.bookSourceDao.liveDataSearch("%$searchKey%") + appDb.bookSourceDao.liveDataSearch("%$searchKey%") } }.apply { observe(this@BookSourceActivity, { data -> @@ -247,7 +245,7 @@ class BookSourceActivity : VMBaseActivity groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) @@ -304,7 +302,7 @@ class BookSourceActivity : VMBaseActivity(Pair("source", it)) + startActivity { + putExtra("source", it) + } } } cancelButton() @@ -412,7 +412,7 @@ class BookSourceActivity : VMBaseActivity if (group.contains("失效")) { searchView.setQuery("失效", true) - toast("发现有失效书源,已为您自动筛选!") + toastOnUi("发现有失效书源,已为您自动筛选!") } } } @@ -443,7 +443,9 @@ class BookSourceActivity : VMBaseActivity(Pair("data", bookSource.bookSourceUrl)) + startActivity { + putExtra("data", bookSource.bookSourceUrl) + } } override fun upOrder() { @@ -463,7 +465,9 @@ class BookSourceActivity : VMBaseActivity if (resultCode == RESULT_OK) { data?.getStringExtra("result")?.let { - startActivity("source" to it) + startActivity { + putExtra("source", it) + } } } importRequestCode -> if (resultCode == Activity.RESULT_OK) { @@ -471,10 +475,12 @@ class BookSourceActivity : VMBaseActivity("dataKey" to dataKey) + startActivity { + putExtra("dataKey", dataKey) + } } } catch (e: Exception) { - toast("readTextError:${e.localizedMessage}") + toastOnUi("readTextError:${e.localizedMessage}") } } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt index 1545a3108..2b17c3189 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt @@ -20,7 +20,7 @@ import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback.Callback import io.legado.app.utils.invisible import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick + class BookSourceAdapter(context: Context, val callBack: CallBack) : RecyclerAdapter(context), @@ -132,12 +132,12 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) : } } } - ivEdit.onClick { + ivEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.edit(it) } } - ivMenuMore.onClick { + ivMenuMore.setOnClickListener { showMenu(ivMenuMore, holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt index 25094113f..92fb7e4fa 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt @@ -5,52 +5,51 @@ import android.content.Intent import android.text.TextUtils import androidx.core.content.FileProvider import androidx.documentfile.provider.DocumentFile -import io.legado.app.App import io.legado.app.BuildConfig import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.utils.* -import org.jetbrains.anko.longToast import java.io.File class BookSourceViewModel(application: Application) : BaseViewModel(application) { fun topSource(vararg sources: BookSource) { execute { - val minOrder = App.db.bookSourceDao.minOrder - 1 + val minOrder = appDb.bookSourceDao.minOrder - 1 sources.forEachIndexed { index, bookSource -> bookSource.customOrder = minOrder - index } - App.db.bookSourceDao.update(*sources) + appDb.bookSourceDao.update(*sources) } } fun bottomSource(vararg sources: BookSource) { execute { - val maxOrder = App.db.bookSourceDao.maxOrder + 1 + val maxOrder = appDb.bookSourceDao.maxOrder + 1 sources.forEachIndexed { index, bookSource -> bookSource.customOrder = maxOrder + index } - App.db.bookSourceDao.update(*sources) + appDb.bookSourceDao.update(*sources) } } fun del(bookSource: BookSource) { - execute { App.db.bookSourceDao.delete(bookSource) } + execute { appDb.bookSourceDao.delete(bookSource) } } fun update(vararg bookSource: BookSource) { - execute { App.db.bookSourceDao.update(*bookSource) } + execute { appDb.bookSourceDao.update(*bookSource) } } fun upOrder() { execute { - val sources = App.db.bookSourceDao.all + val sources = appDb.bookSourceDao.all for ((index: Int, source: BookSource) in sources.withIndex()) { source.customOrder = index + 1 } - App.db.bookSourceDao.update(*sources.toTypedArray()) + appDb.bookSourceDao.update(*sources.toTypedArray()) } } @@ -60,7 +59,7 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) sources.forEach { list.add(it.copy(enabled = true)) } - App.db.bookSourceDao.update(*list.toTypedArray()) + appDb.bookSourceDao.update(*list.toTypedArray()) } } @@ -70,7 +69,7 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) sources.forEach { list.add(it.copy(enabled = false)) } - App.db.bookSourceDao.update(*list.toTypedArray()) + appDb.bookSourceDao.update(*list.toTypedArray()) } } @@ -80,7 +79,7 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) sources.forEach { list.add(it.copy(enabledExplore = true)) } - App.db.bookSourceDao.update(*list.toTypedArray()) + appDb.bookSourceDao.update(*list.toTypedArray()) } } @@ -90,7 +89,7 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) sources.forEach { list.add(it.copy(enabledExplore = false)) } - App.db.bookSourceDao.update(*list.toTypedArray()) + appDb.bookSourceDao.update(*list.toTypedArray()) } } @@ -109,7 +108,7 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) val newGroup = ArrayList(lh).joinToString(separator = ",") list.add(source.copy(bookSourceGroup = newGroup)) } - App.db.bookSourceDao.update(*list.toTypedArray()) + appDb.bookSourceDao.update(*list.toTypedArray()) } } @@ -128,13 +127,13 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) val newGroup = ArrayList(lh).joinToString(separator = ",") list.add(source.copy(bookSourceGroup = newGroup)) } - App.db.bookSourceDao.update(*list.toTypedArray()) + appDb.bookSourceDao.update(*list.toTypedArray()) } } fun delSelection(sources: List) { execute { - App.db.bookSourceDao.delete(*sources.toTypedArray()) + appDb.bookSourceDao.delete(*sources.toTypedArray()) } } @@ -144,9 +143,9 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) FileUtils.createFileIfNotExist(file, "exportBookSource.json") .writeText(json) }.onSuccess { - context.longToast("成功导出至\n${file.absolutePath}") + context.longToastOnUi("成功导出至\n${file.absolutePath}") }.onError { - context.longToast("导出失败\n${it.localizedMessage}") + context.longToastOnUi("导出失败\n${it.localizedMessage}") } } @@ -157,9 +156,9 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) doc.createFile("", "exportBookSource.json") ?.writeText(context, json) }.onSuccess { - context.longToast("成功导出至\n${doc.uri.path}") + context.longToastOnUi("成功导出至\n${doc.uri.path}") }.onError { - context.longToast("导出失败\n${it.localizedMessage}") + context.longToastOnUi("导出失败\n${it.localizedMessage}") } } @@ -181,23 +180,23 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) }.onSuccess { success.invoke(it) }.onError { - toast(it.msg) + toastOnUi(it.msg) } } fun addGroup(group: String) { execute { - val sources = App.db.bookSourceDao.noGroup + val sources = appDb.bookSourceDao.noGroup sources.map { source -> source.bookSourceGroup = group } - App.db.bookSourceDao.update(*sources.toTypedArray()) + appDb.bookSourceDao.update(*sources.toTypedArray()) } } fun upGroup(oldGroup: String, newGroup: String?) { execute { - val sources = App.db.bookSourceDao.getByGroup(oldGroup) + val sources = appDb.bookSourceDao.getByGroup(oldGroup) sources.map { source -> source.bookSourceGroup?.splitNotBlank(",")?.toHashSet()?.let { it.remove(oldGroup) @@ -206,18 +205,18 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) source.bookSourceGroup = TextUtils.join(",", it) } } - App.db.bookSourceDao.update(*sources.toTypedArray()) + appDb.bookSourceDao.update(*sources.toTypedArray()) } } fun delGroup(group: String) { execute { execute { - val sources = App.db.bookSourceDao.getByGroup(group) + val sources = appDb.bookSourceDao.getByGroup(group) sources.map { source -> source.removeGroup(group) } - App.db.bookSourceDao.update(*sources.toTypedArray()) + appDb.bookSourceDao.update(*sources.toTypedArray()) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt index 45e973c8b..59344bfdc 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/GroupManageDialog.kt @@ -9,12 +9,13 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.DialogFragment +import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogRecyclerViewBinding import io.legado.app.databinding.ItemGroupManageBinding @@ -22,12 +23,15 @@ import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.backgroundColor import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.* +import io.legado.app.utils.applyTint +import io.legado.app.utils.getSize +import io.legado.app.utils.requestInputMethod +import io.legado.app.utils.splitNotBlank import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { - private lateinit var viewModel: BookSourceViewModel + private val viewModel: BookSourceViewModel by activityViewModels() private lateinit var adapter: GroupAdapter private val binding by viewBinding(DialogRecyclerViewBinding::bind) @@ -42,7 +46,6 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { container: ViewGroup?, savedInstanceState: Bundle? ): View? { - viewModel = getViewModelOfActivity(BookSourceViewModel::class.java) return inflater.inflate(R.layout.dialog_recycler_view, container) } @@ -62,7 +65,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { } private fun initData() { - App.db.bookSourceDao.liveGroup().observe(viewLifecycleOwner, { + appDb.bookSourceDao.liveGroup().observe(viewLifecycleOwner, { val groups = linkedSetOf() it.map { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) @@ -83,7 +86,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { alert(title = getString(R.string.add_group)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater) alertBinding.editView.setHint(R.string.group_name) - customView = alertBinding.root + customView { alertBinding.root } yesButton { alertBinding.editView.text?.toString()?.let { if (it.isNotBlank()) { @@ -100,7 +103,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { alert(title = getString(R.string.group_edit)) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater) alertBinding.editView.setHint(R.string.group_name) - customView = alertBinding.root + customView { alertBinding.root } yesButton { viewModel.upGroup(group, alertBinding.editView.text?.toString()) } @@ -129,12 +132,12 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { override fun registerListener(holder: ItemViewHolder, binding: ItemGroupManageBinding) { binding.apply { - tvEdit.onClick { + tvEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { editGroup(it) } } - tvDel.onClick { + tvDel.setOnClickListener { getItem(holder.layoutPosition)?.let { viewModel.delGroup(it) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt b/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt index 914414a60..8300aa3da 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/BookmarkAdapter.kt @@ -7,9 +7,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import io.legado.app.data.entities.Bookmark import io.legado.app.databinding.ItemBookmarkBinding -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick - +import splitties.views.onLongClick class BookmarkAdapter(val callback: Callback) : PagedListAdapter(DIFF_CALLBACK) { @@ -46,12 +44,11 @@ class BookmarkAdapter(val callback: Callback) : PagedListAdapter(R.layout.fragment_bookmark), BookmarkAdapter.Callback, ChapterListViewModel.BookmarkCallBack { - override val viewModel: ChapterListViewModel - get() = getViewModelOfActivity(ChapterListViewModel::class.java) + override val viewModel: ChapterListViewModel by activityViewModels() private val binding by viewBinding(FragmentBookmarkBinding::bind) private lateinit var adapter: BookmarkAdapter private var bookmarkLiveData: LiveData>? = null @@ -52,7 +51,7 @@ class BookmarkFragment : VMBaseFragment(R.layout.fragment_ bookmarkLiveData?.removeObservers(viewLifecycleOwner) bookmarkLiveData = LivePagedListBuilder( - App.db.bookmarkDao.observeByBook(book.bookUrl, book.name, book.author), 20 + appDb.bookmarkDao.observeByBook(book.bookUrl, book.name, book.author), 20 ).build() bookmarkLiveData?.observe(viewLifecycleOwner, { adapter.submitList(it) }) } @@ -64,7 +63,7 @@ class BookmarkFragment : VMBaseFragment(R.layout.fragment_ } else { bookmarkLiveData?.removeObservers(viewLifecycleOwner) bookmarkLiveData = LivePagedListBuilder( - App.db.bookmarkDao.liveDataSearch( + appDb.bookmarkDao.liveDataSearch( viewModel.bookUrl, newText ), 20 @@ -85,24 +84,24 @@ class BookmarkFragment : VMBaseFragment(R.layout.fragment_ @SuppressLint("InflateParams") override fun onLongClick(bookmark: Bookmark) { requireContext().alert(R.string.bookmark) { - message = bookmark.chapterName + setMessage(bookmark.chapterName) val alertBinding = DialogBookmarkBinding.inflate(layoutInflater).apply { editBookText.setText(bookmark.bookText) editView.setText(bookmark.content) } - customView = alertBinding.root + customView { alertBinding.root } yesButton { alertBinding.apply { Coroutine.async { bookmark.bookText = editBookText.text.toString() bookmark.content = editView.text.toString() - App.db.bookmarkDao.insert(bookmark) + appDb.bookmarkDao.insert(bookmark) } } } noButton() neutralButton(R.string.delete) { - App.db.bookmarkDao.delete(bookmark) + appDb.bookmarkDao.delete(bookmark) } }.show().requestInputMethod() } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListActivity.kt b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListActivity.kt index 4fa998b22..dfe49d6e7 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListActivity.kt @@ -2,6 +2,7 @@ package io.legado.app.ui.book.toc import android.os.Bundle import android.view.Menu +import androidx.activity.viewModels import androidx.appcompat.widget.SearchView import androidx.core.view.isGone import androidx.fragment.app.Fragment @@ -14,14 +15,14 @@ import io.legado.app.databinding.ActivityChapterListBinding import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.accentColor import io.legado.app.lib.theme.primaryTextColor -import io.legado.app.utils.getViewModel + import io.legado.app.utils.gone import io.legado.app.utils.visible class ChapterListActivity : VMBaseActivity() { override val viewModel: ChapterListViewModel - get() = getViewModel(ChapterListViewModel::class.java) + by viewModels() private lateinit var tabLayout: TabLayout private var searchView: SearchView? = null diff --git a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt index 13176acae..1af21f922 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListAdapter.kt @@ -10,7 +10,7 @@ import io.legado.app.databinding.ItemChapterListBinding import io.legado.app.lib.theme.accentColor import io.legado.app.utils.getCompatColor import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick + class ChapterListAdapter(context: Context, val callback: Callback) : RecyclerAdapter(context) { @@ -49,7 +49,7 @@ class ChapterListAdapter(context: Context, val callback: Callback) : } override fun registerListener(holder: ItemViewHolder, binding: ItemChapterListBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callback.openChapter(it) } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt index 0a4b060fb..72bca9746 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListFragment.kt @@ -5,11 +5,12 @@ import android.app.Activity.RESULT_OK import android.content.Intent import android.os.Bundle import android.view.View +import androidx.fragment.app.activityViewModels import androidx.lifecycle.LiveData -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseFragment import io.legado.app.constant.EventBus +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter import io.legado.app.databinding.FragmentChapterListBinding @@ -19,21 +20,18 @@ import io.legado.app.lib.theme.getPrimaryTextColor import io.legado.app.ui.widget.recycler.UpLinearLayoutManager import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.ColorUtils -import io.legado.app.utils.getViewModelOfActivity import io.legado.app.utils.observeEvent import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.jetbrains.anko.sdk27.listeners.onClick import kotlin.math.min class ChapterListFragment : VMBaseFragment(R.layout.fragment_chapter_list), ChapterListAdapter.Callback, ChapterListViewModel.ChapterListCallBack { - override val viewModel: ChapterListViewModel - get() = getViewModelOfActivity(ChapterListViewModel::class.java) + override val viewModel: ChapterListViewModel by activityViewModels() private val binding by viewBinding(FragmentChapterListBinding::bind) lateinit var adapter: ChapterListAdapter private var durChapterIndex = 0 @@ -63,13 +61,13 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme } private fun initView() = with(binding) { - ivChapterTop.onClick { mLayoutManager.scrollToPositionWithOffset(0, 0) } - ivChapterBottom.onClick { + ivChapterTop.setOnClickListener { mLayoutManager.scrollToPositionWithOffset(0, 0) } + ivChapterBottom.setOnClickListener { if (adapter.itemCount > 0) { mLayoutManager.scrollToPositionWithOffset(adapter.itemCount - 1, 0) } } - tvCurrentChapterInfo.onClick { + tvCurrentChapterInfo.setOnClickListener { mLayoutManager.scrollToPositionWithOffset(durChapterIndex, 0) } } @@ -89,7 +87,7 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme private fun initDoc() { tocLiveData?.removeObservers(this@ChapterListFragment) - tocLiveData = App.db.bookChapterDao.observeByBook(viewModel.bookUrl) + tocLiveData = appDb.bookChapterDao.observeByBook(viewModel.bookUrl) tocLiveData?.observe(viewLifecycleOwner, { adapter.setItems(it) if (!scrollToDurChapter) { @@ -124,7 +122,7 @@ class ChapterListFragment : VMBaseFragment(R.layout.fragme initDoc() } else { tocLiveData?.removeObservers(this) - tocLiveData = App.db.bookChapterDao.liveDataSearch(viewModel.bookUrl, newText) + tocLiveData = appDb.bookChapterDao.liveDataSearch(viewModel.bookUrl, newText) tocLiveData?.observe(viewLifecycleOwner, { adapter.setItems(it) }) diff --git a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListViewModel.kt b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListViewModel.kt index 48682630c..27f6011ae 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/ChapterListViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/ChapterListViewModel.kt @@ -2,8 +2,8 @@ package io.legado.app.ui.book.toc import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book class ChapterListViewModel(application: Application) : BaseViewModel(application) { @@ -15,7 +15,7 @@ class ChapterListViewModel(application: Application) : BaseViewModel(application fun initBook(bookUrl: String, success: () -> Unit) { this.bookUrl = bookUrl execute { - book = App.db.bookDao.getBook(bookUrl) + book = appDb.bookDao.getBook(bookUrl) }.onSuccess { success.invoke() } diff --git a/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt b/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt index 794271d3e..d538cc7a8 100644 --- a/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt +++ b/app/src/main/java/io/legado/app/ui/config/BackupRestoreUi.kt @@ -5,7 +5,6 @@ import android.content.Intent import android.net.Uri import androidx.documentfile.provider.DocumentFile import androidx.fragment.app.Fragment -import io.legado.app.App import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.help.AppConfig @@ -20,9 +19,9 @@ import io.legado.app.ui.filepicker.FilePicker import io.legado.app.utils.getPrefString import io.legado.app.utils.isContentScheme import io.legado.app.utils.longToast -import io.legado.app.utils.toast +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers.Main -import org.jetbrains.anko.toast +import splitties.init.appCtx object BackupRestoreUi { private const val selectFolderRequestCode = 21 @@ -42,7 +41,7 @@ object BackupRestoreUi { Coroutine.async { Backup.backup(fragment.requireContext(), backupPath) }.onSuccess { - fragment.toast(R.string.backup_success) + fragment.toastOnUi(R.string.backup_success) } } else { selectBackupFolder(fragment, backupSelectRequestCode) @@ -65,7 +64,7 @@ object BackupRestoreUi { AppConfig.backupPath = path Backup.backup(fragment.requireContext(), path) }.onSuccess { - fragment.toast(R.string.backup_success) + fragment.toastOnUi(R.string.backup_success) } } .request() @@ -126,24 +125,24 @@ object BackupRestoreUi { backupSelectRequestCode -> if (resultCode == RESULT_OK) { data?.data?.let { uri -> if (uri.isContentScheme()) { - App.INSTANCE.contentResolver.takePersistableUriPermission( + appCtx.contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) AppConfig.backupPath = uri.toString() Coroutine.async { - Backup.backup(App.INSTANCE, uri.toString()) + Backup.backup(appCtx, uri.toString()) }.onSuccess { - App.INSTANCE.toast(R.string.backup_success) + appCtx.toastOnUi(R.string.backup_success) } } else { uri.path?.let { path -> AppConfig.backupPath = path Coroutine.async { - Backup.backup(App.INSTANCE, path) + Backup.backup(appCtx, path) }.onSuccess { - App.INSTANCE.toast(R.string.backup_success) + appCtx.toastOnUi(R.string.backup_success) } } } @@ -152,20 +151,20 @@ object BackupRestoreUi { restoreSelectRequestCode -> if (resultCode == RESULT_OK) { data?.data?.let { uri -> if (uri.isContentScheme()) { - App.INSTANCE.contentResolver.takePersistableUriPermission( + appCtx.contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) AppConfig.backupPath = uri.toString() Coroutine.async { - Restore.restore(App.INSTANCE, uri.toString()) + Restore.restore(appCtx, uri.toString()) } } else { uri.path?.let { path -> AppConfig.backupPath = path Coroutine.async { - Restore.restore(App.INSTANCE, path) + Restore.restore(appCtx, path) } } } @@ -174,7 +173,7 @@ object BackupRestoreUi { selectFolderRequestCode -> if (resultCode == RESULT_OK) { data?.data?.let { uri -> if (uri.isContentScheme()) { - App.INSTANCE.contentResolver.takePersistableUriPermission( + appCtx.contentResolver.takePersistableUriPermission( uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION @@ -187,7 +186,7 @@ object BackupRestoreUi { } oldDataRequestCode -> if (resultCode == RESULT_OK) { data?.data?.let { uri -> - ImportOldData.importUri(App.INSTANCE, uri) + ImportOldData.importUri(appCtx, uri) } } } diff --git a/app/src/main/java/io/legado/app/ui/config/ConfigActivity.kt b/app/src/main/java/io/legado/app/ui/config/ConfigActivity.kt index 8b6c7701c..2d7ab0cbd 100644 --- a/app/src/main/java/io/legado/app/ui/config/ConfigActivity.kt +++ b/app/src/main/java/io/legado/app/ui/config/ConfigActivity.kt @@ -1,16 +1,17 @@ package io.legado.app.ui.config import android.os.Bundle +import androidx.activity.viewModels import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.EventBus import io.legado.app.databinding.ActivityConfigBinding -import io.legado.app.utils.getViewModel + import io.legado.app.utils.observeEvent class ConfigActivity : VMBaseActivity() { override val viewModel: ConfigViewModel - get() = getViewModel(ConfigViewModel::class.java) + by viewModels() override fun getViewBinding(): ActivityConfigBinding { return ActivityConfigBinding.inflate(layoutInflater) diff --git a/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt index 42945d48f..b44909711 100644 --- a/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt +++ b/app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt @@ -13,7 +13,6 @@ import android.view.View import androidx.documentfile.provider.DocumentFile import androidx.preference.ListPreference import androidx.preference.Preference -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BasePreferenceFragment import io.legado.app.constant.EventBus @@ -32,6 +31,7 @@ import io.legado.app.ui.main.MainActivity import io.legado.app.ui.widget.image.CoverImageView import io.legado.app.ui.widget.number.NumberPickerDialog import io.legado.app.utils.* +import splitties.init.appCtx import java.io.File @@ -40,9 +40,9 @@ class OtherConfigFragment : BasePreferenceFragment(), private val requestCodeCover = 231 - private val packageManager = App.INSTANCE.packageManager + private val packageManager = appCtx.packageManager private val componentName = ComponentName( - App.INSTANCE, + appCtx, SharedReceiverActivity::class.java.name ) private val webPort get() = getPrefInt(PreferKey.webPort, 1122) @@ -124,10 +124,10 @@ class OtherConfigFragment : BasePreferenceFragment(), key, getPrefString(PreferKey.defaultCover) ) PreferKey.language -> listView.postDelayed({ - LanguageUtils.setConfiguration(App.INSTANCE) - val intent = Intent(App.INSTANCE, MainActivity::class.java) + LanguageUtils.setConfiguration(appCtx) + val intent = Intent(appCtx, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) - App.INSTANCE.startActivity(intent) + appCtx.startActivity(intent) Process.killProcess(Process.myPid()) }, 1000) PreferKey.userAgent -> listView.post { @@ -156,7 +156,7 @@ class OtherConfigFragment : BasePreferenceFragment(), alert("UserAgent") { val alertBinding = DialogEditTextBinding.inflate(layoutInflater) alertBinding.editView.setText(AppConfig.userAgent) - customView = alertBinding.root + customView { alertBinding.root } okButton { val userAgent = alertBinding.editView.text?.toString() if (userAgent.isNullOrBlank()) { @@ -177,7 +177,7 @@ class OtherConfigFragment : BasePreferenceFragment(), okButton { BookHelp.clearCache() FileUtils.deleteFile(requireActivity().cacheDir.absolutePath) - toast(R.string.clear_cache_success) + toastOnUi(R.string.clear_cache_success) } noButton() }.show() @@ -221,7 +221,7 @@ class OtherConfigFragment : BasePreferenceFragment(), file.writeBytes(byteArray) putPrefString(PreferKey.defaultCover, file.absolutePath) CoverImageView.upDefaultCover() - } ?: toast("获取文件出错") + } ?: toastOnUi("获取文件出错") } } else { PermissionsCompat.Builder(this) 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 ce5cf3814..834e53eb9 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 @@ -13,7 +13,6 @@ import android.view.MenuItem import android.view.View import androidx.documentfile.provider.DocumentFile import androidx.preference.Preference -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BasePreferenceFragment import io.legado.app.constant.AppConst @@ -60,7 +59,7 @@ class ThemeConfigFragment : BasePreferenceFragment(), findPreference(PreferKey.cBackground)?.let { it.onSaveColor = { color -> if (!ColorUtils.isColorLight(color)) { - toast(R.string.day_background_too_dark) + toastOnUi(R.string.day_background_too_dark) true } else { false @@ -70,7 +69,7 @@ class ThemeConfigFragment : BasePreferenceFragment(), findPreference(PreferKey.cNBackground)?.let { it.onSaveColor = { color -> if (ColorUtils.isColorLight(color)) { - toast(R.string.night_background_too_light) + toastOnUi(R.string.night_background_too_light) true } else { false @@ -84,11 +83,11 @@ class ThemeConfigFragment : BasePreferenceFragment(), val textColor = getCompatColor(R.color.primaryText) when { ColorUtils.getColorDifference(color, background) <= 60 -> { - toast(R.string.accent_background_diff) + toastOnUi(R.string.accent_background_diff) true } ColorUtils.getColorDifference(color, textColor) <= 60 -> { - toast(R.string.accent_text_diff) + toastOnUi(R.string.accent_text_diff) true } else -> false @@ -102,11 +101,11 @@ class ThemeConfigFragment : BasePreferenceFragment(), val textColor = getCompatColor(R.color.primaryText) when { ColorUtils.getColorDifference(color, background) <= 60 -> { - toast(R.string.accent_background_diff) + toastOnUi(R.string.accent_background_diff) true } ColorUtils.getColorDifference(color, textColor) <= 60 -> { - toast(R.string.accent_text_diff) + toastOnUi(R.string.accent_text_diff) true } else -> false @@ -140,7 +139,7 @@ class ThemeConfigFragment : BasePreferenceFragment(), when (item.itemId) { R.id.menu_theme_mode -> { AppConfig.isNightTheme = !AppConfig.isNightTheme - App.INSTANCE.applyDayNight() + ThemeConfig.applyDayNight(requireContext()) } } return super.onOptionsItemSelected(item) @@ -225,7 +224,7 @@ class ThemeConfigFragment : BasePreferenceFragment(), private fun saveThemeAlert(key: String) { alert(R.string.theme_name) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.editView.text?.toString()?.let { themeName -> when (key) { @@ -277,7 +276,7 @@ class ThemeConfigFragment : BasePreferenceFragment(), putPrefString(preferenceKey, file.absolutePath) upPreferenceSummary(preferenceKey, file.absolutePath) success() - } ?: toast("获取文件出错") + } ?: toastOnUi("获取文件出错") } } else { PermissionsCompat.Builder(this) 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 974924802..358b16613 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 @@ -19,8 +19,6 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.share class ThemeListDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { private val binding by viewBinding(DialogRecyclerViewBinding::bind) @@ -72,7 +70,7 @@ class ThemeListDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { if (ThemeConfig.addConfig(it)) { initData() } else { - toast("格式不对,添加失败") + toastOnUi("格式不对,添加失败") } } } @@ -115,13 +113,13 @@ class ThemeListDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { override fun registerListener(holder: ItemViewHolder, binding: ItemThemeConfigBinding) { binding.apply { - root.onClick { + root.setOnClickListener { ThemeConfig.applyConfig(context, ThemeConfig.configList[holder.layoutPosition]) } - ivShare.onClick { + ivShare.setOnClickListener { share(holder.layoutPosition) } - ivDelete.onClick { + ivDelete.setOnClickListener { delete(holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/filepicker/FilePickerDialog.kt b/app/src/main/java/io/legado/app/ui/filepicker/FilePickerDialog.kt index 9c4d1358f..2f574f2cd 100644 --- a/app/src/main/java/io/legado/app/ui/filepicker/FilePickerDialog.kt +++ b/app/src/main/java/io/legado/app/ui/filepicker/FilePickerDialog.kt @@ -170,14 +170,14 @@ class FilePickerDialog : DialogFragment(), } else { fileItem?.path?.let { path -> if (mode == DIRECTORY) { - toast("这是文件夹选择,不能选择文件,点击右上角的确定选择文件夹") + toastOnUi("这是文件夹选择,不能选择文件,点击右上角的确定选择文件夹") } else if (allowExtensions.isNullOrEmpty() || allowExtensions?.contains(FileUtils.getExtension(path)) == true ) { setData(path) dismiss() } else { - toast("不能打开此文件") + toastOnUi("不能打开此文件") } } } diff --git a/app/src/main/java/io/legado/app/ui/filepicker/adapter/FileAdapter.kt b/app/src/main/java/io/legado/app/ui/filepicker/adapter/FileAdapter.kt index cdd8301fc..e4bedec58 100644 --- a/app/src/main/java/io/legado/app/ui/filepicker/adapter/FileAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/filepicker/adapter/FileAdapter.kt @@ -13,7 +13,7 @@ import io.legado.app.ui.filepicker.entity.FileItem import io.legado.app.ui.filepicker.utils.ConvertUtils import io.legado.app.ui.filepicker.utils.FilePickerIcon import io.legado.app.utils.FileUtils -import org.jetbrains.anko.sdk27.listeners.onClick + import java.io.File import java.util.* @@ -118,7 +118,7 @@ class FileAdapter(context: Context, val callBack: CallBack) : } override fun registerListener(holder: ItemViewHolder, binding: ItemFileFilepickerBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { callBack.onFileClick(holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/filepicker/adapter/PathAdapter.kt b/app/src/main/java/io/legado/app/ui/filepicker/adapter/PathAdapter.kt index 4ad56534f..60ea3f648 100644 --- a/app/src/main/java/io/legado/app/ui/filepicker/adapter/PathAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/filepicker/adapter/PathAdapter.kt @@ -8,7 +8,7 @@ import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.databinding.ItemPathFilepickerBinding import io.legado.app.ui.filepicker.utils.ConvertUtils import io.legado.app.ui.filepicker.utils.FilePickerIcon -import org.jetbrains.anko.sdk27.listeners.onClick + import java.util.* @@ -61,7 +61,7 @@ class PathAdapter(context: Context, val callBack: CallBack) : } override fun registerListener(holder: ItemViewHolder, binding: ItemPathFilepickerBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { callBack.onPathClick(holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/login/SourceLogin.kt b/app/src/main/java/io/legado/app/ui/login/SourceLogin.kt index d357e9c53..028b85b98 100644 --- a/app/src/main/java/io/legado/app/ui/login/SourceLogin.kt +++ b/app/src/main/java/io/legado/app/ui/login/SourceLogin.kt @@ -19,6 +19,7 @@ class SourceLogin : BaseActivity() { var sourceUrl: String? = null var loginUrl: String? = null + var userAgent: String? = null var checking = false override fun getViewBinding(): ActivitySourceLoginBinding { @@ -28,6 +29,7 @@ class SourceLogin : BaseActivity() { override fun onActivityCreated(savedInstanceState: Bundle?) { sourceUrl = intent.getStringExtra("sourceUrl") loginUrl = intent.getStringExtra("loginUrl") + userAgent = intent.getStringExtra("userAgent") title = getString(R.string.login_source, sourceUrl) initWebView() } @@ -38,6 +40,9 @@ class SourceLogin : BaseActivity() { settings.setSupportZoom(true) settings.builtInZoomControls = true settings.javaScriptEnabled = true + userAgent?.let { + settings.userAgentString = it + } val cookieManager = CookieManager.getInstance() binding.webView.webViewClient = object : WebViewClient() { override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt index 4890d22da..1edd9c2bb 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt @@ -4,17 +4,18 @@ import android.os.Bundle import android.view.KeyEvent import android.view.MenuItem import android.view.ViewGroup +import androidx.activity.viewModels import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentStatePagerAdapter import androidx.viewpager.widget.ViewPager import com.google.android.material.bottomnavigation.BottomNavigationView -import io.legado.app.App import io.legado.app.BuildConfig import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.constant.appInfo import io.legado.app.databinding.ActivityMainBinding import io.legado.app.help.AppConfig import io.legado.app.help.BookHelp @@ -29,18 +30,16 @@ import io.legado.app.ui.main.explore.ExploreFragment import io.legado.app.ui.main.my.MyFragment import io.legado.app.ui.main.rss.RssFragment import io.legado.app.ui.widget.dialog.TextDialog -import io.legado.app.utils.getViewModel import io.legado.app.utils.hideSoftInput import io.legado.app.utils.observeEvent -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi class MainActivity : VMBaseActivity(), BottomNavigationView.OnNavigationItemSelectedListener, BottomNavigationView.OnNavigationItemReselectedListener, ViewPager.OnPageChangeListener by ViewPager.SimpleOnPageChangeListener() { - override val viewModel: MainViewModel - get() = getViewModel(MainViewModel::class.java) + override val viewModel: MainViewModel by viewModels() private var exitTime: Long = 0 private var bookshelfReselected: Long = 0 private var exploreReselected: Long = 0 @@ -108,8 +107,8 @@ class MainActivity : VMBaseActivity(), } private fun upVersion() { - if (LocalConfig.versionCode != App.versionCode) { - LocalConfig.versionCode = App.versionCode + if (LocalConfig.versionCode != appInfo.versionCode) { + LocalConfig.versionCode = appInfo.versionCode if (LocalConfig.isFirstOpenApp) { val text = String(assets.open("help/appHelp.md").readBytes()) TextDialog.show(supportFragmentManager, text, TextDialog.MD) @@ -144,7 +143,7 @@ class MainActivity : VMBaseActivity(), return true } if (System.currentTimeMillis() - exitTime > 2000) { - toast(R.string.double_click_exit) + toastOnUi(R.string.double_click_exit) exitTime = System.currentTimeMillis() } else { if (BaseReadAloudService.pause) { 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 ef266e4bb..b701c4f5d 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 @@ -1,10 +1,10 @@ package io.legado.app.ui.main import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel import io.legado.app.constant.BookType import io.legado.app.constant.EventBus +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.help.AppConfig import io.legado.app.help.BookHelp @@ -44,7 +44,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) { fun upAllBookToc() { execute { - upToc(App.db.bookDao.hasUpdateBooks) + upToc(appDb.bookDao.hasUpdateBooks) } } @@ -66,21 +66,23 @@ class MainViewModel(application: Application) : BaseViewModel(application) { @Synchronized private fun updateToc() { + var update = false bookMap.forEach { bookEntry -> if (!updateList.contains(bookEntry.key)) { + update = true val book = bookEntry.value synchronized(this) { updateList.add(book.bookUrl) postEvent(EventBus.UP_BOOK, book.bookUrl) } - App.db.bookSourceDao.getBookSource(book.origin)?.let { bookSource -> + appDb.bookSourceDao.getBookSource(book.origin)?.let { bookSource -> val webBook = WebBook(bookSource) webBook.getChapterList(this, book, context = upTocPool) .timeout(60000) .onSuccess(IO) { - App.db.bookDao.update(book) - App.db.bookChapterDao.delByBook(book.bookUrl) - App.db.bookChapterDao.insert(*it.toTypedArray()) + appDb.bookDao.update(book) + appDb.bookChapterDao.delByBook(book.bookUrl) + appDb.bookChapterDao.insert(*it.toTypedArray()) if (AppConfig.preDownload) { cacheBook(webBook, book) } @@ -105,6 +107,9 @@ class MainViewModel(application: Application) : BaseViewModel(application) { return } } + if (!update) { + usePoolCount-- + } } private fun cacheBook(webBook: WebBook, book: Book) { @@ -112,7 +117,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) { if (book.totalChapterNum > book.durChapterIndex) { val downloadToIndex = min(book.totalChapterNum, book.durChapterIndex.plus(10)) for (i in book.durChapterIndex until downloadToIndex) { - App.db.bookChapterDao.getChapter(book.bookUrl, i)?.let { chapter -> + appDb.bookChapterDao.getChapter(book.bookUrl, i)?.let { chapter -> if (!BookHelp.hasContent(book, chapter)) { var addToCache = false while (!addToCache) { @@ -141,9 +146,9 @@ class MainViewModel(application: Application) : BaseViewModel(application) { fun postLoad() { execute { FileUtils.deleteFile(FileUtils.getPath(context.cacheDir, "Fonts")) - if (App.db.httpTTSDao.count == 0) { + if (appDb.httpTTSDao.count == 0) { DefaultData.httpTTS.let { - App.db.httpTTSDao.insert(*it.toTypedArray()) + appDb.httpTTSDao.insert(*it.toTypedArray()) } } } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt index fd67e259b..4ff1e9b50 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfFragment.kt @@ -9,16 +9,14 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.SearchView -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.fragment.app.FragmentStatePagerAdapter +import androidx.fragment.app.* import androidx.lifecycle.LiveData import com.google.android.material.tabs.TabLayout -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseFragment import io.legado.app.constant.AppConst import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.BookGroup import io.legado.app.databinding.DialogBookshelfConfigBinding import io.legado.app.databinding.DialogEditTextBinding @@ -37,7 +35,6 @@ import io.legado.app.ui.main.MainViewModel import io.legado.app.ui.main.bookshelf.books.BooksFragment import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.share /** * 书架界面 @@ -49,10 +46,8 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b private val requestCodeImportBookshelf = 312 private val binding by viewBinding(FragmentBookshelfBinding::bind) - override val viewModel: BookshelfViewModel - get() = getViewModel(BookshelfViewModel::class.java) - private val activityViewModel: MainViewModel - get() = getViewModelOfActivity(MainViewModel::class.java) + override val viewModel: BookshelfViewModel by viewModels() + private val activityViewModel: MainViewModel by activityViewModels() private lateinit var adapter: FragmentStatePagerAdapter private lateinit var tabLayout: TabLayout private var bookGroupLiveData: LiveData>? = null @@ -85,14 +80,14 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b .show(childFragmentManager, "groupManageDialog") R.id.menu_add_local -> startActivity() R.id.menu_add_url -> addBookByUrl() - R.id.menu_arrange_bookshelf -> startActivity( - Pair("groupId", selectedGroup.groupId), - Pair("groupName", selectedGroup.groupName) - ) - R.id.menu_download -> startActivity( - Pair("groupId", selectedGroup.groupId), - Pair("groupName", selectedGroup.groupName) - ) + R.id.menu_arrange_bookshelf -> startActivity { + putExtra("groupId", selectedGroup.groupId) + putExtra("groupName", selectedGroup.groupName) + } + R.id.menu_download -> startActivity { + putExtra("groupId", selectedGroup.groupId) + putExtra("groupName", selectedGroup.groupName) + } R.id.menu_export_bookshelf -> { val fragment = fragmentMap[selectedGroup.groupId] viewModel.exportBookshelf(fragment?.getBooks()) { @@ -119,7 +114,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b private fun initBookGroupData() { bookGroupLiveData?.removeObservers(viewLifecycleOwner) - bookGroupLiveData = App.db.bookGroupDao.liveDataShow().apply { + bookGroupLiveData = appDb.bookGroupDao.liveDataShow().apply { observe(viewLifecycleOwner) { viewModel.checkGroup(it) upGroup(it) @@ -128,7 +123,9 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b } override fun onQueryTextSubmit(query: String?): Boolean { - startActivity(Pair("key", query)) + startActivity { + putExtra("key", query) + } return false } @@ -139,7 +136,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b @Synchronized private fun upGroup(data: List) { if (data.isEmpty()) { - App.db.bookGroupDao.enableGroup(AppConst.bookGroupAllId) + appDb.bookGroupDao.enableGroup(AppConst.bookGroupAllId) } else { if (data != bookGroups) { bookGroups.clear() @@ -168,7 +165,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b rgLayout.checkByIndex(bookshelfLayout) rgSort.checkByIndex(bookshelfSort) } - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.apply { var changed = false @@ -193,7 +190,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b private fun addBookByUrl() { alert(titleResource = R.string.add_book_url) { val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.editView.text?.toString()?.let { viewModel.addBookByUrl(it) @@ -205,7 +202,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b override fun onTabReselected(tab: TabLayout.Tab) { fragmentMap[selectedGroup.groupId]?.let { - toast("${selectedGroup.groupName}(${it.getBooksCount()})") + toastOnUi("${selectedGroup.groupName}(${it.getBooksCount()})") } } @@ -224,7 +221,7 @@ class BookshelfFragment : VMBaseFragment(R.layout.fragment_b val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { editView.hint = "url/json" } - customView = alertBinding.root + customView { alertBinding.root } okButton { alertBinding.editView.text?.toString()?.let { viewModel.importBookshelf(it, selectedGroup.groupId) diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt index e2e1b50e3..0f937abbc 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt @@ -1,9 +1,9 @@ package io.legado.app.ui.main.bookshelf import android.app.Application -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookGroup import io.legado.app.data.entities.BookSource @@ -25,12 +25,12 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application) for (url in urls) { val bookUrl = url.trim() if (bookUrl.isEmpty()) continue - if (App.db.bookDao.getBook(bookUrl) != null) continue + if (appDb.bookDao.getBook(bookUrl) != null) continue val baseUrl = NetworkUtils.getBaseUrl(bookUrl) ?: continue - var source = App.db.bookSourceDao.getBookSource(baseUrl) + var source = appDb.bookSourceDao.getBookSource(baseUrl) if (source == null) { if (hasBookUrlPattern == null) { - hasBookUrlPattern = App.db.bookSourceDao.hasBookUrlPattern + hasBookUrlPattern = appDb.bookSourceDao.hasBookUrlPattern } hasBookUrlPattern.forEach { bookSource -> if (bookUrl.matches(bookSource.bookUrlPattern!!.toRegex())) { @@ -47,8 +47,8 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application) ) WebBook(bookSource).getBookInfo(this, book) .onSuccess(IO) { - it.order = App.db.bookDao.maxOrder + 1 - App.db.bookDao.insert(it) + it.order = appDb.bookDao.maxOrder + 1 + appDb.bookDao.insert(it) successCount++ }.onError { throw Exception(it.localizedMessage) @@ -57,12 +57,12 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application) } }.onSuccess { if (successCount > 0) { - toast(R.string.success) + toastOnUi(R.string.success) } else { - toast("ERROR") + toastOnUi("ERROR") } }.onError { - toast(it.localizedMessage ?: "ERROR") + toastOnUi(it.localizedMessage ?: "ERROR") } } @@ -98,30 +98,30 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application) } } }.onError { - toast(it.localizedMessage ?: "ERROR") + toastOnUi(it.localizedMessage ?: "ERROR") } } private fun importBookshelfByJson(json: String, groupId: Long) { execute { - val bookSources = App.db.bookSourceDao.allEnabled + val bookSources = appDb.bookSourceDao.allEnabled GSON.fromJsonArray>(json)?.forEach { if (!isActive) return@execute val name = it["name"] ?: "" val author = it["author"] ?: "" - if (name.isNotEmpty() && App.db.bookDao.getBook(name, author) == null) { + if (name.isNotEmpty() && appDb.bookDao.getBook(name, author) == null) { val book = PreciseSearch .searchFirstBook(this, bookSources, name, author) book?.let { if (groupId > 0) { book.group = groupId } - App.db.bookDao.insert(book) + appDb.bookDao.insert(book) } } } }.onFinally { - toast(R.string.success) + toastOnUi(R.string.success) } } @@ -129,13 +129,13 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application) groups.forEach { group -> if (group.groupId >= 0 && group.groupId and (group.groupId - 1) != 0L) { var id = 1L - val idsSum = App.db.bookGroupDao.idsSum + val idsSum = appDb.bookGroupDao.idsSum while (id and idsSum != 0L) { id = id.shl(1) } - App.db.bookGroupDao.delete(group) - App.db.bookGroupDao.insert(group.copy(groupId = id)) - App.db.bookDao.upGroup(group.groupId, id) + appDb.bookGroupDao.delete(group) + appDb.bookGroupDao.insert(group.copy(groupId = id)) + appDb.bookDao.upGroup(group.groupId, id) } } } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt index 27fe663d3..f8897ca9e 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterGrid.kt @@ -9,8 +9,7 @@ import io.legado.app.data.entities.Book import io.legado.app.databinding.ItemBookshelfGridBinding import io.legado.app.lib.theme.ATH import io.legado.app.utils.invisible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick +import splitties.views.onLongClick class BooksAdapterGrid(context: Context, private val callBack: CallBack) : BaseBooksAdapter(context) { @@ -55,7 +54,7 @@ class BooksAdapterGrid(context: Context, private val callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemBookshelfGridBinding) { holder.itemView.apply { - onClick { + setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.open(it) } @@ -65,7 +64,6 @@ class BooksAdapterGrid(context: Context, private val callBack: CallBack) : getItem(holder.layoutPosition)?.let { callBack.openBookInfo(it) } - true } } } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterList.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterList.kt index 5f3822e01..343ba19fd 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterList.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksAdapterList.kt @@ -9,8 +9,7 @@ import io.legado.app.data.entities.Book import io.legado.app.databinding.ItemBookshelfListBinding import io.legado.app.lib.theme.ATH import io.legado.app.utils.invisible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick +import splitties.views.onLongClick class BooksAdapterList(context: Context, private val callBack: CallBack) : BaseBooksAdapter(context) { @@ -61,7 +60,7 @@ class BooksAdapterList(context: Context, private val callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemBookshelfListBinding) { holder.itemView.apply { - onClick { + setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.open(it) } @@ -71,7 +70,6 @@ class BooksAdapterList(context: Context, private val callBack: CallBack) : getItem(holder.layoutPosition)?.let { callBack.openBookInfo(it) } - true } } } diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt index 6f0990a76..a37a27087 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/books/BooksFragment.kt @@ -3,17 +3,18 @@ package io.legado.app.ui.main.bookshelf.books import android.os.Bundle import android.view.View import androidx.core.view.isGone +import androidx.fragment.app.activityViewModels import androidx.lifecycle.LiveData import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseFragment import io.legado.app.constant.AppConst import io.legado.app.constant.BookType import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.databinding.FragmentBooksBinding import io.legado.app.help.AppConfig @@ -24,7 +25,10 @@ import io.legado.app.ui.audio.AudioPlayActivity import io.legado.app.ui.book.info.BookInfoActivity import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.main.MainViewModel -import io.legado.app.utils.* +import io.legado.app.utils.cnCompare +import io.legado.app.utils.getPrefInt +import io.legado.app.utils.observeEvent +import io.legado.app.utils.startActivity import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlin.math.max @@ -47,7 +51,7 @@ class BooksFragment : BaseFragment(R.layout.fragment_books), private val binding by viewBinding(FragmentBooksBinding::bind) private val activityViewModel: MainViewModel - get() = getViewModelOfActivity(MainViewModel::class.java) + by activityViewModels() private lateinit var booksAdapter: BaseBooksAdapter<*> private var bookshelfLiveData: LiveData>? = null private var position = 0 @@ -100,11 +104,11 @@ class BooksFragment : BaseFragment(R.layout.fragment_books), private fun upRecyclerData() { bookshelfLiveData?.removeObservers(this) bookshelfLiveData = when (groupId) { - AppConst.bookGroupAllId -> App.db.bookDao.observeAll() - AppConst.bookGroupLocalId -> App.db.bookDao.observeLocal() - AppConst.bookGroupAudioId -> App.db.bookDao.observeAudio() - AppConst.bookGroupNoneId -> App.db.bookDao.observeNoGroup() - else -> App.db.bookDao.observeByGroup(groupId) + AppConst.bookGroupAllId -> appDb.bookDao.observeAll() + AppConst.bookGroupLocalId -> appDb.bookDao.observeLocal() + AppConst.bookGroupAudioId -> appDb.bookDao.observeAudio() + AppConst.bookGroupNoneId -> appDb.bookDao.observeNoGroup() + else -> appDb.bookDao.observeByGroup(groupId) }.apply { observe(viewLifecycleOwner) { list -> binding.tvEmptyMsg.isGone = list.isNotEmpty() @@ -140,19 +144,21 @@ class BooksFragment : BaseFragment(R.layout.fragment_books), override fun open(book: Book) { when (book.type) { BookType.audio -> - startActivity(Pair("bookUrl", book.bookUrl)) - else -> startActivity( - Pair("bookUrl", book.bookUrl), - Pair("key", IntentDataHelp.putData(book)) - ) + startActivity { + putExtra("bookUrl", book.bookUrl) + } + else -> startActivity { + putExtra("bookUrl", book.bookUrl) + putExtra("key", IntentDataHelp.putData(book)) + } } } override fun openBookInfo(book: Book) { - startActivity( - Pair("name", book.name), - Pair("author", book.author) - ) + startActivity { + putExtra("name", book.name) + putExtra("author", book.author) + } } override fun isUpdate(bookUrl: String): Boolean { 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 b0aba869f..0944c2a03 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 @@ -5,10 +5,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.PopupMenu -import io.legado.app.App import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.databinding.ItemFilletTextBinding import io.legado.app.databinding.ItemFindBookBinding @@ -19,9 +19,7 @@ import io.legado.app.utils.dp import io.legado.app.utils.gone import io.legado.app.utils.visible import kotlinx.coroutines.CoroutineScope -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick - +import splitties.views.onLongClick class ExploreAdapter(context: Context, private val scope: CoroutineScope, val callBack: CallBack) : RecyclerAdapter(context) { @@ -69,7 +67,7 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca glChild.addView(tv.root) tv.textView.text = kind.title if (!kind.url.isNullOrEmpty()) { - tv.textView.onClick { + tv.textView.setOnClickListener { callBack.openExplore( item.bookSourceUrl, kind.title, @@ -96,7 +94,7 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca override fun registerListener(holder: ItemViewHolder, binding: ItemFindBookBinding) { binding.apply { - llTitle.onClick { + llTitle.setOnClickListener { val position = holder.layoutPosition val oldEx = exIndex exIndex = if (exIndex == position) -1 else position @@ -137,7 +135,7 @@ class ExploreAdapter(context: Context, private val scope: CoroutineScope, val ca notifyItemChanged(position) } R.id.menu_del -> Coroutine.async(scope) { - App.db.bookSourceDao.delete(source) + appDb.bookSourceDao.delete(source) } } true diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt index ff311f503..92e5404da 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreFragment.kt @@ -7,14 +7,15 @@ import android.view.SubMenu import android.view.View import androidx.appcompat.widget.SearchView import androidx.core.view.isGone +import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseFragment import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.databinding.FragmentExploreBinding import io.legado.app.help.AppConfig @@ -23,7 +24,6 @@ import io.legado.app.lib.theme.primaryTextColor import io.legado.app.ui.book.explore.ExploreShowActivity import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.utils.cnCompare -import io.legado.app.utils.getViewModel import io.legado.app.utils.splitNotBlank import io.legado.app.utils.startActivity import io.legado.app.utils.viewbindingdelegate.viewBinding @@ -33,8 +33,7 @@ import io.legado.app.utils.viewbindingdelegate.viewBinding */ class ExploreFragment : VMBaseFragment(R.layout.fragment_explore), ExploreAdapter.CallBack { - override val viewModel: ExploreViewModel - get() = getViewModel(ExploreViewModel::class.java) + override val viewModel: ExploreViewModel by viewModels() private val binding by viewBinding(FragmentExploreBinding::bind) private lateinit var adapter: ExploreAdapter private lateinit var linearLayoutManager: LinearLayoutManager @@ -97,7 +96,7 @@ class ExploreFragment : VMBaseFragment(R.layout.fragment_explo private fun initGroupData() { liveGroup?.removeObservers(viewLifecycleOwner) - liveGroup = App.db.bookSourceDao.liveExploreGroup() + liveGroup = appDb.bookSourceDao.liveExploreGroup() liveGroup?.observe(viewLifecycleOwner, { groups.clear() it.map { group -> @@ -111,14 +110,14 @@ class ExploreFragment : VMBaseFragment(R.layout.fragment_explo liveExplore?.removeObservers(viewLifecycleOwner) liveExplore = when { searchKey.isNullOrBlank() -> { - App.db.bookSourceDao.liveExplore() + appDb.bookSourceDao.liveExplore() } searchKey.startsWith("group:") -> { val key = searchKey.substringAfter("group:") - App.db.bookSourceDao.liveGroupExplore("%$key%") + appDb.bookSourceDao.liveGroupExplore("%$key%") } else -> { - App.db.bookSourceDao.liveExplore("%$searchKey%") + appDb.bookSourceDao.liveExplore("%$searchKey%") } } liveExplore?.observe(viewLifecycleOwner, { @@ -151,15 +150,17 @@ class ExploreFragment : VMBaseFragment(R.layout.fragment_explo } override fun openExplore(sourceUrl: String, title: String, exploreUrl: String) { - startActivity( - Pair("exploreName", title), - Pair("sourceUrl", sourceUrl), - Pair("exploreUrl", exploreUrl) - ) + startActivity { + putExtra("exploreName", title) + putExtra("sourceUrl", sourceUrl) + putExtra("exploreUrl", exploreUrl) + } } override fun editSource(sourceUrl: String) { - startActivity(Pair("data", sourceUrl)) + startActivity { + putExtra("data", sourceUrl) + } } override fun toTop(source: BookSource) { diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt index 8a9551a57..e6a2cc569 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt @@ -1,17 +1,17 @@ package io.legado.app.ui.main.explore import android.app.Application -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource class ExploreViewModel(application: Application) : BaseViewModel(application) { fun topSource(bookSource: BookSource) { execute { - val minXh = App.db.bookSourceDao.minOrder + val minXh = appDb.bookSourceDao.minOrder bookSource.customOrder = minXh - 1 - App.db.bookSourceDao.insert(bookSource) + appDb.bookSourceDao.insert(bookSource) } } diff --git a/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt b/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt index ce6065e27..4ce39781a 100644 --- a/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/my/MyFragment.kt @@ -7,7 +7,6 @@ import android.view.Menu import android.view.MenuItem import android.view.View import androidx.preference.Preference -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseFragment import io.legado.app.base.BasePreferenceFragment @@ -15,6 +14,7 @@ import io.legado.app.constant.EventBus import io.legado.app.constant.PreferKey import io.legado.app.databinding.FragmentMyConfigBinding import io.legado.app.help.AppConfig +import io.legado.app.help.ThemeConfig import io.legado.app.lib.theme.ATH import io.legado.app.service.WebService import io.legado.app.ui.about.AboutActivity @@ -90,7 +90,7 @@ class MyFragment : BaseFragment(R.layout.fragment_my_config), FilePickerDialog.C } findPreference(PreferKey.themeMode)?.let { it.setOnPreferenceChangeListener { _, _ -> - view?.post { App.INSTANCE.applyDayNight() } + view?.post { ThemeConfig.applyDayNight(requireContext()) } true } } @@ -135,15 +135,15 @@ class MyFragment : BaseFragment(R.layout.fragment_my_config), FilePickerDialog.C when (preference?.key) { "bookSourceManage" -> startActivity() "replaceManage" -> startActivity() - "setting" -> startActivity( - Pair("configType", ConfigViewModel.TYPE_CONFIG) - ) - "web_dav_setting" -> startActivity( - Pair("configType", ConfigViewModel.TYPE_WEB_DAV_CONFIG) - ) - "theme_setting" -> startActivity( - Pair("configType", ConfigViewModel.TYPE_THEME_CONFIG) - ) + "setting" -> startActivity { + putExtra("configType", ConfigViewModel.TYPE_CONFIG) + } + "web_dav_setting" -> startActivity { + putExtra("configType", ConfigViewModel.TYPE_WEB_DAV_CONFIG) + } + "theme_setting" -> startActivity { + putExtra("configType", ConfigViewModel.TYPE_THEME_CONFIG) + } "readRecord" -> startActivity() "donate" -> startActivity() "about" -> startActivity() diff --git a/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt b/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt index 40218e5d3..1af9bdb9b 100644 --- a/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/main/rss/RssAdapter.kt @@ -10,8 +10,7 @@ import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.data.entities.RssSource import io.legado.app.databinding.ItemRssBinding import io.legado.app.help.ImageLoader -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.sdk27.listeners.onLongClick +import splitties.views.onLongClick class RssAdapter(context: Context, val callBack: CallBack) : RecyclerAdapter(context) { @@ -38,7 +37,7 @@ class RssAdapter(context: Context, val callBack: CallBack) : override fun registerListener(holder: ItemViewHolder, binding: ItemRssBinding) { binding.apply { - root.onClick { + root.setOnClickListener { getItemByLayoutPosition(holder.layoutPosition)?.let { callBack.openRss(it) } @@ -47,7 +46,6 @@ class RssAdapter(context: Context, val callBack: CallBack) : getItemByLayoutPosition(holder.layoutPosition)?.let { showMenu(ivIcon, it) } - true } } } diff --git a/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt b/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt index daf1dde0d..039c54f75 100644 --- a/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt +++ b/app/src/main/java/io/legado/app/ui/main/rss/RssFragment.kt @@ -6,11 +6,12 @@ import android.view.MenuItem import android.view.SubMenu import android.view.View import androidx.appcompat.widget.SearchView +import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseFragment import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.data.entities.RssSource import io.legado.app.databinding.FragmentRssBinding import io.legado.app.databinding.ItemRssBinding @@ -24,11 +25,10 @@ import io.legado.app.ui.rss.source.manage.RssSourceActivity import io.legado.app.ui.rss.source.manage.RssSourceViewModel import io.legado.app.ui.rss.subscription.RuleSubActivity import io.legado.app.utils.cnCompare -import io.legado.app.utils.getViewModel import io.legado.app.utils.splitNotBlank import io.legado.app.utils.startActivity import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + /** * 订阅界面 @@ -39,7 +39,7 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), private lateinit var adapter: RssAdapter private lateinit var searchView: SearchView override val viewModel: RssSourceViewModel - get() = getViewModel(RssSourceViewModel::class.java) + by viewModels() private var liveRssData: LiveData>? = null private val groups = linkedSetOf() private var liveGroup: LiveData>? = null @@ -106,7 +106,7 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), ItemRssBinding.inflate(layoutInflater, it, false).apply { tvName.setText(R.string.rule_subscription) ivIcon.setImageResource(R.drawable.image_legado) - root.onClick { + root.setOnClickListener { startActivity() } } @@ -116,12 +116,12 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), private fun initData(searchKey: String? = null) { liveRssData?.removeObservers(this) liveRssData = when { - searchKey.isNullOrEmpty() -> App.db.rssSourceDao.liveEnabled() + searchKey.isNullOrEmpty() -> appDb.rssSourceDao.liveEnabled() searchKey.startsWith("group:") -> { val key = searchKey.substringAfter("group:") - App.db.rssSourceDao.liveEnabledByGroup("%$key%") + appDb.rssSourceDao.liveEnabledByGroup("%$key%") } - else -> App.db.rssSourceDao.liveEnabled("%$searchKey%") + else -> appDb.rssSourceDao.liveEnabled("%$searchKey%") }.apply { observe(viewLifecycleOwner, { adapter.setItems(it) @@ -131,7 +131,7 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), private fun initGroupData() { liveGroup?.removeObservers(viewLifecycleOwner) - liveGroup = App.db.rssSourceDao.liveGroup() + liveGroup = appDb.rssSourceDao.liveGroup() liveGroup?.observe(viewLifecycleOwner, { groups.clear() it.map { group -> @@ -143,12 +143,14 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), override fun openRss(rssSource: RssSource) { if (rssSource.singleUrl) { - startActivity( - Pair("title", rssSource.sourceName), - Pair("origin", rssSource.sourceUrl) - ) + startActivity { + putExtra("title", rssSource.sourceName) + putExtra("origin", rssSource.sourceUrl) + } } else { - startActivity(Pair("url", rssSource.sourceUrl)) + startActivity { + putExtra("url", rssSource.sourceUrl) + } } } @@ -157,7 +159,9 @@ class RssFragment : VMBaseFragment(R.layout.fragment_rss), } override fun edit(rssSource: RssSource) { - startActivity(Pair("data", rssSource.sourceUrl)) + startActivity { + putExtra("data", rssSource.sourceUrl) + } } override fun del(rssSource: RssSource) { diff --git a/app/src/main/java/io/legado/app/ui/qrcode/QrCodeActivity.kt b/app/src/main/java/io/legado/app/ui/qrcode/QrCodeActivity.kt index 2d0ed31e6..72a2f980b 100644 --- a/app/src/main/java/io/legado/app/ui/qrcode/QrCodeActivity.kt +++ b/app/src/main/java/io/legado/app/ui/qrcode/QrCodeActivity.kt @@ -6,36 +6,28 @@ import android.graphics.BitmapFactory import android.os.Bundle import android.view.Menu import android.view.MenuItem -import android.view.View -import cn.bingoogolapple.qrcode.core.QRCodeView +import com.google.zxing.Result +import com.king.zxing.CameraScan.OnScanResultCallback import io.legado.app.R import io.legado.app.base.BaseActivity import io.legado.app.databinding.ActivityQrcodeCaptureBinding -import io.legado.app.help.permission.Permissions -import io.legado.app.help.permission.PermissionsCompat +import io.legado.app.utils.QRCodeUtils import io.legado.app.utils.readBytes -import org.jetbrains.anko.toast -class QrCodeActivity : BaseActivity(), QRCodeView.Delegate { +class QrCodeActivity : BaseActivity(), OnScanResultCallback { private val requestQrImage = 202 - private var flashlightIsOpen: Boolean = false override fun getViewBinding(): ActivityQrcodeCaptureBinding { return ActivityQrcodeCaptureBinding.inflate(layoutInflater) } override fun onActivityCreated(savedInstanceState: Bundle?) { - binding.zXingView.setDelegate(this) - binding.fabFlashlight.setOnClickListener { - if (flashlightIsOpen) { - flashlightIsOpen = false - binding.zXingView.closeFlashlight() - } else { - flashlightIsOpen = true - binding.zXingView.openFlashlight() - } - } + val fTag = "qrCodeFragment" + val qrCodeFragment = QrCodeFragment() + supportFragmentManager.beginTransaction() + .replace(R.id.fl_content, qrCodeFragment, fTag) + .commit() } override fun onCompatCreateOptionsMenu(menu: Menu): Boolean { @@ -55,60 +47,21 @@ class QrCodeActivity : BaseActivity(), QRCodeView. return super.onCompatOptionsItemSelected(item) } - override fun onStart() { - super.onStart() - startCamera() - } - - private fun startCamera() { - PermissionsCompat.Builder(this) - .addPermissions(*Permissions.Group.CAMERA) - .rationale(R.string.qr_per) - .onGranted { - binding.zXingView.visibility = View.VISIBLE - //TODO 显示扫描框,并开始识别 - binding.zXingView.startSpotAndShowRect() - }.request() - } - - override fun onStop() { - //TODO 关闭摄像头预览,并且隐藏扫描框 - binding.zXingView.stopCamera() - super.onStop() - } - - override fun onDestroy() { - //TODO 销毁二维码扫描控件 - binding.zXingView.onDestroy() - super.onDestroy() - } - - override fun onScanQRCodeSuccess(result: String) { + override fun onScanResultCallback(result: Result?): Boolean { val intent = Intent() - intent.putExtra("result", result) + intent.putExtra("result", result?.text) setResult(RESULT_OK, intent) finish() - } - - override fun onCameraAmbientBrightnessChanged(isDark: Boolean) { - - } - - override fun onScanQRCodeOpenCameraError() { - toast("打开相机失败") + return true } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) data?.data?.let { - //TODO 显示扫描框,并开始识别 - binding.zXingView.startSpotAndShowRect() - if (resultCode == Activity.RESULT_OK && requestCode == requestQrImage) { - // 本来就用到 QRCodeView 时可直接调 QRCodeView 的方法,走通用的回调 it.readBytes(this)?.let { bytes -> val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size) - binding.zXingView.decodeQRCode(bitmap) + onScanResultCallback(QRCodeUtils.parseCodeResult(bitmap)) } } } diff --git a/app/src/main/java/io/legado/app/ui/qrcode/QrCodeFragment.kt b/app/src/main/java/io/legado/app/ui/qrcode/QrCodeFragment.kt new file mode 100644 index 000000000..d279ca9eb --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/qrcode/QrCodeFragment.kt @@ -0,0 +1,13 @@ +package io.legado.app.ui.qrcode + +import com.google.zxing.Result +import com.king.zxing.CaptureFragment + +class QrCodeFragment : CaptureFragment() { + + override fun onScanResultCallback(result: Result?): Boolean { + (activity as? QrCodeActivity)?.onScanResultCallback(result) + return true + } + +} \ No newline at end of file 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 a5e23d96f..5917453cf 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 @@ -9,12 +9,13 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.DialogFragment +import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogRecyclerViewBinding import io.legado.app.databinding.ItemGroupManageBinding @@ -24,10 +25,10 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { - private lateinit var viewModel: ReplaceRuleViewModel + private val viewModel: ReplaceRuleViewModel by activityViewModels() private lateinit var adapter: GroupAdapter private val binding by viewBinding(DialogRecyclerViewBinding::bind) @@ -42,7 +43,6 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { container: ViewGroup?, savedInstanceState: Bundle? ): View? { - viewModel = getViewModelOfActivity(ReplaceRuleViewModel::class.java) return inflater.inflate(R.layout.dialog_recycler_view, container) } @@ -62,7 +62,7 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { recyclerView.layoutManager = LinearLayoutManager(requireContext()) recyclerView.addItemDecoration(VerticalDivider(requireContext())) recyclerView.adapter = adapter - App.db.replaceRuleDao.liveGroup().observe(viewLifecycleOwner, { + appDb.replaceRuleDao.liveGroup().observe(viewLifecycleOwner, { val groups = linkedSetOf() it.map { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) @@ -101,11 +101,11 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { @SuppressLint("InflateParams") private fun editGroup(group: String) { alert(title = getString(R.string.group_edit)) { - val alertBinding = DialogEditTextBinding.inflate(layoutInflater) - customView = alertBinding.apply { + val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { editView.hint = "分组名称" editView.setText(group) - }.root + } + customView { alertBinding.root } yesButton { viewModel.upGroup(group, alertBinding.editView.text?.toString()) } @@ -134,13 +134,13 @@ class GroupManageDialog : DialogFragment(), Toolbar.OnMenuItemClickListener { override fun registerListener(holder: ItemViewHolder, binding: ItemGroupManageBinding) { binding.apply { - tvEdit.onClick { + tvEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { editGroup(it) } } - tvDel.onClick { + tvDel.setOnClickListener { getItem(holder.layoutPosition)?.let { viewModel.delGroup(it) } } } 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 af44e0c32..9b5926b5f 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 @@ -7,16 +7,17 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.SubMenu +import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.LiveData import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.data.entities.ReplaceRule import io.legado.app.databinding.ActivityReplaceRuleBinding import io.legado.app.databinding.DialogEditTextBinding @@ -29,14 +30,14 @@ import io.legado.app.service.help.ReadBook import io.legado.app.ui.association.ImportReplaceRuleActivity import io.legado.app.ui.filepicker.FilePicker import io.legado.app.ui.filepicker.FilePickerDialog +import io.legado.app.ui.qrcode.QrCodeActivity import io.legado.app.ui.replace.edit.ReplaceEditActivity import io.legado.app.ui.widget.SelectActionBar +import io.legado.app.ui.widget.dialog.TextDialog import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* -import org.jetbrains.anko.startActivity -import org.jetbrains.anko.toast import java.io.File /** @@ -48,11 +49,11 @@ class ReplaceRuleActivity : VMBaseActivity() @@ -145,14 +146,14 @@ class ReplaceRuleActivity : VMBaseActivity { - App.db.replaceRuleDao.liveDataAll() + appDb.replaceRuleDao.liveDataAll() } searchKey.startsWith("group:") -> { val key = searchKey.substringAfter("group:") - App.db.replaceRuleDao.liveDataGroupSearch("%$key%") + appDb.replaceRuleDao.liveDataGroupSearch("%$key%") } else -> { - App.db.replaceRuleDao.liveDataSearch("%$searchKey%") + appDb.replaceRuleDao.liveDataSearch("%$searchKey%") } }.apply { observe(this@ReplaceRuleActivity, { @@ -166,7 +167,7 @@ class ReplaceRuleActivity : VMBaseActivity groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) @@ -186,6 +187,8 @@ class ReplaceRuleActivity : VMBaseActivity showImportDialog() R.id.menu_import_source_local -> FilePicker .selectFile(this, importRequestCode, allowExtensions = arrayOf("txt", "json")) + R.id.menu_import_source_qr -> startActivityForResult(importRequestCodeQr) + R.id.menu_help -> showHelp() else -> if (item.groupId == R.id.replace_group) { searchView.setQuery("group:${item.title}", true) } @@ -224,7 +227,7 @@ class ReplaceRuleActivity : VMBaseActivity("source" to it) + startActivity { + putExtra("source", it) + } } } cancelButton() }.show() } + private fun showHelp() { + val text = String(assets.open("help/replaceRuleHelp.md").readBytes()) + TextDialog.show(supportFragmentManager, text, TextDialog.MD) + } + override fun onQueryTextChange(newText: String?): Boolean { observeReplaceRuleData(newText) return false @@ -256,10 +266,19 @@ class ReplaceRuleActivity : VMBaseActivity("dataKey" to dataKey) + startActivity { + putExtra("dataKey", dataKey) + } } }.onFailure { - toast("readTextError:${it.localizedMessage}") + toastOnUi("readTextError:${it.localizedMessage}") + } + } + } + importRequestCodeQr -> if (resultCode == Activity.RESULT_OK) { + data?.getStringExtra("result")?.let { + startActivity { + putExtra("source", it) } } } diff --git a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleAdapter.kt b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleAdapter.kt index c8356bea7..f4e68d9a2 100644 --- a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleAdapter.kt @@ -16,7 +16,7 @@ import io.legado.app.databinding.ItemReplaceRuleBinding import io.legado.app.lib.theme.backgroundColor import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback -import org.jetbrains.anko.sdk27.listeners.onClick + import java.util.* @@ -147,12 +147,12 @@ class ReplaceRuleAdapter(context: Context, var callBack: CallBack) : } } } - ivEdit.onClick { + ivEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.edit(it) } } - cbName.onClick { + cbName.setOnClickListener { getItem(holder.layoutPosition)?.let { if (cbName.isChecked) { selected.add(it) @@ -162,7 +162,7 @@ class ReplaceRuleAdapter(context: Context, var callBack: CallBack) : } callBack.upCountView() } - ivMenuMore.onClick { + ivMenuMore.setOnClickListener { showMenu(ivMenuMore, holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleViewModel.kt b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleViewModel.kt index 33e68f6c1..b0f18067d 100644 --- a/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/replace/ReplaceRuleViewModel.kt @@ -3,51 +3,47 @@ package io.legado.app.ui.replace import android.app.Application import android.text.TextUtils import androidx.documentfile.provider.DocumentFile -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.ReplaceRule -import io.legado.app.utils.FileUtils -import io.legado.app.utils.GSON -import io.legado.app.utils.splitNotBlank -import io.legado.app.utils.writeText -import org.jetbrains.anko.toast +import io.legado.app.utils.* import java.io.File class ReplaceRuleViewModel(application: Application) : BaseViewModel(application) { fun update(vararg rule: ReplaceRule) { execute { - App.db.replaceRuleDao.update(*rule) + appDb.replaceRuleDao.update(*rule) } } fun delete(rule: ReplaceRule) { execute { - App.db.replaceRuleDao.delete(rule) + appDb.replaceRuleDao.delete(rule) } } fun toTop(rule: ReplaceRule) { execute { - rule.order = App.db.replaceRuleDao.minOrder - 1 - App.db.replaceRuleDao.update(rule) + rule.order = appDb.replaceRuleDao.minOrder - 1 + appDb.replaceRuleDao.update(rule) } } fun toBottom(rule: ReplaceRule) { execute { - rule.order = App.db.replaceRuleDao.maxOrder + 1 - App.db.replaceRuleDao.update(rule) + rule.order = appDb.replaceRuleDao.maxOrder + 1 + appDb.replaceRuleDao.update(rule) } } fun upOrder() { execute { - val rules = App.db.replaceRuleDao.all + val rules = appDb.replaceRuleDao.all for ((index, rule) in rules.withIndex()) { rule.order = index + 1 } - App.db.replaceRuleDao.update(*rules.toTypedArray()) + appDb.replaceRuleDao.update(*rules.toTypedArray()) } } @@ -57,7 +53,7 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application rules.forEach { list.add(it.copy(isEnabled = true)) } - App.db.replaceRuleDao.update(*list.toTypedArray()) + appDb.replaceRuleDao.update(*list.toTypedArray()) } } @@ -67,13 +63,13 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application rules.forEach { list.add(it.copy(isEnabled = false)) } - App.db.replaceRuleDao.update(*list.toTypedArray()) + appDb.replaceRuleDao.update(*list.toTypedArray()) } } fun delSelection(rules: LinkedHashSet) { execute { - App.db.replaceRuleDao.delete(*rules.toTypedArray()) + appDb.replaceRuleDao.delete(*rules.toTypedArray()) } } @@ -83,9 +79,9 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application FileUtils.createFileIfNotExist(file, "exportReplaceRule.json") .writeText(json) }.onSuccess { - context.toast("成功导出至\n${file.absolutePath}") + context.toastOnUi("成功导出至\n${file.absolutePath}") }.onError { - context.toast("导出失败\n${it.localizedMessage}") + context.toastOnUi("导出失败\n${it.localizedMessage}") } } @@ -96,25 +92,25 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application doc.createFile("", "exportReplaceRule.json") ?.writeText(context, json) }.onSuccess { - context.toast("成功导出至\n${doc.uri.path}") + context.toastOnUi("成功导出至\n${doc.uri.path}") }.onError { - context.toast("导出失败\n${it.localizedMessage}") + context.toastOnUi("导出失败\n${it.localizedMessage}") } } fun addGroup(group: String) { execute { - val sources = App.db.replaceRuleDao.noGroup + val sources = appDb.replaceRuleDao.noGroup sources.map { source -> source.group = group } - App.db.replaceRuleDao.update(*sources.toTypedArray()) + appDb.replaceRuleDao.update(*sources.toTypedArray()) } } fun upGroup(oldGroup: String, newGroup: String?) { execute { - val sources = App.db.replaceRuleDao.getByGroup(oldGroup) + val sources = appDb.replaceRuleDao.getByGroup(oldGroup) sources.map { source -> source.group?.splitNotBlank(",")?.toHashSet()?.let { it.remove(oldGroup) @@ -123,21 +119,21 @@ class ReplaceRuleViewModel(application: Application) : BaseViewModel(application source.group = TextUtils.join(",", it) } } - App.db.replaceRuleDao.update(*sources.toTypedArray()) + appDb.replaceRuleDao.update(*sources.toTypedArray()) } } fun delGroup(group: String) { execute { execute { - val sources = App.db.replaceRuleDao.getByGroup(group) + val sources = appDb.replaceRuleDao.getByGroup(group) sources.map { source -> source.group?.splitNotBlank(",")?.toHashSet()?.let { it.remove(group) source.group = TextUtils.join(",", it) } } - App.db.replaceRuleDao.update(*sources.toTypedArray()) + appDb.replaceRuleDao.update(*sources.toTypedArray()) } } } diff --git a/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditActivity.kt b/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditActivity.kt index 9d56d65e4..e4349c296 100644 --- a/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditActivity.kt @@ -10,20 +10,20 @@ import android.view.MenuItem import android.view.ViewTreeObserver import android.widget.EditText import android.widget.PopupWindow +import androidx.activity.viewModels import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppConst import io.legado.app.constant.EventBus import io.legado.app.data.entities.ReplaceRule import io.legado.app.databinding.ActivityReplaceEditBinding +import io.legado.app.lib.dialogs.selector import io.legado.app.ui.widget.KeyboardToolPop import io.legado.app.ui.widget.dialog.TextDialog -import io.legado.app.utils.getViewModel +import io.legado.app.utils.getSize + import io.legado.app.utils.postEvent -import org.jetbrains.anko.displayMetrics -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.selector -import org.jetbrains.anko.toast +import io.legado.app.utils.toastOnUi import kotlin.math.abs /** @@ -57,7 +57,7 @@ class ReplaceEditActivity : } override val viewModel: ReplaceEditViewModel - get() = getViewModel(ReplaceEditViewModel::class.java) + by viewModels() private var mSoftKeyboardTool: PopupWindow? = null private var mIsSoftKeyBoardShowing = false @@ -68,7 +68,7 @@ class ReplaceEditActivity : viewModel.initData(intent) { upReplaceView(it) } - binding.ivHelp.onClick { + binding.ivHelp.setOnClickListener { showRegexHelp() } } @@ -83,7 +83,7 @@ class ReplaceEditActivity : R.id.menu_save -> { val rule = getReplaceRule() if (!rule.isValid()) { - toast(R.string.replace_rule_invalid) + toastOnUi(R.string.replace_rule_invalid) } else { viewModel.save(rule) { postEvent(EventBus.REPLACE_RULE_SAVE, "") @@ -171,7 +171,7 @@ class ReplaceEditActivity : val rect = Rect() // 获取当前页面窗口的显示范围 window.decorView.getWindowVisibleDisplayFrame(rect) - val screenHeight = this.displayMetrics.heightPixels + val screenHeight = this.getSize().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/replace/edit/ReplaceEditViewModel.kt b/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditViewModel.kt index 551c73aeb..fd37bb36d 100644 --- a/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/replace/edit/ReplaceEditViewModel.kt @@ -2,8 +2,8 @@ package io.legado.app.ui.replace.edit import android.app.Application import android.content.Intent -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.ReplaceRule class ReplaceEditViewModel(application: Application) : BaseViewModel(application) { @@ -14,7 +14,7 @@ class ReplaceEditViewModel(application: Application) : BaseViewModel(application execute { val id = intent.getLongExtra("id", -1) if (id > 0) { - replaceRule = App.db.replaceRuleDao.findById(id) + replaceRule = appDb.replaceRuleDao.findById(id) } else { val pattern = intent.getStringExtra("pattern") ?: "" val isRegex = intent.getBooleanExtra("isRegex", false) @@ -36,9 +36,9 @@ class ReplaceEditViewModel(application: Application) : BaseViewModel(application fun save(replaceRule: ReplaceRule, success: () -> Unit) { execute { if (replaceRule.order == 0) { - replaceRule.order = App.db.replaceRuleDao.maxOrder + 1 + replaceRule.order = appDb.replaceRuleDao.maxOrder + 1 } - App.db.replaceRuleDao.insert(replaceRule) + appDb.replaceRuleDao.insert(replaceRule) }.onSuccess { success() } diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt index b321a9e74..cabd5b51a 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter.kt @@ -12,10 +12,10 @@ import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.data.entities.RssArticle import io.legado.app.databinding.ItemRssArticleBinding import io.legado.app.help.ImageLoader +import io.legado.app.utils.getCompatColor import io.legado.app.utils.gone import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.textColorResource + class RssArticlesAdapter(context: Context, callBack: CallBack) : BaseRssArticlesAdapter(context, callBack) { @@ -67,15 +67,15 @@ class RssArticlesAdapter(context: Context, callBack: CallBack) : }.into(imageView) } if (item.read) { - tvTitle.textColorResource = R.color.tv_text_summary + tvTitle.setTextColor(context.getCompatColor(R.color.tv_text_summary)) } else { - tvTitle.textColorResource = R.color.primaryText + tvTitle.setTextColor(context.getCompatColor(R.color.primaryText)) } } } override fun registerListener(holder: ItemViewHolder, binding: ItemRssArticleBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.readRss(it) } diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter1.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter1.kt index 4b77fa6e7..2c8ff0d8f 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter1.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter1.kt @@ -12,10 +12,10 @@ import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.data.entities.RssArticle import io.legado.app.databinding.ItemRssArticle1Binding import io.legado.app.help.ImageLoader +import io.legado.app.utils.getCompatColor import io.legado.app.utils.gone import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.textColorResource + class RssArticlesAdapter1(context: Context, callBack: CallBack) : BaseRssArticlesAdapter(context, callBack) { @@ -67,15 +67,15 @@ class RssArticlesAdapter1(context: Context, callBack: CallBack) : }.into(imageView) } if (item.read) { - tvTitle.textColorResource = R.color.tv_text_summary + tvTitle.setTextColor(context.getCompatColor(R.color.tv_text_summary)) } else { - tvTitle.textColorResource = R.color.primaryText + tvTitle.setTextColor(context.getCompatColor(R.color.primaryText)) } } } override fun registerListener(holder: ItemViewHolder, binding: ItemRssArticle1Binding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.readRss(it) } diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter2.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter2.kt index 44c0df7ed..a82300afe 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter2.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesAdapter2.kt @@ -12,10 +12,10 @@ import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.data.entities.RssArticle import io.legado.app.databinding.ItemRssArticle2Binding import io.legado.app.help.ImageLoader +import io.legado.app.utils.getCompatColor import io.legado.app.utils.gone import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.textColorResource + class RssArticlesAdapter2(context: Context, callBack: CallBack) : BaseRssArticlesAdapter(context, callBack) { @@ -67,15 +67,15 @@ class RssArticlesAdapter2(context: Context, callBack: CallBack) : }.into(imageView) } if (item.read) { - tvTitle.textColorResource = R.color.tv_text_summary + tvTitle.setTextColor(context.getCompatColor(R.color.tv_text_summary)) } else { - tvTitle.textColorResource = R.color.primaryText + tvTitle.setTextColor(context.getCompatColor(R.color.primaryText)) } } } override fun registerListener(holder: ItemViewHolder, binding: ItemRssArticle2Binding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.readRss(it) } diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt index 5bda67e44..221b296ae 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesFragment.kt @@ -1,14 +1,17 @@ package io.legado.app.ui.rss.article + import android.os.Bundle import android.view.View +import androidx.fragment.app.activityViewModels +import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseFragment +import io.legado.app.data.appDb import io.legado.app.data.entities.RssArticle import io.legado.app.databinding.FragmentRssArticlesBinding import io.legado.app.databinding.ViewLoadMoreBinding @@ -16,8 +19,6 @@ import io.legado.app.lib.theme.ATH import io.legado.app.ui.rss.read.ReadRssActivity import io.legado.app.ui.widget.recycler.LoadMoreView import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.getViewModel -import io.legado.app.utils.getViewModelOfActivity import io.legado.app.utils.startActivity import io.legado.app.utils.viewbindingdelegate.viewBinding @@ -37,9 +38,9 @@ class RssArticlesFragment : VMBaseFragment(R.layout.fragme private val binding by viewBinding(FragmentRssArticlesBinding::bind) private val activityViewModel: RssSortViewModel - get() = getViewModelOfActivity(RssSortViewModel::class.java) + by activityViewModels() override val viewModel: RssArticlesViewModel - get() = getViewModel(RssArticlesViewModel::class.java) + by viewModels() lateinit var adapter: BaseRssArticlesAdapter<*> private lateinit var loadMoreView: LoadMoreView private var rssArticlesData: LiveData>? = null @@ -93,7 +94,7 @@ class RssArticlesFragment : VMBaseFragment(R.layout.fragme private fun initData() { activityViewModel.url?.let { rssArticlesData?.removeObservers(this) - rssArticlesData = App.db.rssArticleDao.liveByOriginSort(it, viewModel.sortName) + rssArticlesData = appDb.rssArticleDao.liveByOriginSort(it, viewModel.sortName) rssArticlesData?.observe(viewLifecycleOwner, { list -> adapter.setItems(list) }) @@ -123,10 +124,10 @@ class RssArticlesFragment : VMBaseFragment(R.layout.fragme override fun readRss(rssArticle: RssArticle) { activityViewModel.read(rssArticle) - startActivity( - Pair("title", rssArticle.title), - Pair("origin", rssArticle.origin), - Pair("link", rssArticle.link) - ) + startActivity { + putExtra("title", rssArticle.title) + putExtra("origin", rssArticle.origin) + putExtra("link", rssArticle.link) + } } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt index 1196e2ebd..1f81c4ba2 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt @@ -3,8 +3,8 @@ package io.legado.app.ui.rss.article import android.app.Application import android.os.Bundle import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.RssArticle import io.legado.app.data.entities.RssSource import io.legado.app.model.rss.Rss @@ -37,9 +37,9 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application list.forEach { rssArticle -> rssArticle.order = order-- } - App.db.rssArticleDao.insert(*list.toTypedArray()) + appDb.rssArticleDao.insert(*list.toTypedArray()) if (!rssSource.ruleNextPage.isNullOrEmpty()) { - App.db.rssArticleDao.clearOld(rssSource.sourceUrl, sortName, order) + appDb.rssArticleDao.clearOld(rssSource.sourceUrl, sortName, order) loadFinally.postValue(true) } else { withContext(Dispatchers.Main) { @@ -51,7 +51,7 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application }.onError { loadFinally.postValue(false) it.printStackTrace() - toast(it.localizedMessage) + toastOnUi(it.localizedMessage) } } @@ -81,7 +81,7 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application return@let } val firstArticle = list.first() - val dbArticle = App.db.rssArticleDao + val dbArticle = appDb.rssArticleDao .get(firstArticle.origin, firstArticle.link) if (dbArticle != null) { loadFinally.postValue(false) @@ -89,7 +89,7 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application list.forEach { rssArticle -> rssArticle.order = order-- } - App.db.rssArticleDao.insert(*list.toTypedArray()) + appDb.rssArticleDao.insert(*list.toTypedArray()) } } isLoading = false diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssSortActivity.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssSortActivity.kt index 705276072..46d3480d7 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssSortActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssSortActivity.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.activity.viewModels import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentStatePagerAdapter @@ -12,15 +13,14 @@ import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.databinding.ActivityRssArtivlesBinding import io.legado.app.ui.rss.source.edit.RssSourceEditActivity -import io.legado.app.utils.getViewModel import io.legado.app.utils.gone +import io.legado.app.utils.startActivityForResult import io.legado.app.utils.visible -import org.jetbrains.anko.startActivityForResult class RssSortActivity : VMBaseActivity() { override val viewModel: RssSortViewModel - get() = getViewModel(RssSortViewModel::class.java) + by viewModels() private val editSource = 12319 private val fragments = linkedMapOf() private lateinit var adapter: TabFragmentPageAdapter @@ -49,7 +49,9 @@ class RssSortActivity : VMBaseActivity viewModel.rssSource?.sourceUrl?.let { - startActivityForResult(editSource, Pair("data", it)) + startActivityForResult(editSource) { + putExtra("data", it) + } } R.id.menu_clear -> { viewModel.url?.let { diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssSortViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssSortViewModel.kt index a22c3456c..9a3b4be72 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssSortViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssSortViewModel.kt @@ -3,8 +3,8 @@ package io.legado.app.ui.rss.article import android.app.Application import android.content.Intent import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.RssArticle import io.legado.app.data.entities.RssReadRecord import io.legado.app.data.entities.RssSource @@ -21,7 +21,7 @@ class RssSortViewModel(application: Application) : BaseViewModel(application) { execute { url = intent.getStringExtra("url") url?.let { url -> - rssSource = App.db.rssSourceDao.getByKey(url) + rssSource = appDb.rssSourceDao.getByKey(url) rssSource?.let { titleLiveData.postValue(it.sourceName) } ?: let { @@ -41,21 +41,21 @@ class RssSortViewModel(application: Application) : BaseViewModel(application) { it.articleStyle = 0 } execute { - App.db.rssSourceDao.update(it) + appDb.rssSourceDao.update(it) } } } fun read(rssArticle: RssArticle) { execute { - App.db.rssArticleDao.insertRecord(RssReadRecord(rssArticle.link)) + appDb.rssArticleDao.insertRecord(RssReadRecord(rssArticle.link)) } } fun clearArticles() { execute { url?.let { - App.db.rssArticleDao.delete(it) + appDb.rssArticleDao.delete(it) } order = System.currentTimeMillis() }.onSuccess { diff --git a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt index 99d9f47a1..403a06d2e 100644 --- a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesActivity.kt @@ -3,13 +3,13 @@ package io.legado.app.ui.rss.favorites import android.os.Bundle import androidx.lifecycle.LiveData import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.base.BaseActivity +import io.legado.app.data.appDb import io.legado.app.data.entities.RssStar import io.legado.app.databinding.ActivityRssFavoritesBinding import io.legado.app.ui.rss.read.ReadRssActivity import io.legado.app.ui.widget.recycler.VerticalDivider -import org.jetbrains.anko.startActivity +import io.legado.app.utils.startActivity class RssFavoritesActivity : BaseActivity(), @@ -38,17 +38,17 @@ class RssFavoritesActivity : BaseActivity(), private fun initData() { liveData?.removeObservers(this) - liveData = App.db.rssStarDao.liveAll() + liveData = appDb.rssStarDao.liveAll() liveData?.observe(this, { adapter.setItems(it) }) } override fun readRss(rssStar: RssStar) { - startActivity( - Pair("title", rssStar.title), - Pair("origin", rssStar.origin), - Pair("link", rssStar.link) - ) + startActivity { + putExtra("title", rssStar.title) + putExtra("origin", rssStar.origin) + putExtra("link", rssStar.link) + } } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesAdapter.kt b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesAdapter.kt index 775388364..517c4bb27 100644 --- a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesAdapter.kt @@ -14,7 +14,7 @@ import io.legado.app.databinding.ItemRssArticleBinding import io.legado.app.help.ImageLoader import io.legado.app.utils.gone import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick + class RssFavoritesAdapter(context: Context, val callBack: CallBack) : RecyclerAdapter(context) { @@ -65,7 +65,7 @@ class RssFavoritesAdapter(context: Context, val callBack: CallBack) : } override fun registerListener(holder: ItemViewHolder, binding: ItemRssArticleBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.readRss(it) } 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 eb211f0eb..eff2dda40 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 @@ -10,10 +10,13 @@ import android.os.Bundle import android.os.Environment import android.view.* import android.webkit.* +import androidx.activity.viewModels import androidx.core.view.size import io.legado.app.R import io.legado.app.base.VMBaseActivity +import io.legado.app.constant.AppConst import io.legado.app.databinding.ActivityRssReadBinding +import io.legado.app.help.AppConfig import io.legado.app.lib.theme.DrawableUtils import io.legado.app.lib.theme.primaryTextColor import io.legado.app.service.help.Download @@ -25,9 +28,8 @@ import io.legado.app.ui.filepicker.FilePickerDialog import io.legado.app.utils.* import kotlinx.coroutines.launch import org.apache.commons.text.StringEscapeUtils -import org.jetbrains.anko.downloadManager -import org.jetbrains.anko.share import org.jsoup.Jsoup +import splitties.systemservices.downloadManager class ReadRssActivity : VMBaseActivity(false), @@ -35,7 +37,7 @@ class ReadRssActivity : VMBaseActivity ReadRssViewModel.CallBack { override val viewModel: ReadRssViewModel - get() = getViewModel(ReadRssViewModel::class.java) + by viewModels() private val savePathRequestCode = 132 private val imagePathKey = "" private var starMenuItem: MenuItem? = null @@ -94,79 +96,17 @@ class ReadRssActivity : VMBaseActivity return super.onCompatOptionsItemSelected(item) } + @SuppressLint("SetJavaScriptEnabled") private fun initWebView() { - binding.webView.webChromeClient = object : WebChromeClient() { - override fun onShowCustomView(view: View?, callback: CustomViewCallback?) { - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR - binding.llView.invisible() - binding.customWebView.addView(view) - customWebViewCallback = callback - } - - override fun onHideCustomView() { - binding.customWebView.removeAllViews() - binding.llView.visible() - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - } - } - binding.webView.webViewClient = object : WebViewClient() { - override fun shouldOverrideUrlLoading( - view: WebView?, - request: WebResourceRequest? - ): Boolean { - request?.let { - if (it.url.scheme == "http" || it.url.scheme == "https") { - return false - } else if (it.url.scheme == "yuedu") { - when (it.url.host) { - "booksource" -> { - val intent = Intent( - this@ReadRssActivity, - ImportBookSourceActivity::class.java - ) - intent.data = it.url - startActivity(intent) - } - "rsssource" -> { - val intent = Intent( - this@ReadRssActivity, - ImportRssSourceActivity::class.java - ) - intent.data = it.url - startActivity(intent) - } - "replace" -> { - val intent = Intent( - this@ReadRssActivity, - ImportReplaceRuleActivity::class.java - ) - intent.data = it.url - startActivity(intent) - } - } - return true - } - openUrl(it.url) - } - return true - } - - @Suppress("DEPRECATION") - override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { - if (url?.startsWith("http", true) == true) { - return false - } - url?.let { - openUrl(it) - } - return true - } - } + binding.webView.webChromeClient = RssWebChromeClient() + binding.webView.webViewClient = RssWebViewClient() binding.webView.settings.apply { mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW domStorageEnabled = true allowContentAccess = true + //javaScriptEnabled = true } + upWebViewTheme() binding.webView.setOnLongClickListener { val hitTestResult = binding.webView.hitTestResult if (hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE || @@ -207,6 +147,7 @@ class ReadRssActivity : VMBaseActivity Download.start(this, downloadId, fileName) } } + } private fun saveImage() { @@ -254,6 +195,13 @@ class ReadRssActivity : VMBaseActivity } } + private fun upWebViewTheme() { + if (AppConfig.isNightTheme) { + binding.webView + .evaluateJavascript(AppConst.darkWebViewJs, null) + } + } + override fun upStarMenu() { if (viewModel.rssStar != null) { starMenuItem?.setIcon(R.drawable.ic_star) @@ -336,4 +284,78 @@ class ReadRssActivity : VMBaseActivity binding.webView.destroy() } + inner class RssWebChromeClient : WebChromeClient() { + override fun onShowCustomView(view: View?, callback: CustomViewCallback?) { + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR + binding.llView.invisible() + binding.customWebView.addView(view) + customWebViewCallback = callback + } + + override fun onHideCustomView() { + binding.customWebView.removeAllViews() + binding.llView.visible() + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED + } + } + + inner class RssWebViewClient : WebViewClient() { + override fun shouldOverrideUrlLoading( + view: WebView?, + request: WebResourceRequest? + ): Boolean { + request?.let { + if (it.url.scheme == "http" || it.url.scheme == "https") { + return false + } else if (it.url.scheme == "yuedu") { + when (it.url.host) { + "booksource" -> { + val intent = Intent( + this@ReadRssActivity, + ImportBookSourceActivity::class.java + ) + intent.data = it.url + startActivity(intent) + } + "rsssource" -> { + val intent = Intent( + this@ReadRssActivity, + ImportRssSourceActivity::class.java + ) + intent.data = it.url + startActivity(intent) + } + "replace" -> { + val intent = Intent( + this@ReadRssActivity, + ImportReplaceRuleActivity::class.java + ) + intent.data = it.url + startActivity(intent) + } + } + return true + } + openUrl(it.url) + } + return true + } + + @Suppress("DEPRECATION") + override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { + if (url?.startsWith("http", true) == true) { + return false + } + url?.let { + openUrl(it) + } + return true + } + + override fun onPageFinished(view: WebView?, url: String?) { + super.onPageFinished(view, url) + upWebViewTheme() + } + } + } diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt index 452f8c87f..f4cc85fff 100644 --- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt @@ -9,10 +9,10 @@ import android.util.Base64 import android.webkit.URLUtil import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.MutableLiveData -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppConst +import io.legado.app.data.appDb import io.legado.app.data.entities.RssArticle import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssStar @@ -47,10 +47,10 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), val origin = intent.getStringExtra("origin") val link = intent.getStringExtra("link") origin?.let { - rssSource = App.db.rssSourceDao.getByKey(origin) + rssSource = appDb.rssSourceDao.getByKey(origin) if (link != null) { - rssStar = App.db.rssStarDao.get(origin, link) - rssArticle = rssStar?.toRssArticle() ?: App.db.rssArticleDao.get(origin, link) + rssStar = appDb.rssStarDao.get(origin, link) + rssArticle = rssStar?.toRssArticle() ?: appDb.rssArticleDao.get(origin, link) rssArticle?.let { rssArticle -> if (!rssArticle.description.isNullOrBlank()) { contentLiveData.postValue(rssArticle.description) @@ -97,10 +97,10 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), Rss.getContent(this, rssArticle, ruleContent, rssSource) .onSuccess(IO) { body -> rssArticle.description = body - App.db.rssArticleDao.insert(rssArticle) + appDb.rssArticleDao.insert(rssArticle) rssStar?.let { it.description = body - App.db.rssStarDao.insert(it) + appDb.rssStarDao.insert(it) } contentLiveData.postValue(body) } @@ -109,10 +109,10 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), fun favorite() { execute { rssStar?.let { - App.db.rssStarDao.delete(it.origin, it.link) + appDb.rssStarDao.delete(it.origin, it.link) rssStar = null } ?: rssArticle?.toStar()?.let { - App.db.rssStarDao.insert(it) + appDb.rssStarDao.insert(it) rssStar = it } }.onSuccess { @@ -137,9 +137,9 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), } } ?: throw Throwable("NULL") }.onError { - toast("保存图片失败:${it.localizedMessage}") + toastOnUi("保存图片失败:${it.localizedMessage}") }.onSuccess { - toast("保存成功") + toastOnUi("保存成功") } } @@ -186,7 +186,7 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), play() } else { launch { - toast(R.string.tts_init_failed) + toastOnUi(R.string.tts_init_failed) } } } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugActivity.kt b/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugActivity.kt index a57afe2a3..e5cb45db4 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugActivity.kt @@ -2,21 +2,22 @@ package io.legado.app.ui.rss.source.debug import android.os.Bundle import android.widget.SearchView +import androidx.activity.viewModels import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.databinding.ActivitySourceDebugBinding import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.accentColor -import io.legado.app.utils.getViewModel + import io.legado.app.utils.gone +import io.legado.app.utils.toastOnUi import kotlinx.coroutines.launch -import org.jetbrains.anko.toast class RssSourceDebugActivity : VMBaseActivity() { override val viewModel: RssSourceDebugModel - get() = getViewModel(RssSourceDebugModel::class.java) + by viewModels() private lateinit var adapter: RssSourceDebugAdapter @@ -56,7 +57,7 @@ class RssSourceDebugActivity : VMBaseActivity Unit) { sourceUrl?.let { execute { - rssSource = App.db.rssSourceDao.getByKey(sourceUrl) + rssSource = appDb.rssSourceDao.getByKey(sourceUrl) }.onFinally { finally() } 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 2f11ad365..39a288da2 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 @@ -10,6 +10,7 @@ import android.view.MenuItem import android.view.ViewTreeObserver import android.widget.EditText import android.widget.PopupWindow +import androidx.activity.viewModels import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppConst @@ -17,16 +18,13 @@ import io.legado.app.data.entities.RssSource import io.legado.app.databinding.ActivityRssSourceEditBinding import io.legado.app.help.LocalConfig import io.legado.app.lib.dialogs.alert +import io.legado.app.lib.dialogs.selector import io.legado.app.lib.theme.ATH import io.legado.app.ui.qrcode.QrCodeActivity import io.legado.app.ui.rss.source.debug.RssSourceDebugActivity import io.legado.app.ui.widget.KeyboardToolPop import io.legado.app.ui.widget.dialog.TextDialog -import io.legado.app.utils.GSON -import io.legado.app.utils.getViewModel -import io.legado.app.utils.sendToClip -import io.legado.app.utils.shareWithQr -import org.jetbrains.anko.* +import io.legado.app.utils.* import kotlin.math.abs class RssSourceEditActivity : @@ -45,7 +43,7 @@ class RssSourceEditActivity : } override val viewModel: RssSourceEditViewModel - get() = getViewModel(RssSourceEditViewModel::class.java) + by viewModels() override fun onActivityCreated(savedInstanceState: Bundle?) { initView() @@ -65,7 +63,7 @@ class RssSourceEditActivity : val source = getRssSource() if (!source.equal(viewModel.rssSource)) { alert(R.string.exit) { - messageResource = R.string.exit_no_save + setMessage(R.string.exit_no_save) positiveButton(R.string.yes) negativeButton(R.string.no) { super.finish() @@ -102,7 +100,9 @@ class RssSourceEditActivity : val source = getRssSource() if (checkSource(source)) { viewModel.save(source) { - startActivity(Pair("key", source.sourceUrl)) + startActivity { + putExtra("key", source.sourceUrl) + } } } } @@ -184,7 +184,7 @@ class RssSourceEditActivity : private fun checkSource(source: RssSource): Boolean { if (source.sourceName.isBlank() || source.sourceName.isBlank()) { - toast("名称或url不能为空") + toastOnUi("名称或url不能为空") return false } return true @@ -251,7 +251,7 @@ class RssSourceEditActivity : val rect = Rect() // 获取当前页面窗口的显示范围 window.decorView.getWindowVisibleDisplayFrame(rect) - val screenHeight = this@RssSourceEditActivity.displayMetrics.heightPixels + val screenHeight = this@RssSourceEditActivity.getSize().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/edit/RssSourceEditViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt index 63b48d08a..38ace84df 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditViewModel.kt @@ -2,8 +2,8 @@ package io.legado.app.ui.rss.source.edit import android.app.Application import android.content.Intent -import io.legado.app.App import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.RssSource import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonObject @@ -20,7 +20,7 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati execute { val key = intent.getStringExtra("data") if (key != null) { - App.db.rssSourceDao.getByKey(key)?.let { + appDb.rssSourceDao.getByKey(key)?.let { rssSource = it } } @@ -33,14 +33,14 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati fun save(source: RssSource, success: (() -> Unit)) { execute { if (oldSourceUrl != source.sourceUrl) { - App.db.rssSourceDao.delete(oldSourceUrl) + appDb.rssSourceDao.delete(oldSourceUrl) oldSourceUrl = source.sourceUrl } - App.db.rssSourceDao.insert(source) + appDb.rssSourceDao.insert(source) }.onSuccess { success() }.onError { - toast(it.localizedMessage) + toastOnUi(it.localizedMessage) it.printStackTrace() } } @@ -53,12 +53,12 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati } source }.onError { - toast(it.localizedMessage) + toastOnUi(it.localizedMessage) }.onSuccess { if (it != null) { onSuccess(it) } else { - toast("格式不对") + toastOnUi("格式不对") } } } @@ -70,7 +70,7 @@ class RssSourceEditViewModel(application: Application) : BaseViewModel(applicati finally.invoke(it) } }.onError { - toast(it.msg) + toastOnUi(it.msg) } } 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 b5444cebe..534667b88 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 @@ -8,13 +8,14 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.databinding.DialogEditTextBinding import io.legado.app.databinding.DialogRecyclerViewBinding import io.legado.app.databinding.ItemGroupManageBinding @@ -24,10 +25,10 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener { - private lateinit var viewModel: RssSourceViewModel + private val viewModel: RssSourceViewModel by activityViewModels() private lateinit var adapter: GroupAdapter private val binding by viewBinding(DialogRecyclerViewBinding::bind) @@ -42,7 +43,6 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener container: ViewGroup?, savedInstanceState: Bundle? ): View? { - viewModel = getViewModelOfActivity(RssSourceViewModel::class.java) return inflater.inflate(R.layout.dialog_recycler_view, container) } @@ -58,8 +58,8 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener recyclerView.adapter = adapter tvOk.setTextColor(requireContext().accentColor) tvOk.visible() - tvOk.onClick { dismiss() } - App.db.rssSourceDao.liveGroup().observe(viewLifecycleOwner, { + tvOk.setOnClickListener { dismiss() } + appDb.rssSourceDao.liveGroup().observe(viewLifecycleOwner, { val groups = linkedSetOf() it.map { group -> groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) @@ -132,13 +132,13 @@ class GroupManageDialog : BaseDialogFragment(), Toolbar.OnMenuItemClickListener override fun registerListener(holder: ItemViewHolder, binding: ItemGroupManageBinding) { binding.apply { - tvEdit.onClick { + tvEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { editGroup(it) } } - tvDel.onClick { + tvDel.setOnClickListener { getItem(holder.layoutPosition)?.let { viewModel.delGroup(it) } 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 1e6156391..3a763c87b 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 @@ -7,15 +7,16 @@ import android.os.Bundle import android.view.Menu import android.view.MenuItem import android.view.SubMenu +import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView import androidx.documentfile.provider.DocumentFile import androidx.lifecycle.LiveData import androidx.recyclerview.widget.ItemTouchHelper -import io.legado.app.App import io.legado.app.R import io.legado.app.base.VMBaseActivity import io.legado.app.constant.AppPattern +import io.legado.app.data.appDb import io.legado.app.data.entities.RssSource import io.legado.app.databinding.ActivityRssSourceBinding import io.legado.app.databinding.DialogEditTextBinding @@ -34,9 +35,6 @@ import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback import io.legado.app.ui.widget.recycler.VerticalDivider import io.legado.app.utils.* -import org.jetbrains.anko.startActivity -import org.jetbrains.anko.startActivityForResult -import org.jetbrains.anko.toast import java.io.File @@ -47,7 +45,7 @@ class RssSourceActivity : VMBaseActivity groups.addAll(group.splitNotBlank(AppPattern.splitGroupRegex)) @@ -202,14 +200,14 @@ class RssSourceActivity : VMBaseActivity { - App.db.rssSourceDao.liveAll() + appDb.rssSourceDao.liveAll() } searchKey.startsWith("group:") -> { val key = searchKey.substringAfter("group:") - App.db.rssSourceDao.liveGroupSearch("%$key%") + appDb.rssSourceDao.liveGroupSearch("%$key%") } else -> { - App.db.rssSourceDao.liveSearch("%$searchKey%") + appDb.rssSourceDao.liveSearch("%$searchKey%") } }.apply { observe(this@RssSourceActivity, { @@ -245,7 +243,7 @@ class RssSourceActivity : VMBaseActivity("source" to it) + startActivity { + putExtra("source", it) + } } } cancelButton() @@ -268,16 +268,20 @@ class RssSourceActivity : VMBaseActivity("dataKey" to dataKey) + startActivity { + putExtra("dataKey", dataKey) + } } }.onFailure { - toast("readTextError:${it.localizedMessage}") + toastOnUi("readTextError:${it.localizedMessage}") } } } qrRequestCode -> if (resultCode == RESULT_OK) { data?.getStringExtra("result")?.let { - startActivity("source" to it) + startActivity { + putExtra("source", it) + } } } exportRequestCode -> if (resultCode == RESULT_OK) { @@ -301,7 +305,9 @@ class RssSourceActivity : VMBaseActivity(Pair("data", source.sourceUrl)) + startActivity { + putExtra("data", source.sourceUrl) + } } override fun update(vararg source: RssSource) { diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceAdapter.kt index fae25cdb5..a0b8bdccf 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceAdapter.kt @@ -16,7 +16,7 @@ import io.legado.app.databinding.ItemRssSourceBinding import io.legado.app.lib.theme.backgroundColor import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.ItemTouchCallback -import org.jetbrains.anko.sdk27.listeners.onClick + class RssSourceAdapter(context: Context, val callBack: CallBack) : RecyclerAdapter(context), @@ -113,12 +113,12 @@ class RssSourceAdapter(context: Context, val callBack: CallBack) : } } } - ivEdit.onClick { + ivEdit.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.edit(it) } } - ivMenuMore.onClick { + ivMenuMore.setOnClickListener { showMenu(ivMenuMore, holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceViewModel.kt index 7ff23307c..a89dc2e7f 100644 --- a/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/rss/source/manage/RssSourceViewModel.kt @@ -5,52 +5,51 @@ import android.content.Intent import android.text.TextUtils import androidx.core.content.FileProvider import androidx.documentfile.provider.DocumentFile -import io.legado.app.App import io.legado.app.BuildConfig import io.legado.app.base.BaseViewModel +import io.legado.app.data.appDb import io.legado.app.data.entities.RssSource import io.legado.app.help.DefaultData import io.legado.app.utils.* -import org.jetbrains.anko.toast import java.io.File class RssSourceViewModel(application: Application) : BaseViewModel(application) { fun topSource(vararg sources: RssSource) { execute { - val minOrder = App.db.rssSourceDao.minOrder - 1 + val minOrder = appDb.rssSourceDao.minOrder - 1 sources.forEachIndexed { index, rssSource -> rssSource.customOrder = minOrder - index } - App.db.rssSourceDao.update(*sources) + appDb.rssSourceDao.update(*sources) } } fun bottomSource(vararg sources: RssSource) { execute { - val maxOrder = App.db.rssSourceDao.maxOrder + 1 + val maxOrder = appDb.rssSourceDao.maxOrder + 1 sources.forEachIndexed { index, rssSource -> rssSource.customOrder = maxOrder + index } - App.db.rssSourceDao.update(*sources) + appDb.rssSourceDao.update(*sources) } } fun del(rssSource: RssSource) { - execute { App.db.rssSourceDao.delete(rssSource) } + execute { appDb.rssSourceDao.delete(rssSource) } } fun update(vararg rssSource: RssSource) { - execute { App.db.rssSourceDao.update(*rssSource) } + execute { appDb.rssSourceDao.update(*rssSource) } } fun upOrder() { execute { - val sources = App.db.rssSourceDao.all + val sources = appDb.rssSourceDao.all for ((index: Int, source: RssSource) in sources.withIndex()) { source.customOrder = index + 1 } - App.db.rssSourceDao.update(*sources.toTypedArray()) + appDb.rssSourceDao.update(*sources.toTypedArray()) } } @@ -60,7 +59,7 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application) sources.forEach { list.add(it.copy(enabled = true)) } - App.db.rssSourceDao.update(*list.toTypedArray()) + appDb.rssSourceDao.update(*list.toTypedArray()) } } @@ -70,13 +69,13 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application) sources.forEach { list.add(it.copy(enabled = false)) } - App.db.rssSourceDao.update(*list.toTypedArray()) + appDb.rssSourceDao.update(*list.toTypedArray()) } } fun delSelection(sources: List) { execute { - App.db.rssSourceDao.delete(*sources.toTypedArray()) + appDb.rssSourceDao.delete(*sources.toTypedArray()) } } @@ -86,9 +85,9 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application) FileUtils.createFileIfNotExist(file, "exportRssSource.json") .writeText(json) }.onSuccess { - context.toast("成功导出至\n${file.absolutePath}") + context.toastOnUi("成功导出至\n${file.absolutePath}") }.onError { - context.toast("导出失败\n${it.localizedMessage}") + context.toastOnUi("导出失败\n${it.localizedMessage}") } } @@ -99,9 +98,9 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application) doc.createFile("", "exportRssSource.json") ?.writeText(context, json) }.onSuccess { - context.toast("成功导出至\n${doc.uri.path}") + context.toastOnUi("成功导出至\n${doc.uri.path}") }.onError { - context.toast("导出失败\n${it.localizedMessage}") + context.toastOnUi("导出失败\n${it.localizedMessage}") } } @@ -123,23 +122,23 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application) }.onSuccess { success.invoke(it) }.onError { - toast(it.msg) + toastOnUi(it.msg) } } fun addGroup(group: String) { execute { - val sources = App.db.rssSourceDao.noGroup + val sources = appDb.rssSourceDao.noGroup sources.map { source -> source.sourceGroup = group } - App.db.rssSourceDao.update(*sources.toTypedArray()) + appDb.rssSourceDao.update(*sources.toTypedArray()) } } fun upGroup(oldGroup: String, newGroup: String?) { execute { - val sources = App.db.rssSourceDao.getByGroup(oldGroup) + val sources = appDb.rssSourceDao.getByGroup(oldGroup) sources.map { source -> source.sourceGroup?.splitNotBlank(",")?.toHashSet()?.let { it.remove(oldGroup) @@ -148,21 +147,21 @@ class RssSourceViewModel(application: Application) : BaseViewModel(application) source.sourceGroup = TextUtils.join(",", it) } } - App.db.rssSourceDao.update(*sources.toTypedArray()) + appDb.rssSourceDao.update(*sources.toTypedArray()) } } fun delGroup(group: String) { execute { execute { - val sources = App.db.rssSourceDao.getByGroup(group) + val sources = appDb.rssSourceDao.getByGroup(group) sources.map { source -> source.sourceGroup?.splitNotBlank(",")?.toHashSet()?.let { it.remove(group) source.sourceGroup = TextUtils.join(",", it) } } - App.db.rssSourceDao.update(*sources.toTypedArray()) + appDb.rssSourceDao.update(*sources.toTypedArray()) } } } diff --git a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt index 67d9cabc2..78aa3d7da 100644 --- a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt +++ b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubActivity.kt @@ -6,9 +6,9 @@ import android.view.MenuItem import androidx.core.view.isGone import androidx.lifecycle.LiveData import androidx.recyclerview.widget.ItemTouchHelper -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseActivity +import io.legado.app.data.appDb import io.legado.app.data.entities.RuleSub import io.legado.app.databinding.ActivityRuleSubBinding import io.legado.app.databinding.DialogRuleSubEditBinding @@ -17,9 +17,9 @@ import io.legado.app.ui.association.ImportBookSourceActivity import io.legado.app.ui.association.ImportReplaceRuleActivity import io.legado.app.ui.association.ImportRssSourceActivity import io.legado.app.ui.widget.recycler.ItemTouchCallback +import io.legado.app.utils.startActivity import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.launch -import org.jetbrains.anko.startActivity /** * 规则订阅界面 @@ -47,7 +47,7 @@ class RuleSubActivity : BaseActivity(), override fun onCompatOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.menu_add -> { - val order = App.db.ruleSubDao.maxOrder + 1 + val order = appDb.ruleSubDao.maxOrder + 1 editSubscription(RuleSub(customOrder = order)) } } @@ -64,7 +64,7 @@ class RuleSubActivity : BaseActivity(), private fun initData() { liveData?.removeObservers(this) - liveData = App.db.ruleSubDao.observeAll() + liveData = appDb.ruleSubDao.observeAll() liveData?.observe(this) { binding.tvEmptyMsg.isGone = it.isNotEmpty() adapter.setItems(it) @@ -74,13 +74,19 @@ class RuleSubActivity : BaseActivity(), override fun openSubscription(ruleSub: RuleSub) { when (ruleSub.type) { 0 -> { - startActivity("source" to ruleSub.url) + startActivity { + putExtra("source", ruleSub.url) + } } 1 -> { - startActivity("source" to ruleSub.url) + startActivity { + putExtra("source", ruleSub.url) + } } 2 -> { - startActivity("source" to ruleSub.url) + startActivity { + putExtra("source", ruleSub.url) + } } } } @@ -92,13 +98,13 @@ class RuleSubActivity : BaseActivity(), etName.setText(ruleSub.name) etUrl.setText(ruleSub.url) } - customView = alertBinding.root + customView { alertBinding.root } okButton { ruleSub.type = alertBinding.spType.selectedItemPosition ruleSub.name = alertBinding.etName.text?.toString() ?: "" ruleSub.url = alertBinding.etUrl.text?.toString() ?: "" launch(IO) { - App.db.ruleSubDao.insert(ruleSub) + appDb.ruleSubDao.insert(ruleSub) } } cancelButton() @@ -107,23 +113,23 @@ class RuleSubActivity : BaseActivity(), override fun delSubscription(ruleSub: RuleSub) { launch(IO) { - App.db.ruleSubDao.delete(ruleSub) + appDb.ruleSubDao.delete(ruleSub) } } override fun updateSourceSub(vararg ruleSub: RuleSub) { launch(IO) { - App.db.ruleSubDao.update(*ruleSub) + appDb.ruleSubDao.update(*ruleSub) } } override fun upOrder() { launch(IO) { - val sourceSubs = App.db.ruleSubDao.all + val sourceSubs = appDb.ruleSubDao.all for ((index: Int, ruleSub: RuleSub) in sourceSubs.withIndex()) { ruleSub.customOrder = index + 1 } - App.db.ruleSubDao.update(*sourceSubs.toTypedArray()) + appDb.ruleSubDao.update(*sourceSubs.toTypedArray()) } } diff --git a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubAdapter.kt b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubAdapter.kt index d8c3c044d..2bb5560be 100644 --- a/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/rss/subscription/RuleSubAdapter.kt @@ -11,7 +11,7 @@ import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.data.entities.RuleSub import io.legado.app.databinding.ItemRuleSubBinding import io.legado.app.ui.widget.recycler.ItemTouchCallback -import org.jetbrains.anko.sdk27.listeners.onClick + class RuleSubAdapter(context: Context, val callBack: Callback) : RecyclerAdapter(context), @@ -31,13 +31,13 @@ class RuleSubAdapter(context: Context, val callBack: Callback) : } override fun registerListener(holder: ItemViewHolder, binding: ItemRuleSubBinding) { - binding.root.onClick { + binding.root.setOnClickListener { callBack.openSubscription(getItem(holder.layoutPosition)!!) } - binding.ivEdit.onClick { + binding.ivEdit.setOnClickListener { callBack.editSubscription(getItem(holder.layoutPosition)!!) } - binding.ivMenuMore.onClick { + binding.ivMenuMore.setOnClickListener { showMenu(binding.ivMenuMore, holder.layoutPosition) } } diff --git a/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt b/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt index 49fd459fd..4337e9476 100644 --- a/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt +++ b/app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt @@ -3,10 +3,10 @@ package io.legado.app.ui.welcome import android.content.Intent import android.os.Bundle import com.hankcs.hanlp.HanLP -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseActivity import io.legado.app.constant.PreferKey +import io.legado.app.data.appDb import io.legado.app.databinding.ActivityWelcomeBinding import io.legado.app.help.AppConfig import io.legado.app.help.coroutine.Coroutine @@ -14,7 +14,7 @@ import io.legado.app.lib.theme.accentColor import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.main.MainActivity import io.legado.app.utils.getPrefBoolean -import org.jetbrains.anko.startActivity +import io.legado.app.utils.startActivity import java.util.concurrent.TimeUnit open class WelcomeActivity : BaseActivity() { @@ -36,10 +36,10 @@ open class WelcomeActivity : BaseActivity() { private fun init() { Coroutine.async { - App.db.cacheDao.clearDeadline(System.currentTimeMillis()) + appDb.cacheDao.clearDeadline(System.currentTimeMillis()) //清除过期数据 if (getPrefBoolean(PreferKey.autoClearExpired, true)) { - App.db.searchBookDao + appDb.searchBookDao .clearExpired(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1)) } //初始化简繁转换引擎 diff --git a/app/src/main/java/io/legado/app/ui/widget/DetailSeekBar.kt b/app/src/main/java/io/legado/app/ui/widget/DetailSeekBar.kt index b0a8115da..441a1853b 100644 --- a/app/src/main/java/io/legado/app/ui/widget/DetailSeekBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/DetailSeekBar.kt @@ -12,7 +12,7 @@ import io.legado.app.lib.theme.getPrimaryTextColor import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.utils.ColorUtils import io.legado.app.utils.progressAdd -import org.jetbrains.anko.sdk27.listeners.onClick + class DetailSeekBar @JvmOverloads constructor( context: Context, @@ -51,11 +51,11 @@ class DetailSeekBar @JvmOverloads constructor( binding.ivSeekReduce.setColorFilter(textColor) binding.tvSeekValue.setTextColor(textColor) } - binding.ivSeekPlus.onClick { + binding.ivSeekPlus.setOnClickListener { binding.seekBar.progressAdd(1) onChanged?.invoke(binding.seekBar.progress) } - binding.ivSeekReduce.onClick { + binding.ivSeekReduce.setOnClickListener { binding.seekBar.progressAdd(-1) onChanged?.invoke(binding.seekBar.progress) } diff --git a/app/src/main/java/io/legado/app/ui/widget/KeyboardToolPop.kt b/app/src/main/java/io/legado/app/ui/widget/KeyboardToolPop.kt index dbbc10af4..e0fef5da0 100644 --- a/app/src/main/java/io/legado/app/ui/widget/KeyboardToolPop.kt +++ b/app/src/main/java/io/legado/app/ui/widget/KeyboardToolPop.kt @@ -10,7 +10,7 @@ import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.databinding.ItemFilletTextBinding import io.legado.app.databinding.PopupKeyboardToolBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class KeyboardToolPop( @@ -59,7 +59,7 @@ class KeyboardToolPop( override fun registerListener(holder: ItemViewHolder, binding: ItemFilletTextBinding) { holder.itemView.apply { - onClick { + setOnClickListener { getItem(holder.layoutPosition)?.let { callBack?.sendText(it) } diff --git a/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt b/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt index 316f4102c..c95a8e493 100644 --- a/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/SelectActionBar.kt @@ -14,7 +14,7 @@ import io.legado.app.help.AppConfig import io.legado.app.lib.theme.* import io.legado.app.utils.ColorUtils import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick + @Suppress("unused") class SelectActionBar @JvmOverloads constructor( @@ -41,9 +41,9 @@ class SelectActionBar @JvmOverloads constructor( callBack?.selectAll(isChecked) } } - binding.btnRevertSelection.onClick { callBack?.revertSelection() } - binding.btnSelectActionMain.onClick { callBack?.onClickMainAction() } - binding.ivMenuMore.onClick { selMenu?.show() } + binding.btnRevertSelection.setOnClickListener { callBack?.revertSelection() } + binding.btnSelectActionMain.setOnClickListener { callBack?.onClickMainAction() } + binding.ivMenuMore.setOnClickListener { selMenu?.show() } } fun setMainActionText(text: String) = with(binding) { diff --git a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt index 51a04f97d..593ee4c4c 100644 --- a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt @@ -17,9 +17,6 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.utils.activity import io.legado.app.utils.navigationBarHeight import io.legado.app.utils.statusBarHeight -import org.jetbrains.anko.backgroundColor -import org.jetbrains.anko.bottomPadding -import org.jetbrains.anko.topPadding @Suppress("unused") class TitleBar @JvmOverloads constructor( @@ -144,14 +141,14 @@ class TitleBar @JvmOverloads constructor( if (!isInEditMode) { if (a.getBoolean(R.styleable.TitleBar_fitStatusBar, true)) { - topPadding = context.statusBarHeight + setPadding(paddingLeft, context.statusBarHeight, paddingRight, paddingBottom) } if (a.getBoolean(R.styleable.TitleBar_fitNavigationBar, false)) { - bottomPadding = context.navigationBarHeight + setPadding(paddingLeft, paddingTop, paddingRight, context.navigationBarHeight) } - backgroundColor = context.primaryColor + setBackgroundColor(context.primaryColor) stateListAnimator = null elevation = if (AppConfig.elevation < 0) { @@ -198,11 +195,12 @@ class TitleBar @JvmOverloads constructor( fun transparent() { elevation = 0f - backgroundColor = Color.TRANSPARENT + setBackgroundColor(Color.TRANSPARENT) } fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, fullScreen: Boolean) { - topPadding = if (!isInMultiWindowMode && fullScreen) context.statusBarHeight else 0 + val topPadding = if (!isInMultiWindowMode && fullScreen) context.statusBarHeight else 0 + setPadding(paddingLeft, topPadding, paddingRight, paddingBottom) } private fun attachToActivity() { diff --git a/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt b/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt index 9f8bb77ca..5e9e5b4a9 100644 --- a/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/widget/font/FontAdapter.kt @@ -7,13 +7,9 @@ import android.view.ViewGroup import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.databinding.ItemFontBinding -import io.legado.app.utils.DocItem -import io.legado.app.utils.RealPathUtil -import io.legado.app.utils.invisible -import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick -import org.jetbrains.anko.toast +import io.legado.app.utils.* import java.io.File +import java.net.URLDecoder class FontAdapter(context: Context, val callBack: CallBack) : RecyclerAdapter(context) { @@ -46,11 +42,13 @@ class FontAdapter(context: Context, val callBack: CallBack) : tvFont.typeface = typeface }.onFailure { it.printStackTrace() - context.toast("Read ${item.name} Error: ${it.localizedMessage}") + context.toastOnUi("Read ${item.name} Error: ${it.localizedMessage}") } tvFont.text = item.name - root.onClick { callBack.onClick(item) } - if (item.name == callBack.curFilePath.substringAfterLast(File.separator)) { + root.setOnClickListener { callBack.onClick(item) } + if (item.name == URLDecoder.decode(callBack.curFilePath, "utf-8") + .substringAfterLast(File.separator) + ) { ivChecked.visible() } else { ivChecked.invisible() @@ -59,7 +57,7 @@ class FontAdapter(context: Context, val callBack: CallBack) : } override fun registerListener(holder: ItemViewHolder, binding: ItemFontBinding) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { callBack.onClick(it) } diff --git a/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt b/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt index 5ddecbe54..e1bb1f664 100644 --- a/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt +++ b/app/src/main/java/io/legado/app/ui/widget/font/FontSelectDialog.kt @@ -11,7 +11,6 @@ import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.documentfile.provider.DocumentFile import androidx.recyclerview.widget.LinearLayoutManager -import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseDialogFragment import io.legado.app.constant.PreferKey @@ -27,6 +26,7 @@ import io.legado.app.utils.* import io.legado.app.utils.viewbindingdelegate.viewBinding import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch +import splitties.init.appCtx import java.io.File import java.util.* import kotlin.collections.ArrayList @@ -38,7 +38,7 @@ class FontSelectDialog : BaseDialogFragment(), private val fontFolderRequestCode = 35485 private val fontRegex = Regex(".*\\.[ot]tf") private val fontFolder by lazy { - FileUtils.createFolderIfNotExist(App.INSTANCE.filesDir, "Fonts") + FileUtils.createFolderIfNotExist(appCtx.filesDir, "Fonts") } private var adapter: FontAdapter? = null private val binding by viewBinding(DialogFontSelectBinding::bind) @@ -147,7 +147,7 @@ class FontSelectDialog : BaseDialogFragment(), private fun loadFontFiles(doc: DocumentFile) { execute { val fontItems = arrayListOf() - val docItems = DocumentUtils.listFiles(App.INSTANCE, doc.uri) + val docItems = DocumentUtils.listFiles(appCtx, doc.uri) docItems.forEach { item -> if (item.name.toLowerCase(Locale.getDefault()).matches(fontRegex)) { fontItems.add(item) @@ -157,7 +157,7 @@ class FontSelectDialog : BaseDialogFragment(), }.onSuccess { adapter?.setItems(it) }.onError { - toast("getFontFiles:${it.localizedMessage}") + toastOnUi("getFontFiles:${it.localizedMessage}") } } @@ -192,7 +192,7 @@ class FontSelectDialog : BaseDialogFragment(), }.onSuccess { adapter?.setItems(it) }.onError { - toast("getFontFiles:${it.localizedMessage}") + toastOnUi("getFontFiles:${it.localizedMessage}") } } diff --git a/app/src/main/java/io/legado/app/ui/widget/image/CoverImageView.kt b/app/src/main/java/io/legado/app/ui/widget/image/CoverImageView.kt index d09eae0dd..24bdd08fd 100644 --- a/app/src/main/java/io/legado/app/ui/widget/image/CoverImageView.kt +++ b/app/src/main/java/io/legado/app/ui/widget/image/CoverImageView.kt @@ -10,11 +10,11 @@ import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target -import io.legado.app.App import io.legado.app.R import io.legado.app.constant.PreferKey import io.legado.app.help.ImageLoader import io.legado.app.utils.getPrefString +import splitties.init.appCtx /** * 封面 @@ -172,11 +172,11 @@ class CoverImageView @JvmOverloads constructor( @SuppressLint("UseCompatLoadingForDrawables") fun upDefaultCover() { - val path = App.INSTANCE.getPrefString(PreferKey.defaultCover) + val path = appCtx.getPrefString(PreferKey.defaultCover) var dw = Drawable.createFromPath(path) if (dw == null) { showBookName = true - dw = App.INSTANCE.resources.getDrawable(R.drawable.image_cover_default, null) + dw = appCtx.resources.getDrawable(R.drawable.image_cover_default, null) } else { showBookName = false } diff --git a/app/src/main/java/io/legado/app/ui/widget/image/PhotoView.kt b/app/src/main/java/io/legado/app/ui/widget/image/PhotoView.kt index 5d80f087e..b028dd116 100644 --- a/app/src/main/java/io/legado/app/ui/widget/image/PhotoView.kt +++ b/app/src/main/java/io/legado/app/ui/widget/image/PhotoView.kt @@ -881,7 +881,7 @@ class PhotoView @JvmOverloads constructor( ) } - fun getImageViewInfo(imgView: ImageView): Info? { + fun getImageViewInfo(imgView: ImageView): Info { val p = IntArray(2) getLocation(imgView, p) val drawable: Drawable = imgView.drawable diff --git a/app/src/main/java/io/legado/app/ui/widget/prefs/IconListPreference.kt b/app/src/main/java/io/legado/app/ui/widget/prefs/IconListPreference.kt index 673ba1aca..cc65046e7 100644 --- a/app/src/main/java/io/legado/app/ui/widget/prefs/IconListPreference.kt +++ b/app/src/main/java/io/legado/app/ui/widget/prefs/IconListPreference.kt @@ -23,7 +23,7 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.utils.getCompatDrawable import io.legado.app.utils.getSize import io.legado.app.utils.viewbindingdelegate.viewBinding -import org.jetbrains.anko.sdk27.listeners.onClick + class IconListPreference(context: Context, attrs: AttributeSet) : ListPreference(context, attrs) { @@ -186,7 +186,7 @@ class IconListPreference(context: Context, attrs: AttributeSet) : ListPreference } } label.isChecked = item.toString() == dialogValue - root.onClick { + root.setOnClickListener { onChanged?.invoke(item.toString()) this@IconDialog.dismiss() } @@ -197,7 +197,7 @@ class IconListPreference(context: Context, attrs: AttributeSet) : ListPreference holder: ItemViewHolder, binding: ItemIconPreferenceBinding ) { - holder.itemView.onClick { + holder.itemView.setOnClickListener { getItem(holder.layoutPosition)?.let { onChanged?.invoke(it.toString()) } diff --git a/app/src/main/java/io/legado/app/ui/widget/prefs/Preference.kt b/app/src/main/java/io/legado/app/ui/widget/prefs/Preference.kt index 042b03868..baea502b3 100644 --- a/app/src/main/java/io/legado/app/ui/widget/prefs/Preference.kt +++ b/app/src/main/java/io/legado/app/ui/widget/prefs/Preference.kt @@ -17,8 +17,7 @@ import io.legado.app.lib.theme.bottomBackground import io.legado.app.lib.theme.getPrimaryTextColor import io.legado.app.lib.theme.getSecondaryTextColor import io.legado.app.utils.ColorUtils -import org.jetbrains.anko.layoutInflater -import org.jetbrains.anko.sdk27.listeners.onLongClick +import splitties.views.onLongClick import kotlin.math.roundToInt class Preference(context: Context, attrs: AttributeSet) : @@ -77,7 +76,7 @@ class Preference(context: Context, attrs: AttributeSet) : var needRequestLayout = false var v = it.itemView.findViewById(viewId) if (v == null) { - val inflater: LayoutInflater = context.layoutInflater + val inflater: LayoutInflater = LayoutInflater.from(context) val childView = inflater.inflate(weightLayoutRes, null) lay.removeAllViews() lay.addView(childView) @@ -119,7 +118,6 @@ class Preference(context: Context, attrs: AttributeSet) : super.onBindViewHolder(holder) holder?.itemView?.onLongClick { onLongClick?.invoke() - true } } diff --git a/app/src/main/java/io/legado/app/ui/widget/text/AccentTextView.kt b/app/src/main/java/io/legado/app/ui/widget/text/AccentTextView.kt index be3074766..8dee26350 100644 --- a/app/src/main/java/io/legado/app/ui/widget/text/AccentTextView.kt +++ b/app/src/main/java/io/legado/app/ui/widget/text/AccentTextView.kt @@ -5,17 +5,16 @@ import android.util.AttributeSet import androidx.appcompat.widget.AppCompatTextView import io.legado.app.R import io.legado.app.lib.theme.accentColor -import org.jetbrains.anko.textColor -import org.jetbrains.anko.textColorResource +import io.legado.app.utils.getCompatColor class AccentTextView(context: Context, attrs: AttributeSet?) : AppCompatTextView(context, attrs) { init { if (!isInEditMode) { - textColor = context.accentColor + setTextColor(context.accentColor) } else { - textColorResource = R.color.accent + setTextColor(context.getCompatColor(R.color.accent)) } } diff --git a/app/src/main/java/io/legado/app/ui/widget/text/AutoCompleteTextView.kt b/app/src/main/java/io/legado/app/ui/widget/text/AutoCompleteTextView.kt index 9e9153e71..fbf4ac26c 100644 --- a/app/src/main/java/io/legado/app/ui/widget/text/AutoCompleteTextView.kt +++ b/app/src/main/java/io/legado/app/ui/widget/text/AutoCompleteTextView.kt @@ -15,7 +15,7 @@ import io.legado.app.R import io.legado.app.lib.theme.ATH import io.legado.app.utils.gone import io.legado.app.utils.visible -import org.jetbrains.anko.sdk27.listeners.onClick + @Suppress("unused") class AutoCompleteTextView @JvmOverloads constructor( @@ -61,7 +61,7 @@ class AutoCompleteTextView @JvmOverloads constructor( textView.text = getItem(position) val ivDelete = view.findViewById(R.id.iv_delete) if (delCallBack != null) ivDelete.visible() else ivDelete.gone() - ivDelete.onClick { + ivDelete.setOnClickListener { getItem(position)?.let { remove(it) delCallBack?.invoke(it) diff --git a/app/src/main/java/io/legado/app/utils/ACache.kt b/app/src/main/java/io/legado/app/utils/ACache.kt index 6a0a0b9fb..5011a713d 100644 --- a/app/src/main/java/io/legado/app/utils/ACache.kt +++ b/app/src/main/java/io/legado/app/utils/ACache.kt @@ -9,9 +9,9 @@ import android.graphics.PixelFormat import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.util.Log -import io.legado.app.App import org.json.JSONArray import org.json.JSONObject +import splitties.init.appCtx import java.io.* import java.util.* import java.util.concurrent.atomic.AtomicInteger @@ -619,7 +619,7 @@ class ACache private constructor(cacheDir: File, max_size: Long, max_count: Int) fun bitmap2Drawable(bm: Bitmap?): Drawable? { return if (bm == null) { null - } else BitmapDrawable(App.INSTANCE.resources, bm) + } else BitmapDrawable(appCtx.resources, bm) } } diff --git a/app/src/main/java/io/legado/app/utils/ActivityExtensions.kt b/app/src/main/java/io/legado/app/utils/ActivityExtensions.kt index df4bae769..37a46f74c 100644 --- a/app/src/main/java/io/legado/app/utils/ActivityExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/ActivityExtensions.kt @@ -1,12 +1,20 @@ package io.legado.app.utils import android.app.Activity +import android.content.Intent import android.os.Build import android.util.DisplayMetrics import android.view.WindowInsets import android.view.WindowMetrics +inline fun Activity.startActivityForResult( + requestCode: Int, + configIntent: Intent.() -> Unit = {} +) { + startActivityForResult(Intent(this, A::class.java).apply(configIntent), requestCode) +} + fun Activity.getSize(): DisplayMetrics { val displayMetrics = DisplayMetrics() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { 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 6be7ea2c3..ddd29063e 100644 --- a/app/src/main/java/io/legado/app/utils/BitmapUtils.kt +++ b/app/src/main/java/io/legado/app/utils/BitmapUtils.kt @@ -1,17 +1,14 @@ package io.legado.app.utils import android.content.Context -import android.graphics.Bitmap +import android.graphics.* import android.graphics.Bitmap.Config -import android.graphics.BitmapFactory -import android.graphics.Canvas -import android.graphics.Color import android.renderscript.Allocation import android.renderscript.Element import android.renderscript.RenderScript import android.renderscript.ScriptIntrinsicBlur import android.view.View -import io.legado.app.App +import splitties.init.appCtx import java.io.IOException import kotlin.math.* @@ -221,12 +218,36 @@ object BitmapUtils { } } + fun changeBitmapSize(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap { + + val width = bitmap.width + val height = bitmap.height + + //计算压缩的比率 + var scaleWidth = newWidth.toFloat() / width + var scaleHeight = newHeight.toFloat() / height + + if (scaleWidth > scaleHeight) { + scaleWidth = scaleHeight + } else { + scaleHeight = scaleWidth + } + + //获取想要缩放的matrix + val matrix = Matrix() + matrix.postScale(scaleWidth, scaleHeight) + + //获取新的bitmap + return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true) + + } + /** * 高斯模糊 */ fun stackBlur(srcBitmap: Bitmap?): Bitmap? { if (srcBitmap == null) return null - val rs = RenderScript.create(App.INSTANCE) + val rs = RenderScript.create(appCtx) val blurredBitmap = srcBitmap.copy(Config.ARGB_8888, true) //分配用于渲染脚本的内存 diff --git a/app/src/main/java/io/legado/app/utils/ContextExtensions.kt b/app/src/main/java/io/legado/app/utils/ContextExtensions.kt index d0f693069..490ac0f36 100644 --- a/app/src/main/java/io/legado/app/utils/ContextExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/ContextExtensions.kt @@ -3,6 +3,8 @@ package io.legado.app.utils import android.annotation.SuppressLint +import android.app.Activity +import android.app.Service import android.content.* import android.content.pm.PackageManager import android.content.res.ColorStateList @@ -12,23 +14,57 @@ import android.graphics.drawable.Drawable import android.net.Uri import android.os.BatteryManager import android.provider.Settings +import android.widget.Toast import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import androidx.core.content.edit -import cn.bingoogolapple.qrcode.zxing.QRCodeEncoder -import com.google.zxing.EncodeHintType -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel +import androidx.preference.PreferenceManager import io.legado.app.BuildConfig import io.legado.app.R -import org.jetbrains.anko.defaultSharedPreferences -import org.jetbrains.anko.longToast -import org.jetbrains.anko.toast import java.io.File import java.io.FileOutputStream +inline fun Context.startActivity(configIntent: Intent.() -> Unit = {}) { + val intent = Intent(this, A::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + intent.apply(configIntent) + startActivity(intent) +} + +inline fun Context.startService(configIntent: Intent.() -> Unit = {}) { + startService(Intent(this, T::class.java).apply(configIntent)) +} + +fun Context.toastOnUi(message: Int) { + runOnUI { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } +} + +fun Context.toastOnUi(message: CharSequence?) { + runOnUI { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } +} + +fun Context.longToastOnUi(message: Int) { + runOnUI { + Toast.makeText(this, message, Toast.LENGTH_LONG).show() + } +} + +fun Context.longToastOnUi(message: CharSequence?) { + runOnUI { + Toast.makeText(this, message, Toast.LENGTH_LONG).show() + } +} + +val Context.defaultSharedPreferences: SharedPreferences + get() = PreferenceManager.getDefaultSharedPreferences(this) + fun Context.getPrefBoolean(key: String, defValue: Boolean = false) = defaultSharedPreferences.getBoolean(key, defValue) @@ -102,13 +138,26 @@ val Context.navigationBarHeight: Int return resources.getDimensionPixelSize(resourceId) } +fun Context.share(text: String) { + share(getString(R.string.share), text) +} + +fun Context.share(title: String, text: String) { + kotlin.runCatching { + val intent = Intent(Intent.ACTION_SEND) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + intent.putExtra(Intent.EXTRA_SUBJECT, title) + intent.putExtra(Intent.EXTRA_TEXT, text) + intent.type = "text/plain" + startActivity(Intent.createChooser(intent, title)) + } +} + @SuppressLint("SetWorldReadable") fun Context.shareWithQr(title: String, text: String) { - QRCodeEncoder.HINTS[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.L - val bitmap = QRCodeEncoder.syncEncodeQRCode(text, 600) - QRCodeEncoder.HINTS[EncodeHintType.ERROR_CORRECTION] = ErrorCorrectionLevel.H + val bitmap = QRCodeUtils.createQRCode(text) if (bitmap == null) { - toast(R.string.text_too_long_qr_error) + toastOnUi(R.string.text_too_long_qr_error) } else { try { val file = File(externalCacheDir, "qr.png") @@ -128,7 +177,7 @@ fun Context.shareWithQr(title: String, text: String) { intent.type = "image/png" startActivity(Intent.createChooser(intent, title)) } catch (e: Exception) { - toast(e.localizedMessage ?: "ERROR") + toastOnUi(e.localizedMessage ?: "ERROR") } } } @@ -139,7 +188,7 @@ fun Context.sendToClip(text: String) { val clipData = ClipData.newPlainText(null, text) clipboard?.let { clipboard.setPrimaryClip(clipData) - longToast(R.string.copy_complete) + longToastOnUi(R.string.copy_complete) } } @@ -160,7 +209,7 @@ fun Context.sendMail(mail: String) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } catch (e: Exception) { - toast(e.localizedMessage ?: "Error") + toastOnUi(e.localizedMessage ?: "Error") } } @@ -200,13 +249,13 @@ fun Context.openUrl(uri: Uri) { try { startActivity(intent) } catch (e: Exception) { - toast(e.localizedMessage ?: "open url error") + toastOnUi(e.localizedMessage ?: "open url error") } } else { try { startActivity(Intent.createChooser(intent, "请选择浏览器")) } catch (e: Exception) { - toast(e.localizedMessage ?: "open url error") + toastOnUi(e.localizedMessage ?: "open url error") } } } diff --git a/app/src/main/java/io/legado/app/utils/FileUtils.kt b/app/src/main/java/io/legado/app/utils/FileUtils.kt index c42f6f7d4..6c88e70e0 100644 --- a/app/src/main/java/io/legado/app/utils/FileUtils.kt +++ b/app/src/main/java/io/legado/app/utils/FileUtils.kt @@ -3,8 +3,8 @@ package io.legado.app.utils import android.os.Environment import android.webkit.MimeTypeMap import androidx.annotation.IntDef -import io.legado.app.App import io.legado.app.ui.filepicker.utils.ConvertUtils +import splitties.init.appCtx import java.io.* import java.nio.charset.Charset import java.text.SimpleDateFormat @@ -105,8 +105,8 @@ object FileUtils { } fun getCachePath(): String { - return App.INSTANCE.externalCacheDir?.absolutePath - ?: App.INSTANCE.cacheDir.absolutePath + return appCtx.externalCacheDir?.absolutePath + ?: appCtx.cacheDir.absolutePath } fun getSdCardPath(): String { diff --git a/app/src/main/java/io/legado/app/utils/FragmentExtensions.kt b/app/src/main/java/io/legado/app/utils/FragmentExtensions.kt index 15787e7fe..5a086cf29 100644 --- a/app/src/main/java/io/legado/app/utils/FragmentExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/FragmentExtensions.kt @@ -3,7 +3,6 @@ package io.legado.app.utils import android.app.Activity -import android.app.Service import android.content.Intent import android.content.res.ColorStateList import android.graphics.drawable.Drawable @@ -11,13 +10,10 @@ import androidx.annotation.ColorRes import androidx.annotation.DrawableRes import androidx.core.content.edit import androidx.fragment.app.Fragment -import org.jetbrains.anko.connectivityManager -import org.jetbrains.anko.defaultSharedPreferences -import org.jetbrains.anko.internals.AnkoInternals +import splitties.systemservices.connectivityManager @Suppress("DEPRECATION") -fun Fragment.isOnline() = - requireContext().connectivityManager.activeNetworkInfo?.isConnected == true +fun Fragment.isOnline() = connectivityManager.activeNetworkInfo?.isConnected == true fun Fragment.getPrefBoolean(key: String, defValue: Boolean = false) = requireContext().defaultSharedPreferences.getBoolean(key, defValue) @@ -63,22 +59,15 @@ fun Fragment.getCompatDrawable(@DrawableRes id: Int): Drawable? = fun Fragment.getCompatColorStateList(@ColorRes id: Int): ColorStateList? = requireContext().getCompatColorStateList(id) -inline fun Fragment.startActivity(vararg params: Pair) = - AnkoInternals.internalStartActivity(requireActivity(), T::class.java, params) +inline fun Fragment.startActivity( + configIntent: Intent.() -> Unit = {} +) { + startActivity(Intent(requireContext(), T::class.java).apply(configIntent)) +} inline fun Fragment.startActivityForResult( requestCode: Int, - vararg params: Pair -) = startActivityForResult( - AnkoInternals.createIntent(requireActivity(), T::class.java, params), - requestCode -) - -inline fun Fragment.startService(vararg params: Pair) = - AnkoInternals.internalStartService(requireActivity(), T::class.java, params) - -inline fun Fragment.stopService(vararg params: Pair) = - AnkoInternals.internalStopService(requireActivity(), T::class.java, params) - -inline fun Fragment.intentFor(vararg params: Pair): Intent = - AnkoInternals.createIntent(requireActivity(), T::class.java, params) \ No newline at end of file + configIntent: Intent.() -> Unit = {} +) { + startActivityForResult(Intent(requireContext(), T::class.java).apply(configIntent), requestCode) +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/GsonExtensions.kt b/app/src/main/java/io/legado/app/utils/GsonExtensions.kt index b29b4e2b4..db32ca60a 100644 --- a/app/src/main/java/io/legado/app/utils/GsonExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/GsonExtensions.kt @@ -3,7 +3,6 @@ package io.legado.app.utils import com.google.gson.* import com.google.gson.internal.LinkedTreeMap import com.google.gson.reflect.TypeToken -import org.jetbrains.anko.attempt import java.lang.reflect.ParameterizedType import java.lang.reflect.Type import kotlin.math.ceil @@ -24,17 +23,15 @@ val GSON: Gson by lazy { inline fun genericType(): Type = object : TypeToken() {}.type inline fun Gson.fromJsonObject(json: String?): T? {//可转成任意类型 - return attempt { - val result: T? = fromJson(json, genericType()) - result - }.value + return kotlin.runCatching { + fromJson(json, genericType()) as? T + }.getOrNull() } inline fun Gson.fromJsonArray(json: String?): List? { - return attempt { - val result: List? = fromJson(json, ParameterizedTypeImpl(T::class.java)) - result - }.value + return kotlin.runCatching { + fromJson(json, ParameterizedTypeImpl(T::class.java)) as? List + }.getOrNull() } class ParameterizedTypeImpl(private val clazz: Class<*>) : ParameterizedType { diff --git a/app/src/main/java/io/legado/app/utils/HandlerUtils.kt b/app/src/main/java/io/legado/app/utils/HandlerUtils.kt new file mode 100644 index 000000000..0eacea43b --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/HandlerUtils.kt @@ -0,0 +1,52 @@ +@file:Suppress("unused") + +package io.legado.app.utils + +import android.os.Build.VERSION.SDK_INT +import android.os.Handler +import android.os.Looper +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.launch + +/** This main looper cache avoids synchronization overhead when accessed repeatedly. */ +@JvmField +val mainLooper: Looper = Looper.getMainLooper()!! + +@JvmField +val mainThread: Thread = mainLooper.thread + +val isMainThread: Boolean inline get() = mainThread === Thread.currentThread() + +@PublishedApi +internal val currentThread: Any? + inline get() = Thread.currentThread() + +@JvmField +val mainHandler: Handler = if (SDK_INT >= 28) Handler.createAsync(mainLooper) else try { + Handler::class.java.getDeclaredConstructor( + Looper::class.java, + Handler.Callback::class.java, + Boolean::class.javaPrimitiveType // async + ).newInstance(mainLooper, null, true) +} catch (ignored: NoSuchMethodException) { + Handler(mainLooper) // Hidden constructor absent. Fall back to non-async constructor. +} + +fun runOnUI(function: () -> Unit) { + if (isMainThread) { + function() + } else { + mainHandler.post(function) + } +} + +fun CoroutineScope.runOnIO(function: () -> Unit) { + if (isMainThread) { + launch(IO) { + function() + } + } else { + function() + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/JsExtensions.kt b/app/src/main/java/io/legado/app/utils/JsExtensions.kt new file mode 100644 index 000000000..650980863 --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/JsExtensions.kt @@ -0,0 +1,68 @@ +@file:Suppress("unused") + +package io.legado.app.utils + +import org.mozilla.javascript.* + +/** + * 禁止在js里删除文件 + * 参考 https://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/ + */ +fun ContextFactory.eval(jsStr: String, scriptObjects: Map): Any { + val ctx = this.enterContext() + ctx.optimizationLevel = -1 + ctx.setClassShutter { + when { + it.startsWith("java.io") -> false + else -> true + } + } + val scope: Scriptable = ctx.initStandardObjects() + for (name in scriptObjects.keys) { + val obj = scriptObjects[name] + if (obj is Boolean) { + scope.put(name, scope, obj) + } else if (obj != null) { + val jsArgs = Context.toObject(obj, scope) + scope.put(name, scope, jsArgs) + } + } + scope.delete("Packages") + return try { + ctx.evaluateString(scope, jsStr, null, 1, null) + } catch (e: RhinoException) { + e.printStackTrace() + e.toString() + } finally { + Context.exit() + } +} + +class SandboxNativeJavaObject(scope: Scriptable?, javaObject: Any?, staticType: Class<*>?) : + NativeJavaObject(scope, javaObject, staticType) { + override fun get(name: String, start: Scriptable): Any { + return when (name) { + "getClass", "delete" -> NOT_FOUND + else -> super.get(name, start) + } + } +} + +class SandboxWrapFactory : WrapFactory() { + override fun wrapAsJavaObject( + cx: Context?, + scope: Scriptable?, + javaObject: Any?, + staticType: Class<*>? + ): Scriptable { + return SandboxNativeJavaObject(scope, javaObject, staticType) + } +} + +class SandboxContextFactory : ContextFactory() { + override fun makeContext(): Context { + val cx = super.makeContext() + cx.wrapFactory = SandboxWrapFactory() + return cx + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/LogUtils.kt b/app/src/main/java/io/legado/app/utils/LogUtils.kt index a96bc7c75..b94274a3b 100644 --- a/app/src/main/java/io/legado/app/utils/LogUtils.kt +++ b/app/src/main/java/io/legado/app/utils/LogUtils.kt @@ -1,11 +1,10 @@ package io.legado.app.utils import android.annotation.SuppressLint -import io.legado.app.App +import splitties.init.appCtx import java.text.SimpleDateFormat import java.util.* import java.util.logging.* -import java.util.logging.Formatter @Suppress("unused") object LogUtils { @@ -30,17 +29,17 @@ object LogUtils { } private val fileHandler by lazy { - val root = App.INSTANCE.externalCacheDir ?: return@lazy null + val root = appCtx.externalCacheDir ?: return@lazy null val logFolder = FileUtils.createFolderIfNotExist(root, "logs") val logPath = FileUtils.getPath(root = logFolder, "appLog") FileHandler(logPath, 10240, 10).apply { - formatter = object : Formatter() { + formatter = object : java.util.logging.Formatter() { override fun format(record: LogRecord): String { // 设置文件输出格式 return (getCurrentDateStr(TIME_PATTERN) + ": " + record.message + "\n") } } - level = if (App.INSTANCE.getPrefBoolean("recordLog")) { + level = if (appCtx.getPrefBoolean("recordLog")) { Level.INFO } else { Level.OFF @@ -49,7 +48,7 @@ object LogUtils { } fun upLevel() { - fileHandler?.level = if (App.INSTANCE.getPrefBoolean("recordLog")) { + fileHandler?.level = if (appCtx.getPrefBoolean("recordLog")) { Level.INFO } else { Level.OFF diff --git a/app/src/main/java/io/legado/app/utils/QRCodeUtils.kt b/app/src/main/java/io/legado/app/utils/QRCodeUtils.kt new file mode 100644 index 000000000..366abfbe3 --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/QRCodeUtils.kt @@ -0,0 +1,467 @@ +package io.legado.app.utils + +import android.graphics.* +import android.text.TextPaint +import android.text.TextUtils +import androidx.annotation.ColorInt +import androidx.annotation.FloatRange +import com.google.zxing.* +import com.google.zxing.common.GlobalHistogramBinarizer +import com.google.zxing.common.HybridBinarizer +import com.google.zxing.qrcode.QRCodeWriter +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel +import com.king.zxing.DecodeFormatManager +import com.king.zxing.util.LogUtils +import java.util.* +import kotlin.math.max + + +@Suppress("MemberVisibilityCanBePrivate", "unused") +object QRCodeUtils { + + const val DEFAULT_REQ_WIDTH = 480 + const val DEFAULT_REQ_HEIGHT = 640 + + /** + * 生成二维码 + * @param content 二维码的内容 + * @param heightPix 二维码的高 + * @param logo 二维码中间的logo + * @param ratio logo所占比例 因为二维码的最大容错率为30%,所以建议ratio的范围小于0.3 + * @return + */ + fun createQRCode( + content: String, + heightPix: Int = DEFAULT_REQ_HEIGHT, + logo: Bitmap? = null, + @FloatRange(from = 0.0, to = 1.0) ratio: Float = 0.2f, + errorCorrectionLevel: ErrorCorrectionLevel = ErrorCorrectionLevel.H + ): Bitmap? { + //配置参数 + val hints: MutableMap = EnumMap(EncodeHintType::class.java) + hints[EncodeHintType.CHARACTER_SET] = "utf-8" + //容错级别 + hints[EncodeHintType.ERROR_CORRECTION] = errorCorrectionLevel + //设置空白边距的宽度 + hints[EncodeHintType.MARGIN] = 1 //default is 4 + return createQRCode(content, heightPix, logo, ratio, hints) + } + + /** + * 生成二维码 + * @param content 二维码的内容 + * @param heightPix 二维码的高 + * @param logo 二维码中间的logo + * @param ratio logo所占比例 因为二维码的最大容错率为30%,所以建议ratio的范围小于0.3 + * @param hints + * @param codeColor 二维码的颜色 + * @return + */ + fun createQRCode( + content: String?, + heightPix: Int, + logo: Bitmap?, + @FloatRange(from = 0.0, to = 1.0) ratio: Float = 0.2f, + hints: Map, + codeColor: Int = Color.BLACK + ): Bitmap? { + try { + // 图像数据转换,使用了矩阵转换 + val bitMatrix = + QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, heightPix, heightPix, hints) + val pixels = IntArray(heightPix * heightPix) + // 下面这里按照二维码的算法,逐个生成二维码的图片, + // 两个for循环是图片横列扫描的结果 + for (y in 0 until heightPix) { + for (x in 0 until heightPix) { + if (bitMatrix[x, y]) { + pixels[y * heightPix + x] = codeColor + } else { + pixels[y * heightPix + x] = Color.WHITE + } + } + } + + // 生成二维码图片的格式 + var bitmap = Bitmap.createBitmap(heightPix, heightPix, Bitmap.Config.ARGB_8888) + bitmap!!.setPixels(pixels, 0, heightPix, 0, 0, heightPix, heightPix) + if (logo != null) { + bitmap = addLogo(bitmap, logo, ratio) + } + return bitmap + } catch (e: WriterException) { + LogUtils.w(e.message) + } + return null + } + + /** + * 在二维码中间添加Logo图案 + * @param src + * @param logo + * @param ratio logo所占比例 因为二维码的最大容错率为30%,所以建议ratio的范围小于0.3 + * @return + */ + private fun addLogo( + src: Bitmap?, + logo: Bitmap?, + @FloatRange(from = 0.0, to = 1.0) ratio: Float + ): Bitmap? { + if (src == null) { + return null + } + if (logo == null) { + return src + } + + //获取图片的宽高 + val srcWidth = src.width + val srcHeight = src.height + val logoWidth = logo.width + val logoHeight = logo.height + if (srcWidth == 0 || srcHeight == 0) { + return null + } + if (logoWidth == 0 || logoHeight == 0) { + return src + } + + //logo大小为二维码整体大小 + val scaleFactor = srcWidth * ratio / logoWidth + var bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888) + try { + val canvas = Canvas(bitmap!!) + canvas.drawBitmap(src, 0f, 0f, null) + canvas.scale( + scaleFactor, + scaleFactor, + (srcWidth / 2).toFloat(), + (srcHeight / 2).toFloat() + ) + canvas.drawBitmap( + logo, + ((srcWidth - logoWidth) / 2).toFloat(), + ((srcHeight - logoHeight) / 2).toFloat(), + null + ) + canvas.save() + canvas.restore() + } catch (e: Exception) { + bitmap = null + LogUtils.w(e.message) + } + return bitmap + } + + /** + * 解析一维码/二维码图片 + * @param bitmap 解析的图片 + * @param hints 解析编码类型 + * @return + */ + fun parseCode( + bitmap: Bitmap, + reqWidth: Int = DEFAULT_REQ_WIDTH, + reqHeight: Int = DEFAULT_REQ_HEIGHT, + hints: Map = DecodeFormatManager.ALL_HINTS + ): String? { + val result = parseCodeResult(bitmap, reqWidth, reqHeight, hints) + return result?.text + } + + /** + * 解析一维码/二维码图片 + * @param bitmap 解析的图片 + * @param hints 解析编码类型 + * @return + */ + fun parseCodeResult( + bitmap: Bitmap, + reqWidth: Int = DEFAULT_REQ_WIDTH, + reqHeight: Int = DEFAULT_REQ_HEIGHT, + hints: Map = DecodeFormatManager.ALL_HINTS + ): Result? { + if (bitmap.width > reqWidth || bitmap.height > reqHeight) { + val bm = BitmapUtils.changeBitmapSize(bitmap, reqWidth, reqHeight) + return parseCodeResult(getRGBLuminanceSource(bm), hints) + } + return parseCodeResult(getRGBLuminanceSource(bitmap), hints) + } + + /** + * 解析一维码/二维码图片 + * @param source + * @param hints + * @return + */ + fun parseCodeResult(source: LuminanceSource?, hints: Map?): Result? { + var result: Result? = null + val reader = MultiFormatReader() + try { + reader.setHints(hints) + if (source != null) { + result = decodeInternal(reader, source) + if (result == null) { + result = decodeInternal(reader, source.invert()) + } + if (result == null && source.isRotateSupported) { + result = decodeInternal(reader, source.rotateCounterClockwise()) + } + } + } catch (e: java.lang.Exception) { + LogUtils.w(e.message) + } finally { + reader.reset() + } + return result + } + + /** + * 解析二维码图片 + * @param bitmapPath 需要解析的图片路径 + * @return + */ + fun parseQRCode(bitmapPath: String?): String? { + val result = parseQRCodeResult(bitmapPath) + return result?.text + } + + /** + * 解析二维码图片 + * @param bitmapPath 需要解析的图片路径 + * @param reqWidth 请求目标宽度,如果实际图片宽度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理 + * @param reqHeight 请求目标高度,如果实际图片高度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理 + * @return + */ + fun parseQRCodeResult( + bitmapPath: String?, + reqWidth: Int = DEFAULT_REQ_WIDTH, + reqHeight: Int = DEFAULT_REQ_HEIGHT + ): Result? { + return parseCodeResult(bitmapPath, reqWidth, reqHeight, DecodeFormatManager.QR_CODE_HINTS) + } + + /** + * 解析一维码/二维码图片 + * @param bitmapPath 需要解析的图片路径 + * @return + */ + fun parseCode( + bitmapPath: String?, + reqWidth: Int = DEFAULT_REQ_WIDTH, + reqHeight: Int = DEFAULT_REQ_HEIGHT, + hints: Map = DecodeFormatManager.ALL_HINTS + ): String? { + return parseCodeResult(bitmapPath, reqWidth, reqHeight, hints)?.text + } + + /** + * 解析一维码/二维码图片 + * @param bitmapPath 需要解析的图片路径 + * @param reqWidth 请求目标宽度,如果实际图片宽度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理 + * @param reqHeight 请求目标高度,如果实际图片高度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理 + * @param hints 解析编码类型 + * @return + */ + fun parseCodeResult( + bitmapPath: String?, + reqWidth: Int = DEFAULT_REQ_WIDTH, + reqHeight: Int = DEFAULT_REQ_HEIGHT, + hints: Map = DecodeFormatManager.ALL_HINTS + ): Result? { + var result: Result? = null + val reader = MultiFormatReader() + try { + reader.setHints(hints) + val source = getRGBLuminanceSource(compressBitmap(bitmapPath, reqWidth, reqHeight)) + result = decodeInternal(reader, source) + if (result == null) { + result = decodeInternal(reader, source.invert()) + } + if (result == null && source.isRotateSupported) { + result = decodeInternal(reader, source.rotateCounterClockwise()) + } + } catch (e: Exception) { + LogUtils.w(e.message) + } finally { + reader.reset() + } + return result + } + + private fun decodeInternal(reader: MultiFormatReader, source: LuminanceSource): Result? { + var result: Result? = null + try { + try { + //采用HybridBinarizer解析 + result = reader.decodeWithState(BinaryBitmap(HybridBinarizer(source))) + } catch (e: Exception) { + } + if (result == null) { + //如果没有解析成功,再采用GlobalHistogramBinarizer解析一次 + result = reader.decodeWithState(BinaryBitmap(GlobalHistogramBinarizer(source))) + } + } catch (e: Exception) { + } + return result + } + + + /** + * 压缩图片 + * @param path + * @return + */ + private fun compressBitmap(path: String?, reqWidth: Int, reqHeight: Int): Bitmap { + if (reqWidth > 0 && reqHeight > 0) { //都大于进行判断是否压缩 + val newOpts = BitmapFactory.Options() + // 开始读入图片,此时把options.inJustDecodeBounds 设回true了 + newOpts.inJustDecodeBounds = true //获取原始图片大小 + BitmapFactory.decodeFile(path, newOpts) // 此时返回bm为空 + val width = newOpts.outWidth.toFloat() + val height = newOpts.outHeight.toFloat() + // 缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 + var wSize = 1 // wSize=1表示不缩放 + if (width > reqWidth) { // 如果宽度大的话根据宽度固定大小缩放 + wSize = (width / reqWidth).toInt() + } + var hSize = 1 // wSize=1表示不缩放 + if (height > reqHeight) { // 如果高度高的话根据宽度固定大小缩放 + hSize = (height / reqHeight).toInt() + } + var size = max(wSize, hSize) + if (size <= 0) size = 1 + newOpts.inSampleSize = size // 设置缩放比例 + // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 + newOpts.inJustDecodeBounds = false + return BitmapFactory.decodeFile(path, newOpts) + } + return BitmapFactory.decodeFile(path) + } + + + /** + * 获取RGBLuminanceSource + * @param bitmap + * @return + */ + private fun getRGBLuminanceSource(bitmap: Bitmap): RGBLuminanceSource { + val width = bitmap.width + val height = bitmap.height + val pixels = IntArray(width * height) + bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height) + return RGBLuminanceSource(width, height, pixels) + } + + /** + * 生成条形码 + * @param content + * @param format + * @param desiredWidth + * @param desiredHeight + * @param hints + * @param isShowText + * @param textSize + * @param codeColor + * @return + */ + fun createBarCode( + content: String?, + desiredWidth: Int, + desiredHeight: Int, + format: BarcodeFormat = BarcodeFormat.CODE_128, + hints: Map? = null, + isShowText: Boolean = true, + textSize: Int = 40, + @ColorInt codeColor: Int = Color.BLACK + ): Bitmap? { + if (TextUtils.isEmpty(content)) { + return null + } + val writer = MultiFormatWriter() + try { + val result = writer.encode( + content, format, desiredWidth, + desiredHeight, hints + ) + val width = result.width + val height = result.height + val pixels = IntArray(width * height) + // All are 0, or black, by default + for (y in 0 until height) { + val offset = y * width + for (x in 0 until width) { + pixels[offset + x] = if (result[x, y]) codeColor else Color.WHITE + } + } + val bitmap = Bitmap.createBitmap( + width, height, + Bitmap.Config.ARGB_8888 + ) + bitmap.setPixels(pixels, 0, width, 0, 0, width, height) + return if (isShowText) { + addCode(bitmap, content, textSize, codeColor, textSize / 2) + } else bitmap + } catch (e: WriterException) { + LogUtils.w(e.message) + } + return null + } + + /** + * 条形码下面添加文本信息 + * @param src + * @param code + * @param textSize + * @param textColor + * @return + */ + private fun addCode( + src: Bitmap?, + code: String?, + textSize: Int, + @ColorInt textColor: Int, + offset: Int + ): Bitmap? { + if (src == null) { + return null + } + if (TextUtils.isEmpty(code)) { + return src + } + + //获取图片的宽高 + val srcWidth = src.width + val srcHeight = src.height + if (srcWidth <= 0 || srcHeight <= 0) { + return null + } + var bitmap = Bitmap.createBitmap( + srcWidth, + srcHeight + textSize + offset * 2, + Bitmap.Config.ARGB_8888 + ) + try { + val canvas = Canvas(bitmap!!) + canvas.drawBitmap(src, 0f, 0f, null) + val paint = TextPaint() + paint.textSize = textSize.toFloat() + paint.color = textColor + paint.textAlign = Paint.Align.CENTER + canvas.drawText( + code!!, + (srcWidth / 2).toFloat(), + (srcHeight + textSize / 2 + offset).toFloat(), + paint + ) + canvas.save() + canvas.restore() + } catch (e: Exception) { + bitmap = null + LogUtils.w(e.message) + } + return bitmap + } + + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/Toasts.kt b/app/src/main/java/io/legado/app/utils/Toasts.kt index 9038c2231..c98f3561c 100644 --- a/app/src/main/java/io/legado/app/utils/Toasts.kt +++ b/app/src/main/java/io/legado/app/utils/Toasts.kt @@ -4,8 +4,6 @@ package io.legado.app.utils import android.widget.Toast import androidx.fragment.app.Fragment -import org.jetbrains.anko.longToast -import org.jetbrains.anko.toast /** @@ -13,25 +11,25 @@ import org.jetbrains.anko.toast * * @param message the message text resource. */ -fun Fragment.toast(message: Int) = requireActivity().toast(message) +fun Fragment.toastOnUi(message: Int) = requireActivity().toastOnUi(message) /** * Display the simple Toast message with the [Toast.LENGTH_SHORT] duration. * * @param message the message text. */ -fun Fragment.toast(message: CharSequence) = requireActivity().toast(message) +fun Fragment.toastOnUi(message: CharSequence) = requireActivity().toastOnUi(message) /** * Display the simple Toast message with the [Toast.LENGTH_LONG] duration. * * @param message the message text resource. */ -fun Fragment.longToast(message: Int) = requireActivity().longToast(message) +fun Fragment.longToast(message: Int) = requireContext().longToastOnUi(message) /** * Display the simple Toast message with the [Toast.LENGTH_LONG] duration. * * @param message the message text. */ -fun Fragment.longToast(message: CharSequence) = requireActivity().longToast(message) +fun Fragment.longToast(message: CharSequence) = requireContext().longToastOnUi(message) diff --git a/app/src/main/java/io/legado/app/utils/ViewExtensions.kt b/app/src/main/java/io/legado/app/utils/ViewExtensions.kt index 988072bb3..3b3f20270 100644 --- a/app/src/main/java/io/legado/app/utils/ViewExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/ViewExtensions.kt @@ -14,7 +14,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.menu.MenuPopupHelper import androidx.appcompat.widget.PopupMenu import androidx.core.view.get -import io.legado.app.App +import splitties.init.appCtx import java.lang.reflect.Field @@ -31,7 +31,7 @@ val View.activity: AppCompatActivity? get() = getCompatActivity(context) fun View.hideSoftInput() = run { - val imm = App.INSTANCE.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager + val imm = appCtx.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager imm?.let { imm.hideSoftInputFromWindow(this.windowToken, 0) } diff --git a/app/src/main/java/io/legado/app/utils/ViewModelKt.kt b/app/src/main/java/io/legado/app/utils/ViewModelKt.kt deleted file mode 100644 index 9e1f74f24..000000000 --- a/app/src/main/java/io/legado/app/utils/ViewModelKt.kt +++ /dev/null @@ -1,18 +0,0 @@ -package io.legado.app.utils - -import androidx.appcompat.app.AppCompatActivity -import androidx.fragment.app.Fragment -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider - -fun AppCompatActivity.getViewModel(clazz: Class) = - ViewModelProvider(this).get(clazz) - -fun Fragment.getViewModel(clazz: Class) = - ViewModelProvider(this).get(clazz) - -/** - * 与activity数据同步 - */ -fun Fragment.getViewModelOfActivity(clazz: Class) = - ViewModelProvider(requireActivity()).get(clazz) \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt b/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt index 2b5a1c11b..b5a77e2a3 100644 --- a/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt +++ b/app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt @@ -1,18 +1,19 @@ package io.legado.app.web -import android.os.Looper import fi.iki.elonen.NanoHTTPD import fi.iki.elonen.NanoWSD -import io.legado.app.App import io.legado.app.R +import io.legado.app.data.appDb import io.legado.app.model.Debug import io.legado.app.model.webBook.WebBook import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonObject import io.legado.app.utils.isJson +import io.legado.app.utils.runOnIO import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers.IO +import splitties.init.appCtx import java.io.IOException @@ -54,11 +55,11 @@ class SourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) : val tag = debugBean["tag"] val key = debugBean["key"] if (tag.isNullOrBlank() || key.isNullOrBlank()) { - send(App.INSTANCE.getString(R.string.cannot_empty)) + send(appCtx.getString(R.string.cannot_empty)) close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false) return@launch } - App.db.bookSourceDao.getBookSource(tag)?.let { + appDb.bookSourceDao.getBookSource(tag)?.let { Debug.callback = this@SourceDebugWebSocket Debug.startDebug(this, WebBook(it), key) } @@ -76,19 +77,7 @@ class SourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) : } override fun printLog(state: Int, msg: String) { - if (Looper.getMainLooper() == Looper.myLooper()) { - launch(IO) { - runCatching { - send(msg) - if (state == -1 || state == 1000) { - Debug.cancelDebug(true) - close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false) - } - }.onFailure { - it.printStackTrace() - } - } - } else { + runOnIO { runCatching { send(msg) if (state == -1 || state == 1000) { diff --git a/app/src/main/java/io/legado/app/web/utils/AssetsWeb.kt b/app/src/main/java/io/legado/app/web/utils/AssetsWeb.kt index 503f7aad5..22e375555 100644 --- a/app/src/main/java/io/legado/app/web/utils/AssetsWeb.kt +++ b/app/src/main/java/io/legado/app/web/utils/AssetsWeb.kt @@ -3,13 +3,13 @@ package io.legado.app.web.utils import android.content.res.AssetManager import android.text.TextUtils import fi.iki.elonen.NanoHTTPD -import io.legado.app.App +import splitties.init.appCtx import java.io.File import java.io.IOException class AssetsWeb(rootPath: String) { - private val assetManager: AssetManager = App.INSTANCE.assets + private val assetManager: AssetManager = appCtx.assets private var rootPath = "web" init { diff --git a/app/src/main/res/layout/activity_qrcode_capture.xml b/app/src/main/res/layout/activity_qrcode_capture.xml index cfc732dd6..379109187 100644 --- a/app/src/main/res/layout/activity_qrcode_capture.xml +++ b/app/src/main/res/layout/activity_qrcode_capture.xml @@ -1,45 +1,9 @@ - - - - + android:layout_height="match_parent" + android:orientation="vertical"> - - - - - - - + android:layout_height="match_parent" /> - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_book_group_manage.xml b/app/src/main/res/layout/item_book_group_manage.xml new file mode 100644 index 000000000..7c41898db --- /dev/null +++ b/app/src/main/res/layout/item_book_group_manage.xml @@ -0,0 +1,29 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_group_manage.xml b/app/src/main/res/layout/item_group_manage.xml index 9aa18e82a..763a19acd 100644 --- a/app/src/main/res/layout/item_group_manage.xml +++ b/app/src/main/res/layout/item_group_manage.xml @@ -29,10 +29,4 @@ android:padding="8dp" android:text="@string/delete" /> - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_read_record.xml b/app/src/main/res/layout/item_read_record.xml index 2587d759a..7c6316058 100644 --- a/app/src/main/res/layout/item_read_record.xml +++ b/app/src/main/res/layout/item_read_record.xml @@ -1,36 +1,42 @@ - + android:paddingRight="10dp"> + android:padding="6dp" + android:singleLine="true" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_book_name" + app:layout_constraintRight_toLeftOf="@+id/tv_remove" /> - + android:padding="6dp" + android:text="@string/clear" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="@id/tv_book_name" + app:layout_constraintBottom_toBottomOf="@+id/tv_read_time" /> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/menu/replace_rule.xml b/app/src/main/res/menu/replace_rule.xml index 00cf348fe..f650ab792 100644 --- a/app/src/main/res/menu/replace_rule.xml +++ b/app/src/main/res/menu/replace_rule.xml @@ -48,4 +48,10 @@ android:title="@string/import_by_qr_code" app:showAsAction="never" /> + +