From d6793c5b4172f569e44b53227d0a702be1d4b891 Mon Sep 17 00:00:00 2001 From: Xwite Date: Mon, 8 May 2023 01:32:49 +0000 Subject: [PATCH 01/12] Bump cronet from 113.0.5672.61 to 113.0.5672.76 - Changes in the [Git log](https://chromium.googlesource.com/chromium/src/+log/113.0.5672.61..113.0.5672.76) --- app/cronetlib/cronet_api.jar | Bin 166552 -> 166553 bytes app/cronetlib/cronet_impl_common_java.jar | Bin 118982 -> 118983 bytes app/src/main/assets/cronet.json | 2 +- app/src/main/assets/updateLog.md | 1 + gradle.properties | 2 +- 5 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/cronetlib/cronet_api.jar b/app/cronetlib/cronet_api.jar index 27b4ea4e70bc33aee9fc4a2b42684f3b3c26de85..fc622ad643c9e08645a98fb26da0e5cbd2cbddbd 100644 GIT binary patch delta 1530 zcmY+DYfPJE6vuf^rQEkdOMxP-OdSKQeP2q;OIQLZh7V4yy3EX(jZ!E?BG7Uvl$KF0 z<6^Qo-@;+H40MZvZa~apjL|?`VwT0Y55^Dbvf^bGiSy{vTo(w^V{Jpboh zp3cprpPEU}cRizdz>uVTip%DveakD!Nl7co;?_#uNn2+_L$jl@#Vu4hgqCK(mgP;>X&eLV8JtkdXALPmEaAC377}es5 zE+~UHAC(zbv>U$Z2C*o!~$`xM2oNZD6!R!8$Q^Bmwmvq2QlUYFU(d`o>el^ z;kX}6tRCn6;9@uNPd~f_Uk6Dpz$4utz(Y~`tru^c&bfEDPE4OqtZwtXoS~b|5MBE- zm1?*is^;Q?DwxFBmDKIyZA*#A4=vrx!dMS*><(u4!gH(<8+)N0j8{ees(=$cRB3J> zRl15?AB3Uq8uEQ$$4)=>{x1ozl8(LrSWvfvWnxW$oOWSX0Gc4@5lJY;O=1w(Ed_dU z?YaRE^b`1!mjRyXhZkYXt^~^hOTpt#mWCzLZ1)V1e?*9D7W_Rz^`!1)x{U2D{f7$! z&l=uK}CP+HOar9fzonUpnL1fU!O*lv2zNzDyR{V83Na8Nljx^1nSF;@ zq?vMXcuh&sty7)#BSg-BArTAiy~#|tOoTZxHUb^6{Iim}e4822K1H*f8>LH%e~sfD zG>;O#E8*aO9z2H69s^FZSd^IcyczV$^1nSs7UwL9;%^pd?h{a^ z`LT4HC%%e1Jm|8v-}!gEoW^7M6g~6&NpigCl#zh1Pm+(fT1~hpe?HxcD{|^yj=;8nX delta 1499 zcmY+EYfPJE6vufEqujbuZMj3sE^e+1@V3wbGWA`=`C%F*;5Er+QaQ;f>XmQhl16G^WDOfF5m&@WRvo{D% ztJ6~95K66O6%MDPytK?*UT-&-x(ZvIE^o2DrQY4pSlH;ScX*4fwla&@xuZg;82x1y zZ01jfm6uvM2d#81Q>%^+88^#5%2d3;-0c|j zQ_6HRr3^o#Kp}rO-jSi&L$G~!G%^Q|ct8MG2@g7_$9WG}ST3%3zy;%#G2Gk&0(%K( zTA&(!^zm$M8a^wR-0P*1-})6O+BDecrIN-mvJH}UJW&xNrA}*8|CjnNu6p53n4O`Z zN*rmXSx(GtoTX-tJcY8l4E*af)qfBnkdHzu>8Qo}RyYOeUl7tsb=QrwA%R8E+y(&< zZz;6-)-F8mqhHe2lD7I7ZHuSWE9iH0BdEIq27G$#&Tq7s6?TXT6 zJs$HBxNTMdPWj+fSS#U1q?{$5Z3`OxPyvhk*MUx6qQFYUz=iBKj9(yN4qHayVEhM!+DvwI%J|pAsdo$x`S!Z?WHkt z15{&g*JfW57Mmau=lUq%L}=5THKADOR*VE_fNER`z){c-$qvJLZxYsa6TXHc-EaiN zF&Xc~)iIXDRo6^xDtK^04#-D)4~cwlQZ}-1d6H(l*#joHH>D6s)TE%{BHbh}NVIAO z4~M~kJu@tyzb`3BbA0*%$Kr=f#Nx~A7u*pd-`%;GFBg3wY9=jmGV+KSWoZH&zro4< zM$q8Py+kg3#mT-q^nfBnm=#xg!OiBeIt&d^@KE*(XbjWE{|Qqc?Vmj3MhT>0RUg&x zKHfkUAJd6wu_h>b!ts)wuA<}{`YB&X#o!sRU{5MtU@%M<2+MeX8pk7Pgum~n{LTzc zzRsXUD7U*k!LML1uVi5UZD MAwzZ24fNmfAHoUem;e9( diff --git a/app/cronetlib/cronet_impl_common_java.jar b/app/cronetlib/cronet_impl_common_java.jar index c52da2321e647355df76183507fdf04b1984ffa7..25e6c28c1dfaaebd7e7ae3799fc37595af517062 100644 GIT binary patch delta 723 zcmYk3Ur19?9LM)N(8g+ug<{h%gGIBf{c*eQuDz^>@Ik0O1gnQy*QpSM7J@~BII9Pf z9^%A)5LwQxVUlYV%Vc%QIp_ZAEQu(3@Hu+19-=|ex%bBE!r}7${C?;AJLh|H5zR_O zldMkbom<~>o!e9@X_@KeR3qIN9cu0D;at4}@8({6kK+9chDj9 z*##kJqhi#k33Rl3hfVGDOEgAY9WTaWM+y617vu9{94bxP+6W9ULLa$0L+uBRH1W8O ziZg1oX5bJxF)J|~%z&GGn3L-ZiF*8;0UPnBWPK}T!1*i~s3&dEss4U3u%s2Y*LvEY zR^!AHb9*kzZj~iC277T=76zaTLs>XaqVMS9#sS*)UXKmS%salp^kMX*!GJfGp@}^D z#DIwo=(ppl)X)kT%7YO%^g4<2M>iOD{JT&QArB*P8%OhSliWG3w7)sWTuv6i27@?S zfGb4r!%zV%I28ab+KRxF(CHf4jZcfL^%QOv;VhXJFj4|5_Lsm8KXIxALE^b6F&lDa zcGSd>(hx3#gM1%WM70cd@-ifg@EB;6!#c;||Mbn{O0&4i9`474BrIrNW1ikgNi<{f z0(*kH64`p7kV_RXqwgWB-CJX^yDBUdAy%vT$(dPMgp*K@)e77BWUl756aDLq{7y=- P)ZzVg*sl)10v6vNw0{Xh delta 707 zcmY+C-AmI^7{~pd;Ut=EP`DSI21343{x<#TenMy$N(6xt$SzW+ZiB#^BJ{$b4e=rp z3J&&klR3AB8KXsvg32}Bo1321Qc%r(lS6+Mdpax|uj<rmMH2;Ys^sd^0t?ui+673CGeP)vBtd_Jb9#sm!1w*d=Il4}D) z?8(|*hT;a!Fl%bB!u5=izewq6FbRpB%aoaw7Skd&n}mfezvYRK4ZQiCfs833da$F~ zG?_v>LbQ~^2pZ{63X`l>cPEWjx|>#0)r-5CeDyd|dIvJFXzE%)moEy<>o(Mql0yy6 zs5~l{`41V#=tBlAnoXsQ+OinLJo&Sj)7isshsiY{ z%J$?$8lUqYH&ZkxA}-M99EK5~o;=3zodS7Gu+S%?*$vAxt zRi##vejJ>5%wG}=Z^MQYbZZ-z*teT1J4H=z#4LL5sfLx7=1@lqD*3v&PxRy~z(o2m yjH<7O90f6SSLlDiS>{|lKnzh-(yxNZ^e9roKA-5=SrqO4rW-{#v Date: Mon, 8 May 2023 00:34:19 -0400 Subject: [PATCH 02/12] =?UTF-8?q?=E5=8D=95=E7=AB=A0=E6=8D=A2=E6=BA=90?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=AD=97=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChangeChapterSourceAdapter.kt | 35 ++++++++++++++++--- .../changesource/ChangeChapterSourceDialog.kt | 26 ++++++++++++-- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceAdapter.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceAdapter.kt index ca7d14cad..b61b33da8 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceAdapter.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceAdapter.kt @@ -13,6 +13,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.ItemChangeSourceBinding +import io.legado.app.help.config.AppConfig import io.legado.app.utils.getCompatColor import io.legado.app.utils.gone import io.legado.app.utils.invisible @@ -55,6 +56,8 @@ class ChangeChapterSourceAdapter( tvOrigin.text = item.originName tvAuthor.text = item.author tvLast.text = item.getDisplayLastChapterTitle() + tvCurrentChapterWordCount.text = item.chapterWordCountText + tvRespondTime.text = context.getString(R.string.respondTime, item.respondTime) if (callBack.oldBookUrl == item.bookUrl) { ivChecked.visible() } else { @@ -82,13 +85,37 @@ class ChangeChapterSourceAdapter( } else if (score < 0) { binding.ivGood.gone() binding.ivBad.visible() - DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100)) - DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_A200)) + DrawableCompat.setTint( + binding.ivGood.drawable, + appCtx.getCompatColor(R.color.md_red_100) + ) + DrawableCompat.setTint( + binding.ivBad.drawable, + appCtx.getCompatColor(R.color.md_blue_A200) + ) } else { binding.ivGood.visible() binding.ivBad.visible() - DrawableCompat.setTint(binding.ivGood.drawable, appCtx.getCompatColor(R.color.md_red_100)) - DrawableCompat.setTint(binding.ivBad.drawable, appCtx.getCompatColor(R.color.md_blue_100)) + DrawableCompat.setTint( + binding.ivGood.drawable, + appCtx.getCompatColor(R.color.md_red_100) + ) + DrawableCompat.setTint( + binding.ivBad.drawable, + appCtx.getCompatColor(R.color.md_blue_100) + ) + } + + if (AppConfig.changeSourceLoadWordCount && !item.chapterWordCountText.isNullOrBlank()) { + tvCurrentChapterWordCount.visible() + } else { + tvCurrentChapterWordCount.gone() + } + + if (AppConfig.changeSourceLoadWordCount && item.respondTime >= 0) { + tvRespondTime.visible() + } else { + tvRespondTime.gone() } } } diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt index dc14e1dc0..3d464088c 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt @@ -2,16 +2,20 @@ package io.legado.app.ui.book.changesource import android.content.DialogInterface import android.os.Bundle -import android.view.* +import android.view.KeyEvent import android.view.KeyEvent.ACTION_UP +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.Toolbar import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.fragment.app.viewModels +import androidx.lifecycle.Lifecycle.State.STARTED import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle -import androidx.lifecycle.Lifecycle.State.STARTED import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import io.legado.app.R @@ -31,8 +35,17 @@ import io.legado.app.lib.theme.primaryColor import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.* +import io.legado.app.utils.StartActivityContract +import io.legado.app.utils.applyTint +import io.legado.app.utils.cnCompare +import io.legado.app.utils.dpToPx +import io.legado.app.utils.gone +import io.legado.app.utils.observeEvent +import io.legado.app.utils.setLayout +import io.legado.app.utils.startActivity +import io.legado.app.utils.toastOnUi import io.legado.app.utils.viewbindingdelegate.viewBinding +import io.legado.app.utils.visible import kotlinx.coroutines.delay import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.launch @@ -124,6 +137,8 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c ?.isChecked = AppConfig.changeSourceLoadInfo binding.toolBar.menu.findItem(R.id.menu_load_toc) ?.isChecked = AppConfig.changeSourceLoadToc + binding.toolBar.menu.findItem(R.id.menu_load_word_count) + ?.isChecked = AppConfig.changeSourceLoadWordCount } private fun initView() { @@ -239,6 +254,11 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c AppConfig.changeSourceLoadToc = !item.isChecked item.isChecked = !item.isChecked } + R.id.menu_load_word_count -> { + AppConfig.changeSourceLoadWordCount = !item.isChecked + item.isChecked = !item.isChecked + viewModel.onLoadWordCountChecked(item.isChecked) + } R.id.menu_start_stop -> viewModel.startOrStopSearch() R.id.menu_source_manage -> startActivity() else -> if (item?.groupId == R.id.source_group) { From f5ac6c7b5a46ccb50562c8d96b94a0d2283e3496 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 05:13:52 +0000 Subject: [PATCH 03/12] Bump coroutines_version from 1.6.4 to 1.7.0 Bumps `coroutines_version` from 1.6.4 to 1.7.0. Updates `org.jetbrains.kotlinx:kotlinx-coroutines-core` from 1.6.4 to 1.7.0 - [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases) - [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md) - [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.6.4...1.7.0) Updates `org.jetbrains.kotlinx:kotlinx-coroutines-android` from 1.6.4 to 1.7.0 - [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases) - [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md) - [Commits](https://github.com/Kotlin/kotlinx.coroutines/compare/1.6.4...1.7.0) --- updated-dependencies: - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-android dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9a53e024e..54800517a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -149,7 +149,7 @@ dependencies { //noinspection GradleDependency,DifferentStdlibGradleVersion implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version") //协程 - def coroutines_version = '1.6.4' + def coroutines_version = '1.7.0' implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version") From 3b8df026e106e30c6992cbbc3f3a4c2c98961e02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 05:13:59 +0000 Subject: [PATCH 04/12] Bump com.google.protobuf:protobuf-javalite from 3.22.3 to 3.22.4 Bumps com.google.protobuf:protobuf-javalite from 3.22.3 to 3.22.4. --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-javalite dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9a53e024e..b76ca5e32 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -210,7 +210,7 @@ dependencies { //网络 implementation('com.squareup.okhttp3:okhttp:4.11.0') appImplementation(fileTree(dir: 'cronetlib', include: ['*.jar', '*.aar'])) - appImplementation 'com.google.protobuf:protobuf-javalite:3.22.3' + appImplementation 'com.google.protobuf:protobuf-javalite:3.22.4' //Glide def glideVersion = "4.15.1" From 7e5d8bbd7ec045acdb29634b0b836e7c68468c9f Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Mon, 8 May 2023 17:33:59 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io.legado.app.data.AppDatabase/67.json | 1879 +++++++++++++++++ .../io/legado/app/help/source/SourceHelp.kt | 50 +- .../main/java/io/legado/app/model/ReadBook.kt | 66 +- .../changesource/ChangeBookSourceDialog.kt | 9 +- .../changesource/ChangeBookSourceViewModel.kt | 62 +- .../changesource/ChangeChapterSourceDialog.kt | 3 +- .../ChangeChapterSourceViewModel.kt | 4 +- 7 files changed, 1987 insertions(+), 86 deletions(-) create mode 100644 app/schemas/io.legado.app.data.AppDatabase/67.json diff --git a/app/schemas/io.legado.app.data.AppDatabase/67.json b/app/schemas/io.legado.app.data.AppDatabase/67.json new file mode 100644 index 000000000..5da3ea902 --- /dev/null +++ b/app/schemas/io.legado.app.data.AppDatabase/67.json @@ -0,0 +1,1879 @@ +{ + "formatVersion": 1, + "database": { + "version": 67, + "identityHash": "48855e5272b008e4c6b202a41654b575", + "entities": [ + { + "tableName": "books", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookUrl` TEXT NOT NULL DEFAULT '', `tocUrl` TEXT NOT NULL DEFAULT '', `origin` TEXT NOT NULL DEFAULT 'loc_book', `originName` TEXT NOT NULL DEFAULT '', `name` TEXT NOT NULL DEFAULT '', `author` TEXT NOT NULL DEFAULT '', `kind` TEXT, `customTag` TEXT, `coverUrl` TEXT, `customCoverUrl` TEXT, `intro` TEXT, `customIntro` TEXT, `charset` TEXT, `type` INTEGER NOT NULL DEFAULT 0, `group` INTEGER NOT NULL DEFAULT 0, `latestChapterTitle` TEXT, `latestChapterTime` INTEGER NOT NULL DEFAULT 0, `lastCheckTime` INTEGER NOT NULL DEFAULT 0, `lastCheckCount` INTEGER NOT NULL DEFAULT 0, `totalChapterNum` INTEGER NOT NULL DEFAULT 0, `durChapterTitle` TEXT, `durChapterIndex` INTEGER NOT NULL DEFAULT 0, `durChapterPos` INTEGER NOT NULL DEFAULT 0, `durChapterTime` INTEGER NOT NULL DEFAULT 0, `wordCount` TEXT, `canUpdate` INTEGER NOT NULL DEFAULT 1, `order` INTEGER NOT NULL DEFAULT 0, `originOrder` INTEGER NOT NULL DEFAULT 0, `variable` TEXT, `readConfig` TEXT, PRIMARY KEY(`bookUrl`))", + "fields": [ + { + "fieldPath": "bookUrl", + "columnName": "bookUrl", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "tocUrl", + "columnName": "tocUrl", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "'loc_book'" + }, + { + "fieldPath": "originName", + "columnName": "originName", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customTag", + "columnName": "customTag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverUrl", + "columnName": "coverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customCoverUrl", + "columnName": "customCoverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "intro", + "columnName": "intro", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customIntro", + "columnName": "customIntro", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "charset", + "columnName": "charset", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "latestChapterTitle", + "columnName": "latestChapterTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "latestChapterTime", + "columnName": "latestChapterTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "lastCheckTime", + "columnName": "lastCheckTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "lastCheckCount", + "columnName": "lastCheckCount", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "totalChapterNum", + "columnName": "totalChapterNum", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "durChapterTitle", + "columnName": "durChapterTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "durChapterIndex", + "columnName": "durChapterIndex", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "durChapterPos", + "columnName": "durChapterPos", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "durChapterTime", + "columnName": "durChapterTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "wordCount", + "columnName": "wordCount", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "canUpdate", + "columnName": "canUpdate", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "originOrder", + "columnName": "originOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "readConfig", + "columnName": "readConfig", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bookUrl" + ] + }, + "indices": [ + { + "name": "index_books_name_author", + "unique": true, + "columnNames": [ + "name", + "author" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_books_name_author` ON `${TABLE_NAME}` (`name`, `author`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "book_groups", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`groupId` INTEGER NOT NULL, `groupName` TEXT NOT NULL, `cover` TEXT, `order` INTEGER NOT NULL, `enableRefresh` INTEGER NOT NULL DEFAULT 1, `show` INTEGER NOT NULL DEFAULT 1, `bookSort` INTEGER NOT NULL DEFAULT -1, PRIMARY KEY(`groupId`))", + "fields": [ + { + "fieldPath": "groupId", + "columnName": "groupId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "groupName", + "columnName": "groupName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "cover", + "columnName": "cover", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enableRefresh", + "columnName": "enableRefresh", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "show", + "columnName": "show", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "bookSort", + "columnName": "bookSort", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "groupId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "book_sources", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookSourceUrl` TEXT NOT NULL, `bookSourceName` TEXT NOT NULL, `bookSourceGroup` TEXT, `bookSourceType` INTEGER NOT NULL, `bookUrlPattern` TEXT, `customOrder` INTEGER NOT NULL DEFAULT 0, `enabled` INTEGER NOT NULL DEFAULT 1, `enabledExplore` INTEGER NOT NULL DEFAULT 1, `jsLib` TEXT, `enabledCookieJar` INTEGER DEFAULT 0, `concurrentRate` TEXT, `header` TEXT, `loginUrl` TEXT, `loginUi` TEXT, `loginCheckJs` TEXT, `coverDecodeJs` TEXT, `bookSourceComment` TEXT, `variableComment` TEXT, `lastUpdateTime` INTEGER NOT NULL, `respondTime` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `exploreUrl` TEXT, `exploreScreen` TEXT, `ruleExplore` TEXT, `searchUrl` TEXT, `ruleSearch` TEXT, `ruleBookInfo` TEXT, `ruleToc` TEXT, `ruleContent` TEXT, `ruleReview` TEXT, PRIMARY KEY(`bookSourceUrl`))", + "fields": [ + { + "fieldPath": "bookSourceUrl", + "columnName": "bookSourceUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookSourceName", + "columnName": "bookSourceName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookSourceGroup", + "columnName": "bookSourceGroup", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bookSourceType", + "columnName": "bookSourceType", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookUrlPattern", + "columnName": "bookUrlPattern", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customOrder", + "columnName": "customOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "enabledExplore", + "columnName": "enabledExplore", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "jsLib", + "columnName": "jsLib", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabledCookieJar", + "columnName": "enabledCookieJar", + "affinity": "INTEGER", + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "concurrentRate", + "columnName": "concurrentRate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "header", + "columnName": "header", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUrl", + "columnName": "loginUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUi", + "columnName": "loginUi", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginCheckJs", + "columnName": "loginCheckJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverDecodeJs", + "columnName": "coverDecodeJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bookSourceComment", + "columnName": "bookSourceComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "variableComment", + "columnName": "variableComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastUpdateTime", + "columnName": "lastUpdateTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "respondTime", + "columnName": "respondTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exploreUrl", + "columnName": "exploreUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "exploreScreen", + "columnName": "exploreScreen", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleExplore", + "columnName": "ruleExplore", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "searchUrl", + "columnName": "searchUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleSearch", + "columnName": "ruleSearch", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleBookInfo", + "columnName": "ruleBookInfo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleToc", + "columnName": "ruleToc", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleContent", + "columnName": "ruleContent", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleReview", + "columnName": "ruleReview", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bookSourceUrl" + ] + }, + "indices": [ + { + "name": "index_book_sources_bookSourceUrl", + "unique": false, + "columnNames": [ + "bookSourceUrl" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_book_sources_bookSourceUrl` ON `${TABLE_NAME}` (`bookSourceUrl`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "chapters", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `title` TEXT NOT NULL, `isVolume` INTEGER NOT NULL, `baseUrl` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `index` INTEGER NOT NULL, `isVip` INTEGER NOT NULL, `isPay` INTEGER NOT NULL, `resourceUrl` TEXT, `tag` TEXT, `start` INTEGER, `end` INTEGER, `startFragmentId` TEXT, `endFragmentId` TEXT, `variable` TEXT, PRIMARY KEY(`url`, `bookUrl`), FOREIGN KEY(`bookUrl`) REFERENCES `books`(`bookUrl`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isVolume", + "columnName": "isVolume", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "baseUrl", + "columnName": "baseUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookUrl", + "columnName": "bookUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "index", + "columnName": "index", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isVip", + "columnName": "isVip", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isPay", + "columnName": "isPay", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "resourceUrl", + "columnName": "resourceUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tag", + "columnName": "tag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "start", + "columnName": "start", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "end", + "columnName": "end", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "startFragmentId", + "columnName": "startFragmentId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "endFragmentId", + "columnName": "endFragmentId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "url", + "bookUrl" + ] + }, + "indices": [ + { + "name": "index_chapters_bookUrl", + "unique": false, + "columnNames": [ + "bookUrl" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_chapters_bookUrl` ON `${TABLE_NAME}` (`bookUrl`)" + }, + { + "name": "index_chapters_bookUrl_index", + "unique": true, + "columnNames": [ + "bookUrl", + "index" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapters_bookUrl_index` ON `${TABLE_NAME}` (`bookUrl`, `index`)" + } + ], + "foreignKeys": [ + { + "table": "books", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "bookUrl" + ], + "referencedColumns": [ + "bookUrl" + ] + } + ] + }, + { + "tableName": "replace_rules", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL DEFAULT '', `group` TEXT, `pattern` TEXT NOT NULL DEFAULT '', `replacement` TEXT NOT NULL DEFAULT '', `scope` TEXT, `scopeTitle` INTEGER NOT NULL DEFAULT 0, `scopeContent` INTEGER NOT NULL DEFAULT 1, `isEnabled` INTEGER NOT NULL DEFAULT 1, `isRegex` INTEGER NOT NULL DEFAULT 1, `timeoutMillisecond` INTEGER NOT NULL DEFAULT 3000, `sortOrder` INTEGER NOT NULL DEFAULT 0)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "group", + "columnName": "group", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pattern", + "columnName": "pattern", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "replacement", + "columnName": "replacement", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "scope", + "columnName": "scope", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "scopeTitle", + "columnName": "scopeTitle", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "scopeContent", + "columnName": "scopeContent", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "isEnabled", + "columnName": "isEnabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "isRegex", + "columnName": "isRegex", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "timeoutMillisecond", + "columnName": "timeoutMillisecond", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "3000" + }, + { + "fieldPath": "order", + "columnName": "sortOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_replace_rules_id", + "unique": false, + "columnNames": [ + "id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_replace_rules_id` ON `${TABLE_NAME}` (`id`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "searchBooks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookUrl` TEXT NOT NULL, `origin` TEXT NOT NULL, `originName` TEXT NOT NULL, `type` INTEGER NOT NULL, `name` TEXT NOT NULL, `author` TEXT NOT NULL, `kind` TEXT, `coverUrl` TEXT, `intro` TEXT, `wordCount` TEXT, `latestChapterTitle` TEXT, `tocUrl` TEXT NOT NULL, `time` INTEGER NOT NULL, `variable` TEXT, `originOrder` INTEGER NOT NULL, `chapterWordCountText` TEXT, `chapterWordCount` INTEGER NOT NULL DEFAULT -1, `respondTime` INTEGER NOT NULL DEFAULT -1, PRIMARY KEY(`bookUrl`), FOREIGN KEY(`origin`) REFERENCES `book_sources`(`bookSourceUrl`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "bookUrl", + "columnName": "bookUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "originName", + "columnName": "originName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "author", + "columnName": "author", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverUrl", + "columnName": "coverUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "intro", + "columnName": "intro", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "wordCount", + "columnName": "wordCount", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "latestChapterTitle", + "columnName": "latestChapterTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "tocUrl", + "columnName": "tocUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "originOrder", + "columnName": "originOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "chapterWordCountText", + "columnName": "chapterWordCountText", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "chapterWordCount", + "columnName": "chapterWordCount", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + }, + { + "fieldPath": "respondTime", + "columnName": "respondTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "-1" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "bookUrl" + ] + }, + "indices": [ + { + "name": "index_searchBooks_bookUrl", + "unique": true, + "columnNames": [ + "bookUrl" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_searchBooks_bookUrl` ON `${TABLE_NAME}` (`bookUrl`)" + }, + { + "name": "index_searchBooks_origin", + "unique": false, + "columnNames": [ + "origin" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_searchBooks_origin` ON `${TABLE_NAME}` (`origin`)" + } + ], + "foreignKeys": [ + { + "table": "book_sources", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "origin" + ], + "referencedColumns": [ + "bookSourceUrl" + ] + } + ] + }, + { + "tableName": "search_keywords", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`word` TEXT NOT NULL, `usage` INTEGER NOT NULL, `lastUseTime` INTEGER NOT NULL, PRIMARY KEY(`word`))", + "fields": [ + { + "fieldPath": "word", + "columnName": "word", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "usage", + "columnName": "usage", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUseTime", + "columnName": "lastUseTime", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "word" + ] + }, + "indices": [ + { + "name": "index_search_keywords_word", + "unique": true, + "columnNames": [ + "word" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_search_keywords_word` ON `${TABLE_NAME}` (`word`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "cookies", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `cookie` TEXT NOT NULL, PRIMARY KEY(`url`))", + "fields": [ + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "cookie", + "columnName": "cookie", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "url" + ] + }, + "indices": [ + { + "name": "index_cookies_url", + "unique": true, + "columnNames": [ + "url" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_cookies_url` ON `${TABLE_NAME}` (`url`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "rssSources", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sourceUrl` TEXT NOT NULL, `sourceName` TEXT NOT NULL, `sourceIcon` TEXT NOT NULL, `sourceGroup` TEXT, `sourceComment` TEXT, `enabled` INTEGER NOT NULL, `variableComment` TEXT, `jsLib` TEXT, `enabledCookieJar` INTEGER DEFAULT 0, `concurrentRate` TEXT, `header` TEXT, `loginUrl` TEXT, `loginUi` TEXT, `loginCheckJs` TEXT, `coverDecodeJs` TEXT, `sortUrl` TEXT, `singleUrl` INTEGER NOT NULL, `articleStyle` INTEGER NOT NULL DEFAULT 0, `ruleArticles` TEXT, `ruleNextPage` TEXT, `ruleTitle` TEXT, `rulePubDate` TEXT, `ruleDescription` TEXT, `ruleImage` TEXT, `ruleLink` TEXT, `ruleContent` TEXT, `contentWhitelist` TEXT, `contentBlacklist` TEXT, `style` TEXT, `enableJs` INTEGER NOT NULL DEFAULT 1, `loadWithBaseUrl` INTEGER NOT NULL DEFAULT 1, `injectJs` TEXT, `lastUpdateTime` INTEGER NOT NULL DEFAULT 0, `customOrder` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`sourceUrl`))", + "fields": [ + { + "fieldPath": "sourceUrl", + "columnName": "sourceUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceName", + "columnName": "sourceName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceIcon", + "columnName": "sourceIcon", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sourceGroup", + "columnName": "sourceGroup", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sourceComment", + "columnName": "sourceComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "variableComment", + "columnName": "variableComment", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsLib", + "columnName": "jsLib", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabledCookieJar", + "columnName": "enabledCookieJar", + "affinity": "INTEGER", + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "concurrentRate", + "columnName": "concurrentRate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "header", + "columnName": "header", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUrl", + "columnName": "loginUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUi", + "columnName": "loginUi", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginCheckJs", + "columnName": "loginCheckJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "coverDecodeJs", + "columnName": "coverDecodeJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sortUrl", + "columnName": "sortUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "singleUrl", + "columnName": "singleUrl", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "articleStyle", + "columnName": "articleStyle", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "ruleArticles", + "columnName": "ruleArticles", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleNextPage", + "columnName": "ruleNextPage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleTitle", + "columnName": "ruleTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "rulePubDate", + "columnName": "rulePubDate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleDescription", + "columnName": "ruleDescription", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleImage", + "columnName": "ruleImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleLink", + "columnName": "ruleLink", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "ruleContent", + "columnName": "ruleContent", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentWhitelist", + "columnName": "contentWhitelist", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "contentBlacklist", + "columnName": "contentBlacklist", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "style", + "columnName": "style", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enableJs", + "columnName": "enableJs", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "loadWithBaseUrl", + "columnName": "loadWithBaseUrl", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "injectJs", + "columnName": "injectJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastUpdateTime", + "columnName": "lastUpdateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "customOrder", + "columnName": "customOrder", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "sourceUrl" + ] + }, + "indices": [ + { + "name": "index_rssSources_sourceUrl", + "unique": false, + "columnNames": [ + "sourceUrl" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_rssSources_sourceUrl` ON `${TABLE_NAME}` (`sourceUrl`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "bookmarks", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`time` INTEGER NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `chapterPos` INTEGER NOT NULL, `chapterName` TEXT NOT NULL, `bookText` TEXT NOT NULL, `content` TEXT NOT NULL, PRIMARY KEY(`time`))", + "fields": [ + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "bookName", + "columnName": "bookName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookAuthor", + "columnName": "bookAuthor", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "chapterIndex", + "columnName": "chapterIndex", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "chapterPos", + "columnName": "chapterPos", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "chapterName", + "columnName": "chapterName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookText", + "columnName": "bookText", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "time" + ] + }, + "indices": [ + { + "name": "index_bookmarks_bookName_bookAuthor", + "unique": false, + "columnNames": [ + "bookName", + "bookAuthor" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_bookmarks_bookName_bookAuthor` ON `${TABLE_NAME}` (`bookName`, `bookAuthor`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "rssArticles", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`origin` TEXT NOT NULL, `sort` TEXT NOT NULL, `title` TEXT NOT NULL, `order` INTEGER NOT NULL, `link` TEXT NOT NULL, `pubDate` TEXT, `description` TEXT, `content` TEXT, `image` TEXT, `read` INTEGER NOT NULL, `variable` TEXT, PRIMARY KEY(`origin`, `link`))", + "fields": [ + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sort", + "columnName": "sort", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "order", + "columnName": "order", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "link", + "columnName": "link", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pubDate", + "columnName": "pubDate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "read", + "columnName": "read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "origin", + "link" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "rssReadRecords", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record` TEXT NOT NULL, `read` INTEGER NOT NULL, PRIMARY KEY(`record`))", + "fields": [ + { + "fieldPath": "record", + "columnName": "record", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "read", + "columnName": "read", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "record" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "rssStars", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`origin` TEXT NOT NULL, `sort` TEXT NOT NULL, `title` TEXT NOT NULL, `starTime` INTEGER NOT NULL, `link` TEXT NOT NULL, `pubDate` TEXT, `description` TEXT, `content` TEXT, `image` TEXT, `variable` TEXT, PRIMARY KEY(`origin`, `link`))", + "fields": [ + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sort", + "columnName": "sort", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "starTime", + "columnName": "starTime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "link", + "columnName": "link", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "pubDate", + "columnName": "pubDate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "image", + "columnName": "image", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "variable", + "columnName": "variable", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "origin", + "link" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "txtTocRules", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `rule` TEXT NOT NULL, `example` TEXT, `serialNumber` INTEGER NOT NULL, `enable` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "rule", + "columnName": "rule", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "example", + "columnName": "example", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "serialNumber", + "columnName": "serialNumber", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enable", + "columnName": "enable", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "readRecord", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `readTime` INTEGER NOT NULL DEFAULT 0, `lastRead` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`deviceId`, `bookName`))", + "fields": [ + { + "fieldPath": "deviceId", + "columnName": "deviceId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookName", + "columnName": "bookName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "readTime", + "columnName": "readTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "lastRead", + "columnName": "lastRead", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "deviceId", + "bookName" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "httpTTS", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `contentType` TEXT, `concurrentRate` TEXT DEFAULT '0', `loginUrl` TEXT, `loginUi` TEXT, `header` TEXT, `jsLib` TEXT, `enabledCookieJar` INTEGER DEFAULT 0, `loginCheckJs` TEXT, `lastUpdateTime` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contentType", + "columnName": "contentType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "concurrentRate", + "columnName": "concurrentRate", + "affinity": "TEXT", + "notNull": false, + "defaultValue": "'0'" + }, + { + "fieldPath": "loginUrl", + "columnName": "loginUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginUi", + "columnName": "loginUi", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "header", + "columnName": "header", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "jsLib", + "columnName": "jsLib", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enabledCookieJar", + "columnName": "enabledCookieJar", + "affinity": "INTEGER", + "notNull": false, + "defaultValue": "0" + }, + { + "fieldPath": "loginCheckJs", + "columnName": "loginCheckJs", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lastUpdateTime", + "columnName": "lastUpdateTime", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "caches", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` TEXT, `deadline` INTEGER NOT NULL, PRIMARY KEY(`key`))", + "fields": [ + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "deadline", + "columnName": "deadline", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "key" + ] + }, + "indices": [ + { + "name": "index_caches_key", + "unique": true, + "columnNames": [ + "key" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_caches_key` ON `${TABLE_NAME}` (`key`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "ruleSubs", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, `type` INTEGER NOT NULL, `customOrder` INTEGER NOT NULL, `autoUpdate` INTEGER NOT NULL, `update` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customOrder", + "columnName": "customOrder", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "autoUpdate", + "columnName": "autoUpdate", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "update", + "columnName": "update", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "dictRules", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `urlRule` TEXT NOT NULL, `showRule` TEXT NOT NULL, `enabled` INTEGER NOT NULL DEFAULT 1, `sortNumber` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`name`))", + "fields": [ + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "urlRule", + "columnName": "urlRule", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "showRule", + "columnName": "showRule", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "1" + }, + { + "fieldPath": "sortNumber", + "columnName": "sortNumber", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "name" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "keyboardAssists", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` INTEGER NOT NULL DEFAULT 0, `key` TEXT NOT NULL DEFAULT '', `value` TEXT NOT NULL DEFAULT '', `serialNo` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`type`, `key`))", + "fields": [ + { + "fieldPath": "type", + "columnName": "type", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + }, + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + }, + { + "fieldPath": "serialNo", + "columnName": "serialNo", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "type", + "key" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "servers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `type` TEXT NOT NULL, `config` TEXT, `sortNumber` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "config", + "columnName": "config", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sortNumber", + "columnName": "sortNumber", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '48855e5272b008e4c6b202a41654b575')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/source/SourceHelp.kt b/app/src/main/java/io/legado/app/help/source/SourceHelp.kt index ec6af0d6f..bf4fe3a04 100644 --- a/app/src/main/java/io/legado/app/help/source/SourceHelp.kt +++ b/app/src/main/java/io/legado/app/help/source/SourceHelp.kt @@ -19,9 +19,11 @@ object SourceHelp { private val list18Plus by lazy { try { return@lazy String(appCtx.assets.open("18PlusList.txt").readBytes()) - .splitNotBlank("\n") + .splitNotBlank("\n").map { + EncoderUtils.base64Decode(it) + }.toHashSet() } catch (e: Exception) { - return@lazy arrayOf() + return@lazy hashSetOf() } } @@ -32,42 +34,42 @@ object SourceHelp { } fun insertRssSource(vararg rssSources: RssSource) { - rssSources.forEach { rssSource -> - if (is18Plus(rssSource.sourceUrl)) { - handler.post { - appCtx.toastOnUi("${rssSource.sourceName}是18+网址,禁止导入.") - } - } else { - appDb.rssSourceDao.insert(rssSource) + val rssSourcesGroup = rssSources.groupBy { + is18Plus(it.sourceUrl) + } + rssSourcesGroup[true]?.forEach { + handler.post { + appCtx.toastOnUi("${it.sourceName}是18+网址,禁止导入.") } } + rssSourcesGroup[false]?.let { + appDb.rssSourceDao.insert(*it.toTypedArray()) + } } fun insertBookSource(vararg bookSources: BookSource) { - bookSources.forEach { bookSource -> - if (is18Plus(bookSource.bookSourceUrl)) { - handler.post { - appCtx.toastOnUi("${bookSource.bookSourceName}是18+网址,禁止导入.") - } - } else { - appDb.bookSourceDao.insert(bookSource) + val bookSourcesGroup = bookSources.groupBy { + is18Plus(it.bookSourceUrl) + } + bookSourcesGroup[true]?.forEach { + handler.post { + appCtx.toastOnUi("${it.bookSourceName}是18+网址,禁止导入.") } } + bookSourcesGroup[false]?.let { + appDb.bookSourceDao.insert(*it.toTypedArray()) + } } private fun is18Plus(url: String?): Boolean { url ?: return false - val baseUrl = NetworkUtils.getBaseUrl(url) - baseUrl ?: return false if (AppConst.isPlayChannel) return false + val baseUrl = NetworkUtils.getBaseUrl(url) ?: return false kotlin.runCatching { - val host = baseUrl.split("//", ".") - val base64Url = EncoderUtils.base64Encode("${host[host.lastIndex - 1]}.${host.last()}") - list18Plus.forEach { - if (base64Url == it) { - return true - } + val host = baseUrl.split("//", ".").let { + if (it.size > 2) "${it[it.lastIndex - 1]}.${it.last()}" else return false } + return list18Plus.contains(host) } return false } diff --git a/app/src/main/java/io/legado/app/model/ReadBook.kt b/app/src/main/java/io/legado/app/model/ReadBook.kt index bdf55e39a..d66457326 100644 --- a/app/src/main/java/io/legado/app/model/ReadBook.kt +++ b/app/src/main/java/io/legado/app/model/ReadBook.kt @@ -307,7 +307,6 @@ object ReadBook : CoroutineScope by MainScope() { contentLoadFinish(book, chapter, it, upContent, resetPageOffset) { success?.invoke() } - removeLoading(chapter.index) } ?: download(this, chapter, resetPageOffset = resetPageOffset) } ?: removeLoading(index) }.onError { @@ -320,26 +319,24 @@ object ReadBook : CoroutineScope by MainScope() { /** * 下载正文 */ - private fun download(index: Int) { + private fun downloadIndex(index: Int) { if (index < 0) return if (index > chapterSize - 1) { upToc() return } - book?.let { book -> - if (book.isLocal) return - if (addLoading(index)) { - Coroutine.async { - appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter -> - if (BookHelp.hasContent(book, chapter)) { - removeLoading(chapter.index) - } else { - download(this, chapter, false) - } - } ?: removeLoading(index) - }.onError { - removeLoading(index) - } + val book = book ?: return + if (addLoading(index)) { + try { + appDb.bookChapterDao.getChapter(book.bookUrl, index)?.let { chapter -> + if (BookHelp.hasContent(book, chapter)) { + removeLoading(chapter.index) + } else { + download(this, chapter, false) + } + } ?: removeLoading(index) + } catch (e: Exception) { + removeLoading(index) } } } @@ -353,20 +350,17 @@ object ReadBook : CoroutineScope by MainScope() { resetPageOffset: Boolean, success: (() -> Unit)? = null ) { - val book = book + val book = book ?: return removeLoading(chapter.index) val bookSource = bookSource - if (book != null && bookSource != null) { + if (bookSource != null) { CacheBook.getOrCreate(bookSource, book).download(scope, chapter) - } else if (book != null) { + } else { val msg = if (book.isLocal) "无内容" else "没有书源" contentLoadFinish( book, chapter, "加载正文失败\n$msg", resetPageOffset = resetPageOffset ) { success?.invoke() } - removeLoading(chapter.index) - } else { - removeLoading(chapter.index) } } @@ -415,10 +409,12 @@ object ReadBook : CoroutineScope by MainScope() { curPageChanged() callBack?.contentLoadFinish() } + -1 -> { prevTextChapter = textChapter if (upContent) callBack?.upContent(offset, resetPageOffset) } + 1 -> { nextTextChapter = textChapter if (upContent) callBack?.upContent(offset, resetPageOffset) @@ -464,18 +460,17 @@ object ReadBook : CoroutineScope by MainScope() { fun saveRead() { Coroutine.async { - book?.let { book -> - book.lastCheckCount = 0 - book.durChapterTime = System.currentTimeMillis() - book.durChapterIndex = durChapterIndex - book.durChapterPos = durChapterPos - appDb.bookChapterDao.getChapter(book.bookUrl, durChapterIndex)?.let { - book.durChapterTitle = it.getDisplayTitle( - ContentProcessor.get(book.name, book.origin).getTitleReplaceRules() - ) - } - appDb.bookDao.update(book) + val book = book ?: return@async + book.lastCheckCount = 0 + book.durChapterTime = System.currentTimeMillis() + book.durChapterIndex = durChapterIndex + book.durChapterPos = durChapterPos + appDb.bookChapterDao.getChapter(book.bookUrl, durChapterIndex)?.let { + book.durChapterTitle = it.getDisplayTitle( + ContentProcessor.get(book.name, book.origin).getTitleReplaceRules() + ) } + appDb.bookDao.update(book) } } @@ -483,6 +478,7 @@ object ReadBook : CoroutineScope by MainScope() { * 预下载 */ private fun preDownload() { + if (book?.isLocal == true) return if (AppConfig.preDownloadNum < 2) { return } @@ -491,12 +487,12 @@ object ReadBook : CoroutineScope by MainScope() { val maxChapterIndex = durChapterIndex + AppConfig.preDownloadNum for (i in durChapterIndex.plus(2)..maxChapterIndex) { delay(1000) - download(i) + downloadIndex(i) } val minChapterIndex = durChapterIndex - min(5, AppConfig.preDownloadNum) for (i in durChapterIndex.minus(2) downTo minChapterIndex) { delay(1000) - download(i) + downloadIndex(i) } } } diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt index 0c3389a8a..098e59e18 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceDialog.kt @@ -27,6 +27,7 @@ import io.legado.app.databinding.DialogBookChangeSourceBinding import io.legado.app.help.config.AppConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.primaryColor +import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.ui.widget.dialog.WaitDialog @@ -86,7 +87,7 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { binding.toolBar.setBackgroundColor(primaryColor) - viewModel.initData(arguments) + viewModel.initData(arguments, callBack?.oldBook, activity is ReadBookActivity) showTitle() initMenu() initRecyclerView() @@ -212,19 +213,23 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ item.isChecked = !item.isChecked viewModel.refresh() } + R.id.menu_load_info -> { AppConfig.changeSourceLoadInfo = !item.isChecked item.isChecked = !item.isChecked } + R.id.menu_load_toc -> { AppConfig.changeSourceLoadToc = !item.isChecked item.isChecked = !item.isChecked } + R.id.menu_load_word_count -> { AppConfig.changeSourceLoadWordCount = !item.isChecked item.isChecked = !item.isChecked viewModel.onLoadWordCountChecked(item.isChecked) } + R.id.menu_start_stop -> viewModel.startOrStopSearch() R.id.menu_source_manage -> startActivity() R.id.menu_refresh_list -> viewModel.startRefreshList() @@ -306,7 +311,7 @@ class ChangeBookSourceDialog() : BaseDialogFragment(R.layout.dialog_book_change_ } override fun setBookScore(searchBook: SearchBook, score: Int) { - viewModel.setBookScore(searchBook,score) + viewModel.setBookScore(searchBook, score) } override fun getBookScore(searchBook: SearchBook): Int { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt index a58113ced..9933b101d 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt @@ -16,12 +16,14 @@ import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.SearchBook import io.legado.app.exception.NoStackTraceException +import io.legado.app.help.book.BookHelp import io.legado.app.help.config.AppConfig import io.legado.app.help.config.SourceConfig import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.help.coroutine.Coroutine import io.legado.app.model.ReadBook import io.legado.app.model.webBook.WebBook +import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.postEvent import io.legado.app.utils.toastOnUi @@ -44,6 +46,8 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a var searchFinishCallback: ((isEmpty: Boolean) -> Unit)? = null var name: String = "" var author: String = "" + private var fromReadBookActivity = false + private var oldBook: Book? = null private var tasks = CompositeCoroutine() private var screenKey: String = "" private var bookSourceList = arrayListOf() @@ -114,7 +118,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a } @CallSuper - open fun initData(arguments: Bundle?) { + open fun initData(arguments: Bundle?, book: Book?, fromReadBookActivity: Boolean) { arguments?.let { bundle -> bundle.getString("name")?.let { name = it @@ -122,6 +126,8 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a bundle.getString("author")?.let { author = it.replace(AppPattern.authorRegex, "") } + this.fromReadBookActivity = fromReadBookActivity + oldBook = book } } @@ -180,22 +186,24 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a val task = Coroutine.async(scope = viewModelScope, context = searchPool!!) { val resultBooks = WebBook.searchBookAwait(source, name) resultBooks.forEach { searchBook -> - if (searchBook.name == name) { - if ((AppConfig.changeSourceCheckAuthor && searchBook.author.contains(author)) - || !AppConfig.changeSourceCheckAuthor - ) { - when { - searchBook.latestChapterTitle.isNullOrEmpty() && - (AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) -> { - loadBookInfo(source, searchBook.toBook()) - } - searchBook.chapterWordCountText.isNullOrBlank() && AppConfig.changeSourceLoadWordCount -> { - loadBookToc(source, searchBook.toBook()) - } - else -> { - searchCallback?.searchSuccess(searchBook) - } - } + if (searchBook.name != name) { + return@forEach + } + if (AppConfig.changeSourceCheckAuthor && !searchBook.author.contains(author)) { + return@forEach + } + when { + searchBook.latestChapterTitle.isNullOrEmpty() && + (AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc) -> { + loadBookInfo(source, searchBook.toBook()) + } + + AppConfig.changeSourceLoadWordCount -> { + loadBookToc(source, searchBook.toBook()) + } + + else -> { + searchCallback?.searchSuccess(searchBook) } } } @@ -211,7 +219,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a private suspend fun loadBookInfo(source: BookSource, book: Book) { WebBook.getBookInfoAwait(source, book) - if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) { + if (AppConfig.changeSourceLoadToc || AppConfig.changeSourceLoadWordCount) { loadBookToc(source, book) } else { //从详情页里获取最新章节 @@ -224,7 +232,7 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a val chapters = WebBook.getChapterListAwait(source, book).getOrThrow() tocMap[book.bookUrl] = chapters bookMap[book.bookUrl] = book - if (context.getPrefBoolean(PreferKey.changeSourceLoadWordCount)) { + if (AppConfig.changeSourceLoadWordCount) { loadBookWordCount(source, book, chapters) } else { val searchBook = book.toSearchBook() @@ -237,16 +245,26 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a book: Book, chapters: List ) = coroutineScope { - val chapterIndex = ReadBook.curTextChapter?.chapter?.index ?: (chapters.size - 1) + val chapterIndex = if (fromReadBookActivity) { + oldBook?.let { + BookHelp.getDurChapter( + it.durChapterIndex, + it.durChapterTitle, + chapters, + it.totalChapterNum + ) + } ?: chapters.lastIndex + } else chapters.lastIndex val bookChapter = chapters.getOrNull(chapterIndex) val startTime = System.currentTimeMillis() val pair = try { if (bookChapter == null) throw NoStackTraceException("章节缺失,总章节数${chapters.size}") - if (!isActive) return@coroutineScope - WebBook.getContentAwait(source, book, bookChapter, null, false).length.let { + val nextChapterUrl = chapters.getOrNull(chapterIndex + 1)?.url + WebBook.getContentAwait(source, book, bookChapter, nextChapterUrl, false).length.let { it to "第${chapterIndex + 1}章 字数:${it}" } } catch (t: Throwable) { + if (t is CancellationException) throw t -1 to "第${chapterIndex + 1}章 获取字数失败:${t.localizedMessage}" } val endTime = System.currentTimeMillis() diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt index 3d464088c..9f0351865 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceDialog.kt @@ -32,6 +32,7 @@ import io.legado.app.help.config.AppConfig import io.legado.app.lib.dialogs.alert import io.legado.app.lib.theme.elevation import io.legado.app.lib.theme.primaryColor +import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.ui.widget.recycler.VerticalDivider @@ -112,7 +113,7 @@ class ChangeChapterSourceDialog() : BaseDialogFragment(R.layout.dialog_chapter_c override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { binding.toolBar.setBackgroundColor(primaryColor) - viewModel.initData(arguments) + viewModel.initData(arguments, callBack?.oldBook, activity is ReadBookActivity) showTitle() initMenu() initView() diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt index 139a857b2..c97d0406d 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeChapterSourceViewModel.kt @@ -15,8 +15,8 @@ class ChangeChapterSourceViewModel(application: Application) : var chapterIndex: Int = 0 var chapterTitle: String = "" - override fun initData(arguments: Bundle?) { - super.initData(arguments) + override fun initData(arguments: Bundle?, book: Book?, fromReadBookActivity: Boolean) { + super.initData(arguments, book, fromReadBookActivity) arguments?.let { bundle -> bundle.getString("chapterTitle")?.let { chapterTitle = it From 61c7317419cbad92f512e084cddb53eafe350158 Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 8 May 2023 20:39:20 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 998182b61..9ec75f141 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -12,10 +12,16 @@ * 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。 * 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源! +**2023/05/08** + +* 更新cronet: 113.0.5672.76 +* 修复全文搜索开始bug +* 单章换源加载字数 +* 优化web端 +* 其中一些更新由 Xwite, Horis, Jason Yao提供 + **2023/05/03** -* 更新cronet: 113.0.5672.76 -* 更新cronet: 113.0.5672.61 * 文件类书源文件后缀识别:自动识别失败后会读取下载链接UrlOption的type字段 ``` From 90e0f6111d36a7d057da5ab5a4d714404c249ead Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 8 May 2023 20:39:50 +0800 Subject: [PATCH 07/12] [skip ci] update updateLog --- app/src/main/assets/updateLog.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 9ec75f141..e0426feb3 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -15,9 +15,12 @@ **2023/05/08** * 更新cronet: 113.0.5672.76 +* web: 全新传书页面 [MakeHui](https://github.com/MakeHui);修正源编辑列表多谢编辑逻辑,优化超大源列表多选性能 +* 优化部分文本提示toast +* webView: 忽略部分网站的证书错误 +* 备份恢复webDav: 输入密码后自动验证 +* 换源添加加载字数选项 * 修复全文搜索开始bug -* 单章换源加载字数 -* 优化web端 * 其中一些更新由 Xwite, Horis, Jason Yao提供 **2023/05/03** From 9f5d1bc0d5c589bca85257718ecbe4e492e3541e Mon Sep 17 00:00:00 2001 From: kunfei Date: Mon, 8 May 2023 20:44:33 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/assets/updateLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index 9ec75f141..eb01b8984 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -18,6 +18,7 @@ * 修复全文搜索开始bug * 单章换源加载字数 * 优化web端 +* 其它一些优化 * 其中一些更新由 Xwite, Horis, Jason Yao提供 **2023/05/03** From d71a4e8ce8d0f040aa648052490acb2e80bce7b3 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 8 May 2023 21:05:13 +0800 Subject: [PATCH 09/12] [skip ci] update updateLog --- app/src/main/assets/updateLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/updateLog.md b/app/src/main/assets/updateLog.md index e0426feb3..0c4072997 100644 --- a/app/src/main/assets/updateLog.md +++ b/app/src/main/assets/updateLog.md @@ -15,7 +15,7 @@ **2023/05/08** * 更新cronet: 113.0.5672.76 -* web: 全新传书页面 [MakeHui](https://github.com/MakeHui);修正源编辑列表多谢编辑逻辑,优化超大源列表多选性能 +* web: 全新传书页面 [MakeHui](https://github.com/MakeHui);修正源编辑列表操作逻辑和多选性能 * 优化部分文本提示toast * webView: 忽略部分网站的证书错误 * 备份恢复webDav: 输入密码后自动验证 From 401020c82461b936171add1009ed39dc2ef5bc73 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Mon, 8 May 2023 22:33:12 +0800 Subject: [PATCH 10/12] =?UTF-8?q?[skip=20ci]=20wip:=20web=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=AD=97=E8=B7=9D=20=E6=AE=B5=E8=B7=9D=20=E8=A1=8C?= =?UTF-8?q?=E8=B7=9D=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/web/src/components/ChapterContent.vue | 20 ++++++++++++++++++- modules/web/src/store/bookStore.js | 7 ++++++- modules/web/src/store/sourceStore.js | 17 ++++++++++------ modules/web/src/views/BookChapter.vue | 16 ++++++--------- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/modules/web/src/components/ChapterContent.vue b/modules/web/src/components/ChapterContent.vue index 5ead981f6..cca741a08 100644 --- a/modules/web/src/components/ChapterContent.vue +++ b/modules/web/src/components/ChapterContent.vue @@ -1,4 +1,5 @@