diff --git a/app/schemas/io.legado.app.data.AppDatabase/53.json b/app/schemas/io.legado.app.data.AppDatabase/53.json new file mode 100644 index 000000000..518a1bfb7 --- /dev/null +++ b/app/schemas/io.legado.app.data.AppDatabase/53.json @@ -0,0 +1,1692 @@ +{ + "formatVersion": 1, + "database": { + "version": 53, + "identityHash": "c55dac79aa9cc3dcdb72e91da4282005", + "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 '', `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": "''" + }, + { + "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": { + "columnNames": [ + "bookUrl" + ], + "autoGenerate": false + }, + "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, `show` INTEGER NOT NULL, 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": "show", + "columnName": "show", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "groupId" + ], + "autoGenerate": false + }, + "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, `enabled` INTEGER NOT NULL, `enabledExplore` INTEGER NOT NULL, `enabledReview` INTEGER, `enabledCookieJar` INTEGER DEFAULT 0, `concurrentRate` TEXT, `header` TEXT, `loginUrl` TEXT, `loginUi` TEXT, `loginCheckJs` TEXT, `bookSourceComment` TEXT, `variableComment` TEXT, `lastUpdateTime` INTEGER NOT NULL, `respondTime` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `exploreUrl` 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 + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enabledExplore", + "columnName": "enabledExplore", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "enabledReview", + "columnName": "enabledReview", + "affinity": "INTEGER", + "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": "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": "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": { + "columnNames": [ + "bookSourceUrl" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "url", + "bookUrl" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "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, 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 + } + ], + "primaryKey": { + "columnNames": [ + "bookUrl" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "word" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "url" + ], + "autoGenerate": false + }, + "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, `enabledCookieJar` INTEGER DEFAULT 0, `concurrentRate` TEXT, `header` TEXT, `loginUrl` TEXT, `loginUi` TEXT, `loginCheckJs` TEXT, `sortUrl` TEXT, `singleUrl` INTEGER NOT NULL, `articleStyle` INTEGER NOT NULL, `ruleArticles` TEXT, `ruleNextPage` TEXT, `ruleTitle` TEXT, `rulePubDate` TEXT, `ruleDescription` TEXT, `ruleImage` TEXT, `ruleLink` TEXT, `ruleContent` TEXT, `style` TEXT, `enableJs` INTEGER NOT NULL, `loadWithBaseUrl` INTEGER NOT NULL, `customOrder` INTEGER NOT NULL, 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": "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": "sortUrl", + "columnName": "sortUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "singleUrl", + "columnName": "singleUrl", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "articleStyle", + "columnName": "articleStyle", + "affinity": "INTEGER", + "notNull": true + }, + { + "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": "style", + "columnName": "style", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "enableJs", + "columnName": "enableJs", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "loadWithBaseUrl", + "columnName": "loadWithBaseUrl", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "customOrder", + "columnName": "customOrder", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "sourceUrl" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "time" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "origin", + "link" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "record" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "origin", + "link" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "deviceId", + "bookName" + ], + "autoGenerate": false + }, + "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, `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": "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": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "key" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "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": { + "columnNames": [ + "type", + "key" + ], + "autoGenerate": false + }, + "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, 'c55dac79aa9cc3dcdb72e91da4282005')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt index b1bbf3663..761250413 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -32,6 +32,7 @@ object PreferKey { const val prevKeys = "prevKeyCodes" const val nextKeys = "nextKeyCodes" const val showDiscovery = "showDiscovery" + const val enableReview = "enableReview" const val showRss = "showRss" const val bookshelfLayout = "bookshelfLayout" const val bookshelfSort = "bookshelfSort" 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 64624717a..270614a1e 100644 --- a/app/src/main/java/io/legado/app/data/AppDatabase.kt +++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt @@ -20,7 +20,7 @@ val appDb by lazy { } @Database( - version = 52, + version = 53, exportSchema = true, entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class, ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class, @@ -36,7 +36,8 @@ val appDb by lazy { AutoMigration(from = 48, to = 49), AutoMigration(from = 49, to = 50), AutoMigration(from = 50, to = 51), - AutoMigration(from = 51, to = 52) + AutoMigration(from = 51, to = 52), + AutoMigration(from = 52, to = 53) ] ) abstract class AppDatabase : RoomDatabase() { diff --git a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt index f98063115..c9aff1b65 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookSourceDao.kt @@ -50,6 +50,9 @@ interface BookSourceDao { @Query("select * from book_sources where enabledExplore = 1 and trim(exploreUrl) <> '' order by customOrder asc") fun flowExplore(): Flow> +// @Query("select * from book_sources where enabledReview = 1 order by customOrder asc") +// fun flowReview(): Flow> + @Query("select * from book_sources where loginUrl is not null and loginUrl != ''") fun flowLogin(): Flow> diff --git a/app/src/main/java/io/legado/app/data/entities/BookChapterReview.kt b/app/src/main/java/io/legado/app/data/entities/BookChapterReview.kt new file mode 100644 index 000000000..64a838f42 --- /dev/null +++ b/app/src/main/java/io/legado/app/data/entities/BookChapterReview.kt @@ -0,0 +1,15 @@ +package io.legado.app.data.entities + +import android.os.Parcelable +import androidx.room.ColumnInfo +import kotlinx.parcelize.Parcelize + +@Parcelize +class BookChapterReview( + @ColumnInfo(defaultValue = "0") + var bookId: Long = 0, + var chapterId: Long = 0, + var summaryUrl: String = "", +): Parcelable { + +} 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 9f27a31a7..0184b8688 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 @@ -37,7 +37,9 @@ data class BookSource( // 是否启用 var enabled: Boolean = true, // 启用发现 - var enabledExplore: Boolean = true, + var enabledExplore: Boolean = false, + // 启用段评 + var enabledReview: Boolean? = false, // 启用okhttp CookieJAr 自动保存每次请求的cookie @ColumnInfo(defaultValue = "0") override var enabledCookieJar: Boolean? = false, @@ -74,7 +76,9 @@ data class BookSource( // 目录页规则 var ruleToc: TocRule? = null, // 正文页规则 - var ruleContent: ContentRule? = null + var ruleContent: ContentRule? = null, + // 段评规则 + var ruleReview: ReviewRule? = null ) : Parcelable, BaseSource { override fun getTag(): String { @@ -170,6 +174,13 @@ data class BookSource( return rule } + fun getReviewRule(): ReviewRule { + ruleReview?.let { return it } + val rule = ReviewRule() + ruleReview = rule + return rule + } + fun getDisPlayNameGroup(): String { return if (bookSourceGroup.isNullOrBlank()) { bookSourceName @@ -303,5 +314,13 @@ data class BookSource( fun stringToContentRule(json: String?) = GSON.fromJsonObject(json).getOrNull() + @TypeConverter + fun stringToReviewRule(json: String?) = + GSON.fromJsonObject(json).getOrNull() + + @TypeConverter + fun reviewRuleToString(reviewRule: ReviewRule?): String = + GSON.toJson(reviewRule) + } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/data/entities/rule/ReviewRule.kt b/app/src/main/java/io/legado/app/data/entities/rule/ReviewRule.kt new file mode 100644 index 000000000..07ff9fb32 --- /dev/null +++ b/app/src/main/java/io/legado/app/data/entities/rule/ReviewRule.kt @@ -0,0 +1,20 @@ +package io.legado.app.data.entities.rule + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class ReviewRule( + var reviewUrl: String? = null, // 段评URL + var avatarRule: String? = null, // 段评发布者头像 + var contentRule: String? = null, // 段评内容 + var postTimeRule: String? = null, // 段评发布时间 + var reviewQuoteUrl: String? = null, // 获取段评回复URL + + // 这些功能将在以上功能完成以后实现 + var voteUpUrl: String? = null, // 点赞URL + var voteDownUrl: String? = null, // 点踩URL + var postReviewUrl: String? = null, // 发送回复URL + var postQuoteUrl: String? = null, // 发送回复段评URL + var deleteUrl: String? = null, // 删除段评URL +): Parcelable diff --git a/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt b/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt index 55fcdc40d..25b80b893 100644 --- a/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt +++ b/app/src/main/java/io/legado/app/help/SourceAnalyzer.kt @@ -151,6 +151,7 @@ object SourceAnalyzer { source.enabled = sourceAny.enabled source.enabledExplore = sourceAny.enabledExplore source.enabledCookieJar = sourceAny.enabledCookieJar + source.enabledReview = sourceAny.enabledReview source.concurrentRate = sourceAny.concurrentRate source.header = sourceAny.header source.loginUrl = when (sourceAny.loginUrl) { @@ -206,6 +207,13 @@ object SourceAnalyzer { GSON.fromJsonObject(GSON.toJson(sourceAny.ruleContent)) .getOrNull() } + source.ruleReview = if (sourceAny.ruleReview is String) { + GSON.fromJsonObject(sourceAny.ruleReview.toString()) + .getOrNull() + } else { + GSON.fromJsonObject(GSON.toJson(sourceAny.ruleReview)) + .getOrNull() + } } source } @@ -221,6 +229,7 @@ object SourceAnalyzer { var customOrder: Int = 0, // 手动排序编号 var enabled: Boolean = true, // 是否启用 var enabledExplore: Boolean = true, // 启用发现 + var enabledReview: Boolean = false, // 启用段评 var enabledCookieJar: Boolean = false, // 启用CookieJar var concurrentRate: String? = null, // 并发率 var header: String? = null, // 请求头 @@ -238,7 +247,8 @@ object SourceAnalyzer { var ruleSearch: Any? = null, // 搜索规则 var ruleBookInfo: Any? = null, // 书籍信息页规则 var ruleToc: Any? = null, // 目录页规则 - var ruleContent: Any? = null // 正文页规则 + var ruleContent: Any? = null, // 正文页规则 + var ruleReview: Any? = null // 段评规则 ) // default规则适配 diff --git a/app/src/main/java/io/legado/app/help/config/AppConfig.kt b/app/src/main/java/io/legado/app/help/config/AppConfig.kt index 60ea20f46..dcc797eec 100644 --- a/app/src/main/java/io/legado/app/help/config/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/config/AppConfig.kt @@ -154,6 +154,12 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { val autoRefreshBook: Boolean get() = appCtx.getPrefBoolean(PreferKey.autoRefresh) + var enableReview: Boolean + get() = appCtx.getPrefBoolean(PreferKey.enableReview, false) + set(value) { + appCtx.putPrefBoolean(PreferKey.enableReview, value) + } + var threadCount: Int get() = appCtx.getPrefInt(PreferKey.threadCount, 16) set(value) { diff --git a/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt b/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt index 605070c0e..4b500e078 100644 --- a/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt +++ b/app/src/main/java/io/legado/app/help/config/ReadBookConfig.kt @@ -449,7 +449,7 @@ object ReadBookConfig { var letterSpacing: Float = 0.1f,//字间距 var lineSpacingExtra: Int = 12,//行间距 var paragraphSpacing: Int = 2,//段距 - var titleMode: Int = 0,//标题居中 + var titleMode: Int = 0,//标题位置 0:居左 1:居中 2:隐藏 var titleSize: Int = 0, var titleTopSpacing: Int = 0, var titleBottomSpacing: Int = 0, diff --git a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt index 7d37300a1..f80a4e0a7 100644 --- a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt +++ b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt @@ -300,6 +300,13 @@ object WebBook { } } + /** + * 获取段评 + */ + fun getReview() { + // TODO + } + /** * 精准搜索 */ 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 c4a97a1ce..3aba40f8b 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 @@ -255,6 +255,7 @@ class ReadBookActivity : BaseReadBookActivity(), else -> when (item.itemId) { R.id.menu_enable_replace -> item.isChecked = book.getUseReplaceRule() R.id.menu_re_segment -> item.isChecked = book.getReSegment() + R.id.menu_enable_review -> item.isChecked = AppConfig.enableReview R.id.menu_reverse_content -> item.isVisible = onLine } } @@ -355,6 +356,11 @@ class ReadBookActivity : BaseReadBookActivity(), menu?.findItem(R.id.menu_re_segment)?.isChecked = it.getReSegment() ReadBook.loadContent(false) } + R.id.menu_enable_review -> { + AppConfig.enableReview = !AppConfig.enableReview + menu?.findItem(R.id.menu_enable_review)?.isChecked = AppConfig.enableReview + ReadBook.loadContent(false) + } R.id.menu_page_anim -> showPageAnimConfig { binding.readView.upPageAnim() ReadBook.loadContent(false) diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt index 7408efd7d..27642ab6a 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ContentTextView.kt @@ -4,6 +4,8 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.graphics.RectF +import android.text.StaticLayout +import android.text.TextPaint import android.util.AttributeSet import android.view.View import io.legado.app.R @@ -14,10 +16,7 @@ import io.legado.app.help.config.AppConfig import io.legado.app.help.config.ReadBookConfig import io.legado.app.lib.theme.accentColor import io.legado.app.model.ReadBook -import io.legado.app.ui.book.read.page.entities.TextColumn -import io.legado.app.ui.book.read.page.entities.TextLine -import io.legado.app.ui.book.read.page.entities.TextPage -import io.legado.app.ui.book.read.page.entities.TextPos +import io.legado.app.ui.book.read.page.entities.* import io.legado.app.ui.book.read.page.provider.ChapterProvider import io.legado.app.ui.book.read.page.provider.ImageProvider import io.legado.app.ui.book.read.page.provider.TextPageFactory @@ -159,15 +158,90 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at ChapterProvider.contentPaint } val textColor = if (textLine.isReadAloud) context.accentColor else ReadBookConfig.textColor + val linePaint = Paint() + linePaint.strokeWidth = textPaint.textSize / 21 + linePaint.color = textColor + val reviewCountPaint = TextPaint() + reviewCountPaint.textSize = textPaint.textSize * 0.6F + reviewCountPaint.color = textColor textLine.textChars.forEach { - if (it.style == 1) { - drawImage(canvas, textPage, textLine, it, lineTop, lineBottom) - } else { - textPaint.color = textColor - if (it.isSearchResult) { - textPaint.color = context.accentColor + when (it.style) { + 0 -> { + textPaint.color = textColor + if (it.isSearchResult) { + textPaint.color = context.accentColor + } + canvas.drawText(it.charData, it.start, lineBase, textPaint) + } + 1 -> drawImage(canvas, textPage, textLine, it, lineTop, lineBottom) + 2 -> { + if (textLine.reviewCount <= 0) return@forEach + canvas.drawLine( + it.start, + lineBase - textPaint.textSize * 2 / 5, + it.start + textPaint.textSize / 6, + lineBase - textPaint.textSize / 4, + linePaint + ) + canvas.drawLine( + it.start, + lineBase - textPaint.textSize * 0.38F, + it.start + textPaint.textSize / 6, + lineBase - textPaint.textSize * 0.55F, + linePaint + ) + canvas.drawLine( + it.start + textPaint.textSize / 6, + lineBase - textPaint.textSize / 4, + it.start + textPaint.textSize / 6, + lineBase, + linePaint + ) + canvas.drawLine( + it.start + textPaint.textSize / 6, + lineBase - textPaint.textSize * 0.55F, + it.start + textPaint.textSize / 6, + lineBase - textPaint.textSize * 0.8F, + linePaint + ) + canvas.drawLine( + it.start + textPaint.textSize / 6, + lineBase, + it.start + textPaint.textSize * 1.6F, + lineBase, + linePaint + ) + canvas.drawLine( + it.start + textPaint.textSize / 6, + lineBase - textPaint.textSize * 0.8F, + it.start + textPaint.textSize * 1.6F, + lineBase - textPaint.textSize * 0.8F, + linePaint + ) + canvas.drawLine( + it.start + textPaint.textSize * 1.6F, + lineBase - textPaint.textSize * 0.8F, + it.start + textPaint.textSize * 1.6F, + lineBase, + linePaint + ) + if (textLine.reviewCount < 100) canvas.drawText( + textLine.reviewCount.toString(), + it.start + textPaint.textSize * 0.87F - + StaticLayout.getDesiredWidth( + textLine.reviewCount.toString(), + reviewCountPaint + ) / 2, + lineBase - textPaint.textSize / 6, + reviewCountPaint + ) + else canvas.drawText( + "99+", + it.start + textPaint.textSize * 0.35F, + lineBase - textPaint.textSize / 6, + reviewCountPaint + ) } - canvas.drawText(it.charData, it.start, lineBase, textPaint) } if (it.selected) { canvas.drawRect(it.start, lineTop, it.end, lineBottom, selectedPaint) @@ -283,12 +357,13 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at y: Float, select: (textPos: TextPos) -> Unit, ) { - touch(x, y) { _, textPos, _, _, textChar -> - if (textChar.style == 1) { - callBack.onImageLongPress(x, y, textChar.charData) + touch(x, y) { _, textPos, _, _, textColumn -> + if (textColumn.style == 2) return@touch + if (textColumn.style == 1) { + callBack.onImageLongPress(x, y, textColumn.charData) } else { if (!selectAble) return@touch - textChar.selected = true + textColumn.selected = true invalidate() select(textPos) } @@ -300,10 +375,14 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at * @return true:已处理, false:未处理 */ fun click(x: Float, y: Float): Boolean { - touch(x, y) { _, textPos, textPage, textLine, textChar -> - + var handled = false + touch(x, y) { _, textPos, textPage, textLine, textColumn -> + if (textColumn.style == 2) { + context.toastOnUi("Button Pressed!") + handled = true + } } - return false + return handled } /** @@ -314,8 +393,9 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at y: Float, select: (textPos: TextPos) -> Unit, ) { - touch(x, y) { _, textPos, _, _, textChar -> - textChar.selected = true + touch(x, y) { _, textPos, _, _, textColumn -> + if (textColumn.style == 2) return@touch + textColumn.selected = true invalidate() select(textPos) } @@ -437,6 +517,7 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at textPos.lineIndex = lineIndex for ((charIndex, textChar) in textLine.textChars.withIndex()) { textPos.charIndex = charIndex + if (textChar.style == 2) continue textChar.selected = textPos.compare(selectStart) >= 0 && textPos.compare(selectEnd) <= 0 textChar.isSearchResult = textChar.selected && callBack.isSelectingSearchResult diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt b/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt index 3ac543f11..b2218c710 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/ReadView.kt @@ -28,6 +28,7 @@ import io.legado.app.ui.book.read.page.provider.TextPageFactory import io.legado.app.utils.activity import io.legado.app.utils.invisible import io.legado.app.utils.screenshot +import io.legado.app.utils.toastOnUi import java.text.BreakIterator import java.util.* import kotlin.math.abs diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt index 28ac5b24f..076c1bc2f 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/entities/TextLine.kt @@ -11,6 +11,7 @@ import io.legado.app.utils.textHeight data class TextLine( var text: String = "", val textChars: ArrayList = arrayListOf(), + val reviewCount: Int = 0, var lineTop: Float = 0f, var lineBase: Float = 0f, var lineBottom: Float = 0f, 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 a69483ab2..9c9446860 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 @@ -114,7 +114,12 @@ data class TextPage( val cw = StaticLayout.getDesiredWidth(char, ChapterProvider.contentPaint) val x1 = x + cw textLine.textChars.add( - TextColumn(char, start = x, end = x1) + TextColumn( + char, + start = x, + end = x1, + style = if (textLine.text.length - 1 == index && char == "\uD83D\uDCAC") 2 else 0 + ) ) x = x1 } 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 185d251e6..8dd49e208 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 @@ -116,7 +116,13 @@ object ChapterProvider { if (ReadBookConfig.titleMode != 2) { displayTitle.splitNotBlank("\n").forEach { text -> setTypeText( - book, absStartX, durY, text, textPages, stringBuilder, titlePaint, + book, + absStartX, + durY, + if (AppConfig.enableReview) text + "\ud83d\udcac" else text, + textPages, + stringBuilder, + titlePaint, isTitle = true, isTitleWithNoContent = contents.isEmpty(), isVolumeTitle = bookChapter.isVolume @@ -171,7 +177,13 @@ object ChapterProvider { val text = content.substring(start, content.length) if (text.isNotBlank()) { setTypeText( - book, absStartX, durY, text, textPages, stringBuilder, contentPaint + book, + absStartX, + durY, + if (AppConfig.enableReview) text + "\ud83d\udcac" else text, + textPages, + stringBuilder, + contentPaint ).let { absStartX = it.first durY = it.second @@ -276,9 +288,8 @@ object ChapterProvider { srcList: LinkedList? = null ): Pair { var absStartX = x - val layout = if (ReadBookConfig.useZhLayout) { - ZhLayout(text, textPaint, visibleWidth) - } else StaticLayout( + val layout = if (ReadBookConfig.useZhLayout) ZhLayout(text, textPaint, visibleWidth) + else StaticLayout( text, textPaint, visibleWidth, Layout.Alignment.ALIGN_NORMAL, 0f, 0f, true ) var durY = when { @@ -398,10 +409,14 @@ object ChapterProvider { } val bodyIndent = ReadBookConfig.paragraphIndent val icw = StaticLayout.getDesiredWidth(bodyIndent, textPaint) / bodyIndent.length - bodyIndent.toStringArray().forEach { char -> + for (char in bodyIndent.toStringArray()) { val x1 = x + icw textLine.textChars.add( - TextColumn(charData = char, start = absStartX + x, end = absStartX + x1) + TextColumn( + charData = char, + start = absStartX + x, + end = absStartX + x1 + ) ) x = x1 } @@ -436,7 +451,7 @@ object ChapterProvider { words.forEachIndexed { index, char -> val cw = StaticLayout.getDesiredWidth(char, textPaint) val x1 = if (index != words.lastIndex) (x + cw + d) else (x + cw) - addCharToLine(book, absStartX, textLine, char, x, x1, srcList) + addCharToLine(book, absStartX, textLine, char, x, x1, index + 1 == words.size, srcList) x = x1 } exceed(absStartX, textLine, words) @@ -455,10 +470,10 @@ object ChapterProvider { srcList: LinkedList? ) { var x = startX - words.forEach { char -> + words.forEachIndexed { index, char -> val cw = StaticLayout.getDesiredWidth(char, textPaint) val x1 = x + cw - addCharToLine(book, absStartX, textLine, char, x, x1, srcList) + addCharToLine(book, absStartX, textLine, char, x, x1, index + 1 == words.size, srcList) x = x1 } exceed(absStartX, textLine, words) @@ -474,6 +489,7 @@ object ChapterProvider { char: String, xStart: Float, xEnd: Float, + isLineEnd: Boolean, srcList: LinkedList? ) { if (srcList != null && char == srcReplaceChar) { @@ -492,7 +508,8 @@ object ChapterProvider { TextColumn( charData = char, start = absStartX + xStart, - end = absStartX + xEnd + end = absStartX + xEnd, + style = if (isLineEnd && char == "\uD83D\uDCAC") 2 else 0 ) ) } @@ -612,12 +629,12 @@ object ChapterProvider { * 更新绘制尺寸 */ fun upLayout() { - when(AppConfig.doublePageHorizontal){ + when (AppConfig.doublePageHorizontal) { "0" -> doublePage = false "1" -> doublePage = true "2" -> { doublePage = (viewWidth > viewHeight) - && ReadBook.pageAnim() != 3 + && ReadBook.pageAnim() != 3 } } 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 da0d39aac..b1e799e51 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,10 +41,11 @@ class BookSourceEditActivity : private val adapter by lazy { BookSourceEditAdapter() } private val sourceEntities: ArrayList = ArrayList() private val searchEntities: ArrayList = ArrayList() - private val findEntities: ArrayList = ArrayList() + private val exploreEntities: ArrayList = ArrayList() private val infoEntities: ArrayList = ArrayList() private val tocEntities: ArrayList = ArrayList() private val contentEntities: ArrayList = ArrayList() + private val reviewEntities: ArrayList = ArrayList() private val qrCodeResult = registerForActivityResult(QrCodeResult()) { it ?: return@registerForActivityResult viewModel.importSource(it) { source -> @@ -180,10 +181,11 @@ class BookSourceEditActivity : private fun setEditEntities(tabPosition: Int?) { when (tabPosition) { 1 -> adapter.editEntities = searchEntities - 2 -> adapter.editEntities = findEntities + 2 -> adapter.editEntities = exploreEntities 3 -> adapter.editEntities = infoEntities 4 -> adapter.editEntities = tocEntities 5 -> adapter.editEntities = contentEntities + 6 -> adapter.editEntities = reviewEntities else -> adapter.editEntities = sourceEntities } binding.recyclerView.scrollToPosition(0) @@ -192,8 +194,9 @@ class BookSourceEditActivity : private fun upSourceView(source: BookSource? = viewModel.bookSource) { source?.let { binding.cbIsEnable.isChecked = it.enabled - binding.cbIsEnableFind.isChecked = it.enabledExplore + binding.cbIsEnableExplore.isChecked = it.enabledExplore binding.cbIsEnableCookie.isChecked = it.enabledCookieJar ?: false + binding.cbIsEnableReview.isChecked = it.enabledReview ?: false binding.spType.setSelection( when (it.bookSourceType) { BookType.file -> 3 @@ -203,7 +206,7 @@ class BookSourceEditActivity : } ) } - //基本信息 + // 基本信息 sourceEntities.clear() sourceEntities.apply { add(EditEntity("bookSourceUrl", source?.bookSourceUrl, R.string.source_url)) @@ -218,7 +221,7 @@ class BookSourceEditActivity : add(EditEntity("variableComment", source?.variableComment, R.string.variable_comment)) add(EditEntity("concurrentRate", source?.concurrentRate, R.string.concurrent_rate)) } - //搜索 + // 搜索 val sr = source?.getSearchRule() searchEntities.clear() searchEntities.apply { @@ -234,10 +237,10 @@ class BookSourceEditActivity : add(EditEntity("coverUrl", sr?.coverUrl, R.string.rule_cover_url)) add(EditEntity("bookUrl", sr?.bookUrl, R.string.r_book_url)) } - //发现 + // 发现 val er = source?.getExploreRule() - findEntities.clear() - findEntities.apply { + exploreEntities.clear() + exploreEntities.apply { add(EditEntity("exploreUrl", source?.exploreUrl, R.string.r_find_url)) add(EditEntity("bookList", er?.bookList, R.string.r_book_list)) add(EditEntity("name", er?.name, R.string.r_book_name)) @@ -249,7 +252,7 @@ class BookSourceEditActivity : add(EditEntity("coverUrl", er?.coverUrl, R.string.rule_cover_url)) add(EditEntity("bookUrl", er?.bookUrl, R.string.r_book_url)) } - //详情页 + // 详情页 val ir = source?.getBookInfoRule() infoEntities.clear() infoEntities.apply { @@ -265,7 +268,7 @@ class BookSourceEditActivity : add(EditEntity("canReName", ir?.canReName, R.string.rule_can_re_name)) add(EditEntity("downloadUrls", ir?.downloadUrls, R.string.download_url_rule)) } - //目录页 + // 目录页 val tr = source?.getTocRule() tocEntities.clear() tocEntities.apply { @@ -279,7 +282,7 @@ class BookSourceEditActivity : add(EditEntity("isPay", tr?.isPay, R.string.rule_is_pay)) add(EditEntity("nextTocUrl", tr?.nextTocUrl, R.string.rule_next_toc_url)) } - //正文页 + // 正文页 val cr = source?.getContentRule() contentEntities.clear() contentEntities.apply { @@ -291,6 +294,21 @@ class BookSourceEditActivity : add(EditEntity("imageStyle", cr?.imageStyle, R.string.rule_image_style)) add(EditEntity("payAction", cr?.payAction, R.string.rule_pay_action)) } + // 段评 + val rr = source?.getReviewRule() + reviewEntities.clear() + reviewEntities.apply { + add(EditEntity("reviewUrl", rr?.reviewUrl, R.string.rule_review_url)) + add(EditEntity("avatarRule", rr?.avatarRule, R.string.rule_avatar)) + add(EditEntity("contentRule", rr?.contentRule, R.string.rule_review_content)) + add(EditEntity("postTimeRule", rr?.postTimeRule, R.string.rule_post_time)) + add(EditEntity("reviewQuoteUrl", rr?.reviewQuoteUrl, R.string.rule_review_quote)) + add(EditEntity("voteUpUrl", rr?.voteUpUrl, R.string.review_vote_up)) + add(EditEntity("voteDownUrl", rr?.voteDownUrl, R.string.review_vote_down)) + add(EditEntity("postReviewUrl", rr?.postReviewUrl, R.string.post_review_url)) + add(EditEntity("postQuoteUrl", rr?.postQuoteUrl, R.string.post_quote_url)) + add(EditEntity("deleteUrl", rr?.deleteUrl, R.string.delete_review_url)) + } binding.tabLayout.selectTab(binding.tabLayout.getTabAt(0)) setEditEntities(0) } @@ -298,8 +316,9 @@ class BookSourceEditActivity : private fun getSource(): BookSource { val source = viewModel.bookSource?.copy() ?: BookSource() source.enabled = binding.cbIsEnable.isChecked - source.enabledExplore = binding.cbIsEnableFind.isChecked + source.enabledExplore = binding.cbIsEnableExplore.isChecked source.enabledCookieJar = binding.cbIsEnableCookie.isChecked + source.enabledReview = binding.cbIsEnableReview.isChecked source.bookSourceType = when (binding.spType.selectedItemPosition) { 3 -> BookType.file 2 -> BookType.image @@ -311,6 +330,7 @@ class BookSourceEditActivity : val bookInfoRule = BookInfoRule() val tocRule = TocRule() val contentRule = ContentRule() + val reviewRule = ReviewRule() sourceEntities.forEach { when (it.key) { "bookSourceUrl" -> source.bookSourceUrl = it.value ?: "" @@ -351,7 +371,7 @@ class BookSourceEditActivity : viewModel.ruleComplete(it.value, searchRule.bookList, 2) } } - findEntities.forEach { + exploreEntities.forEach { when (it.key) { "exploreUrl" -> source.exploreUrl = it.value "bookList" -> exploreRule.bookList = it.value @@ -429,11 +449,30 @@ class BookSourceEditActivity : "payAction" -> contentRule.payAction = it.value } } + reviewEntities.forEach { + when (it.key) { + "reviewUrl" -> reviewRule.reviewUrl = it.value + "avatarRule" -> reviewRule.avatarRule = + viewModel.ruleComplete(it.value, reviewRule.reviewUrl, 3) + "contentRule" -> reviewRule.contentRule = + viewModel.ruleComplete(it.value, reviewRule.reviewUrl) + "postTimeRule" -> reviewRule.postTimeRule = + viewModel.ruleComplete(it.value, reviewRule.reviewUrl) + "reviewQuoteUrl" -> reviewRule.reviewQuoteUrl = + viewModel.ruleComplete(it.value, reviewRule.reviewUrl, 2) + "voteUpUrl" -> reviewRule.voteUpUrl = it.value + "voteDownUrl" -> reviewRule.voteDownUrl = it.value + "postReviewUrl" -> reviewRule.postReviewUrl = it.value + "postQuoteUrl" -> reviewRule.postQuoteUrl = it.value + "deleteUrl" -> reviewRule.deleteUrl =it.value + } + } source.ruleSearch = searchRule source.ruleExplore = exploreRule source.ruleBookInfo = bookInfoRule source.ruleToc = tocRule source.ruleContent = contentRule + source.ruleReview = reviewRule return source } diff --git a/app/src/main/res/layout/activity_book_source_edit.xml b/app/src/main/res/layout/activity_book_source_edit.xml index ceae414f2..bed6d5a36 100644 --- a/app/src/main/res/layout/activity_book_source_edit.xml +++ b/app/src/main/res/layout/activity_book_source_edit.xml @@ -27,7 +27,7 @@ android:text="@string/is_enable" /> - + + + + + @@ -94,6 +109,11 @@ android:layout_height="wrap_content" android:text="@string/source_tab_content" /> + + + + 选中所选区间 返回时提示放入书架 阅读未放入书架的书籍在返回时提示放入书架 + Review + 段评URL(reviewUrl) + 段评发布者头像(avatarRule) + 段评内容(contentRule) + 段评回复URL(reviewQuoteUrl) + 段评发布时间(postTimeRule) + 点踩URL(voteUpUrl) + 点赞URL(voteDownUrl) + 发送回复URL(postReviewUrl) + 发送回复段评URL(postQuoteUrl) + 删除段评URL(deleteUrl) 标志:发现已启用 标志:发现已禁用 diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index c6c3c0521..fc16ac653 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -1013,6 +1013,17 @@ 选中所选区间 返回时提示放入书架 阅读未放入书架的书籍在返回时提示放入书架 + Review + 段评URL(reviewUrl) + 段评发布者头像(avatarRule) + 段评内容(contentRule) + 段评发布时间(postTimeRule) + 段评回复URL(reviewQuoteUrl) + 点踩URL(voteUpUrl) + 点赞URL(voteDownUrl) + 发送回复URL(postReviewUrl) + 发送回复段评URL(postQuoteUrl) + 删除段评URL(deleteUrl) 标志:发现已启用 标志:发现已禁用 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d126d2470..c13a06ddb 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1013,6 +1013,17 @@ 选中所选区间 返回时提示放入书架 阅读未放入书架的书籍在返回时提示放入书架 + Review + 段评URL(reviewUrl) + 段评发布者头像(avatarRule) + 段评内容(contentRule) + 段评发布时间(postTimeRule) + 段评回复URL(reviewQuoteUrl) + 点踩URL(voteUpUrl) + 点赞URL(voteDownUrl) + 发送回复URL(postReviewUrl) + 发送回复段评URL(postQuoteUrl) + 删除段评URL(deleteUrl) 标志:发现已启用 标志:发现已禁用 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 518017c67..e364dce4a 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -1010,6 +1010,17 @@ 选中所选区间 返回时提示放入书架 阅读未放入书架的书籍在返回时提示放入书架 + 段评 + 段评URL(reviewUrl) + 段评发布者头像(avatarRule) + 段评内容(contentRule) + 段评发布时间(postTimeRule) + 段评回复URL(reviewQuoteUrl) + 点踩URL(voteUpUrl) + 点赞URL(voteDownUrl) + 发送回复URL(postReviewUrl) + 发送回复段评URL(postQuoteUrl) + 删除段评URL(deleteUrl) 标志:发现已启用 标志:发现已禁用 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index eb43ecdbc..9ac1be71c 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1012,6 +1012,17 @@ 选中所选区间 返回时提示放入书架 阅读未放入书架的书籍在返回时提示放入书架 + 段评 + 段评URL(reviewUrl) + 段评发布者头像(avatarRule) + 段评内容(contentRule) + 段评发布时间(postTimeRule) + 段评回复URL(reviewQuoteUrl) + 点踩URL(voteUpUrl) + 点赞URL(voteDownUrl) + 发送回复URL(postReviewUrl) + 发送回复段评URL(postQuoteUrl) + 删除段评URL(deleteUrl) 标志:发现已启用 标志:发现已禁用 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index db2a80a04..9c67824ab 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1012,6 +1012,17 @@ 选中所选区间 返回时提示放入书架 阅读未放入书架的书籍在返回时提示放入书架 + 段评 + 段评URL(reviewUrl) + 段评发布者头像(avatarRule) + 段评内容(contentRule) + 段评发布时间(postTimeRule) + 段评回复URL(reviewQuoteUrl) + 点踩URL(voteUpUrl) + 点赞URL(voteDownUrl) + 发送回复URL(postReviewUrl) + 发送回复段评URL(postQuoteUrl) + 删除段评URL(deleteUrl) 标志:发现已启用 标志:发现已禁用 diff --git a/app/src/main/res/values/non_translat.xml b/app/src/main/res/values/non_translat.xml index 14d5c13bd..2b6917391 100644 --- a/app/src/main/res/values/non_translat.xml +++ b/app/src/main/res/values/non_translat.xml @@ -1,25 +1,25 @@ - bookshelf_px - 开源阅读 - kunfei.ge@gmail.com + bookshelf_px + 开源阅读 + kunfei.ge@gmail.com - https://alanskycn.gitee.io/teachme/ - https://github.com/gedoor/legado - https://github.com/gedoor/legado/graphs/contributors - https://gedoor.github.io - https://github.com/gedoor/legado/blob/master/LICENSE - https://github.com/gedoor/legado/releases/latest - https://api.github.com/repos/gedoor/legado/releases/latest - https://t.me/legado_channels - https://discord.gg/qDE52P5xGW + https://alanskycn.gitee.io/teachme/ + https://github.com/gedoor/legado + https://github.com/gedoor/legado/graphs/contributors + https://gedoor.github.io + https://github.com/gedoor/legado/blob/master/LICENSE + https://github.com/gedoor/legado/releases/latest + https://api.github.com/repos/gedoor/legado/releases/latest + https://t.me/legado_channels + https://discord.gg/qDE52P5xGW - http://%1$s:%2$d - GitHub - 【%s】 - 🔒%s - 🔓%s + http://%1$s:%2$d + GitHub + 【%s】 + 🔒%s + 🔓%s - + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f78e4c912..8c6dd9cac 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1013,6 +1013,17 @@ 选中所选区间 返回时提示放入书架 阅读未放入书架的书籍在返回时提示放入书架 + Review + 段评发布者头像(avatarRule) + 段评URL(reviewUrl) + 段评内容(contentRule) + 段评发布时间(postTimeRule) + 段评回复URL(reviewQuoteUrl) + 点踩URL(voteUpUrl) + 点赞URL(voteDownUrl) + 发送回复URL(postReviewUrl) + 发送回复段评URL(postQuoteUrl) + 删除段评URL(deleteUrl) 标志:发现已启用 标志:发现已禁用