diff --git a/app/schemas/io.legado.app.data.AppDatabase/35.json b/app/schemas/io.legado.app.data.AppDatabase/35.json index d9828072e..9e3eeb6fa 100644 --- a/app/schemas/io.legado.app.data.AppDatabase/35.json +++ b/app/schemas/io.legado.app.data.AppDatabase/35.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 35, - "identityHash": "cb54781f92ec7a911a363d0bcefa4845", + "identityHash": "25948a8defe4d091514bb725b4db7683", "entities": [ { "tableName": "books", @@ -254,7 +254,7 @@ }, { "tableName": "book_sources", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookSourceName` TEXT NOT NULL, `bookSourceGroup` TEXT, `bookSourceUrl` TEXT NOT NULL, `bookSourceType` INTEGER NOT NULL, `bookUrlPattern` TEXT, `concurrentRate` TEXT, `customOrder` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `enabledExplore` INTEGER NOT NULL, `header` TEXT, `loginUrl` TEXT, `bookSourceComment` TEXT, `lastUpdateTime` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `exploreUrl` TEXT, `ruleExplore` TEXT, `searchUrl` TEXT, `ruleSearch` TEXT, `ruleBookInfo` TEXT, `ruleToc` TEXT, `ruleContent` TEXT, PRIMARY KEY(`bookSourceUrl`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookSourceName` TEXT NOT NULL, `bookSourceGroup` TEXT, `bookSourceUrl` TEXT NOT NULL, `bookSourceType` INTEGER NOT NULL, `bookUrlPattern` TEXT, `concurrentRate` TEXT, `customOrder` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `enabledExplore` INTEGER NOT NULL, `header` TEXT, `loginUrl` TEXT, `loginUi` TEXT, `loginCheckJs` TEXT, `bookSourceComment` TEXT, `lastUpdateTime` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `exploreUrl` TEXT, `ruleExplore` TEXT, `searchUrl` TEXT, `ruleSearch` TEXT, `ruleBookInfo` TEXT, `ruleToc` TEXT, `ruleContent` TEXT, PRIMARY KEY(`bookSourceUrl`))", "fields": [ { "fieldPath": "bookSourceName", @@ -322,6 +322,18 @@ "affinity": "TEXT", "notNull": false }, + { + "fieldPath": "loginUi", + "columnName": "loginUi", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "loginCheckJs", + "columnName": "loginCheckJs", + "affinity": "TEXT", + "notNull": false + }, { "fieldPath": "bookSourceComment", "columnName": "bookSourceComment", @@ -1423,7 +1435,7 @@ "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, 'cb54781f92ec7a911a363d0bcefa4845')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '25948a8defe4d091514bb725b4db7683')" ] } } \ 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 afc847d29..7e47aefa4 100644 --- a/app/src/main/java/io/legado/app/data/AppDatabase.kt +++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt @@ -16,13 +16,13 @@ val appDb by lazy { } @Database( - version = 35, + version = 36, exportSchema = true, entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class, ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class, RssSource::class, Bookmark::class, RssArticle::class, RssReadRecord::class, RssStar::class, TxtTocRule::class, ReadRecord::class, HttpTTS::class, Cache::class, - RuleSub::class], + RuleSub::class] ) abstract class AppDatabase : RoomDatabase() { diff --git a/app/src/main/java/io/legado/app/data/DatabaseMigrations.kt b/app/src/main/java/io/legado/app/data/DatabaseMigrations.kt index e3f82759d..ba8946da4 100644 --- a/app/src/main/java/io/legado/app/data/DatabaseMigrations.kt +++ b/app/src/main/java/io/legado/app/data/DatabaseMigrations.kt @@ -31,7 +31,8 @@ object DatabaseMigrations { migration_31_32, migration_32_33, migration_33_34, - migration_34_35 + migration_34_35, + migration_35_36 ) } @@ -280,4 +281,10 @@ object DatabaseMigrations { } } + private val migration_35_36 = object : Migration(35, 36) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE `book_sources` ADD `loginUi` TEXT") + database.execSQL("ALTER TABLE `book_sources` ADD`loginCheckJs` TEXT") + } + } } \ No newline at end of file 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 fe3e41dce..3a23d3c6e 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 @@ -31,8 +31,10 @@ data class BookSource( var customOrder: Int = 0, // 手动排序编号 var enabled: Boolean = true, // 是否启用 var enabledExplore: Boolean = true, // 启用发现 - override var header: String? = null, // 请求头 - var loginUrl: LoginRule? = null, // 登录地址 + override var header: String? = null, // 请求头 + var loginUrl: String? = null, // 登录地址 + var loginUi: List? = null, //登录UI + var loginCheckJs: String? = null, //登录检测js var bookSourceComment: String? = null, // 注释 var lastUpdateTime: Long = 0, // 最后更新时间,用于排序 var weight: Int = 0, // 智能排序的权重 @@ -153,16 +155,10 @@ data class BookSource( class Converters { @TypeConverter - fun loginRuleToString(loginRule: LoginRule?): String = GSON.toJson(loginRule) + fun loginUiRuleToString(loginUi: List?): String = GSON.toJson(loginUi) @TypeConverter - fun stringToLoginRule(json: String?): LoginRule? { - return when { - json.isNullOrEmpty() -> null - json.isJsonObject() -> GSON.fromJsonObject(json) - else -> LoginRule(url = json) - } - } + fun stringToLoginRule(json: String?): List? = GSON.fromJsonArray(json) @TypeConverter fun exploreRuleToString(exploreRule: ExploreRule?): String = GSON.toJson(exploreRule) diff --git a/app/src/main/java/io/legado/app/data/entities/rule/LoginRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/LoginRule.kt deleted file mode 100644 index d0391b9f8..000000000 --- a/app/src/main/java/io/legado/app/data/entities/rule/LoginRule.kt +++ /dev/null @@ -1,20 +0,0 @@ -package io.legado.app.data.entities.rule - -import android.os.Parcelable -import kotlinx.parcelize.Parcelize - -@Parcelize -data class LoginRule( - var ui: List? = null, - var url: String? = null, //url或js,js必须使用js标记 - var checkJs: String? = null, //只能写js,不用js标记 -) : Parcelable { - - @Parcelize - data class RowUi( - var name: String, - var type: String, - ) : Parcelable - - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/data/entities/rule/RowUi.kt b/app/src/main/java/io/legado/app/data/entities/rule/RowUi.kt new file mode 100644 index 000000000..c61658594 --- /dev/null +++ b/app/src/main/java/io/legado/app/data/entities/rule/RowUi.kt @@ -0,0 +1,10 @@ +package io.legado.app.data.entities.rule + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class RowUi( + var name: String, + var type: String, +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/storage/BookSourceAnalyzer.kt b/app/src/main/java/io/legado/app/help/storage/BookSourceAnalyzer.kt index fc08222bf..62c549c10 100644 --- a/app/src/main/java/io/legado/app/help/storage/BookSourceAnalyzer.kt +++ b/app/src/main/java/io/legado/app/help/storage/BookSourceAnalyzer.kt @@ -1,6 +1,7 @@ package io.legado.app.help.storage import androidx.annotation.Keep +import com.jayway.jsonpath.JsonPath import io.legado.app.constant.AppConst import io.legado.app.constant.BookType import io.legado.app.data.entities.BookSource @@ -28,8 +29,7 @@ object BookSourceAnalyzer { bookSourceUrl = jsonItem.readString("bookSourceUrl") ?: return null bookSourceName = jsonItem.readString("bookSourceName") ?: "" bookSourceGroup = jsonItem.readString("bookSourceGroup") - loginUrl = - BookSource.Converters().stringToLoginRule(jsonItem.readString("loginUrl")) + loginUrl = jsonItem.readString("loginUrl") bookSourceComment = jsonItem.readString("bookSourceComment") ?: "" bookUrlPattern = jsonItem.readString("ruleBookUrlPattern") customOrder = jsonItem.readInt("serialNumber") ?: 0 @@ -99,10 +99,12 @@ object BookSourceAnalyzer { source.enabledExplore = sourceAny.enabledExplore source.header = sourceAny.header source.loginUrl = if (sourceAny.loginUrl is String) { - BookSource.Converters().stringToLoginRule(sourceAny.loginUrl.toString()) + sourceAny.loginUrl.toString() } else { - GSON.fromJsonObject(GSON.toJson(sourceAny.loginUrl)) + JsonPath.parse(sourceAny.loginUrl).readString("url") } + source.loginUi = sourceAny.loginUi + source.loginCheckJs = sourceAny.loginCheckJs source.bookSourceComment = sourceAny.bookSourceComment source.lastUpdateTime = sourceAny.lastUpdateTime source.weight = sourceAny.weight @@ -152,6 +154,8 @@ object BookSourceAnalyzer { var enabledExplore: Boolean = true, // 启用发现 var header: String? = null, // 请求头 var loginUrl: Any? = null, // 登录规则 + var loginUi: List? = null, //登录UI + var loginCheckJs: String? = null, //登录检测js var bookSourceComment: String? = "", //书源注释 var lastUpdateTime: Long = 0, // 最后更新时间,用于排序 var weight: Int = 0, // 智能排序的权重 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 cc525b035..cbc25b782 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 @@ -119,7 +119,7 @@ class BookInfoActivity : menu.findItem(R.id.menu_can_update)?.isChecked = viewModel.bookData.value?.canUpdate ?: true menu.findItem(R.id.menu_login)?.isVisible = - !viewModel.bookSource?.loginUrl?.url.isNullOrBlank() + !viewModel.bookSource?.loginUrl.isNullOrBlank() return super.onMenuOpened(featureId, menu) } @@ -156,7 +156,7 @@ class BookInfoActivity : R.id.menu_login -> viewModel.bookSource?.let { startActivity { putExtra("sourceUrl", it.bookSourceUrl) - putExtra("loginUrl", it.loginUrl?.url) + putExtra("loginUrl", it.loginUrl) putExtra("userAgent", it.getHeaderMap()[AppConst.UA_NAME]) } } diff --git a/app/src/main/java/io/legado/app/ui/book/login/SourceLoginDialog.kt b/app/src/main/java/io/legado/app/ui/book/login/SourceLoginDialog.kt index 564c17b3e..bed0799b5 100644 --- a/app/src/main/java/io/legado/app/ui/book/login/SourceLoginDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/login/SourceLoginDialog.kt @@ -40,8 +40,8 @@ class SourceLoginDialog : BaseDialogFragment() { val sourceUrl = arguments?.getString("sourceUrl") ?: return val bookSource = appDb.bookSourceDao.getBookSource(sourceUrl) ?: return val loginHeader = bookSource.getLoginHeader() - val loginRule = bookSource.loginUrl - loginRule?.ui?.forEachIndexed { index, rowUi -> + val loginUi = bookSource.loginUi + loginUi?.forEachIndexed { index, rowUi -> when (rowUi.type) { "text" -> layoutInflater.inflate(R.layout.item_source_edit, binding.root) .apply { @@ -67,7 +67,7 @@ class SourceLoginDialog : BaseDialogFragment() { when (it.itemId) { R.id.menu_ok -> { val loginData = hashMapOf() - loginRule?.ui?.forEachIndexed { index, rowUi -> + loginUi?.forEachIndexed { index, rowUi -> when (rowUi.type) { "text", "password" -> { val value = binding.root.findViewById(index) diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index 61b06b940..575342c5c 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -789,7 +789,7 @@ class ReadBookActivity : ReadBookBaseActivity(), ReadBook.webBook?.bookSource?.let { startActivity { putExtra("sourceUrl", it.bookSourceUrl) - putExtra("loginUrl", it.loginUrl?.url) + putExtra("loginUrl", it.loginUrl) putExtra("userAgent", it.getHeaderMap()[AppConst.UA_NAME]) } } 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 27c5b7602..179109c6c 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 @@ -284,7 +284,7 @@ class ReadMenu @JvmOverloads constructor( } fun upBookView() { - binding.tvLogin.isGone = ReadBook.webBook?.bookSource?.loginUrl?.url.isNullOrEmpty() + binding.tvLogin.isGone = ReadBook.webBook?.bookSource?.loginUrl.isNullOrEmpty() ReadBook.curTextChapter?.let { binding.tvChapterName.text = it.title binding.tvChapterName.visible() diff --git a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt index 70a119f22..97aefc952 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt @@ -41,7 +41,7 @@ class BookSourceEditActivity : override val binding by viewBinding(ActivityBookSourceEditBinding::inflate) override val viewModel by viewModels() - private val converters = BookSource.Converters() + private val adapter = BookSourceEditAdapter() private val sourceEntities: ArrayList = ArrayList() private val searchEntities: ArrayList = ArrayList() @@ -117,12 +117,12 @@ class BookSourceEditActivity : R.id.menu_help -> showRuleHelp() R.id.menu_login -> getSource().let { if (checkSource(it)) { - if (it.loginUrl?.url.isNullOrEmpty()) { + if (it.loginUrl.isNullOrEmpty()) { toastOnUi(R.string.source_no_login) } else { startActivity { putExtra("sourceUrl", it.bookSourceUrl) - putExtra("loginUrl", it.loginUrl?.url) + putExtra("loginUrl", it.loginUrl) putExtra("userAgent", it.getHeaderMap()[AppConst.UA_NAME]) } } @@ -202,7 +202,7 @@ class BookSourceEditActivity : add( EditEntity( "loginUrl", - converters.loginRuleToString(source?.loginUrl), + source?.loginUrl, R.string.login_url ) ) @@ -302,7 +302,7 @@ class BookSourceEditActivity : "bookSourceUrl" -> source.bookSourceUrl = it.value ?: "" "bookSourceName" -> source.bookSourceName = it.value ?: "" "bookSourceGroup" -> source.bookSourceGroup = it.value - "loginUrl" -> source.loginUrl = converters.stringToLoginRule(it.value) + "loginUrl" -> source.loginUrl = it.value "bookUrlPattern" -> source.bookUrlPattern = it.value "header" -> source.header = it.value "bookSourceComment" -> source.bookSourceComment = it.value ?: "" 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 840e86466..f16e0702a 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 @@ -6,8 +6,6 @@ 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.BookSourceAnalyzer -import io.legado.app.utils.GSON -import io.legado.app.utils.fromJsonObject import io.legado.app.utils.getClipText import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers @@ -54,29 +52,21 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat fun pasteSource(onSuccess: (source: BookSource) -> Unit) { execute(context = Dispatchers.Main) { - var source: BookSource? = null - context.getClipText()?.let { json -> - source = BookSourceAnalyzer.jsonToBookSource(json) + context.getClipText()?.let { text -> + importSource(text, onSuccess) } - source }.onError { - context.toastOnUi(it.localizedMessage) + context.toastOnUi(it.localizedMessage ?: "Error") it.printStackTrace() - }.onSuccess { - if (it != null) { - onSuccess(it) - } else { - context.toastOnUi("格式不对") - } } } fun importSource(text: String, finally: (source: BookSource) -> Unit) { execute { val text1 = text.trim() - GSON.fromJsonObject(text1)?.let { - finally.invoke(it) - } + BookSourceAnalyzer.jsonToBookSource(text1) + }.onSuccess { + it?.let(finally) ?: context.toastOnUi("格式不对") }.onError { context.toastOnUi(it.localizedMessage ?: "Error") }