ソースを参照

refactor: 优化朗读引擎与知识入口

HapeLee 3 ヶ月 前
親
コミット
5067c384e1
20 ファイル変更、1016 行追加、9199 行削除
  1. 582 2
      app/schemas/io.legado.app.data.AppDatabase/95.json
  2. 0 4408
      app/schemas/io.legado.app.data.AppDatabase/96.json
  3. 0 4518
      app/schemas/io.legado.app.data.AppDatabase/97.json
  4. 2 4
      app/src/main/java/io/legado/app/data/AppDatabase.kt
  5. 1 1
      app/src/main/java/io/legado/app/ui/book/import/local/ImportBookScreen.kt
  6. 24 18
      app/src/main/java/io/legado/app/ui/book/info/BookInfoScreen.kt
  7. 14 1
      app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt
  8. 83 4
      app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt
  9. 2 1
      app/src/main/java/io/legado/app/ui/book/knowledge/CharacterAvatarCropDialog.kt
  10. 2 1
      app/src/main/java/io/legado/app/ui/book/read/sheet/AutoReadSheet.kt
  11. 1 1
      app/src/main/java/io/legado/app/ui/book/read/sheet/ContentProcessesSheet.kt
  12. 2 1
      app/src/main/java/io/legado/app/ui/book/read/sheet/PaddingConfigSheet.kt
  13. 1 2
      app/src/main/java/io/legado/app/ui/book/read/sheet/ReadAloudConfigSheet.kt
  14. 4 4
      app/src/main/java/io/legado/app/ui/book/readaloud/casting/BookVoiceCastingScreen.kt
  15. 2 0
      app/src/main/java/io/legado/app/ui/book/readaloud/cloudtts/CloudTtsContract.kt
  16. 284 227
      app/src/main/java/io/legado/app/ui/book/readaloud/cloudtts/CloudTtsScreen.kt
  17. 8 2
      app/src/main/java/io/legado/app/ui/book/readaloud/cloudtts/CloudTtsViewModel.kt
  18. 1 1
      app/src/main/java/io/legado/app/ui/book/toc/rule/preview/TxtTocRulePreviewScreen.kt
  19. 2 2
      app/src/main/java/io/legado/app/ui/config/ai/prompt/AiPromptConfigScreen.kt
  20. 1 1
      app/src/main/java/io/legado/app/ui/config/coverConfig/CoverAlbumManageScreen.kt

+ 582 - 2
app/schemas/io.legado.app.data.AppDatabase/95.json

@@ -2,7 +2,7 @@
   "formatVersion": 1,
   "database": {
     "version": 95,
-    "identityHash": "9087640670cf6cbc3be250a569ed106e",
+    "identityHash": "f5e225667da6bf6e50b9435bfb2ffb6d",
     "entities": [
       {
         "tableName": "books",
@@ -3922,6 +3922,586 @@
             "createSql": "CREATE INDEX IF NOT EXISTS `index_book_outline_nodes_bookUrl_parentId_order` ON `${TABLE_NAME}` (`bookUrl`, `parentId`, `order`)"
           }
         ]
+      },
+      {
+        "tableName": "read_aloud_voices",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `engineType` TEXT NOT NULL, `engineId` TEXT NOT NULL DEFAULT '', `speakerId` TEXT NOT NULL DEFAULT '', `displayName` TEXT NOT NULL, `traitsJson` TEXT NOT NULL DEFAULT '[]', `emotionCatalogJson` TEXT NOT NULL DEFAULT '[]', `managedBy` TEXT NOT NULL DEFAULT 'user', `enabled` INTEGER NOT NULL DEFAULT 1, `available` INTEGER NOT NULL DEFAULT 1, `revision` INTEGER NOT NULL DEFAULT 0, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "engineType",
+            "columnName": "engineType",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "engineId",
+            "columnName": "engineId",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "speakerId",
+            "columnName": "speakerId",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "displayName",
+            "columnName": "displayName",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "traitsJson",
+            "columnName": "traitsJson",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "'[]'"
+          },
+          {
+            "fieldPath": "emotionCatalogJson",
+            "columnName": "emotionCatalogJson",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "'[]'"
+          },
+          {
+            "fieldPath": "managedBy",
+            "columnName": "managedBy",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "'user'"
+          },
+          {
+            "fieldPath": "enabled",
+            "columnName": "enabled",
+            "affinity": "INTEGER",
+            "notNull": true,
+            "defaultValue": "1"
+          },
+          {
+            "fieldPath": "available",
+            "columnName": "available",
+            "affinity": "INTEGER",
+            "notNull": true,
+            "defaultValue": "1"
+          },
+          {
+            "fieldPath": "revision",
+            "columnName": "revision",
+            "affinity": "INTEGER",
+            "notNull": true,
+            "defaultValue": "0"
+          },
+          {
+            "fieldPath": "createdAt",
+            "columnName": "createdAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "updatedAt",
+            "columnName": "updatedAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [
+          {
+            "name": "index_read_aloud_voices_engineType_engineId_speakerId",
+            "unique": true,
+            "columnNames": [
+              "engineType",
+              "engineId",
+              "speakerId"
+            ],
+            "orders": [],
+            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_read_aloud_voices_engineType_engineId_speakerId` ON `${TABLE_NAME}` (`engineType`, `engineId`, `speakerId`)"
+          },
+          {
+            "name": "index_read_aloud_voices_enabled_displayName",
+            "unique": false,
+            "columnNames": [
+              "enabled",
+              "displayName"
+            ],
+            "orders": [],
+            "createSql": "CREATE INDEX IF NOT EXISTS `index_read_aloud_voices_enabled_displayName` ON `${TABLE_NAME}` (`enabled`, `displayName`)"
+          }
+        ]
+      },
+      {
+        "tableName": "book_voice_bindings",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookUrl` TEXT NOT NULL, `subjectType` TEXT NOT NULL, `subjectId` TEXT NOT NULL, `voiceId` TEXT NOT NULL, `locked` INTEGER NOT NULL DEFAULT 0, `source` TEXT NOT NULL DEFAULT 'user', `confidence` REAL NOT NULL DEFAULT 1, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`bookUrl`, `subjectType`, `subjectId`))",
+        "fields": [
+          {
+            "fieldPath": "bookUrl",
+            "columnName": "bookUrl",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "subjectType",
+            "columnName": "subjectType",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "subjectId",
+            "columnName": "subjectId",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "voiceId",
+            "columnName": "voiceId",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "locked",
+            "columnName": "locked",
+            "affinity": "INTEGER",
+            "notNull": true,
+            "defaultValue": "0"
+          },
+          {
+            "fieldPath": "source",
+            "columnName": "source",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "'user'"
+          },
+          {
+            "fieldPath": "confidence",
+            "columnName": "confidence",
+            "affinity": "REAL",
+            "notNull": true,
+            "defaultValue": "1"
+          },
+          {
+            "fieldPath": "createdAt",
+            "columnName": "createdAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "updatedAt",
+            "columnName": "updatedAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "bookUrl",
+            "subjectType",
+            "subjectId"
+          ]
+        },
+        "indices": [
+          {
+            "name": "index_book_voice_bindings_bookUrl_subjectType",
+            "unique": false,
+            "columnNames": [
+              "bookUrl",
+              "subjectType"
+            ],
+            "orders": [],
+            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_voice_bindings_bookUrl_subjectType` ON `${TABLE_NAME}` (`bookUrl`, `subjectType`)"
+          },
+          {
+            "name": "index_book_voice_bindings_voiceId",
+            "unique": false,
+            "columnNames": [
+              "voiceId"
+            ],
+            "orders": [],
+            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_voice_bindings_voiceId` ON `${TABLE_NAME}` (`voiceId`)"
+          }
+        ]
+      },
+      {
+        "tableName": "chapter_speech_analysis",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `contentHash` TEXT NOT NULL, `resolverVersion` TEXT NOT NULL, `characterRevision` TEXT NOT NULL DEFAULT '', `status` TEXT NOT NULL DEFAULT 'pending', `error` TEXT NOT NULL DEFAULT '', `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "bookUrl",
+            "columnName": "bookUrl",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "chapterIndex",
+            "columnName": "chapterIndex",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "contentHash",
+            "columnName": "contentHash",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "resolverVersion",
+            "columnName": "resolverVersion",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "characterRevision",
+            "columnName": "characterRevision",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "status",
+            "columnName": "status",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "'pending'"
+          },
+          {
+            "fieldPath": "error",
+            "columnName": "error",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "createdAt",
+            "columnName": "createdAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "updatedAt",
+            "columnName": "updatedAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [
+          {
+            "name": "index_chapter_speech_analysis_bookUrl_chapterIndex_contentHash_resolverVersion",
+            "unique": true,
+            "columnNames": [
+              "bookUrl",
+              "chapterIndex",
+              "contentHash",
+              "resolverVersion"
+            ],
+            "orders": [],
+            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapter_speech_analysis_bookUrl_chapterIndex_contentHash_resolverVersion` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `contentHash`, `resolverVersion`)"
+          },
+          {
+            "name": "index_chapter_speech_analysis_bookUrl_chapterIndex_updatedAt",
+            "unique": false,
+            "columnNames": [
+              "bookUrl",
+              "chapterIndex",
+              "updatedAt"
+            ],
+            "orders": [],
+            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_analysis_bookUrl_chapterIndex_updatedAt` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `updatedAt`)"
+          }
+        ]
+      },
+      {
+        "tableName": "chapter_speech_segments",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `analysisId` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `paragraphIndex` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `chapterPosition` INTEGER NOT NULL, `text` TEXT NOT NULL, `roleType` TEXT NOT NULL, `characterId` TEXT, `characterName` TEXT NOT NULL DEFAULT '', `emotion` TEXT NOT NULL DEFAULT '', `confidence` REAL NOT NULL DEFAULT 0, `source` TEXT NOT NULL, `userLocked` INTEGER NOT NULL DEFAULT 0, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "analysisId",
+            "columnName": "analysisId",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "bookUrl",
+            "columnName": "bookUrl",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "chapterIndex",
+            "columnName": "chapterIndex",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "paragraphIndex",
+            "columnName": "paragraphIndex",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "start",
+            "columnName": "start",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "end",
+            "columnName": "end",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "chapterPosition",
+            "columnName": "chapterPosition",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "text",
+            "columnName": "text",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "roleType",
+            "columnName": "roleType",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "characterId",
+            "columnName": "characterId",
+            "affinity": "TEXT"
+          },
+          {
+            "fieldPath": "characterName",
+            "columnName": "characterName",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "emotion",
+            "columnName": "emotion",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "confidence",
+            "columnName": "confidence",
+            "affinity": "REAL",
+            "notNull": true,
+            "defaultValue": "0"
+          },
+          {
+            "fieldPath": "source",
+            "columnName": "source",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "userLocked",
+            "columnName": "userLocked",
+            "affinity": "INTEGER",
+            "notNull": true,
+            "defaultValue": "0"
+          },
+          {
+            "fieldPath": "createdAt",
+            "columnName": "createdAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "updatedAt",
+            "columnName": "updatedAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [
+          {
+            "name": "index_chapter_speech_segments_analysisId_paragraphIndex_start_end",
+            "unique": true,
+            "columnNames": [
+              "analysisId",
+              "paragraphIndex",
+              "start",
+              "end"
+            ],
+            "orders": [],
+            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapter_speech_segments_analysisId_paragraphIndex_start_end` ON `${TABLE_NAME}` (`analysisId`, `paragraphIndex`, `start`, `end`)"
+          },
+          {
+            "name": "index_chapter_speech_segments_bookUrl_chapterIndex_paragraphIndex",
+            "unique": false,
+            "columnNames": [
+              "bookUrl",
+              "chapterIndex",
+              "paragraphIndex"
+            ],
+            "orders": [],
+            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_segments_bookUrl_chapterIndex_paragraphIndex` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `paragraphIndex`)"
+          },
+          {
+            "name": "index_chapter_speech_segments_characterId",
+            "unique": false,
+            "columnNames": [
+              "characterId"
+            ],
+            "orders": [],
+            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_segments_characterId` ON `${TABLE_NAME}` (`characterId`)"
+          }
+        ]
+      },
+      {
+        "tableName": "cloud_tts_engines",
+        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `provider` TEXT NOT NULL, `baseUrl` TEXT NOT NULL DEFAULT '', `apiKey` TEXT NOT NULL DEFAULT '', `secretKey` TEXT NOT NULL DEFAULT '', `region` TEXT NOT NULL DEFAULT '', `appId` TEXT NOT NULL DEFAULT '', `model` TEXT NOT NULL DEFAULT '', `optionsJson` TEXT NOT NULL DEFAULT '{}', `enabled` INTEGER NOT NULL DEFAULT 1, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
+        "fields": [
+          {
+            "fieldPath": "id",
+            "columnName": "id",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "name",
+            "columnName": "name",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "provider",
+            "columnName": "provider",
+            "affinity": "TEXT",
+            "notNull": true
+          },
+          {
+            "fieldPath": "baseUrl",
+            "columnName": "baseUrl",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "apiKey",
+            "columnName": "apiKey",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "secretKey",
+            "columnName": "secretKey",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "region",
+            "columnName": "region",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "appId",
+            "columnName": "appId",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "model",
+            "columnName": "model",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "''"
+          },
+          {
+            "fieldPath": "optionsJson",
+            "columnName": "optionsJson",
+            "affinity": "TEXT",
+            "notNull": true,
+            "defaultValue": "'{}'"
+          },
+          {
+            "fieldPath": "enabled",
+            "columnName": "enabled",
+            "affinity": "INTEGER",
+            "notNull": true,
+            "defaultValue": "1"
+          },
+          {
+            "fieldPath": "createdAt",
+            "columnName": "createdAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          },
+          {
+            "fieldPath": "updatedAt",
+            "columnName": "updatedAt",
+            "affinity": "INTEGER",
+            "notNull": true
+          }
+        ],
+        "primaryKey": {
+          "autoGenerate": false,
+          "columnNames": [
+            "id"
+          ]
+        },
+        "indices": [
+          {
+            "name": "index_cloud_tts_engines_provider_enabled",
+            "unique": false,
+            "columnNames": [
+              "provider",
+              "enabled"
+            ],
+            "orders": [],
+            "createSql": "CREATE INDEX IF NOT EXISTS `index_cloud_tts_engines_provider_enabled` ON `${TABLE_NAME}` (`provider`, `enabled`)"
+          }
+        ]
       }
     ],
     "views": [
@@ -3932,7 +4512,7 @@
     ],
     "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, '9087640670cf6cbc3be250a569ed106e')"
+      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f5e225667da6bf6e50b9435bfb2ffb6d')"
     ]
   }
 }

+ 0 - 4408
app/schemas/io.legado.app.data.AppDatabase/96.json

@@ -1,4408 +0,0 @@
-{
-  "formatVersion": 1,
-  "database": {
-    "version": 96,
-    "identityHash": "e0461f0c22e57cbd4ed01c2628df8a71",
-    "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, `remark` 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, `syncTime` INTEGER NOT NULL DEFAULT 0, 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"
-          },
-          {
-            "fieldPath": "customTag",
-            "columnName": "customTag",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "coverUrl",
-            "columnName": "coverUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customCoverUrl",
-            "columnName": "customCoverUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "intro",
-            "columnName": "intro",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customIntro",
-            "columnName": "customIntro",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "remark",
-            "columnName": "remark",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "charset",
-            "columnName": "charset",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "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"
-          },
-          {
-            "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"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "readConfig",
-            "columnName": "readConfig",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "syncTime",
-            "columnName": "syncTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "bookUrl"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_books_name_author",
-            "unique": false,
-            "columnNames": [
-              "name",
-              "author"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_books_name_author` ON `${TABLE_NAME}` (`name`, `author`)"
-          },
-          {
-            "name": "index_books_durChapterTime",
-            "unique": false,
-            "columnNames": [
-              "durChapterTime"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_books_durChapterTime` ON `${TABLE_NAME}` (`durChapterTime`)"
-          }
-        ]
-      },
-      {
-        "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, `isPrivate` INTEGER NOT NULL DEFAULT 0, 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"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "isPrivate",
-            "columnName": "isPrivate",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "groupId"
-          ]
-        }
-      },
-      {
-        "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, `eventListener` INTEGER NOT NULL DEFAULT 0, `customButton` INTEGER NOT NULL DEFAULT 0, `homepageModules` 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"
-          },
-          {
-            "fieldPath": "bookSourceType",
-            "columnName": "bookSourceType",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrlPattern",
-            "columnName": "bookUrlPattern",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "enabledCookieJar",
-            "columnName": "enabledCookieJar",
-            "affinity": "INTEGER",
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "concurrentRate",
-            "columnName": "concurrentRate",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "header",
-            "columnName": "header",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUrl",
-            "columnName": "loginUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUi",
-            "columnName": "loginUi",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginCheckJs",
-            "columnName": "loginCheckJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "coverDecodeJs",
-            "columnName": "coverDecodeJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "bookSourceComment",
-            "columnName": "bookSourceComment",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "variableComment",
-            "columnName": "variableComment",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "exploreScreen",
-            "columnName": "exploreScreen",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleExplore",
-            "columnName": "ruleExplore",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "searchUrl",
-            "columnName": "searchUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleSearch",
-            "columnName": "ruleSearch",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleBookInfo",
-            "columnName": "ruleBookInfo",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleToc",
-            "columnName": "ruleToc",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleContent",
-            "columnName": "ruleContent",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleReview",
-            "columnName": "ruleReview",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "eventListener",
-            "columnName": "eventListener",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "customButton",
-            "columnName": "customButton",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "homepageModules",
-            "columnName": "homepageModules",
-            "affinity": "TEXT"
-          }
-        ],
-        "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`)"
-          }
-        ]
-      },
-      {
-        "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, `wordCount` TEXT, `start` INTEGER, `end` INTEGER, `startFragmentId` TEXT, `endFragmentId` TEXT, `variable` TEXT, `reviewImg` 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"
-          },
-          {
-            "fieldPath": "tag",
-            "columnName": "tag",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "wordCount",
-            "columnName": "wordCount",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "start",
-            "columnName": "start",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "end",
-            "columnName": "end",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "startFragmentId",
-            "columnName": "startFragmentId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "endFragmentId",
-            "columnName": "endFragmentId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "reviewImg",
-            "columnName": "reviewImg",
-            "affinity": "TEXT"
-          }
-        ],
-        "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, `excludeScope` TEXT, `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"
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "replacement",
-            "columnName": "replacement",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "scope",
-            "columnName": "scope",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "scopeTitle",
-            "columnName": "scopeTitle",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "scopeContent",
-            "columnName": "scopeContent",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "excludeScope",
-            "columnName": "excludeScope",
-            "affinity": "TEXT"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "coverUrl",
-            "columnName": "coverUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "intro",
-            "columnName": "intro",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "wordCount",
-            "columnName": "wordCount",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "latestChapterTitle",
-            "columnName": "latestChapterTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "tocUrl",
-            "columnName": "tocUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "time",
-            "columnName": "time",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "originOrder",
-            "columnName": "originOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterWordCountText",
-            "columnName": "chapterWordCountText",
-            "affinity": "TEXT"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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`)"
-          }
-        ]
-      },
-      {
-        "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, `shouldOverrideUrlLoading` TEXT, `style` TEXT, `enableJs` INTEGER NOT NULL DEFAULT 1, `loadWithBaseUrl` INTEGER NOT NULL DEFAULT 1, `injectJs` TEXT, `preloadJs` TEXT, `startHtml` TEXT, `startStyle` TEXT, `startJs` TEXT, `showWebLog` INTEGER NOT NULL DEFAULT 0, `lastUpdateTime` INTEGER NOT NULL DEFAULT 0, `customOrder` INTEGER NOT NULL DEFAULT 0, `type` INTEGER NOT NULL DEFAULT 0, `preload` INTEGER NOT NULL DEFAULT 0, `cacheFirst` INTEGER NOT NULL DEFAULT 0, `searchUrl` TEXT, `redirectPolicy` TEXT NOT NULL DEFAULT 'ASK_CROSS_ORIGIN', 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"
-          },
-          {
-            "fieldPath": "sourceComment",
-            "columnName": "sourceComment",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "variableComment",
-            "columnName": "variableComment",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "jsLib",
-            "columnName": "jsLib",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabledCookieJar",
-            "columnName": "enabledCookieJar",
-            "affinity": "INTEGER",
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "concurrentRate",
-            "columnName": "concurrentRate",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "header",
-            "columnName": "header",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUrl",
-            "columnName": "loginUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUi",
-            "columnName": "loginUi",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginCheckJs",
-            "columnName": "loginCheckJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "coverDecodeJs",
-            "columnName": "coverDecodeJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "sortUrl",
-            "columnName": "sortUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "singleUrl",
-            "columnName": "singleUrl",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "articleStyle",
-            "columnName": "articleStyle",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "ruleArticles",
-            "columnName": "ruleArticles",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleNextPage",
-            "columnName": "ruleNextPage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleTitle",
-            "columnName": "ruleTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "rulePubDate",
-            "columnName": "rulePubDate",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleDescription",
-            "columnName": "ruleDescription",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleImage",
-            "columnName": "ruleImage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleLink",
-            "columnName": "ruleLink",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleContent",
-            "columnName": "ruleContent",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "contentWhitelist",
-            "columnName": "contentWhitelist",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "contentBlacklist",
-            "columnName": "contentBlacklist",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "shouldOverrideUrlLoading",
-            "columnName": "shouldOverrideUrlLoading",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "style",
-            "columnName": "style",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "preloadJs",
-            "columnName": "preloadJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "startHtml",
-            "columnName": "startHtml",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "startStyle",
-            "columnName": "startStyle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "startJs",
-            "columnName": "startJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "showWebLog",
-            "columnName": "showWebLog",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "lastUpdateTime",
-            "columnName": "lastUpdateTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "customOrder",
-            "columnName": "customOrder",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "preload",
-            "columnName": "preload",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "cacheFirst",
-            "columnName": "cacheFirst",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "searchUrl",
-            "columnName": "searchUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "redirectPolicy",
-            "columnName": "redirectPolicy",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'ASK_CROSS_ORIGIN'"
-          }
-        ],
-        "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`)"
-          }
-        ]
-      },
-      {
-        "tableName": "bookmarks",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`time` INTEGER NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `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,
-            "defaultValue": "''"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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, `group` TEXT NOT NULL DEFAULT '默认分组', `read` INTEGER NOT NULL, `variable` TEXT, `type` INTEGER NOT NULL DEFAULT 0, `durPos` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`origin`, `link`, `sort`))",
-        "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"
-          },
-          {
-            "fieldPath": "description",
-            "columnName": "description",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "image",
-            "columnName": "image",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "group",
-            "columnName": "group",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'默认分组'"
-          },
-          {
-            "fieldPath": "read",
-            "columnName": "read",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "durPos",
-            "columnName": "durPos",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "origin",
-            "link",
-            "sort"
-          ]
-        }
-      },
-      {
-        "tableName": "rssReadRecords",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record` TEXT NOT NULL, `title` TEXT, `readTime` INTEGER, `read` INTEGER NOT NULL, `origin` TEXT NOT NULL DEFAULT '', `sort` TEXT NOT NULL DEFAULT '', `image` TEXT, `type` INTEGER NOT NULL DEFAULT 0, `durPos` INTEGER NOT NULL DEFAULT 0, `pubDate` TEXT, PRIMARY KEY(`record`))",
-        "fields": [
-          {
-            "fieldPath": "record",
-            "columnName": "record",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "readTime",
-            "columnName": "readTime",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "read",
-            "columnName": "read",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "origin",
-            "columnName": "origin",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "sort",
-            "columnName": "sort",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "image",
-            "columnName": "image",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "durPos",
-            "columnName": "durPos",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "pubDate",
-            "columnName": "pubDate",
-            "affinity": "TEXT"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "record"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_rssReadRecords_origin",
-            "unique": false,
-            "columnNames": [
-              "origin"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_rssReadRecords_origin` ON `${TABLE_NAME}` (`origin`)"
-          }
-        ]
-      },
-      {
-        "tableName": "readRecordDetail",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `date` TEXT NOT NULL, `readTime` INTEGER NOT NULL DEFAULT 0, `readWords` INTEGER NOT NULL DEFAULT 0, `firstReadTime` INTEGER NOT NULL DEFAULT 0, `lastReadTime` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`deviceId`, `bookName`, `bookAuthor`, `date`))",
-        "fields": [
-          {
-            "fieldPath": "deviceId",
-            "columnName": "deviceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "date",
-            "columnName": "date",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "readTime",
-            "columnName": "readTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "readWords",
-            "columnName": "readWords",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "firstReadTime",
-            "columnName": "firstReadTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "lastReadTime",
-            "columnName": "lastReadTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "deviceId",
-            "bookName",
-            "bookAuthor",
-            "date"
-          ]
-        }
-      },
-      {
-        "tableName": "readRecordSession",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `startTime` INTEGER NOT NULL, `endTime` INTEGER NOT NULL, `words` INTEGER NOT NULL)",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "deviceId",
-            "columnName": "deviceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "startTime",
-            "columnName": "startTime",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "endTime",
-            "columnName": "endTime",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "words",
-            "columnName": "words",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": true,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "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, `group` TEXT NOT NULL DEFAULT '默认分组', `variable` TEXT, `type` INTEGER NOT NULL DEFAULT 0, `durPos` INTEGER NOT NULL DEFAULT 0, 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"
-          },
-          {
-            "fieldPath": "description",
-            "columnName": "description",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "image",
-            "columnName": "image",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "group",
-            "columnName": "group",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'默认分组'"
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "durPos",
-            "columnName": "durPos",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "origin",
-            "link"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "serialNumber",
-            "columnName": "serialNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enable",
-            "columnName": "enable",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "readRecord",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `readTime` INTEGER NOT NULL DEFAULT 0, `lastRead` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`deviceId`, `bookName`, `bookAuthor`))",
-        "fields": [
-          {
-            "fieldPath": "deviceId",
-            "columnName": "deviceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "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",
-            "bookAuthor"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "concurrentRate",
-            "columnName": "concurrentRate",
-            "affinity": "TEXT",
-            "defaultValue": "'0'"
-          },
-          {
-            "fieldPath": "loginUrl",
-            "columnName": "loginUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUi",
-            "columnName": "loginUi",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "header",
-            "columnName": "header",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "jsLib",
-            "columnName": "jsLib",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabledCookieJar",
-            "columnName": "enabledCookieJar",
-            "affinity": "INTEGER",
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "loginCheckJs",
-            "columnName": "loginCheckJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "lastUpdateTime",
-            "columnName": "lastUpdateTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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"
-          ]
-        }
-      },
-      {
-        "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"
-          ]
-        }
-      },
-      {
-        "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"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "search_content_history",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `bookName` TEXT DEFAULT '', `bookAuthor` TEXT DEFAULT '', `query` TEXT NOT NULL, `time` INTEGER NOT NULL)",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "query",
-            "columnName": "query",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "time",
-            "columnName": "time",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": true,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_search_content_history_bookName_bookAuthor_query",
-            "unique": true,
-            "columnNames": [
-              "bookName",
-              "bookAuthor",
-              "query"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_search_content_history_bookName_bookAuthor_query` ON `${TABLE_NAME}` (`bookName`, `bookAuthor`, `query`)"
-          }
-        ]
-      },
-      {
-        "tableName": "homepage_modules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `sourceUrl` TEXT NOT NULL, `moduleKey` TEXT NOT NULL, `type` TEXT NOT NULL, `title` TEXT NOT NULL, `args` TEXT, `layoutConfig` TEXT, `url` TEXT, `isEnabled` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `customSetId` TEXT, `isUserCreated` INTEGER NOT NULL, `customTitle` TEXT, `customSetTitle` TEXT, `sourceJsonHash` TEXT, `syncedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sourceUrl",
-            "columnName": "sourceUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "moduleKey",
-            "columnName": "moduleKey",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "args",
-            "columnName": "args",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "layoutConfig",
-            "columnName": "layoutConfig",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "url",
-            "columnName": "url",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "isEnabled",
-            "columnName": "isEnabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortOrder",
-            "columnName": "sortOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "customSetId",
-            "columnName": "customSetId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "isUserCreated",
-            "columnName": "isUserCreated",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "customTitle",
-            "columnName": "customTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customSetTitle",
-            "columnName": "customSetTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "sourceJsonHash",
-            "columnName": "sourceJsonHash",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "syncedAt",
-            "columnName": "syncedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "homepage_custom_sets",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortOrder",
-            "columnName": "sortOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "highlightRules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `pattern` TEXT NOT NULL, `sampleText` TEXT NOT NULL, `targetScope` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `position` INTEGER NOT NULL, `textColor` INTEGER, `bgColor` INTEGER, `underlineMode` INTEGER NOT NULL, `underlineColor` INTEGER, `underlineWidth` REAL NOT NULL, `underlineOffset` REAL NOT NULL, `underlineSvgPath` TEXT, `bgImage` TEXT, `bgImageFit` INTEGER NOT NULL, `bgImageScale` REAL NOT NULL, `configName` TEXT, `fontPath` TEXT, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sampleText",
-            "columnName": "sampleText",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "targetScope",
-            "columnName": "targetScope",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "position",
-            "columnName": "position",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "textColor",
-            "columnName": "textColor",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "bgColor",
-            "columnName": "bgColor",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "underlineMode",
-            "columnName": "underlineMode",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "underlineColor",
-            "columnName": "underlineColor",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "underlineWidth",
-            "columnName": "underlineWidth",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "underlineOffset",
-            "columnName": "underlineOffset",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "underlineSvgPath",
-            "columnName": "underlineSvgPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "bgImage",
-            "columnName": "bgImage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "bgImageFit",
-            "columnName": "bgImageFit",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bgImageScale",
-            "columnName": "bgImageScale",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "configName",
-            "columnName": "configName",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "fontPath",
-            "columnName": "fontPath",
-            "affinity": "TEXT"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "ai_provider_profiles",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `protocol` TEXT NOT NULL, `baseUrl` TEXT NOT NULL, `modelsUrl` TEXT, `apiKey` TEXT NOT NULL, `authType` TEXT NOT NULL, `secretRef` TEXT, `headersJson` TEXT, `chatPath` TEXT, `responsesPath` TEXT, `messagesPath` TEXT, `modelsPath` TEXT, `customHeadersJson` TEXT, `enabled` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "protocol",
-            "columnName": "protocol",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "baseUrl",
-            "columnName": "baseUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelsUrl",
-            "columnName": "modelsUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "apiKey",
-            "columnName": "apiKey",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "authType",
-            "columnName": "authType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "secretRef",
-            "columnName": "secretRef",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "headersJson",
-            "columnName": "headersJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "chatPath",
-            "columnName": "chatPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "responsesPath",
-            "columnName": "responsesPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "messagesPath",
-            "columnName": "messagesPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "modelsPath",
-            "columnName": "modelsPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customHeadersJson",
-            "columnName": "customHeadersJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "ai_model_profiles",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `providerId` TEXT NOT NULL, `displayName` TEXT NOT NULL, `modelId` TEXT NOT NULL, `contextWindow` INTEGER NOT NULL, `maxOutputTokens` INTEGER NOT NULL, `capabilities` TEXT NOT NULL, `defaultParamsJson` TEXT, `enabled` INTEGER NOT NULL, `sortNumber` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "providerId",
-            "columnName": "providerId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "displayName",
-            "columnName": "displayName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelId",
-            "columnName": "modelId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "contextWindow",
-            "columnName": "contextWindow",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "maxOutputTokens",
-            "columnName": "maxOutputTokens",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "capabilities",
-            "columnName": "capabilities",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "defaultParamsJson",
-            "columnName": "defaultParamsJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_model_profiles_providerId",
-            "unique": false,
-            "columnNames": [
-              "providerId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_model_profiles_providerId` ON `${TABLE_NAME}` (`providerId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_task_presets",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `taskType` TEXT NOT NULL, `name` TEXT NOT NULL, `modelProfileId` TEXT NOT NULL, `promptTemplate` TEXT NOT NULL, `paramsJson` TEXT, `chunkPolicyJson` TEXT, `enabled` INTEGER NOT NULL, `isDefault` INTEGER NOT NULL, `sortNumber` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "taskType",
-            "columnName": "taskType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelProfileId",
-            "columnName": "modelProfileId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "promptTemplate",
-            "columnName": "promptTemplate",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "paramsJson",
-            "columnName": "paramsJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "chunkPolicyJson",
-            "columnName": "chunkPolicyJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "isDefault",
-            "columnName": "isDefault",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_task_presets_taskType",
-            "unique": false,
-            "columnNames": [
-              "taskType"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_task_presets_taskType` ON `${TABLE_NAME}` (`taskType`)"
-          },
-          {
-            "name": "index_ai_task_presets_modelProfileId",
-            "unique": false,
-            "columnNames": [
-              "modelProfileId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_task_presets_modelProfileId` ON `${TABLE_NAME}` (`modelProfileId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_artifacts",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `taskType` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER, `contentHash` TEXT NOT NULL, `promptHash` TEXT NOT NULL, `modelProfileId` TEXT NOT NULL, `status` INTEGER NOT NULL, `output` TEXT, `errorMessage` TEXT, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "taskType",
-            "columnName": "taskType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "contentHash",
-            "columnName": "contentHash",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "promptHash",
-            "columnName": "promptHash",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelProfileId",
-            "columnName": "modelProfileId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "output",
-            "columnName": "output",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "errorMessage",
-            "columnName": "errorMessage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_artifacts_bookUrl_chapterIndex_taskType",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "taskType"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_artifacts_bookUrl_chapterIndex_taskType` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `taskType`)"
-          },
-          {
-            "name": "index_ai_artifacts_contentHash_promptHash_modelProfileId",
-            "unique": false,
-            "columnNames": [
-              "contentHash",
-              "promptHash",
-              "modelProfileId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_artifacts_contentHash_promptHash_modelProfileId` ON `${TABLE_NAME}` (`contentHash`, `promptHash`, `modelProfileId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_chat_conversations",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `reasoningLevel` TEXT NOT NULL, `modelProfileId` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "reasoningLevel",
-            "columnName": "reasoningLevel",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelProfileId",
-            "columnName": "modelProfileId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "ai_chat_messages",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `conversationId` TEXT NOT NULL, `role` TEXT NOT NULL, `partsJson` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `branchIndex` INTEGER NOT NULL, `isSelected` INTEGER NOT NULL, `parentMessageId` TEXT, `thinkingDuration` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "conversationId",
-            "columnName": "conversationId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "role",
-            "columnName": "role",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "partsJson",
-            "columnName": "partsJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "branchIndex",
-            "columnName": "branchIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "isSelected",
-            "columnName": "isSelected",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "parentMessageId",
-            "columnName": "parentMessageId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "thinkingDuration",
-            "columnName": "thinkingDuration",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_chat_messages_conversationId_createdAt",
-            "unique": false,
-            "columnNames": [
-              "conversationId",
-              "createdAt"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_chat_messages_conversationId_createdAt` ON `${TABLE_NAME}` (`conversationId`, `createdAt`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_memory",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`conversationId` TEXT NOT NULL, `key` TEXT NOT NULL, `value` TEXT NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`conversationId`, `key`))",
-        "fields": [
-          {
-            "fieldPath": "conversationId",
-            "columnName": "conversationId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "key",
-            "columnName": "key",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "value",
-            "columnName": "value",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "conversationId",
-            "key"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_memory_conversationId",
-            "unique": false,
-            "columnNames": [
-              "conversationId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_memory_conversationId` ON `${TABLE_NAME}` (`conversationId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "highlight_tag_rules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `pattern` TEXT NOT NULL, `enabled` INTEGER NOT NULL, `order` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "order",
-            "columnName": "order",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "tag_group_rules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `pattern` TEXT NOT NULL, `groupName` TEXT NOT NULL, `order` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "groupName",
-            "columnName": "groupName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "order",
-            "columnName": "order",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "book_content_processes",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER, `kind` TEXT NOT NULL, `stage` TEXT NOT NULL, `target` TEXT NOT NULL, `anchorJson` TEXT NOT NULL, `actionJson` TEXT NOT NULL, `styleJson` TEXT, `source` TEXT NOT NULL, `aiArtifactId` TEXT, `sourceContentHash` TEXT, `enabled` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `status` INTEGER NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "kind",
-            "columnName": "kind",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "stage",
-            "columnName": "stage",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "target",
-            "columnName": "target",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "anchorJson",
-            "columnName": "anchorJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "actionJson",
-            "columnName": "actionJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "styleJson",
-            "columnName": "styleJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "aiArtifactId",
-            "columnName": "aiArtifactId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "sourceContentHash",
-            "columnName": "sourceContentHash",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortOrder",
-            "columnName": "sortOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_content_processes_bookUrl_chapterIndex_enabled_sortOrder",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "enabled",
-              "sortOrder"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_content_processes_bookUrl_chapterIndex_enabled_sortOrder` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `enabled`, `sortOrder`)"
-          },
-          {
-            "name": "index_book_content_processes_bookUrl_kind",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "kind"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_content_processes_bookUrl_kind` ON `${TABLE_NAME}` (`bookUrl`, `kind`)"
-          },
-          {
-            "name": "index_book_content_processes_aiArtifactId",
-            "unique": false,
-            "columnNames": [
-              "aiArtifactId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_content_processes_aiArtifactId` ON `${TABLE_NAME}` (`aiArtifactId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_prompt_presets",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `taskType` TEXT NOT NULL, `name` TEXT NOT NULL, `instruction` TEXT NOT NULL, `enabled` INTEGER NOT NULL, `builtIn` INTEGER NOT NULL, `sortNumber` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "taskType",
-            "columnName": "taskType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "instruction",
-            "columnName": "instruction",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "builtIn",
-            "columnName": "builtIn",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_prompt_presets_taskType_enabled_sortNumber",
-            "unique": false,
-            "columnNames": [
-              "taskType",
-              "enabled",
-              "sortNumber"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_prompt_presets_taskType_enabled_sortNumber` ON `${TABLE_NAME}` (`taskType`, `enabled`, `sortNumber`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_character_profiles",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `name` TEXT NOT NULL, `aliasesJson` TEXT NOT NULL, `avatarUri` TEXT, `tagsJson` TEXT NOT NULL, `role` TEXT NOT NULL, `personality` TEXT NOT NULL, `summary` TEXT NOT NULL, `status` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "aliasesJson",
-            "columnName": "aliasesJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "avatarUri",
-            "columnName": "avatarUri",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "tagsJson",
-            "columnName": "tagsJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "role",
-            "columnName": "role",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "personality",
-            "columnName": "personality",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "summary",
-            "columnName": "summary",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_character_profiles_bookUrl_name",
-            "unique": true,
-            "columnNames": [
-              "bookUrl",
-              "name"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_book_character_profiles_bookUrl_name` ON `${TABLE_NAME}` (`bookUrl`, `name`)"
-          },
-          {
-            "name": "index_book_character_profiles_bookUrl_updatedAt",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "updatedAt"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_profiles_bookUrl_updatedAt` ON `${TABLE_NAME}` (`bookUrl`, `updatedAt`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_character_events",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `characterId` TEXT NOT NULL, `chapterIndex` INTEGER, `chapterTitle` TEXT NOT NULL, `eventTimeText` TEXT NOT NULL, `content` TEXT NOT NULL, `importance` INTEGER NOT NULL, `sourceTextHash` TEXT, `evidenceJson` TEXT NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "characterId",
-            "columnName": "characterId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "chapterTitle",
-            "columnName": "chapterTitle",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "eventTimeText",
-            "columnName": "eventTimeText",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "importance",
-            "columnName": "importance",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sourceTextHash",
-            "columnName": "sourceTextHash",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "evidenceJson",
-            "columnName": "evidenceJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_character_events_bookUrl_characterId_chapterIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "characterId",
-              "chapterIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_events_bookUrl_characterId_chapterIndex` ON `${TABLE_NAME}` (`bookUrl`, `characterId`, `chapterIndex`)"
-          },
-          {
-            "name": "index_book_character_events_bookUrl_chapterIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_events_bookUrl_chapterIndex` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_character_relations",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `fromCharacterId` TEXT NOT NULL, `toCharacterId` TEXT NOT NULL, `relationType` TEXT NOT NULL, `summary` TEXT NOT NULL, `attitude` TEXT NOT NULL, `evidenceJson` TEXT NOT NULL, `chapterIndex` INTEGER, `status` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "fromCharacterId",
-            "columnName": "fromCharacterId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "toCharacterId",
-            "columnName": "toCharacterId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "relationType",
-            "columnName": "relationType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "summary",
-            "columnName": "summary",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "attitude",
-            "columnName": "attitude",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "evidenceJson",
-            "columnName": "evidenceJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_character_relations_bookUrl_fromCharacterId_toCharacterId",
-            "unique": true,
-            "columnNames": [
-              "bookUrl",
-              "fromCharacterId",
-              "toCharacterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_book_character_relations_bookUrl_fromCharacterId_toCharacterId` ON `${TABLE_NAME}` (`bookUrl`, `fromCharacterId`, `toCharacterId`)"
-          },
-          {
-            "name": "index_book_character_relations_bookUrl_fromCharacterId",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "fromCharacterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_relations_bookUrl_fromCharacterId` ON `${TABLE_NAME}` (`bookUrl`, `fromCharacterId`)"
-          },
-          {
-            "name": "index_book_character_relations_bookUrl_toCharacterId",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "toCharacterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_relations_bookUrl_toCharacterId` ON `${TABLE_NAME}` (`bookUrl`, `toCharacterId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_knowledge_entries",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `type` TEXT NOT NULL, `title` TEXT NOT NULL, `keywordsJson` TEXT NOT NULL, `content` TEXT NOT NULL, `scopeStartChapter` INTEGER, `scopeEndChapter` INTEGER, `priority` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `evidenceJson` TEXT NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "keywordsJson",
-            "columnName": "keywordsJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "scopeStartChapter",
-            "columnName": "scopeStartChapter",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "scopeEndChapter",
-            "columnName": "scopeEndChapter",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "priority",
-            "columnName": "priority",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "evidenceJson",
-            "columnName": "evidenceJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_knowledge_entries_bookUrl_type_priority",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "type",
-              "priority"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_knowledge_entries_bookUrl_type_priority` ON `${TABLE_NAME}` (`bookUrl`, `type`, `priority`)"
-          },
-          {
-            "name": "index_book_knowledge_entries_bookUrl_title",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "title"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_knowledge_entries_bookUrl_title` ON `${TABLE_NAME}` (`bookUrl`, `title`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_outline_nodes",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `parentId` TEXT, `nodeType` TEXT NOT NULL, `title` TEXT NOT NULL, `summary` TEXT NOT NULL, `startChapterIndex` INTEGER, `endChapterIndex` INTEGER, `order` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "parentId",
-            "columnName": "parentId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "nodeType",
-            "columnName": "nodeType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "summary",
-            "columnName": "summary",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "startChapterIndex",
-            "columnName": "startChapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "endChapterIndex",
-            "columnName": "endChapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "order",
-            "columnName": "order",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_outline_nodes_bookUrl_nodeType_startChapterIndex_endChapterIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "nodeType",
-              "startChapterIndex",
-              "endChapterIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_outline_nodes_bookUrl_nodeType_startChapterIndex_endChapterIndex` ON `${TABLE_NAME}` (`bookUrl`, `nodeType`, `startChapterIndex`, `endChapterIndex`)"
-          },
-          {
-            "name": "index_book_outline_nodes_bookUrl_parentId_order",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "parentId",
-              "order"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_outline_nodes_bookUrl_parentId_order` ON `${TABLE_NAME}` (`bookUrl`, `parentId`, `order`)"
-          }
-        ]
-      },
-      {
-        "tableName": "read_aloud_voices",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `engineType` TEXT NOT NULL, `engineId` TEXT NOT NULL DEFAULT '', `speakerId` TEXT NOT NULL DEFAULT '', `displayName` TEXT NOT NULL, `traitsJson` TEXT NOT NULL DEFAULT '[]', `emotionCatalogJson` TEXT NOT NULL DEFAULT '[]', `managedBy` TEXT NOT NULL DEFAULT 'user', `enabled` INTEGER NOT NULL DEFAULT 1, `available` INTEGER NOT NULL DEFAULT 1, `revision` INTEGER NOT NULL DEFAULT 0, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "engineType",
-            "columnName": "engineType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "engineId",
-            "columnName": "engineId",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "speakerId",
-            "columnName": "speakerId",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "displayName",
-            "columnName": "displayName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "traitsJson",
-            "columnName": "traitsJson",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'[]'"
-          },
-          {
-            "fieldPath": "emotionCatalogJson",
-            "columnName": "emotionCatalogJson",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'[]'"
-          },
-          {
-            "fieldPath": "managedBy",
-            "columnName": "managedBy",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'user'"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "available",
-            "columnName": "available",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "revision",
-            "columnName": "revision",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_read_aloud_voices_engineType_engineId_speakerId",
-            "unique": true,
-            "columnNames": [
-              "engineType",
-              "engineId",
-              "speakerId"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_read_aloud_voices_engineType_engineId_speakerId` ON `${TABLE_NAME}` (`engineType`, `engineId`, `speakerId`)"
-          },
-          {
-            "name": "index_read_aloud_voices_enabled_displayName",
-            "unique": false,
-            "columnNames": [
-              "enabled",
-              "displayName"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_read_aloud_voices_enabled_displayName` ON `${TABLE_NAME}` (`enabled`, `displayName`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_voice_bindings",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookUrl` TEXT NOT NULL, `subjectType` TEXT NOT NULL, `subjectId` TEXT NOT NULL, `voiceId` TEXT NOT NULL, `locked` INTEGER NOT NULL DEFAULT 0, `source` TEXT NOT NULL DEFAULT 'user', `confidence` REAL NOT NULL DEFAULT 1, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`bookUrl`, `subjectType`, `subjectId`))",
-        "fields": [
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "subjectType",
-            "columnName": "subjectType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "subjectId",
-            "columnName": "subjectId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "voiceId",
-            "columnName": "voiceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "locked",
-            "columnName": "locked",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'user'"
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "bookUrl",
-            "subjectType",
-            "subjectId"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_voice_bindings_bookUrl_subjectType",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "subjectType"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_voice_bindings_bookUrl_subjectType` ON `${TABLE_NAME}` (`bookUrl`, `subjectType`)"
-          },
-          {
-            "name": "index_book_voice_bindings_voiceId",
-            "unique": false,
-            "columnNames": [
-              "voiceId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_voice_bindings_voiceId` ON `${TABLE_NAME}` (`voiceId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "chapter_speech_analysis",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `contentHash` TEXT NOT NULL, `resolverVersion` TEXT NOT NULL, `characterRevision` TEXT NOT NULL DEFAULT '', `status` TEXT NOT NULL DEFAULT 'pending', `error` TEXT NOT NULL DEFAULT '', `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "contentHash",
-            "columnName": "contentHash",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "resolverVersion",
-            "columnName": "resolverVersion",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "characterRevision",
-            "columnName": "characterRevision",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'pending'"
-          },
-          {
-            "fieldPath": "error",
-            "columnName": "error",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_chapter_speech_analysis_bookUrl_chapterIndex_contentHash_resolverVersion",
-            "unique": true,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "contentHash",
-              "resolverVersion"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapter_speech_analysis_bookUrl_chapterIndex_contentHash_resolverVersion` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `contentHash`, `resolverVersion`)"
-          },
-          {
-            "name": "index_chapter_speech_analysis_bookUrl_chapterIndex_updatedAt",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "updatedAt"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_analysis_bookUrl_chapterIndex_updatedAt` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `updatedAt`)"
-          }
-        ]
-      },
-      {
-        "tableName": "chapter_speech_segments",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `analysisId` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `paragraphIndex` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `chapterPosition` INTEGER NOT NULL, `text` TEXT NOT NULL, `roleType` TEXT NOT NULL, `characterId` TEXT, `characterName` TEXT NOT NULL DEFAULT '', `emotion` TEXT NOT NULL DEFAULT '', `confidence` REAL NOT NULL DEFAULT 0, `source` TEXT NOT NULL, `userLocked` INTEGER NOT NULL DEFAULT 0, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "analysisId",
-            "columnName": "analysisId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "paragraphIndex",
-            "columnName": "paragraphIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "start",
-            "columnName": "start",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "end",
-            "columnName": "end",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterPosition",
-            "columnName": "chapterPosition",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "text",
-            "columnName": "text",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "roleType",
-            "columnName": "roleType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "characterId",
-            "columnName": "characterId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "characterName",
-            "columnName": "characterName",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "emotion",
-            "columnName": "emotion",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "userLocked",
-            "columnName": "userLocked",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_chapter_speech_segments_analysisId_paragraphIndex_start_end",
-            "unique": true,
-            "columnNames": [
-              "analysisId",
-              "paragraphIndex",
-              "start",
-              "end"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapter_speech_segments_analysisId_paragraphIndex_start_end` ON `${TABLE_NAME}` (`analysisId`, `paragraphIndex`, `start`, `end`)"
-          },
-          {
-            "name": "index_chapter_speech_segments_bookUrl_chapterIndex_paragraphIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "paragraphIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_segments_bookUrl_chapterIndex_paragraphIndex` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `paragraphIndex`)"
-          },
-          {
-            "name": "index_chapter_speech_segments_characterId",
-            "unique": false,
-            "columnNames": [
-              "characterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_segments_characterId` ON `${TABLE_NAME}` (`characterId`)"
-          }
-        ]
-      }
-    ],
-    "views": [
-      {
-        "viewName": "book_sources_part",
-        "createSql": "CREATE VIEW `${VIEW_NAME}` AS select bookSourceUrl, bookSourceName, bookSourceGroup, customOrder, enabled, enabledExplore, \n    (loginUrl is not null and trim(loginUrl) <> '') hasLoginUrl, lastUpdateTime, respondTime, weight, \n    (exploreUrl is not null and trim(exploreUrl) <> '') hasExploreUrl \n    from book_sources"
-      }
-    ],
-    "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, 'e0461f0c22e57cbd4ed01c2628df8a71')"
-    ]
-  }
-}

+ 0 - 4518
app/schemas/io.legado.app.data.AppDatabase/97.json

@@ -1,4518 +0,0 @@
-{
-  "formatVersion": 1,
-  "database": {
-    "version": 97,
-    "identityHash": "f5e225667da6bf6e50b9435bfb2ffb6d",
-    "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, `remark` 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, `syncTime` INTEGER NOT NULL DEFAULT 0, 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"
-          },
-          {
-            "fieldPath": "customTag",
-            "columnName": "customTag",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "coverUrl",
-            "columnName": "coverUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customCoverUrl",
-            "columnName": "customCoverUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "intro",
-            "columnName": "intro",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customIntro",
-            "columnName": "customIntro",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "remark",
-            "columnName": "remark",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "charset",
-            "columnName": "charset",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "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"
-          },
-          {
-            "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"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "readConfig",
-            "columnName": "readConfig",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "syncTime",
-            "columnName": "syncTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "bookUrl"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_books_name_author",
-            "unique": false,
-            "columnNames": [
-              "name",
-              "author"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_books_name_author` ON `${TABLE_NAME}` (`name`, `author`)"
-          },
-          {
-            "name": "index_books_durChapterTime",
-            "unique": false,
-            "columnNames": [
-              "durChapterTime"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_books_durChapterTime` ON `${TABLE_NAME}` (`durChapterTime`)"
-          }
-        ]
-      },
-      {
-        "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, `isPrivate` INTEGER NOT NULL DEFAULT 0, 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"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "isPrivate",
-            "columnName": "isPrivate",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "groupId"
-          ]
-        }
-      },
-      {
-        "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, `eventListener` INTEGER NOT NULL DEFAULT 0, `customButton` INTEGER NOT NULL DEFAULT 0, `homepageModules` 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"
-          },
-          {
-            "fieldPath": "bookSourceType",
-            "columnName": "bookSourceType",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrlPattern",
-            "columnName": "bookUrlPattern",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "enabledCookieJar",
-            "columnName": "enabledCookieJar",
-            "affinity": "INTEGER",
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "concurrentRate",
-            "columnName": "concurrentRate",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "header",
-            "columnName": "header",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUrl",
-            "columnName": "loginUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUi",
-            "columnName": "loginUi",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginCheckJs",
-            "columnName": "loginCheckJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "coverDecodeJs",
-            "columnName": "coverDecodeJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "bookSourceComment",
-            "columnName": "bookSourceComment",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "variableComment",
-            "columnName": "variableComment",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "exploreScreen",
-            "columnName": "exploreScreen",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleExplore",
-            "columnName": "ruleExplore",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "searchUrl",
-            "columnName": "searchUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleSearch",
-            "columnName": "ruleSearch",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleBookInfo",
-            "columnName": "ruleBookInfo",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleToc",
-            "columnName": "ruleToc",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleContent",
-            "columnName": "ruleContent",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleReview",
-            "columnName": "ruleReview",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "eventListener",
-            "columnName": "eventListener",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "customButton",
-            "columnName": "customButton",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "homepageModules",
-            "columnName": "homepageModules",
-            "affinity": "TEXT"
-          }
-        ],
-        "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`)"
-          }
-        ]
-      },
-      {
-        "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, `wordCount` TEXT, `start` INTEGER, `end` INTEGER, `startFragmentId` TEXT, `endFragmentId` TEXT, `variable` TEXT, `reviewImg` 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"
-          },
-          {
-            "fieldPath": "tag",
-            "columnName": "tag",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "wordCount",
-            "columnName": "wordCount",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "start",
-            "columnName": "start",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "end",
-            "columnName": "end",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "startFragmentId",
-            "columnName": "startFragmentId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "endFragmentId",
-            "columnName": "endFragmentId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "reviewImg",
-            "columnName": "reviewImg",
-            "affinity": "TEXT"
-          }
-        ],
-        "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, `excludeScope` TEXT, `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"
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "replacement",
-            "columnName": "replacement",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "scope",
-            "columnName": "scope",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "scopeTitle",
-            "columnName": "scopeTitle",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "scopeContent",
-            "columnName": "scopeContent",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "excludeScope",
-            "columnName": "excludeScope",
-            "affinity": "TEXT"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "coverUrl",
-            "columnName": "coverUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "intro",
-            "columnName": "intro",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "wordCount",
-            "columnName": "wordCount",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "latestChapterTitle",
-            "columnName": "latestChapterTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "tocUrl",
-            "columnName": "tocUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "time",
-            "columnName": "time",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "originOrder",
-            "columnName": "originOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterWordCountText",
-            "columnName": "chapterWordCountText",
-            "affinity": "TEXT"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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`)"
-          }
-        ]
-      },
-      {
-        "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, `shouldOverrideUrlLoading` TEXT, `style` TEXT, `enableJs` INTEGER NOT NULL DEFAULT 1, `loadWithBaseUrl` INTEGER NOT NULL DEFAULT 1, `injectJs` TEXT, `preloadJs` TEXT, `startHtml` TEXT, `startStyle` TEXT, `startJs` TEXT, `showWebLog` INTEGER NOT NULL DEFAULT 0, `lastUpdateTime` INTEGER NOT NULL DEFAULT 0, `customOrder` INTEGER NOT NULL DEFAULT 0, `type` INTEGER NOT NULL DEFAULT 0, `preload` INTEGER NOT NULL DEFAULT 0, `cacheFirst` INTEGER NOT NULL DEFAULT 0, `searchUrl` TEXT, `redirectPolicy` TEXT NOT NULL DEFAULT 'ASK_CROSS_ORIGIN', 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"
-          },
-          {
-            "fieldPath": "sourceComment",
-            "columnName": "sourceComment",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "variableComment",
-            "columnName": "variableComment",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "jsLib",
-            "columnName": "jsLib",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabledCookieJar",
-            "columnName": "enabledCookieJar",
-            "affinity": "INTEGER",
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "concurrentRate",
-            "columnName": "concurrentRate",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "header",
-            "columnName": "header",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUrl",
-            "columnName": "loginUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUi",
-            "columnName": "loginUi",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginCheckJs",
-            "columnName": "loginCheckJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "coverDecodeJs",
-            "columnName": "coverDecodeJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "sortUrl",
-            "columnName": "sortUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "singleUrl",
-            "columnName": "singleUrl",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "articleStyle",
-            "columnName": "articleStyle",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "ruleArticles",
-            "columnName": "ruleArticles",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleNextPage",
-            "columnName": "ruleNextPage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleTitle",
-            "columnName": "ruleTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "rulePubDate",
-            "columnName": "rulePubDate",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleDescription",
-            "columnName": "ruleDescription",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleImage",
-            "columnName": "ruleImage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleLink",
-            "columnName": "ruleLink",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "ruleContent",
-            "columnName": "ruleContent",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "contentWhitelist",
-            "columnName": "contentWhitelist",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "contentBlacklist",
-            "columnName": "contentBlacklist",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "shouldOverrideUrlLoading",
-            "columnName": "shouldOverrideUrlLoading",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "style",
-            "columnName": "style",
-            "affinity": "TEXT"
-          },
-          {
-            "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"
-          },
-          {
-            "fieldPath": "preloadJs",
-            "columnName": "preloadJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "startHtml",
-            "columnName": "startHtml",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "startStyle",
-            "columnName": "startStyle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "startJs",
-            "columnName": "startJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "showWebLog",
-            "columnName": "showWebLog",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "lastUpdateTime",
-            "columnName": "lastUpdateTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "customOrder",
-            "columnName": "customOrder",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "preload",
-            "columnName": "preload",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "cacheFirst",
-            "columnName": "cacheFirst",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "searchUrl",
-            "columnName": "searchUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "redirectPolicy",
-            "columnName": "redirectPolicy",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'ASK_CROSS_ORIGIN'"
-          }
-        ],
-        "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`)"
-          }
-        ]
-      },
-      {
-        "tableName": "bookmarks",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`time` INTEGER NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `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,
-            "defaultValue": "''"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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, `group` TEXT NOT NULL DEFAULT '默认分组', `read` INTEGER NOT NULL, `variable` TEXT, `type` INTEGER NOT NULL DEFAULT 0, `durPos` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`origin`, `link`, `sort`))",
-        "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"
-          },
-          {
-            "fieldPath": "description",
-            "columnName": "description",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "image",
-            "columnName": "image",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "group",
-            "columnName": "group",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'默认分组'"
-          },
-          {
-            "fieldPath": "read",
-            "columnName": "read",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "durPos",
-            "columnName": "durPos",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "origin",
-            "link",
-            "sort"
-          ]
-        }
-      },
-      {
-        "tableName": "rssReadRecords",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`record` TEXT NOT NULL, `title` TEXT, `readTime` INTEGER, `read` INTEGER NOT NULL, `origin` TEXT NOT NULL DEFAULT '', `sort` TEXT NOT NULL DEFAULT '', `image` TEXT, `type` INTEGER NOT NULL DEFAULT 0, `durPos` INTEGER NOT NULL DEFAULT 0, `pubDate` TEXT, PRIMARY KEY(`record`))",
-        "fields": [
-          {
-            "fieldPath": "record",
-            "columnName": "record",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "readTime",
-            "columnName": "readTime",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "read",
-            "columnName": "read",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "origin",
-            "columnName": "origin",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "sort",
-            "columnName": "sort",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "image",
-            "columnName": "image",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "durPos",
-            "columnName": "durPos",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "pubDate",
-            "columnName": "pubDate",
-            "affinity": "TEXT"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "record"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_rssReadRecords_origin",
-            "unique": false,
-            "columnNames": [
-              "origin"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_rssReadRecords_origin` ON `${TABLE_NAME}` (`origin`)"
-          }
-        ]
-      },
-      {
-        "tableName": "readRecordDetail",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `date` TEXT NOT NULL, `readTime` INTEGER NOT NULL DEFAULT 0, `readWords` INTEGER NOT NULL DEFAULT 0, `firstReadTime` INTEGER NOT NULL DEFAULT 0, `lastReadTime` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`deviceId`, `bookName`, `bookAuthor`, `date`))",
-        "fields": [
-          {
-            "fieldPath": "deviceId",
-            "columnName": "deviceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "date",
-            "columnName": "date",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "readTime",
-            "columnName": "readTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "readWords",
-            "columnName": "readWords",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "firstReadTime",
-            "columnName": "firstReadTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "lastReadTime",
-            "columnName": "lastReadTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "deviceId",
-            "bookName",
-            "bookAuthor",
-            "date"
-          ]
-        }
-      },
-      {
-        "tableName": "readRecordSession",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `startTime` INTEGER NOT NULL, `endTime` INTEGER NOT NULL, `words` INTEGER NOT NULL)",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "deviceId",
-            "columnName": "deviceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "startTime",
-            "columnName": "startTime",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "endTime",
-            "columnName": "endTime",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "words",
-            "columnName": "words",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": true,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "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, `group` TEXT NOT NULL DEFAULT '默认分组', `variable` TEXT, `type` INTEGER NOT NULL DEFAULT 0, `durPos` INTEGER NOT NULL DEFAULT 0, 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"
-          },
-          {
-            "fieldPath": "description",
-            "columnName": "description",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "image",
-            "columnName": "image",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "group",
-            "columnName": "group",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'默认分组'"
-          },
-          {
-            "fieldPath": "variable",
-            "columnName": "variable",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "durPos",
-            "columnName": "durPos",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "origin",
-            "link"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "serialNumber",
-            "columnName": "serialNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enable",
-            "columnName": "enable",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "readRecord",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`deviceId` TEXT NOT NULL, `bookName` TEXT NOT NULL, `bookAuthor` TEXT NOT NULL DEFAULT '', `readTime` INTEGER NOT NULL DEFAULT 0, `lastRead` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`deviceId`, `bookName`, `bookAuthor`))",
-        "fields": [
-          {
-            "fieldPath": "deviceId",
-            "columnName": "deviceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "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",
-            "bookAuthor"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "concurrentRate",
-            "columnName": "concurrentRate",
-            "affinity": "TEXT",
-            "defaultValue": "'0'"
-          },
-          {
-            "fieldPath": "loginUrl",
-            "columnName": "loginUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "loginUi",
-            "columnName": "loginUi",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "header",
-            "columnName": "header",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "jsLib",
-            "columnName": "jsLib",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabledCookieJar",
-            "columnName": "enabledCookieJar",
-            "affinity": "INTEGER",
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "loginCheckJs",
-            "columnName": "loginCheckJs",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "lastUpdateTime",
-            "columnName": "lastUpdateTime",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "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`)"
-          }
-        ]
-      },
-      {
-        "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"
-          ]
-        }
-      },
-      {
-        "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"
-          ]
-        }
-      },
-      {
-        "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"
-          ]
-        }
-      },
-      {
-        "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"
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "search_content_history",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `bookName` TEXT DEFAULT '', `bookAuthor` TEXT DEFAULT '', `query` TEXT NOT NULL, `time` INTEGER NOT NULL)",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookName",
-            "columnName": "bookName",
-            "affinity": "TEXT",
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "bookAuthor",
-            "columnName": "bookAuthor",
-            "affinity": "TEXT",
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "query",
-            "columnName": "query",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "time",
-            "columnName": "time",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": true,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_search_content_history_bookName_bookAuthor_query",
-            "unique": true,
-            "columnNames": [
-              "bookName",
-              "bookAuthor",
-              "query"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_search_content_history_bookName_bookAuthor_query` ON `${TABLE_NAME}` (`bookName`, `bookAuthor`, `query`)"
-          }
-        ]
-      },
-      {
-        "tableName": "homepage_modules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `sourceUrl` TEXT NOT NULL, `moduleKey` TEXT NOT NULL, `type` TEXT NOT NULL, `title` TEXT NOT NULL, `args` TEXT, `layoutConfig` TEXT, `url` TEXT, `isEnabled` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `customSetId` TEXT, `isUserCreated` INTEGER NOT NULL, `customTitle` TEXT, `customSetTitle` TEXT, `sourceJsonHash` TEXT, `syncedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sourceUrl",
-            "columnName": "sourceUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "moduleKey",
-            "columnName": "moduleKey",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "args",
-            "columnName": "args",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "layoutConfig",
-            "columnName": "layoutConfig",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "url",
-            "columnName": "url",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "isEnabled",
-            "columnName": "isEnabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortOrder",
-            "columnName": "sortOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "customSetId",
-            "columnName": "customSetId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "isUserCreated",
-            "columnName": "isUserCreated",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "customTitle",
-            "columnName": "customTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customSetTitle",
-            "columnName": "customSetTitle",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "sourceJsonHash",
-            "columnName": "sourceJsonHash",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "syncedAt",
-            "columnName": "syncedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "homepage_custom_sets",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `sortOrder` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortOrder",
-            "columnName": "sortOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "highlightRules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `pattern` TEXT NOT NULL, `sampleText` TEXT NOT NULL, `targetScope` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `position` INTEGER NOT NULL, `textColor` INTEGER, `bgColor` INTEGER, `underlineMode` INTEGER NOT NULL, `underlineColor` INTEGER, `underlineWidth` REAL NOT NULL, `underlineOffset` REAL NOT NULL, `underlineSvgPath` TEXT, `bgImage` TEXT, `bgImageFit` INTEGER NOT NULL, `bgImageScale` REAL NOT NULL, `configName` TEXT, `fontPath` TEXT, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sampleText",
-            "columnName": "sampleText",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "targetScope",
-            "columnName": "targetScope",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "position",
-            "columnName": "position",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "textColor",
-            "columnName": "textColor",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "bgColor",
-            "columnName": "bgColor",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "underlineMode",
-            "columnName": "underlineMode",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "underlineColor",
-            "columnName": "underlineColor",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "underlineWidth",
-            "columnName": "underlineWidth",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "underlineOffset",
-            "columnName": "underlineOffset",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "underlineSvgPath",
-            "columnName": "underlineSvgPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "bgImage",
-            "columnName": "bgImage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "bgImageFit",
-            "columnName": "bgImageFit",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bgImageScale",
-            "columnName": "bgImageScale",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "configName",
-            "columnName": "configName",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "fontPath",
-            "columnName": "fontPath",
-            "affinity": "TEXT"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "ai_provider_profiles",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `protocol` TEXT NOT NULL, `baseUrl` TEXT NOT NULL, `modelsUrl` TEXT, `apiKey` TEXT NOT NULL, `authType` TEXT NOT NULL, `secretRef` TEXT, `headersJson` TEXT, `chatPath` TEXT, `responsesPath` TEXT, `messagesPath` TEXT, `modelsPath` TEXT, `customHeadersJson` TEXT, `enabled` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "protocol",
-            "columnName": "protocol",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "baseUrl",
-            "columnName": "baseUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelsUrl",
-            "columnName": "modelsUrl",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "apiKey",
-            "columnName": "apiKey",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "authType",
-            "columnName": "authType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "secretRef",
-            "columnName": "secretRef",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "headersJson",
-            "columnName": "headersJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "chatPath",
-            "columnName": "chatPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "responsesPath",
-            "columnName": "responsesPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "messagesPath",
-            "columnName": "messagesPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "modelsPath",
-            "columnName": "modelsPath",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "customHeadersJson",
-            "columnName": "customHeadersJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "ai_model_profiles",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `providerId` TEXT NOT NULL, `displayName` TEXT NOT NULL, `modelId` TEXT NOT NULL, `contextWindow` INTEGER NOT NULL, `maxOutputTokens` INTEGER NOT NULL, `capabilities` TEXT NOT NULL, `defaultParamsJson` TEXT, `enabled` INTEGER NOT NULL, `sortNumber` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "providerId",
-            "columnName": "providerId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "displayName",
-            "columnName": "displayName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelId",
-            "columnName": "modelId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "contextWindow",
-            "columnName": "contextWindow",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "maxOutputTokens",
-            "columnName": "maxOutputTokens",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "capabilities",
-            "columnName": "capabilities",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "defaultParamsJson",
-            "columnName": "defaultParamsJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_model_profiles_providerId",
-            "unique": false,
-            "columnNames": [
-              "providerId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_model_profiles_providerId` ON `${TABLE_NAME}` (`providerId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_task_presets",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `taskType` TEXT NOT NULL, `name` TEXT NOT NULL, `modelProfileId` TEXT NOT NULL, `promptTemplate` TEXT NOT NULL, `paramsJson` TEXT, `chunkPolicyJson` TEXT, `enabled` INTEGER NOT NULL, `isDefault` INTEGER NOT NULL, `sortNumber` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "taskType",
-            "columnName": "taskType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelProfileId",
-            "columnName": "modelProfileId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "promptTemplate",
-            "columnName": "promptTemplate",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "paramsJson",
-            "columnName": "paramsJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "chunkPolicyJson",
-            "columnName": "chunkPolicyJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "isDefault",
-            "columnName": "isDefault",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_task_presets_taskType",
-            "unique": false,
-            "columnNames": [
-              "taskType"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_task_presets_taskType` ON `${TABLE_NAME}` (`taskType`)"
-          },
-          {
-            "name": "index_ai_task_presets_modelProfileId",
-            "unique": false,
-            "columnNames": [
-              "modelProfileId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_task_presets_modelProfileId` ON `${TABLE_NAME}` (`modelProfileId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_artifacts",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `taskType` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER, `contentHash` TEXT NOT NULL, `promptHash` TEXT NOT NULL, `modelProfileId` TEXT NOT NULL, `status` INTEGER NOT NULL, `output` TEXT, `errorMessage` TEXT, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "taskType",
-            "columnName": "taskType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "contentHash",
-            "columnName": "contentHash",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "promptHash",
-            "columnName": "promptHash",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelProfileId",
-            "columnName": "modelProfileId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "output",
-            "columnName": "output",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "errorMessage",
-            "columnName": "errorMessage",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_artifacts_bookUrl_chapterIndex_taskType",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "taskType"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_artifacts_bookUrl_chapterIndex_taskType` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `taskType`)"
-          },
-          {
-            "name": "index_ai_artifacts_contentHash_promptHash_modelProfileId",
-            "unique": false,
-            "columnNames": [
-              "contentHash",
-              "promptHash",
-              "modelProfileId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_artifacts_contentHash_promptHash_modelProfileId` ON `${TABLE_NAME}` (`contentHash`, `promptHash`, `modelProfileId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_chat_conversations",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `reasoningLevel` TEXT NOT NULL, `modelProfileId` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "reasoningLevel",
-            "columnName": "reasoningLevel",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "modelProfileId",
-            "columnName": "modelProfileId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "ai_chat_messages",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `conversationId` TEXT NOT NULL, `role` TEXT NOT NULL, `partsJson` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `branchIndex` INTEGER NOT NULL, `isSelected` INTEGER NOT NULL, `parentMessageId` TEXT, `thinkingDuration` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "conversationId",
-            "columnName": "conversationId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "role",
-            "columnName": "role",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "partsJson",
-            "columnName": "partsJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "branchIndex",
-            "columnName": "branchIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "isSelected",
-            "columnName": "isSelected",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "parentMessageId",
-            "columnName": "parentMessageId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "thinkingDuration",
-            "columnName": "thinkingDuration",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_chat_messages_conversationId_createdAt",
-            "unique": false,
-            "columnNames": [
-              "conversationId",
-              "createdAt"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_chat_messages_conversationId_createdAt` ON `${TABLE_NAME}` (`conversationId`, `createdAt`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_memory",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`conversationId` TEXT NOT NULL, `key` TEXT NOT NULL, `value` TEXT NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`conversationId`, `key`))",
-        "fields": [
-          {
-            "fieldPath": "conversationId",
-            "columnName": "conversationId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "key",
-            "columnName": "key",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "value",
-            "columnName": "value",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "conversationId",
-            "key"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_memory_conversationId",
-            "unique": false,
-            "columnNames": [
-              "conversationId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_memory_conversationId` ON `${TABLE_NAME}` (`conversationId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "highlight_tag_rules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `title` TEXT NOT NULL, `pattern` TEXT NOT NULL, `enabled` INTEGER NOT NULL, `order` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "order",
-            "columnName": "order",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "tag_group_rules",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `pattern` TEXT NOT NULL, `groupName` TEXT NOT NULL, `order` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "pattern",
-            "columnName": "pattern",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "groupName",
-            "columnName": "groupName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "order",
-            "columnName": "order",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        }
-      },
-      {
-        "tableName": "book_content_processes",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER, `kind` TEXT NOT NULL, `stage` TEXT NOT NULL, `target` TEXT NOT NULL, `anchorJson` TEXT NOT NULL, `actionJson` TEXT NOT NULL, `styleJson` TEXT, `source` TEXT NOT NULL, `aiArtifactId` TEXT, `sourceContentHash` TEXT, `enabled` INTEGER NOT NULL, `sortOrder` INTEGER NOT NULL, `status` INTEGER NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "kind",
-            "columnName": "kind",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "stage",
-            "columnName": "stage",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "target",
-            "columnName": "target",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "anchorJson",
-            "columnName": "anchorJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "actionJson",
-            "columnName": "actionJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "styleJson",
-            "columnName": "styleJson",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "aiArtifactId",
-            "columnName": "aiArtifactId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "sourceContentHash",
-            "columnName": "sourceContentHash",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortOrder",
-            "columnName": "sortOrder",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_content_processes_bookUrl_chapterIndex_enabled_sortOrder",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "enabled",
-              "sortOrder"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_content_processes_bookUrl_chapterIndex_enabled_sortOrder` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `enabled`, `sortOrder`)"
-          },
-          {
-            "name": "index_book_content_processes_bookUrl_kind",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "kind"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_content_processes_bookUrl_kind` ON `${TABLE_NAME}` (`bookUrl`, `kind`)"
-          },
-          {
-            "name": "index_book_content_processes_aiArtifactId",
-            "unique": false,
-            "columnNames": [
-              "aiArtifactId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_content_processes_aiArtifactId` ON `${TABLE_NAME}` (`aiArtifactId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "ai_prompt_presets",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `taskType` TEXT NOT NULL, `name` TEXT NOT NULL, `instruction` TEXT NOT NULL, `enabled` INTEGER NOT NULL, `builtIn` INTEGER NOT NULL, `sortNumber` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "taskType",
-            "columnName": "taskType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "instruction",
-            "columnName": "instruction",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "builtIn",
-            "columnName": "builtIn",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sortNumber",
-            "columnName": "sortNumber",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_ai_prompt_presets_taskType_enabled_sortNumber",
-            "unique": false,
-            "columnNames": [
-              "taskType",
-              "enabled",
-              "sortNumber"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_ai_prompt_presets_taskType_enabled_sortNumber` ON `${TABLE_NAME}` (`taskType`, `enabled`, `sortNumber`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_character_profiles",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `name` TEXT NOT NULL, `aliasesJson` TEXT NOT NULL, `avatarUri` TEXT, `tagsJson` TEXT NOT NULL, `role` TEXT NOT NULL, `personality` TEXT NOT NULL, `summary` TEXT NOT NULL, `status` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "aliasesJson",
-            "columnName": "aliasesJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "avatarUri",
-            "columnName": "avatarUri",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "tagsJson",
-            "columnName": "tagsJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "role",
-            "columnName": "role",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "personality",
-            "columnName": "personality",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "summary",
-            "columnName": "summary",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_character_profiles_bookUrl_name",
-            "unique": true,
-            "columnNames": [
-              "bookUrl",
-              "name"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_book_character_profiles_bookUrl_name` ON `${TABLE_NAME}` (`bookUrl`, `name`)"
-          },
-          {
-            "name": "index_book_character_profiles_bookUrl_updatedAt",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "updatedAt"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_profiles_bookUrl_updatedAt` ON `${TABLE_NAME}` (`bookUrl`, `updatedAt`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_character_events",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `characterId` TEXT NOT NULL, `chapterIndex` INTEGER, `chapterTitle` TEXT NOT NULL, `eventTimeText` TEXT NOT NULL, `content` TEXT NOT NULL, `importance` INTEGER NOT NULL, `sourceTextHash` TEXT, `evidenceJson` TEXT NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "characterId",
-            "columnName": "characterId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "chapterTitle",
-            "columnName": "chapterTitle",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "eventTimeText",
-            "columnName": "eventTimeText",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "importance",
-            "columnName": "importance",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "sourceTextHash",
-            "columnName": "sourceTextHash",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "evidenceJson",
-            "columnName": "evidenceJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_character_events_bookUrl_characterId_chapterIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "characterId",
-              "chapterIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_events_bookUrl_characterId_chapterIndex` ON `${TABLE_NAME}` (`bookUrl`, `characterId`, `chapterIndex`)"
-          },
-          {
-            "name": "index_book_character_events_bookUrl_chapterIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_events_bookUrl_chapterIndex` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_character_relations",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `fromCharacterId` TEXT NOT NULL, `toCharacterId` TEXT NOT NULL, `relationType` TEXT NOT NULL, `summary` TEXT NOT NULL, `attitude` TEXT NOT NULL, `evidenceJson` TEXT NOT NULL, `chapterIndex` INTEGER, `status` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "fromCharacterId",
-            "columnName": "fromCharacterId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "toCharacterId",
-            "columnName": "toCharacterId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "relationType",
-            "columnName": "relationType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "summary",
-            "columnName": "summary",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "attitude",
-            "columnName": "attitude",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "evidenceJson",
-            "columnName": "evidenceJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_character_relations_bookUrl_fromCharacterId_toCharacterId",
-            "unique": true,
-            "columnNames": [
-              "bookUrl",
-              "fromCharacterId",
-              "toCharacterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_book_character_relations_bookUrl_fromCharacterId_toCharacterId` ON `${TABLE_NAME}` (`bookUrl`, `fromCharacterId`, `toCharacterId`)"
-          },
-          {
-            "name": "index_book_character_relations_bookUrl_fromCharacterId",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "fromCharacterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_relations_bookUrl_fromCharacterId` ON `${TABLE_NAME}` (`bookUrl`, `fromCharacterId`)"
-          },
-          {
-            "name": "index_book_character_relations_bookUrl_toCharacterId",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "toCharacterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_character_relations_bookUrl_toCharacterId` ON `${TABLE_NAME}` (`bookUrl`, `toCharacterId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_knowledge_entries",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `type` TEXT NOT NULL, `title` TEXT NOT NULL, `keywordsJson` TEXT NOT NULL, `content` TEXT NOT NULL, `scopeStartChapter` INTEGER, `scopeEndChapter` INTEGER, `priority` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `evidenceJson` TEXT NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "type",
-            "columnName": "type",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "keywordsJson",
-            "columnName": "keywordsJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "content",
-            "columnName": "content",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "scopeStartChapter",
-            "columnName": "scopeStartChapter",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "scopeEndChapter",
-            "columnName": "scopeEndChapter",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "priority",
-            "columnName": "priority",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "evidenceJson",
-            "columnName": "evidenceJson",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_knowledge_entries_bookUrl_type_priority",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "type",
-              "priority"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_knowledge_entries_bookUrl_type_priority` ON `${TABLE_NAME}` (`bookUrl`, `type`, `priority`)"
-          },
-          {
-            "name": "index_book_knowledge_entries_bookUrl_title",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "title"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_knowledge_entries_bookUrl_title` ON `${TABLE_NAME}` (`bookUrl`, `title`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_outline_nodes",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `parentId` TEXT, `nodeType` TEXT NOT NULL, `title` TEXT NOT NULL, `summary` TEXT NOT NULL, `startChapterIndex` INTEGER, `endChapterIndex` INTEGER, `order` INTEGER NOT NULL, `source` TEXT NOT NULL, `confidence` REAL NOT NULL, `schemaVersion` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "parentId",
-            "columnName": "parentId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "nodeType",
-            "columnName": "nodeType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "title",
-            "columnName": "title",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "summary",
-            "columnName": "summary",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "startChapterIndex",
-            "columnName": "startChapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "endChapterIndex",
-            "columnName": "endChapterIndex",
-            "affinity": "INTEGER"
-          },
-          {
-            "fieldPath": "order",
-            "columnName": "order",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true
-          },
-          {
-            "fieldPath": "schemaVersion",
-            "columnName": "schemaVersion",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_outline_nodes_bookUrl_nodeType_startChapterIndex_endChapterIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "nodeType",
-              "startChapterIndex",
-              "endChapterIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_outline_nodes_bookUrl_nodeType_startChapterIndex_endChapterIndex` ON `${TABLE_NAME}` (`bookUrl`, `nodeType`, `startChapterIndex`, `endChapterIndex`)"
-          },
-          {
-            "name": "index_book_outline_nodes_bookUrl_parentId_order",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "parentId",
-              "order"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_outline_nodes_bookUrl_parentId_order` ON `${TABLE_NAME}` (`bookUrl`, `parentId`, `order`)"
-          }
-        ]
-      },
-      {
-        "tableName": "read_aloud_voices",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `engineType` TEXT NOT NULL, `engineId` TEXT NOT NULL DEFAULT '', `speakerId` TEXT NOT NULL DEFAULT '', `displayName` TEXT NOT NULL, `traitsJson` TEXT NOT NULL DEFAULT '[]', `emotionCatalogJson` TEXT NOT NULL DEFAULT '[]', `managedBy` TEXT NOT NULL DEFAULT 'user', `enabled` INTEGER NOT NULL DEFAULT 1, `available` INTEGER NOT NULL DEFAULT 1, `revision` INTEGER NOT NULL DEFAULT 0, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "engineType",
-            "columnName": "engineType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "engineId",
-            "columnName": "engineId",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "speakerId",
-            "columnName": "speakerId",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "displayName",
-            "columnName": "displayName",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "traitsJson",
-            "columnName": "traitsJson",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'[]'"
-          },
-          {
-            "fieldPath": "emotionCatalogJson",
-            "columnName": "emotionCatalogJson",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'[]'"
-          },
-          {
-            "fieldPath": "managedBy",
-            "columnName": "managedBy",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'user'"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "available",
-            "columnName": "available",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "revision",
-            "columnName": "revision",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_read_aloud_voices_engineType_engineId_speakerId",
-            "unique": true,
-            "columnNames": [
-              "engineType",
-              "engineId",
-              "speakerId"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_read_aloud_voices_engineType_engineId_speakerId` ON `${TABLE_NAME}` (`engineType`, `engineId`, `speakerId`)"
-          },
-          {
-            "name": "index_read_aloud_voices_enabled_displayName",
-            "unique": false,
-            "columnNames": [
-              "enabled",
-              "displayName"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_read_aloud_voices_enabled_displayName` ON `${TABLE_NAME}` (`enabled`, `displayName`)"
-          }
-        ]
-      },
-      {
-        "tableName": "book_voice_bindings",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bookUrl` TEXT NOT NULL, `subjectType` TEXT NOT NULL, `subjectId` TEXT NOT NULL, `voiceId` TEXT NOT NULL, `locked` INTEGER NOT NULL DEFAULT 0, `source` TEXT NOT NULL DEFAULT 'user', `confidence` REAL NOT NULL DEFAULT 1, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`bookUrl`, `subjectType`, `subjectId`))",
-        "fields": [
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "subjectType",
-            "columnName": "subjectType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "subjectId",
-            "columnName": "subjectId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "voiceId",
-            "columnName": "voiceId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "locked",
-            "columnName": "locked",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'user'"
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "bookUrl",
-            "subjectType",
-            "subjectId"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_book_voice_bindings_bookUrl_subjectType",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "subjectType"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_voice_bindings_bookUrl_subjectType` ON `${TABLE_NAME}` (`bookUrl`, `subjectType`)"
-          },
-          {
-            "name": "index_book_voice_bindings_voiceId",
-            "unique": false,
-            "columnNames": [
-              "voiceId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_book_voice_bindings_voiceId` ON `${TABLE_NAME}` (`voiceId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "chapter_speech_analysis",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `contentHash` TEXT NOT NULL, `resolverVersion` TEXT NOT NULL, `characterRevision` TEXT NOT NULL DEFAULT '', `status` TEXT NOT NULL DEFAULT 'pending', `error` TEXT NOT NULL DEFAULT '', `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "contentHash",
-            "columnName": "contentHash",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "resolverVersion",
-            "columnName": "resolverVersion",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "characterRevision",
-            "columnName": "characterRevision",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "status",
-            "columnName": "status",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'pending'"
-          },
-          {
-            "fieldPath": "error",
-            "columnName": "error",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_chapter_speech_analysis_bookUrl_chapterIndex_contentHash_resolverVersion",
-            "unique": true,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "contentHash",
-              "resolverVersion"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapter_speech_analysis_bookUrl_chapterIndex_contentHash_resolverVersion` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `contentHash`, `resolverVersion`)"
-          },
-          {
-            "name": "index_chapter_speech_analysis_bookUrl_chapterIndex_updatedAt",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "updatedAt"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_analysis_bookUrl_chapterIndex_updatedAt` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `updatedAt`)"
-          }
-        ]
-      },
-      {
-        "tableName": "chapter_speech_segments",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `analysisId` TEXT NOT NULL, `bookUrl` TEXT NOT NULL, `chapterIndex` INTEGER NOT NULL, `paragraphIndex` INTEGER NOT NULL, `start` INTEGER NOT NULL, `end` INTEGER NOT NULL, `chapterPosition` INTEGER NOT NULL, `text` TEXT NOT NULL, `roleType` TEXT NOT NULL, `characterId` TEXT, `characterName` TEXT NOT NULL DEFAULT '', `emotion` TEXT NOT NULL DEFAULT '', `confidence` REAL NOT NULL DEFAULT 0, `source` TEXT NOT NULL, `userLocked` INTEGER NOT NULL DEFAULT 0, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "analysisId",
-            "columnName": "analysisId",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "bookUrl",
-            "columnName": "bookUrl",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterIndex",
-            "columnName": "chapterIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "paragraphIndex",
-            "columnName": "paragraphIndex",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "start",
-            "columnName": "start",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "end",
-            "columnName": "end",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "chapterPosition",
-            "columnName": "chapterPosition",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "text",
-            "columnName": "text",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "roleType",
-            "columnName": "roleType",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "characterId",
-            "columnName": "characterId",
-            "affinity": "TEXT"
-          },
-          {
-            "fieldPath": "characterName",
-            "columnName": "characterName",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "emotion",
-            "columnName": "emotion",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "confidence",
-            "columnName": "confidence",
-            "affinity": "REAL",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "source",
-            "columnName": "source",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "userLocked",
-            "columnName": "userLocked",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "0"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_chapter_speech_segments_analysisId_paragraphIndex_start_end",
-            "unique": true,
-            "columnNames": [
-              "analysisId",
-              "paragraphIndex",
-              "start",
-              "end"
-            ],
-            "orders": [],
-            "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_chapter_speech_segments_analysisId_paragraphIndex_start_end` ON `${TABLE_NAME}` (`analysisId`, `paragraphIndex`, `start`, `end`)"
-          },
-          {
-            "name": "index_chapter_speech_segments_bookUrl_chapterIndex_paragraphIndex",
-            "unique": false,
-            "columnNames": [
-              "bookUrl",
-              "chapterIndex",
-              "paragraphIndex"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_segments_bookUrl_chapterIndex_paragraphIndex` ON `${TABLE_NAME}` (`bookUrl`, `chapterIndex`, `paragraphIndex`)"
-          },
-          {
-            "name": "index_chapter_speech_segments_characterId",
-            "unique": false,
-            "columnNames": [
-              "characterId"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_chapter_speech_segments_characterId` ON `${TABLE_NAME}` (`characterId`)"
-          }
-        ]
-      },
-      {
-        "tableName": "cloud_tts_engines",
-        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `provider` TEXT NOT NULL, `baseUrl` TEXT NOT NULL DEFAULT '', `apiKey` TEXT NOT NULL DEFAULT '', `secretKey` TEXT NOT NULL DEFAULT '', `region` TEXT NOT NULL DEFAULT '', `appId` TEXT NOT NULL DEFAULT '', `model` TEXT NOT NULL DEFAULT '', `optionsJson` TEXT NOT NULL DEFAULT '{}', `enabled` INTEGER NOT NULL DEFAULT 1, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
-        "fields": [
-          {
-            "fieldPath": "id",
-            "columnName": "id",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "name",
-            "columnName": "name",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "provider",
-            "columnName": "provider",
-            "affinity": "TEXT",
-            "notNull": true
-          },
-          {
-            "fieldPath": "baseUrl",
-            "columnName": "baseUrl",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "apiKey",
-            "columnName": "apiKey",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "secretKey",
-            "columnName": "secretKey",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "region",
-            "columnName": "region",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "appId",
-            "columnName": "appId",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "model",
-            "columnName": "model",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "''"
-          },
-          {
-            "fieldPath": "optionsJson",
-            "columnName": "optionsJson",
-            "affinity": "TEXT",
-            "notNull": true,
-            "defaultValue": "'{}'"
-          },
-          {
-            "fieldPath": "enabled",
-            "columnName": "enabled",
-            "affinity": "INTEGER",
-            "notNull": true,
-            "defaultValue": "1"
-          },
-          {
-            "fieldPath": "createdAt",
-            "columnName": "createdAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          },
-          {
-            "fieldPath": "updatedAt",
-            "columnName": "updatedAt",
-            "affinity": "INTEGER",
-            "notNull": true
-          }
-        ],
-        "primaryKey": {
-          "autoGenerate": false,
-          "columnNames": [
-            "id"
-          ]
-        },
-        "indices": [
-          {
-            "name": "index_cloud_tts_engines_provider_enabled",
-            "unique": false,
-            "columnNames": [
-              "provider",
-              "enabled"
-            ],
-            "orders": [],
-            "createSql": "CREATE INDEX IF NOT EXISTS `index_cloud_tts_engines_provider_enabled` ON `${TABLE_NAME}` (`provider`, `enabled`)"
-          }
-        ]
-      }
-    ],
-    "views": [
-      {
-        "viewName": "book_sources_part",
-        "createSql": "CREATE VIEW `${VIEW_NAME}` AS select bookSourceUrl, bookSourceName, bookSourceGroup, customOrder, enabled, enabledExplore, \n    (loginUrl is not null and trim(loginUrl) <> '') hasLoginUrl, lastUpdateTime, respondTime, weight, \n    (exploreUrl is not null and trim(exploreUrl) <> '') hasExploreUrl \n    from book_sources"
-      }
-    ],
-    "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, 'f5e225667da6bf6e50b9435bfb2ffb6d')"
-    ]
-  }
-}

+ 2 - 4
app/src/main/java/io/legado/app/data/AppDatabase.kt

@@ -108,7 +108,7 @@ val appDb by lazy {
 }
 
 @Database(
-    version = 97,
+    version = 95,
     exportSchema = true,
     entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
         ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
@@ -178,9 +178,7 @@ val appDb by lazy {
         AutoMigration(from = 91, to = 92),
         AutoMigration(from = 92, to = 93),
         AutoMigration(from = 93, to = 94),
-        AutoMigration(from = 94, to = 95),
-        AutoMigration(from = 95, to = 96),
-        AutoMigration(from = 96, to = 97)
+        AutoMigration(from = 94, to = 95)
     ]
 )
 abstract class AppDatabase : RoomDatabase() {

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/import/local/ImportBookScreen.kt

@@ -345,7 +345,7 @@ fun ImportBookScreen(
 
     pendingSingleAddBook?.let { book ->
         AppAlertDialog(
-            show = true,
+            data = book,
             onDismissRequest = { pendingSingleAddBook = null },
             title = stringResource(R.string.add_to_bookshelf),
             text = stringResource(R.string.check_add_bookshelf, book.name),

+ 24 - 18
app/src/main/java/io/legado/app/ui/book/info/BookInfoScreen.kt

@@ -310,24 +310,30 @@ private fun BookInfoScreenContent(
                                     onSourceClick = { onIntent(BookInfoIntent.ChangeSourceClick) },
                                     onReadRecordClick = { onIntent(BookInfoIntent.ReadRecordClick) },
                                 )
-                                BookInfoCharacters(
-                                    characters = state.characters,
-                                    onCharacterClick = {
-                                        onIntent(BookInfoIntent.CharacterClick(it))
-                                    },
-                                    onNetworkClick = {
-                                        onIntent(BookInfoIntent.CharacterNetworkClick)
-                                    },
-                                    onViewAllClick = {
-                                        onIntent(BookInfoIntent.CharacterListClick)
-                                    },
-                                    onKnowledgeClick = {
-                                        onIntent(BookInfoIntent.KnowledgeListClick)
-                                    },
-                                    onEventsClick = {
-                                        onIntent(BookInfoIntent.EventListClick)
-                                    },
-                                )
+                                if (
+                                    state.characters.isNotEmpty() ||
+                                    state.knowledgeEntries.isNotEmpty() ||
+                                    state.recentEvents.isNotEmpty()
+                                ) {
+                                    BookInfoCharacters(
+                                        characters = state.characters,
+                                        onCharacterClick = {
+                                            onIntent(BookInfoIntent.CharacterClick(it))
+                                        },
+                                        onNetworkClick = {
+                                            onIntent(BookInfoIntent.CharacterNetworkClick)
+                                        },
+                                        onViewAllClick = {
+                                            onIntent(BookInfoIntent.CharacterListClick)
+                                        },
+                                        onKnowledgeClick = {
+                                            onIntent(BookInfoIntent.KnowledgeListClick)
+                                        },
+                                        onEventsClick = {
+                                            onIntent(BookInfoIntent.EventListClick)
+                                        },
+                                    )
+                                }
                                 state.relatedBooks.forEach { module ->
                                     RelatedBooksBanner(
                                         title = module.title,

+ 14 - 1
app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditActivity.kt

@@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable
 import io.legado.app.ui.theme.AppTheme
 import io.legado.app.base.BaseComposeActivity
 import io.legado.app.ui.book.changecover.ChangeCoverDialog
+import io.legado.app.ui.main.MainActivity
 
 class BookInfoEditActivity : BaseComposeActivity(), ChangeCoverDialog.CallBack {
 
@@ -24,7 +25,19 @@ class BookInfoEditActivity : BaseComposeActivity(), ChangeCoverDialog.CallBack {
                             setResult(RESULT_OK)
                             finish()
                         }
-                    }
+                    },
+                    onOpenCharacterList = { bookUrl ->
+                        startActivity(MainActivity.createBookCharacterListIntent(this, bookUrl))
+                    },
+                    onOpenCharacterNetwork = { bookUrl ->
+                        startActivity(MainActivity.createBookCharacterNetworkIntent(this, bookUrl))
+                    },
+                    onOpenKnowledgeList = { bookUrl ->
+                        startActivity(MainActivity.createBookKnowledgeListIntent(this, bookUrl))
+                    },
+                    onOpenEventList = { bookUrl ->
+                        startActivity(MainActivity.createBookEventListIntent(this, bookUrl))
+                    },
                 )
             }
         }

+ 83 - 4
app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt

@@ -22,11 +22,15 @@ import androidx.compose.foundation.text.input.rememberTextFieldState
 import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.outlined.FormatListBulleted
+import androidx.compose.material.icons.filled.Book
+import androidx.compose.material.icons.filled.Group
 import androidx.compose.material.icons.filled.Add
 import androidx.compose.material.icons.filled.FolderOpen
 import androidx.compose.material.icons.filled.ImageSearch
 import androidx.compose.material.icons.filled.Replay
 import androidx.compose.material.icons.filled.Save
+import androidx.compose.material.icons.filled.Timeline
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.ExposedDropdownMenuAnchorType
@@ -80,7 +84,11 @@ import sh.calvin.reorderable.rememberReorderableLazyListState
 fun BookInfoEditScreen(
     viewModel: BookInfoEditViewModel,
     onBack: () -> Unit,
-    onSave: () -> Unit
+    onSave: () -> Unit,
+    onOpenCharacterList: (String) -> Unit,
+    onOpenCharacterNetwork: (String) -> Unit,
+    onOpenKnowledgeList: (String) -> Unit,
+    onOpenEventList: (String) -> Unit,
 ) {
     val uiState by viewModel.uiState.collectAsStateWithLifecycle()
     val scrollBehavior = GlassTopAppBarDefaults.defaultScrollBehavior()
@@ -114,7 +122,11 @@ fun BookInfoEditScreen(
                         .imePadding()
                         .verticalScroll(rememberScrollState()),
                     uiState = uiState,
-                    viewModel = viewModel
+                    viewModel = viewModel,
+                    onOpenCharacterList = onOpenCharacterList,
+                    onOpenCharacterNetwork = onOpenCharacterNetwork,
+                    onOpenKnowledgeList = onOpenKnowledgeList,
+                    onOpenEventList = onOpenEventList,
                 )
             }
         }
@@ -126,7 +138,11 @@ fun BookInfoEditScreen(
 fun BookInfoEditContent(
     modifier: Modifier = Modifier,
     uiState: BookInfoEditUiState,
-    viewModel: BookInfoEditViewModel
+    viewModel: BookInfoEditViewModel,
+    onOpenCharacterList: (String) -> Unit,
+    onOpenCharacterNetwork: (String) -> Unit,
+    onOpenKnowledgeList: (String) -> Unit,
+    onOpenEventList: (String) -> Unit,
 ) {
     val context = LocalContext.current
 
@@ -193,6 +209,14 @@ fun BookInfoEditContent(
             }
         }
         Spacer(modifier = Modifier.height(16.dp))
+        BookKnowledgeEditCard(
+            bookUrl = uiState.book?.bookUrl.orEmpty(),
+            onOpenCharacterList = onOpenCharacterList,
+            onOpenCharacterNetwork = onOpenCharacterNetwork,
+            onOpenKnowledgeList = onOpenKnowledgeList,
+            onOpenEventList = onOpenEventList,
+        )
+        Spacer(modifier = Modifier.height(16.dp))
         SwitchSettingItem(
             title = stringResource(R.string.fixed_book_type),
             description = stringResource(R.string.fixed_book_type_summary),
@@ -258,6 +282,61 @@ fun BookInfoEditContent(
     }
 }
 
+@Composable
+private fun BookKnowledgeEditCard(
+    bookUrl: String,
+    onOpenCharacterList: (String) -> Unit,
+    onOpenCharacterNetwork: (String) -> Unit,
+    onOpenKnowledgeList: (String) -> Unit,
+    onOpenEventList: (String) -> Unit,
+) {
+    NormalCard(modifier = Modifier.fillMaxWidth()) {
+        Column(
+            modifier = Modifier.padding(16.dp),
+            verticalArrangement = Arrangement.spacedBy(12.dp),
+        ) {
+            AppText(
+                text = stringResource(R.string.book_info_knowledge),
+                style = LegadoTheme.typography.titleMedium,
+            )
+            LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
+                item {
+                    MediumOutlinedButton(
+                        onClick = { onOpenCharacterList(bookUrl) },
+                        enabled = bookUrl.isNotEmpty(),
+                        icon = Icons.AutoMirrored.Outlined.FormatListBulleted,
+                        text = stringResource(R.string.book_characters),
+                    )
+                }
+                item {
+                    MediumOutlinedButton(
+                        onClick = { onOpenCharacterNetwork(bookUrl) },
+                        enabled = bookUrl.isNotEmpty(),
+                        icon = Icons.Default.Group,
+                        text = stringResource(R.string.character_network),
+                    )
+                }
+                item {
+                    MediumOutlinedButton(
+                        onClick = { onOpenKnowledgeList(bookUrl) },
+                        enabled = bookUrl.isNotEmpty(),
+                        icon = Icons.Default.Book,
+                        text = stringResource(R.string.book_knowledge),
+                    )
+                }
+                item {
+                    MediumOutlinedButton(
+                        onClick = { onOpenEventList(bookUrl) },
+                        enabled = bookUrl.isNotEmpty(),
+                        icon = Icons.Default.Timeline,
+                        text = stringResource(R.string.plot_events),
+                    )
+                }
+            }
+        }
+    }
+}
+
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun BookTypeDropdown(
@@ -413,7 +492,7 @@ fun KindEditor(
     if (editingIndex != null) {
         val isAdding = editingIndex == -1
         AppAlertDialog(
-            show = true,
+            show = editingIndex != null,
             onDismissRequest = { editingIndex = null },
             title = if (isAdding) {
                 stringResource(R.string.add_tag)

+ 2 - 1
app/src/main/java/io/legado/app/ui/book/knowledge/CharacterAvatarCropDialog.kt

@@ -39,6 +39,7 @@ import kotlin.math.roundToInt
 @Composable
 fun CharacterAvatarCropDialog(
     sourceUri: Uri?,
+    show: Boolean = sourceUri != null,
     onDismissRequest: () -> Unit,
     onConfirm: (CharacterAvatarCrop) -> Unit,
 ) {
@@ -52,7 +53,7 @@ fun CharacterAvatarCropDialog(
     var imageHeight by remember(sourceUri) { mutableFloatStateOf(1f) }
 
     AppAlertDialog(
-        show = true,
+        show = show,
         onDismissRequest = onDismissRequest,
         title = stringResource(R.string.character_avatar_crop),
         confirmText = stringResource(R.string.apply),

+ 2 - 1
app/src/main/java/io/legado/app/ui/book/read/sheet/AutoReadSheet.kt

@@ -35,6 +35,7 @@ import kotlin.math.roundToInt
 
 @Composable
 fun AutoReadSheet(
+    show: Boolean,
     onDismissRequest: () -> Unit,
     onIntent: (ReadBookIntent) -> Unit,
     onOpenChapterList: () -> Unit,
@@ -42,7 +43,7 @@ fun AutoReadSheet(
     onShowPageAnimConfig: () -> Unit,
 ) {
     AppModalBottomSheet(
-        show = true,
+        show = show,
         onDismissRequest = onDismissRequest,
         title = stringResource(R.string.auto_page_speed),
     ) {

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/read/sheet/ContentProcessesSheet.kt

@@ -109,7 +109,7 @@ fun ContentProcessesSheet(
 
                 viewingItem?.let { item ->
                     AppAlertDialog(
-                        show = true,
+                        data = item,
                         onDismissRequest = { viewingItem = null },
                         title = contentProcessTitle(item),
                         content = {

+ 2 - 1
app/src/main/java/io/legado/app/ui/book/read/sheet/PaddingConfigSheet.kt

@@ -39,11 +39,12 @@ import kotlinx.coroutines.launch
 
 @Composable
 fun PaddingConfigSheet(
+    show: Boolean,
     onDismissRequest: () -> Unit,
     onIntent: (ReadBookIntent) -> Unit,
 ) {
     AppModalBottomSheet(
-        show = true,
+        show = show,
         onDismissRequest = {
             onIntent(ReadBookIntent.SaveReadStyleConfig)
             onDismissRequest()

+ 1 - 2
app/src/main/java/io/legado/app/ui/book/read/sheet/ReadAloudConfigSheet.kt

@@ -84,8 +84,7 @@ fun ReadAloudConfigSheet(
                 selectedTabIndex = pagerState.currentPage,
                 onTabSelected = { page ->
                     scope.launch { pagerState.animateScrollToPage(page) }
-                },
-                modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
+                }
             )
             HorizontalPager(
                 state = pagerState,

+ 4 - 4
app/src/main/java/io/legado/app/ui/book/readaloud/casting/BookVoiceCastingScreen.kt

@@ -42,6 +42,7 @@ import io.legado.app.ui.widget.components.card.GlassCard
 import io.legado.app.ui.widget.components.icon.AppIcon
 import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
 import io.legado.app.ui.widget.components.settingItem.SettingItem
+import io.legado.app.ui.widget.components.settingItem.TinySettingItem
 import io.legado.app.ui.widget.components.text.AnimatedTextLine
 import io.legado.app.ui.widget.components.text.AppText
 import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar
@@ -280,8 +281,7 @@ private fun VoicePickerSheet(
         if (picker == null) return@AppModalBottomSheet
         Column(
             modifier = Modifier
-                .fillMaxWidth()
-                .padding(horizontal = 16.dp, vertical = 8.dp),
+                .fillMaxWidth(),
             verticalArrangement = Arrangement.spacedBy(8.dp),
         ) {
             if (voices.none { it.selectable }) {
@@ -300,7 +300,7 @@ private fun VoicePickerSheet(
                         items = voices,
                         key = VoiceOptionUi::id,
                     ) { voice ->
-                        SettingItem(
+                        TinySettingItem(
                             title = voice.name,
                             description = voiceDescription(voice),
                             enabled = voice.selectable,
@@ -319,7 +319,7 @@ private fun VoicePickerSheet(
                 }
             }
             if (picker.selectedVoiceId != null) {
-                SettingItem(
+                TinySettingItem(
                     title = stringResource(R.string.clear_voice_binding),
                     color = LegadoTheme.colorScheme.errorContainer,
                     onClick = { onIntent(BookVoiceCastingIntent.ClearBinding) },

+ 2 - 0
app/src/main/java/io/legado/app/ui/book/readaloud/cloudtts/CloudTtsContract.kt

@@ -13,6 +13,7 @@ data class CloudTtsUiState(
     val availableEngines: ImmutableList<TtsEngineOptionUi> = persistentListOf(),
     val engineEditor: CloudTtsEngineEditorUi? = null,
     val voiceEditor: TtsVoicePresetEditorUi? = null,
+    val showVoiceEnginePicker: Boolean = false,
     val activeDialog: CloudTtsDialog? = null,
     val testing: Boolean = false,
     val discovering: Boolean = false,
@@ -94,6 +95,7 @@ sealed interface CloudTtsIntent {
     data class UpdateVoiceEditor(val editor: TtsVoicePresetEditorUi) : CloudTtsIntent
     data object DismissEngineEditor : CloudTtsIntent
     data object DismissVoiceEditor : CloudTtsIntent
+    data object DismissVoiceEnginePicker : CloudTtsIntent
     data class SelectEngine(val engineType: String, val engineId: String) : CloudTtsIntent
     data object DiscoverVoices : CloudTtsIntent
     data class SelectVoice(val id: String) : CloudTtsIntent

+ 284 - 227
app/src/main/java/io/legado/app/ui/book/readaloud/cloudtts/CloudTtsScreen.kt

@@ -2,7 +2,7 @@ package io.legado.app.ui.book.readaloud.cloudtts
 
 import android.content.ClipData
 import android.media.MediaPlayer
-import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -11,16 +11,11 @@ import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material.icons.filled.ContentCopy
+import androidx.compose.material.icons.filled.Delete
 import androidx.compose.material.icons.filled.RecordVoiceOver
-import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.Button
-import androidx.compose.material3.DropdownMenu
-import androidx.compose.material3.DropdownMenuItem
-import androidx.compose.material3.HorizontalDivider
-import androidx.compose.material3.ListItem
-import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.Text
-import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.LaunchedEffect
@@ -39,14 +34,20 @@ import io.legado.app.domain.model.readaloud.CloudTtsProviderType
 import io.legado.app.domain.model.readaloud.ReadAloudVoice
 import io.legado.app.domain.model.readaloud.profile
 import io.legado.app.ui.widget.components.AppScaffold
-import io.legado.app.ui.widget.components.alert.AppAlertDialog
+import io.legado.app.ui.widget.components.AppFloatingActionButton
+import io.legado.app.ui.widget.components.AppTextField
+import io.legado.app.ui.widget.components.SearchBar
+import io.legado.app.ui.widget.components.button.series.MediumTonalButton
+import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
+import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
 import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
-import io.legado.app.ui.widget.components.settingItem.ClickableSettingItem
 import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem
+import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem
+import io.legado.app.ui.widget.components.settingItem.TinySwitchSettingItem
+import io.legado.app.ui.widget.components.text.AppText
 import io.legado.app.ui.widget.components.tabRow.AppTabRow
 import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar
 import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults
-import io.legado.app.ui.widget.components.topbar.TopBarActionButton
 import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
 import io.legado.app.utils.toastOnUi
 import kotlinx.coroutines.flow.Flow
@@ -86,28 +87,31 @@ fun CloudTtsScreen(
         }
     }
     val scrollBehavior = GlassTopAppBarDefaults.defaultScrollBehavior()
-    AppScaffold(topBar = {
+    AppScaffold(
+        topBar = {
         GlassMediumFlexibleTopAppBar(
             title = stringResource(R.string.read_aloud_engines_and_voices),
             navigationIcon = { TopBarNavigationButton(onClick = onBack) },
-            actions = {
-                if (state.selectedTab == CloudTtsTab.Engines) {
-                    TopBarActionButton(
-                        onClick = { onIntent(CloudTtsIntent.AddEngine) },
-                        imageVector = Icons.Default.Add,
-                        contentDescription = stringResource(R.string.cloud_tts_add_engine),
-                    )
-                } else {
-                    TopBarActionButton(
-                        onClick = { onIntent(CloudTtsIntent.AddVoice) },
-                        imageVector = Icons.Default.RecordVoiceOver,
-                        contentDescription = stringResource(R.string.cloud_tts_add_voice),
-                    )
-                }
-            },
             scrollBehavior = scrollBehavior,
         )
-    }) { padding ->
+        },
+        floatingActionButton = {
+            AppFloatingActionButton(
+                onClick = {
+                    onIntent(
+                        if (state.selectedTab == CloudTtsTab.Engines) CloudTtsIntent.AddEngine
+                        else CloudTtsIntent.AddVoice
+                    )
+                },
+                icon = if (state.selectedTab == CloudTtsTab.Engines) Icons.Default.Add
+                    else Icons.Default.RecordVoiceOver,
+                tooltipText = stringResource(
+                    if (state.selectedTab == CloudTtsTab.Engines) R.string.cloud_tts_add_engine
+                    else R.string.cloud_tts_add_voice
+                ),
+            )
+        },
+    ) { padding ->
         LazyColumn(Modifier.fillMaxSize().padding(padding)) {
             item {
                 AppTabRow(
@@ -122,77 +126,120 @@ fun CloudTtsScreen(
                 )
             }
             if (state.selectedTab == CloudTtsTab.Voices) {
-                item { Text(stringResource(R.string.cloud_tts_choose_engine), Modifier.padding(horizontal = 24.dp, vertical = 12.dp)) }
-                items(
-                    items = state.availableEngines,
-                    key = { "available:${it.engineType}:${it.engineId}" },
-                ) { engine ->
-                    ClickableSettingItem(
-                        title = engine.title,
-                        description = "${engine.summary}\n${engine.catalogHint}",
-                        option = stringResource(R.string.cloud_tts_select_voice),
-                        onClick = { onIntent(CloudTtsIntent.AddVoiceForEngine(engine.engineType, engine.engineId)) },
-                    )
-                }
-                item { HorizontalDivider(); Text(stringResource(R.string.cloud_tts_saved_voices), Modifier.padding(24.dp, 12.dp)) }
                 if (state.voices.isEmpty() && !state.loading) {
-                    item { Text(stringResource(R.string.cloud_tts_no_saved_voices), Modifier.padding(24.dp)) }
+                    item { AppText(stringResource(R.string.cloud_tts_no_saved_voices), Modifier.padding(24.dp)) }
                 }
                 items(state.voices, key = { "voice:${it.id}" }) { voice ->
-                    ListItem(
-                        supportingContent = { Text(voice.summary) },
+                    TinyClickableSettingItem(
+                        title = voice.title,
+                        description = voice.summary,
                         trailingContent = if (voice.deletable) {{
-                            TextButton(onClick = { onIntent(CloudTtsIntent.DeleteVoice(voice.id)) }) {
-                                Text(stringResource(R.string.delete))
-                            }
+                            MediumTonalButton(
+                                onClick = { onIntent(CloudTtsIntent.DeleteVoice(voice.id)) },
+                                icon = Icons.Default.Delete,
+                                contentDescription = stringResource(R.string.delete),
+                            )
                         }} else null,
-                        modifier = if (voice.editable) Modifier.clickable {
-                            onIntent(CloudTtsIntent.EditVoice(voice.id))
-                        } else Modifier,
-                    ) { Text(voice.title) }
+                        onClick = {
+                            if (voice.editable) onIntent(CloudTtsIntent.EditVoice(voice.id))
+                        },
+                    )
                 }
             } else {
-                item { Text(stringResource(R.string.cloud_tts_engines), Modifier.padding(horizontal = 24.dp, vertical = 12.dp)) }
+                item { AppText(stringResource(R.string.cloud_tts_engines), Modifier.padding(horizontal = 24.dp, vertical = 12.dp)) }
                 if (state.engines.isEmpty() && !state.loading) {
-                    item { Text(stringResource(R.string.cloud_tts_no_engines), Modifier.padding(24.dp)) }
+                    item { AppText(stringResource(R.string.cloud_tts_no_engines), Modifier.padding(24.dp)) }
                 }
                 items(state.engines, key = { "engine:${it.id}" }) { engine ->
-                    ListItem(
-                        supportingContent = { Text(engine.summary) },
-                        trailingContent = { TextButton(onClick = {
-                            onIntent(CloudTtsIntent.DeleteEngine(engine.id))
-                        }) { Text(stringResource(R.string.delete)) } },
-                        modifier = Modifier.clickable { onIntent(CloudTtsIntent.EditEngine(engine.id)) },
-                    ) { Text(engine.title) }
+                    TinyClickableSettingItem(
+                        title = engine.title,
+                        description = engine.summary,
+                        trailingContent = {
+                            MediumTonalButton(
+                                onClick = { onIntent(CloudTtsIntent.DeleteEngine(engine.id)) },
+                                icon = Icons.Default.Delete,
+                                contentDescription = stringResource(R.string.delete),
+                            )
+                        },
+                        onClick = { onIntent(CloudTtsIntent.EditEngine(engine.id)) },
+                    )
                 }
-                item { HorizontalDivider(); Text(stringResource(R.string.cloud_tts_available_engines), Modifier.padding(24.dp, 12.dp)) }
+                item { AppText(stringResource(R.string.cloud_tts_available_engines), Modifier.padding(24.dp, 12.dp)) }
                 items(state.availableEngines, key = { "engine-info:${it.engineType}:${it.engineId}" }) { engine ->
-                    ClickableSettingItem(
+                    TinyClickableSettingItem(
                         title = engine.title,
-                        description = engine.summary,
-                        option = engine.catalogHint,
+                        description = listOf(engine.summary, engine.catalogHint)
+                            .filter(String::isNotBlank)
+                            .joinToString(" | "),
                         onClick = { onIntent(CloudTtsIntent.AddVoiceForEngine(engine.engineType, engine.engineId)) },
                     )
                 }
             }
         }
     }
-    state.engineEditor?.let { CloudTtsEngineEditorDialog(state, it, onIntent) }
-    state.voiceEditor?.let { TtsVoicePresetEditorSheet(state, it, onIntent) }
-    AppAlertDialog(
+    CloudTtsEngineEditorSheet(state, state.engineEditor, onIntent)
+    VoiceEnginePickerSheet(state.showVoiceEnginePicker, state, onIntent)
+    TtsVoicePresetEditorSheet(state, state.voiceEditor, onIntent)
+    AppModalBottomSheet(
         data = state.activeDialog as? CloudTtsDialog.Error,
         onDismissRequest = { onIntent(CloudTtsIntent.DismissError) },
         title = stringResource(R.string.cloud_tts_error),
-        textProvider = { message },
-        confirmText = stringResource(R.string.cloud_tts_copy_error),
-        onConfirm = { onIntent(CloudTtsIntent.CopyError) },
-        dismissText = stringResource(R.string.close),
-        onDismiss = { onIntent(CloudTtsIntent.DismissError) },
-    )
+        startAction = {
+            MediumTonalButton(
+                onClick = { onIntent(CloudTtsIntent.DismissError) },
+                icon = Icons.Default.Close,
+                contentDescription = stringResource(R.string.close),
+            )
+        },
+        endAction = {
+            MediumTonalButton(
+                onClick = { onIntent(CloudTtsIntent.CopyError) },
+                icon = Icons.Default.ContentCopy,
+                contentDescription = stringResource(R.string.cloud_tts_copy_error),
+            )
+        },
+    ) { error ->
+        AppText(
+            text = error.message,
+            modifier = Modifier.padding(horizontal = 16.dp),
+        )
+    }
 }
 
 @Composable
-private fun CloudTtsEngineEditorDialog(
+private fun CloudTtsEngineEditorSheet(
+    state: CloudTtsUiState,
+    editor: CloudTtsEngineEditorUi?,
+    onIntent: (CloudTtsIntent) -> Unit,
+) {
+    AppModalBottomSheet(
+        data = editor,
+        onDismissRequest = { onIntent(CloudTtsIntent.DismissEngineEditor) },
+        title = stringResource(
+            if (editor?.editingEngineId == null) R.string.cloud_tts_add_engine
+            else R.string.cloud_tts_edit_engine
+        ),
+        startAction = {
+            MediumTonalButton(
+                onClick = { onIntent(CloudTtsIntent.DismissEngineEditor) },
+                icon = Icons.Default.Close,
+                contentDescription = stringResource(R.string.cancel),
+            )
+        },
+        endAction = {
+            MediumTonalButton(
+                onClick = { onIntent(CloudTtsIntent.Save) },
+                icon = Icons.Default.Check,
+                contentDescription = stringResource(R.string.save),
+            )
+        },
+    ) { currentEditor ->
+        CloudTtsEngineEditorContent(state, currentEditor, onIntent)
+    }
+}
+
+@Composable
+private fun CloudTtsEngineEditorContent(
     state: CloudTtsUiState,
     editor: CloudTtsEngineEditorUi,
     onIntent: (CloudTtsIntent) -> Unit,
@@ -210,19 +257,13 @@ private fun CloudTtsEngineEditorDialog(
     val provider = CloudTtsProviderType.entries.firstOrNull { it.storageValue == editor.provider }
         ?: CloudTtsProviderType.Mimo
     val profile = provider.profile
-    AlertDialog(
-        onDismissRequest = { onIntent(CloudTtsIntent.DismissEngineEditor) },
-        title = { Text(stringResource(if (editor.editingEngineId == null) R.string.cloud_tts_add_engine else R.string.cloud_tts_edit_engine)) },
-        text = {
-            LazyColumn {
-                item {
-                    Button(onClick = { providerMenu = true }, Modifier.fillMaxWidth()) {
-                        Text(profile.displayName)
-                    }
-                    DropdownMenu(providerMenu, { providerMenu = false }) {
+    LazyColumn {
+                item { Column(Modifier.padding(horizontal = 16.dp)) {
+                    MenuButton(profile.displayName) { providerMenu = true }
+                    RoundDropdownMenu(providerMenu, { providerMenu = false }) {
                         CloudTtsProviderType.entries.forEach { option ->
-                            DropdownMenuItem(
-                                text = { Text(option.profile.displayName) },
+                            RoundDropdownMenuItem(
+                                text = option.profile.displayName,
                                 onClick = {
                                     providerMenu = false
                                     update(editor.copy(
@@ -244,13 +285,11 @@ private fun CloudTtsEngineEditorDialog(
                         Field(editor.secretKey, { update(editor.copy(secretKey = it)) }, "Secret Access Key")
                     }
                     if (profile.regionOptions.isNotEmpty()) {
-                        Button(onClick = { regionMenu = true }, Modifier.fillMaxWidth()) {
-                            Text(stringResource(R.string.cloud_tts_region_value, editor.region.ifBlank { stringResource(R.string.cloud_tts_please_select) }))
-                        }
-                        DropdownMenu(regionMenu, { regionMenu = false }) {
+                        MenuButton(stringResource(R.string.cloud_tts_region_value, editor.region.ifBlank { stringResource(R.string.cloud_tts_please_select) })) { regionMenu = true }
+                        RoundDropdownMenu(regionMenu, { regionMenu = false }) {
                             profile.regionOptions.forEach { region ->
-                                DropdownMenuItem(
-                                    text = { Text(region) },
+                                RoundDropdownMenuItem(
+                                    text = region,
                                     onClick = {
                                         regionMenu = false
                                         customRegion = false
@@ -258,8 +297,8 @@ private fun CloudTtsEngineEditorDialog(
                                     },
                                 )
                             }
-                            DropdownMenuItem(
-                                text = { Text(stringResource(R.string.cloud_tts_custom_region_action)) },
+                            RoundDropdownMenuItem(
+                                text = stringResource(R.string.cloud_tts_custom_region_action),
                                 onClick = {
                                     regionMenu = false
                                     customRegion = true
@@ -275,13 +314,11 @@ private fun CloudTtsEngineEditorDialog(
                         Field(editor.appId, { update(editor.copy(appId = it)) }, "App ID")
                     }
                     if (profile.modelOptions.isNotEmpty()) {
-                        Button(onClick = { modelMenu = true }, Modifier.fillMaxWidth()) {
-                            Text(stringResource(R.string.cloud_tts_model_value, editor.model.ifBlank { "neural" }))
-                        }
-                        DropdownMenu(modelMenu, { modelMenu = false }) {
+                        MenuButton(stringResource(R.string.cloud_tts_model_value, editor.model.ifBlank { "neural" })) { modelMenu = true }
+                        RoundDropdownMenu(modelMenu, { modelMenu = false }) {
                             profile.modelOptions.forEach { model ->
-                                DropdownMenuItem(
-                                    text = { Text(model) },
+                                RoundDropdownMenuItem(
+                                    text = model,
                                     onClick = { modelMenu = false; update(editor.copy(model = model)) },
                                 )
                             }
@@ -292,26 +329,55 @@ private fun CloudTtsEngineEditorDialog(
                     if (provider == CloudTtsProviderType.Volcengine) {
                         Field(editor.optionsJson, { update(editor.copy(optionsJson = it)) }, stringResource(R.string.cloud_tts_options_json))
                     }
-                    Button(
+                    MediumTonalButton(
                         onClick = { onIntent(CloudTtsIntent.TestEngine) },
                         enabled = !state.testing,
                         modifier = Modifier.fillMaxWidth(),
-                    ) { Text(stringResource(if (state.testing) R.string.cloud_tts_testing else R.string.cloud_tts_connection_test)) }
-                }
-            }
-        },
-        confirmButton = { TextButton(onClick = { onIntent(CloudTtsIntent.Save) }) { Text(stringResource(R.string.save)) } },
-        dismissButton = { TextButton(onClick = { onIntent(CloudTtsIntent.DismissEngineEditor) }) { Text(stringResource(R.string.cancel)) } },
-    )
+                        text = stringResource(if (state.testing) R.string.cloud_tts_testing else R.string.cloud_tts_connection_test),
+                    )
+                } }
+    }
 }
 
 @Composable
 private fun TtsVoicePresetEditorSheet(
+    state: CloudTtsUiState,
+    editor: TtsVoicePresetEditorUi?,
+    onIntent: (CloudTtsIntent) -> Unit,
+) {
+    AppModalBottomSheet(
+        data = editor,
+        onDismissRequest = { onIntent(CloudTtsIntent.DismissVoiceEditor) },
+        title = stringResource(
+            if (editor?.editingVoiceId == null) R.string.cloud_tts_add_voice
+            else R.string.cloud_tts_edit_voice
+        ),
+        startAction = {
+            MediumTonalButton(
+                onClick = { onIntent(CloudTtsIntent.DismissVoiceEditor) },
+                icon = Icons.Default.Close,
+                contentDescription = stringResource(R.string.cancel),
+            )
+        },
+        endAction = {
+            MediumTonalButton(
+                onClick = { onIntent(CloudTtsIntent.Save) },
+                enabled = editor?.voiceId?.isNotBlank() == true,
+                icon = Icons.Default.Check,
+                contentDescription = stringResource(R.string.save),
+            )
+        },
+    ) { currentEditor ->
+        TtsVoicePresetEditorContent(state, currentEditor, onIntent)
+    }
+}
+
+@Composable
+private fun TtsVoicePresetEditorContent(
     state: CloudTtsUiState,
     editor: TtsVoicePresetEditorUi,
     onIntent: (CloudTtsIntent) -> Unit,
 ) {
-    var engineMenu by remember { mutableStateOf(false) }
     var styleMenu by remember { mutableStateOf(false) }
     var roleMenu by remember { mutableStateOf(false) }
     var formatMenu by remember { mutableStateOf(false) }
@@ -327,123 +393,71 @@ private fun TtsVoicePresetEditorSheet(
     }
     fun update(value: TtsVoicePresetEditorUi) = onIntent(CloudTtsIntent.UpdateVoiceEditor(value))
 
-    AppModalBottomSheet(
-        show = true,
-        onDismissRequest = { onIntent(CloudTtsIntent.DismissVoiceEditor) },
-        title = stringResource(if (editor.editingVoiceId == null) R.string.cloud_tts_add_voice else R.string.cloud_tts_edit_voice),
-        startAction = {
-            TextButton(onClick = { onIntent(CloudTtsIntent.DismissVoiceEditor) }) {
-                Text(stringResource(R.string.cancel))
-            }
-        },
-        endAction = {
-            TextButton(
-                onClick = { onIntent(CloudTtsIntent.Save) },
-                enabled = editor.voiceId.isNotBlank(),
-            ) { Text(stringResource(R.string.save)) }
-        },
-    ) {
-        LazyColumn(Modifier.fillMaxWidth()) {
-            item {
-                Text(stringResource(R.string.cloud_tts_step_engine), Modifier.padding(horizontal = 24.dp, vertical = 12.dp))
-                if (selectedEngine == null && editor.editingVoiceId == null) {
-                    state.availableEngines.forEach { engine ->
-                        ClickableSettingItem(
-                            title = engine.title,
-                            description = "${engine.summary}\n${engine.catalogHint}",
-                            option = stringResource(R.string.cloud_tts_select),
-                            onClick = {
-                                onIntent(CloudTtsIntent.SelectEngine(engine.engineType, engine.engineId))
-                            },
-                        )
-                    }
-                } else {
-                    Button(
-                        onClick = { engineMenu = true },
-                        modifier = Modifier.fillMaxWidth(),
-                        enabled = editor.editingVoiceId == null,
-                    ) {
-                        Text(editor.engineName.ifBlank { stringResource(R.string.cloud_tts_select_engine) })
-                    }
-                    DropdownMenu(engineMenu, { engineMenu = false }) {
-                        state.availableEngines.forEach { engine ->
-                            DropdownMenuItem(
-                                text = { Column { Text(engine.title); Text(engine.summary) } },
-                                onClick = {
-                                    engineMenu = false
-                                    onIntent(CloudTtsIntent.SelectEngine(engine.engineType, engine.engineId))
-                                },
-                            )
-                        }
-                    }
-                    selectedEngine?.let {
-                        Text(
-                            it.catalogHint,
-                            Modifier.padding(horizontal = 24.dp, vertical = 8.dp),
-                        )
-                    }
-                    if (editor.editingVoiceId != null) {
-                        Text(
-                            stringResource(R.string.cloud_tts_edit_voice_binding_notice),
-                            Modifier.padding(horizontal = 24.dp),
-                        )
-                    }
-                }
-            }
+    LazyColumn(
+            Modifier.fillMaxWidth(),
+            verticalArrangement = Arrangement.spacedBy(2.dp)
+        ) {
             if (editor.engineId.isNotBlank()) {
                 item {
-                    Text(stringResource(R.string.cloud_tts_step_voice), Modifier.padding(horizontal = 24.dp, vertical = 12.dp))
+                    AppText(stringResource(
+                        R.string.cloud_tts_step_voice),
+                        Modifier.padding(horizontal = 24.dp, vertical = 12.dp)
+                    )
                     if (editor.editingVoiceId == null && state.discoveredVoices.isNotEmpty()) {
-                        OutlinedTextField(
-                            value = voiceQuery,
-                            onValueChange = { voiceQuery = it },
-                            label = { Text(stringResource(R.string.cloud_tts_search_voice)) },
-                            modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp),
-                            singleLine = true,
+                        SearchBar(
+                            query = voiceQuery,
+                            onQueryChange = { voiceQuery = it },
+                            placeholder = stringResource(R.string.cloud_tts_search_voice),
+                            autoFocus = false,
+                            modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
                         )
                     }
                     if (state.discovering) {
-                        Text(stringResource(R.string.cloud_tts_loading_voices), Modifier.padding(24.dp, 12.dp))
+                        AppText(stringResource(R.string.cloud_tts_loading_voices), Modifier.padding(24.dp, 12.dp))
                     } else if (editor.editingVoiceId == null && filteredVoices.isEmpty()) {
-                        Text(stringResource(R.string.cloud_tts_no_matching_voice), Modifier.padding(24.dp, 12.dp))
+                        AppText(stringResource(R.string.cloud_tts_no_matching_voice), Modifier.padding(24.dp, 12.dp))
                     }
                 }
                 if (editor.editingVoiceId == null) {
                     items(filteredVoices, key = { it.id }) { voice ->
-                        ClickableSettingItem(
+                        TinyClickableSettingItem(
                             title = voice.label.substringBefore(" · "),
                             description = buildString {
                                 voice.label.substringAfter(" · ", "").takeIf(String::isNotBlank)?.let(::append)
-                                if (isNotEmpty()) append('\n')
+                                if (isNotEmpty()) append(" | ")
                                 append(voice.id)
+                                if (voice.id == editor.voiceId) {
+                                    append(" | ")
+                                    append(stringResource(R.string.cloud_tts_selected))
+                                }
                             },
-                            option = if (voice.id == editor.voiceId) stringResource(R.string.cloud_tts_selected) else null,
                             onClick = { onIntent(CloudTtsIntent.SelectVoice(voice.id)) },
                         )
                     }
                 } else {
                     item {
-                        ClickableSettingItem(
+                        TinyClickableSettingItem(
                             title = editor.voiceName.ifBlank { editor.voiceId },
-                            description = editor.voiceId,
-                            option = stringResource(R.string.cloud_tts_current_voice),
+                            description = "${editor.voiceId} | ${stringResource(R.string.cloud_tts_current_voice)}",
                             onClick = {},
                         )
                     }
                 }
                 item {
                     if (selectedEngine?.remoteCatalog == true) {
-                        TextButton(
+                        MediumTonalButton(
                             onClick = { onIntent(CloudTtsIntent.DiscoverVoices) },
                             enabled = !state.discovering,
                             modifier = Modifier.padding(horizontal = 12.dp),
-                        ) { Text(stringResource(R.string.cloud_tts_refresh_catalog)) }
+                            text = stringResource(R.string.cloud_tts_refresh_catalog),
+                        )
                     }
                     if (editor.editingVoiceId == null && editor.engineType == ReadAloudVoice.ENGINE_CLOUD) {
-                        TextButton(
+                        MediumTonalButton(
                             onClick = { manualVoiceIdVisible = !manualVoiceIdVisible },
                             modifier = Modifier.padding(horizontal = 12.dp),
-                        ) { Text(stringResource(if (manualVoiceIdVisible) R.string.cloud_tts_hide_manual_voice else R.string.cloud_tts_manual_voice_action)) }
+                            text = stringResource(if (manualVoiceIdVisible) R.string.cloud_tts_hide_manual_voice else R.string.cloud_tts_manual_voice_action),
+                        )
                     }
                     if (manualVoiceIdVisible && editor.editingVoiceId == null &&
                         editor.engineType == ReadAloudVoice.ENGINE_CLOUD) {
@@ -452,62 +466,58 @@ private fun TtsVoicePresetEditorSheet(
                             { update(editor.copy(voiceId = it.trim())) },
                             stringResource(R.string.cloud_tts_native_voice_id),
                         )
-                        Text(
+                        AppText(
                             stringResource(R.string.cloud_tts_manual_voice_hint),
                             Modifier.padding(horizontal = 24.dp),
                         )
                     }
-                    Text(stringResource(R.string.cloud_tts_step_preset), Modifier.padding(horizontal = 24.dp, vertical = 12.dp))
+                    AppText(stringResource(R.string.cloud_tts_step_preset), Modifier.padding(horizontal = 24.dp, vertical = 12.dp))
                     Field(editor.voiceName, { update(editor.copy(voiceName = it)) }, stringResource(R.string.cloud_tts_preset_name))
                     if (editor.engineType == ReadAloudVoice.ENGINE_CLOUD) {
                         if (!selectedVoice?.styles.isNullOrEmpty()) {
-                            Button(onClick = { styleMenu = true }, Modifier.fillMaxWidth()) {
-                                Text(stringResource(R.string.cloud_tts_style_value, editor.style.ifBlank { stringResource(R.string.cloud_tts_default) }))
-                            }
-                            DropdownMenu(styleMenu, { styleMenu = false }) {
-                                DropdownMenuItem(
-                                    text = { Text(stringResource(R.string.cloud_tts_default)) },
+                            MenuButton(stringResource(R.string.cloud_tts_style_value, editor.style.ifBlank { stringResource(R.string.cloud_tts_default) })) { styleMenu = true }
+                            RoundDropdownMenu(styleMenu, { styleMenu = false }) {
+                                RoundDropdownMenuItem(
+                                    text = stringResource(R.string.cloud_tts_default),
                                     onClick = { styleMenu = false; update(editor.copy(style = "")) },
                                 )
                                 selectedVoice.styles.forEach { style ->
-                                    DropdownMenuItem(
-                                        text = { Text(style) },
+                                    RoundDropdownMenuItem(
+                                        text = style,
                                         onClick = { styleMenu = false; update(editor.copy(style = style)) },
                                     )
                                 }
                             }
                         }
                         if (!selectedVoice?.roles.isNullOrEmpty()) {
-                            Button(onClick = { roleMenu = true }, Modifier.fillMaxWidth()) {
-                                Text(stringResource(R.string.cloud_tts_role_value, editor.role.ifBlank { stringResource(R.string.cloud_tts_default) }))
-                            }
-                            DropdownMenu(roleMenu, { roleMenu = false }) {
-                                DropdownMenuItem(
-                                    text = { Text(stringResource(R.string.cloud_tts_default)) },
+                            MenuButton(stringResource(R.string.cloud_tts_role_value, editor.role.ifBlank { stringResource(R.string.cloud_tts_default) })) { roleMenu = true }
+                            RoundDropdownMenu(roleMenu, { roleMenu = false }) {
+                                RoundDropdownMenuItem(
+                                    text = stringResource(R.string.cloud_tts_default),
                                     onClick = { roleMenu = false; update(editor.copy(role = "")) },
                                 )
                                 selectedVoice.roles.forEach { role ->
-                                    DropdownMenuItem(
-                                        text = { Text(role) },
+                                    RoundDropdownMenuItem(
+                                        text = role,
                                         onClick = { roleMenu = false; update(editor.copy(role = role)) },
                                     )
                                 }
                             }
                         }
                         Field(editor.instructions, { update(editor.copy(instructions = it)) }, stringResource(R.string.cloud_tts_instructions))
-                        SwitchSettingItem(
+                        TinySwitchSettingItem(
                             title = stringResource(R.string.cloud_tts_automatic_emotion),
                             description = stringResource(R.string.cloud_tts_automatic_emotion_summary),
                             checked = editor.automaticEmotion,
                             onCheckedChange = { update(editor.copy(automaticEmotion = it)) },
                         )
-                        SwitchSettingItem(
+                        TinySwitchSettingItem(
                             title = stringResource(R.string.cloud_tts_character_personality),
                             description = stringResource(R.string.cloud_tts_character_personality_summary),
                             checked = editor.characterPersonality,
                             onCheckedChange = { update(editor.copy(characterPersonality = it)) },
                         )
-                        SwitchSettingItem(
+                        TinySwitchSettingItem(
                             title = stringResource(R.string.cloud_tts_thought_performance),
                             description = stringResource(R.string.cloud_tts_thought_performance_summary),
                             checked = editor.thoughtPerformance,
@@ -516,44 +526,91 @@ private fun TtsVoicePresetEditorSheet(
                         Field(editor.speed, { update(editor.copy(speed = it)) }, stringResource(R.string.cloud_tts_speed))
                         Field(editor.pitch, { update(editor.copy(pitch = it)) }, stringResource(R.string.cloud_tts_pitch))
                         Field(editor.volume, { update(editor.copy(volume = it)) }, stringResource(R.string.cloud_tts_volume))
-                        Button(onClick = { formatMenu = true }, Modifier.fillMaxWidth()) {
-                            Text(stringResource(R.string.cloud_tts_audio_format, editor.format))
-                        }
-                        DropdownMenu(formatMenu, { formatMenu = false }) {
+                        MenuButton(stringResource(R.string.cloud_tts_audio_format, editor.format)) { formatMenu = true }
+                        RoundDropdownMenu(formatMenu, { formatMenu = false }) {
                             editor.formatOptions.forEach { format ->
-                                DropdownMenuItem(
-                                    text = { Text(format) },
+                                RoundDropdownMenuItem(
+                                    text = format,
                                     onClick = { formatMenu = false; update(editor.copy(format = format)) },
                                 )
                             }
                         }
                     } else if (editor.engineType == ReadAloudVoice.ENGINE_SYSTEM) {
-                        Text(stringResource(R.string.cloud_tts_system_defaults_hint))
+                        AppText(stringResource(R.string.cloud_tts_system_defaults_hint))
                         Field(editor.speed, { update(editor.copy(speed = it)) }, stringResource(R.string.cloud_tts_speed_multiplier))
                         Field(editor.pitch, { update(editor.copy(pitch = it)) }, stringResource(R.string.cloud_tts_pitch_multiplier))
                     }
                     if (editor.engineType == ReadAloudVoice.ENGINE_HTTP) {
-                        Text(stringResource(R.string.cloud_tts_http_voice_hint))
+                        AppText(stringResource(R.string.cloud_tts_http_voice_hint))
                     } else {
-                        Button(
+                        MediumTonalButton(
                             onClick = { onIntent(CloudTtsIntent.Preview) },
                             enabled = editor.voiceId.isNotBlank() && !state.testing,
                             modifier = Modifier.fillMaxWidth(),
-                        ) { Text(stringResource(if (state.testing) R.string.cloud_tts_preview_generating else R.string.cloud_tts_preview)) }
+                            text = stringResource(if (state.testing) R.string.cloud_tts_preview_generating else R.string.cloud_tts_preview),
+                        )
                     }
                 }
             }
-        }
     }
 }
 
 @Composable
 private fun Field(value: String, onValueChange: (String) -> Unit, label: String) {
-    OutlinedTextField(
+    AppTextField(
         value = value,
         onValueChange = onValueChange,
-        label = { Text(label) },
+        label = label,
         modifier = Modifier.fillMaxWidth(),
         singleLine = true,
     )
 }
+
+@Composable
+private fun MenuButton(
+    text: String,
+    onClick: () -> Unit,
+) {
+    MediumTonalButton(
+        onClick = onClick,
+        modifier = Modifier.fillMaxWidth(),
+        text = text,
+    )
+}
+
+@Composable
+private fun VoiceEnginePickerSheet(
+    show: Boolean,
+    state: CloudTtsUiState,
+    onIntent: (CloudTtsIntent) -> Unit,
+) {
+    AppModalBottomSheet(
+        show = show,
+        onDismissRequest = { onIntent(CloudTtsIntent.DismissVoiceEnginePicker) },
+        title = stringResource(R.string.cloud_tts_select_engine),
+        startAction = {
+            MediumTonalButton(
+                onClick = { onIntent(CloudTtsIntent.DismissVoiceEnginePicker) },
+                icon = Icons.Default.Close,
+                contentDescription = stringResource(R.string.cancel),
+            )
+        },
+    ) {
+        LazyColumn(Modifier.fillMaxWidth()) {
+            items(
+                items = state.availableEngines,
+                key = { "picker:${it.engineType}:${it.engineId}" },
+            ) { engine ->
+                TinyClickableSettingItem(
+                    title = engine.title,
+                    description = listOf(engine.summary, engine.catalogHint)
+                        .filter(String::isNotBlank)
+                        .joinToString(" | "),
+                    onClick = {
+                        onIntent(CloudTtsIntent.AddVoiceForEngine(engine.engineType, engine.engineId))
+                    },
+                )
+            }
+        }
+    }
+}

+ 8 - 2
app/src/main/java/io/legado/app/ui/book/readaloud/cloudtts/CloudTtsViewModel.kt

@@ -103,8 +103,11 @@ class CloudTtsViewModel(
             CloudTtsIntent.AddEngine -> _uiState.update { it.copy(
                 engineEditor = CloudTtsEngineEditorUi(name = "MiMo", model = "mimo-v2.5-tts"),
             ) }
-            CloudTtsIntent.AddVoice -> addVoice()
-            is CloudTtsIntent.AddVoiceForEngine -> addVoice(intent.engineType, intent.engineId)
+            CloudTtsIntent.AddVoice -> _uiState.update { it.copy(showVoiceEnginePicker = true) }
+            is CloudTtsIntent.AddVoiceForEngine -> {
+                _uiState.update { it.copy(showVoiceEnginePicker = false) }
+                addVoice(intent.engineType, intent.engineId)
+            }
             is CloudTtsIntent.EditEngine -> editEngine(intent.id)
             is CloudTtsIntent.DeleteEngine -> deleteEngine(intent.id)
             is CloudTtsIntent.DeleteVoice -> deleteVoice(intent.id)
@@ -113,6 +116,9 @@ class CloudTtsViewModel(
             is CloudTtsIntent.UpdateVoiceEditor -> _uiState.update { it.copy(voiceEditor = intent.editor) }
             CloudTtsIntent.DismissEngineEditor -> _uiState.update { it.copy(engineEditor = null) }
             CloudTtsIntent.DismissVoiceEditor -> _uiState.update { it.copy(voiceEditor = null) }
+            CloudTtsIntent.DismissVoiceEnginePicker -> _uiState.update {
+                it.copy(showVoiceEnginePicker = false)
+            }
             is CloudTtsIntent.SelectEngine -> selectEngine(intent.engineType, intent.engineId)
             CloudTtsIntent.DiscoverVoices -> discoverVoices()
             is CloudTtsIntent.SelectVoice -> selectVoice(intent.id)

+ 1 - 1
app/src/main/java/io/legado/app/ui/book/toc/rule/preview/TxtTocRulePreviewScreen.kt

@@ -114,7 +114,7 @@ fun TxtTocRulePreviewScreen(
     when (val sheet = state.activeSheet) {
         is TxtTocRulePreviewSheet.ChapterList -> {
             AppModalBottomSheet(
-                show = true,
+                data = sheet.item,
                 onDismissRequest = { onIntent(TxtTocRulePreviewIntent.DismissSheet) },
             ) {
                 ChapterListSheetContent(

+ 2 - 2
app/src/main/java/io/legado/app/ui/config/ai/prompt/AiPromptConfigScreen.kt

@@ -136,7 +136,7 @@ fun AiPromptConfigScreen(
     when (val dialog = state.activeDialog) {
         is AiPromptConfigDialog.EditPrompt -> {
             AppAlertDialog(
-                show = true,
+                data = dialog,
                 onDismissRequest = { onIntent(AiPromptConfigIntent.CloseDialog) },
                 title = stringResource(R.string.ai_prompt_edit_title),
                 confirmText = stringResource(R.string.confirm),
@@ -162,7 +162,7 @@ fun AiPromptConfigScreen(
 
         is AiPromptConfigDialog.RestoreAllConfirm -> {
             AppAlertDialog(
-                show = true,
+                data = dialog,
                 onDismissRequest = { onIntent(AiPromptConfigIntent.CloseDialog) },
                 title = stringResource(R.string.ai_prompt_restore_all),
                 confirmText = stringResource(R.string.confirm),

+ 1 - 1
app/src/main/java/io/legado/app/ui/config/coverConfig/CoverAlbumManageScreen.kt

@@ -402,7 +402,7 @@ private fun CoverAlbumDialogs(
         )
 
         is CoverAlbumDialog.Delete -> AppAlertDialog(
-            show = true,
+            data = dialog,
             onDismissRequest = { onIntent(CoverAlbumIntent.DismissDialog) },
             title = stringResource(R.string.cover_album_delete),
             text = stringResource(R.string.cover_album_delete_confirmation, dialog.name),