Fix chapters status lost problem (#934)

* ci: rename workflows

* chore: update translations

* fix: use upsert
This commit is contained in:
uy/sun
2024-02-01 10:44:57 +08:00
committed by GitHub
parent ad2412eb62
commit e0dbf87ca7
11 changed files with 98 additions and 44 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
name: CI
name: Build
on:
push:
branches:
+1 -1
View File
@@ -1,4 +1,4 @@
name: CI
name: Lint
on:
push:
branches:
+1 -1
View File
@@ -150,7 +150,7 @@ export const useNovel = (url: string, pluginId: string) => {
novelSettings?.filter,
).then(chapters => setChapters(chapters));
} else {
throw new Error('Unable to get novel');
throw new Error(getString('updatesScreen.unableToGetNovel'));
}
});
};
+4 -1
View File
@@ -12,6 +12,7 @@ import { isUrlAbsolute } from './helpers/isAbsoluteUrl';
import { fetchApi, fetchFile, fetchText } from './helpers/fetch';
import { defaultCover } from './helpers/constants';
import { encode, decode } from 'urlencode';
import { getString } from '@strings/translations';
const packages: Record<string, any> = {
'cheerio': { load },
@@ -122,7 +123,9 @@ const fetchPlugins = async () => {
.then(res => res.json())
.catch(() => {
throw new Error(
`Plugins host error: ${githubUsername}/${githubRepository}`,
`${getString(
'browseScreen.pluginsHostError',
)}: ${githubUsername}/${githubRepository}`,
);
});
return availablePlugins;
+11 -11
View File
@@ -20,11 +20,11 @@ const driveBackupAction = async (taskData?: TaskData) => {
try {
MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.BACKUP);
if (!taskData) {
throw new Error('No data provided');
throw new Error(getString('backupScreen.noDataProvided'));
}
const { delay, backupFolder } = taskData;
await BackgroundService.updateNotification({
taskDesc: 'Preparing Data',
taskDesc: getString('backupScreen.preparingData'),
progressBar: {
indeterminate: true,
value: 0,
@@ -34,7 +34,7 @@ const driveBackupAction = async (taskData?: TaskData) => {
.then(() => prepareBackupData(CACHE_DIR_PATH))
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Uploading Data',
taskDesc: getString('backupScreen.uploadingData'),
progressBar: {
indeterminate: true,
value: 1,
@@ -57,7 +57,7 @@ const driveBackupAction = async (taskData?: TaskData) => {
})
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Uploading Downloaded files',
taskDesc: getString('backupScreen.uploadingDownloadedFiles'),
progressBar: {
indeterminate: true,
value: 2,
@@ -127,7 +127,7 @@ const driveRestoreAction = async (taskData?: TaskData) => {
try {
MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.RESTORE);
if (!taskData) {
throw new Error('No data provided');
throw new Error(getString('backupScreen.noDataProvided'));
}
const { delay, backupFolder } = taskData;
await sleep(delay);
@@ -143,10 +143,10 @@ const driveRestoreAction = async (taskData?: TaskData) => {
backupFolder.id,
);
if (!zipDataFile || !zipDownloadFile) {
throw new Error('Invalid backup folder');
throw new Error(getString('backupScreen.invalidBackupFolder'));
}
await BackgroundService.updateNotification({
taskDesc: 'Downloading Data',
taskDesc: getString('backupScreen.downloadingData'),
progressBar: {
indeterminate: true,
value: 0,
@@ -157,7 +157,7 @@ const driveRestoreAction = async (taskData?: TaskData) => {
.then(() => sleep(delay))
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Restoring Data',
taskDesc: getString('backupScreen.restoringData'),
progressBar: {
indeterminate: true,
value: 1,
@@ -169,7 +169,7 @@ const driveRestoreAction = async (taskData?: TaskData) => {
.then(() => sleep(delay))
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Downloading Downloaded files',
taskDesc: getString('backupScreen.downloadingDownloadedFiles'),
progressBar: {
indeterminate: true,
value: 2,
@@ -209,8 +209,8 @@ const driveRestoreAction = async (taskData?: TaskData) => {
export const driveRestore = async (backupFolder: DriveFile) => {
return BackgroundService.start(driveRestoreAction, {
taskName: 'Drive Restore',
taskTitle: 'Drive Restore',
taskDesc: 'Preparing',
taskTitle: getString('backupScreen.drive.restore'),
taskDesc: getString('common.preparing'),
taskIcon: { name: 'notification_icon', type: 'drawable' },
color: '#00adb5',
parameters: { delay: 500, backupFolder },
+10 -10
View File
@@ -19,11 +19,11 @@ const remoteBackupAction = async (taskData?: TaskData) => {
try {
MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.BACKUP);
if (!taskData) {
throw new Error('No data provided');
throw new Error(getString('backupScreen.noDataProvided'));
}
const { delay, backupFolder, host } = taskData;
await BackgroundService.updateNotification({
taskDesc: 'Preparing Data',
taskDesc: getString('backupScreen.preparingData'),
progressBar: {
indeterminate: true,
value: 0,
@@ -33,7 +33,7 @@ const remoteBackupAction = async (taskData?: TaskData) => {
.then(() => prepareBackupData(CACHE_DIR_PATH))
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Uploading Data',
taskDesc: getString('backupScreen.uploadingData'),
progressBar: {
indeterminate: true,
value: 1,
@@ -47,7 +47,7 @@ const remoteBackupAction = async (taskData?: TaskData) => {
)
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Uploading Downloaded files',
taskDesc: getString('backupScreen.uploadingDownloadedFiles'),
progressBar: {
indeterminate: true,
value: 2,
@@ -112,11 +112,11 @@ const remoteRestoreAction = async (taskData?: TaskData) => {
try {
MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.RESTORE);
if (!taskData) {
throw new Error('No data provided');
throw new Error(getString('backupScreen.noDataProvided'));
}
const { delay, backupFolder, host } = taskData;
await BackgroundService.updateNotification({
taskDesc: 'Downloading Data',
taskDesc: getString('backupScreen.downloadingData'),
progressBar: {
indeterminate: true,
value: 0,
@@ -128,7 +128,7 @@ const remoteRestoreAction = async (taskData?: TaskData) => {
)
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Restoring Data',
taskDesc: getString('backupScreen.restoringData'),
progressBar: {
indeterminate: true,
value: 1,
@@ -140,7 +140,7 @@ const remoteRestoreAction = async (taskData?: TaskData) => {
.then(() => restoreData(CACHE_DIR_PATH))
.then(() =>
BackgroundService.updateNotification({
taskDesc: 'Downloading Downloaded files',
taskDesc: getString('backupScreen.downloadingDownloadedFiles'),
progressBar: {
indeterminate: true,
value: 2,
@@ -183,8 +183,8 @@ const remoteRestoreAction = async (taskData?: TaskData) => {
export const remoteRestore = async (host: string, backupFolder: string) => {
return BackgroundService.start(remoteRestoreAction, {
taskName: 'Self Host Restore',
taskTitle: 'Self Host Restore',
taskDesc: 'Preparing',
taskTitle: getString('backupScreen.remote.restore'),
taskDesc: getString('common.preparing'),
taskIcon: { name: 'notification_icon', type: 'drawable' },
color: '#00adb5',
parameters: { delay: 200, backupFolder, host },
+11 -5
View File
@@ -58,7 +58,9 @@ const insertLocalNovel = (
});
resolve(resultSet.insertId);
} else {
reject(new Error('novel insert failed'));
reject(
new Error(getString('advancedSettingsScreen.novelInsertFailed')),
);
}
},
(txObj, error) => {
@@ -112,7 +114,11 @@ const insertLocalChapter = (
);
resolve(staticPaths);
} else {
reject(new Error('chapter insert failed'));
reject(
new Error(
getString('advancedSettingsScreen.chapterInsertFailed'),
),
);
}
},
(txObj, error) => {
@@ -211,7 +217,7 @@ const parseNovelAndChapters = async (
const importEpubAction = async (taskData?: TaskData) => {
try {
if (!taskData) {
throw new Error('No data provided');
throw new Error(getString('backupScreen.noDataProvided'));
}
const epubFilePath = RNFS.ExternalCachesDirectoryPath + '/novel.epub';
await RNFS.copyFile(taskData.sourceUri, epubFilePath);
@@ -333,8 +339,8 @@ export const importEpub = async () => {
}
await BackgroundService.start<TaskData>(importEpubAction, {
taskName: 'Import Epub',
taskTitle: 'Parse Epub',
taskDesc: 'Parsing',
taskTitle: getString('advancedSettingsScreen.parseEpub'),
taskDesc: getString('common.parsing'),
taskIcon: { name: 'notification_icon', type: 'drawable' },
color: '#00adb5',
parameters: { delay: 500, sourceUri: epubFile.uri },
+1 -1
View File
@@ -67,7 +67,7 @@ const updateNovel = async (
novel.chapters?.forEach(chapter => {
const { name, url, releaseTime } = chapter;
tx.executeSql(
"INSERT OR REPLACE INTO Chapter (url, name, releaseTime, novelId, updatedTime) values (?, ?, ?, ?, datetime('now','localtime'))",
"INSERT INTO Chapter (url, name, releaseTime, novelId, updatedTime) values (?, ?, ?, ?, datetime('now','localtime')) ON CONFLICT(url) DO UPDATE SET name=excluded.name, releaseTime=excluded.releaseTime, novelId=excluded.novelId, updatedTime=excluded.updatedTime",
[url, name, releaseTime || '', novelId],
(txObj, { insertId }) => {
if (insertId && downloadNewChapters) {
+18 -4
View File
@@ -10,6 +10,7 @@
"advancedSettings": "Advanced",
"advancedSettingsScreen": {
"cachedNovelsDeletedToast": "Cached novels deleted",
"chapterInsertFailed": "chapter insert failed",
"clearCachedNovels": "Clear cached novels",
"clearCachedNovelsDesc": "Delete cached novels which not in your library",
"clearDatabaseWarning": "Are you sure? Read and Downloaded chapters and progress of non-library novels will be lost.",
@@ -24,6 +25,8 @@
"importError": "Import Error",
"importNovel": "Import Novel",
"importStaticFiles": "Import Static Files",
"novelInsertFailed": "novel insert failed",
"parseEpub": "Parse Epub",
"useFAB": "Use FAB instead of button",
"userAgent": "User Agent"
},
@@ -56,6 +59,8 @@
"createBackup": "Create backup",
"createBackupDesc": "Can be used to restore current library",
"createBackupWarning": "Create backup may not work on devices with Android 9 or lower.",
"downloadingData": "Downloading Data",
"downloadingDownloadedFiles": "Downloading Downloaded files",
"drive": {
"backup": "Drive Backup",
"backupInterruped": "Drive Backup Interruped",
@@ -65,6 +70,7 @@
},
"googeDrive": "Googe Drive",
"googeDriveDesc": "Backup to your Google Drive",
"invalidBackupFolder": "Invalid backup folder",
"legacy": {
"backupCreated": "Backup created %{fileName}",
"libraryRestored": "Library Restored",
@@ -76,6 +82,8 @@
},
"legacyBackup": "Legacy Backup",
"noBackupFound": "No backup found",
"noDataProvided": "No data provided",
"preparingData": "Preparing Data",
"remote": {
"backup": "Self Host Backup",
"backupInterruped": "Self Host Backup Interruped",
@@ -91,8 +99,11 @@
"restoreErrorDesc": "Using this to restore the remaining. Save your time.",
"restoreLargeBackupsWarning": "Restoring large backups may freeze the app until restoring is finished",
"restorinBackup": "Restoring backup",
"restoringData": "Restoring Data",
"selfHost": "Self Host",
"selfHostDesc": "Backup to your server"
"selfHostDesc": "Backup to your server",
"uploadingData": "Uploading Data",
"uploadingDownloadedFiles": "Uploading Downloaded files"
},
"browse": "Browse",
"browseScreen": {
@@ -100,10 +111,10 @@
"available": "Available",
"discover": "Discover",
"globalSearch": "Global search",
"installFailed": "Installation failed: %{name}",
"installed": "Installed",
"installedPlugin": "Installed %{name}",
"installedPlugins": "Installed plugins",
"installFailed": "Installation failed: %{name}",
"lastUsed": "Last used",
"latest": "Latest",
"listEmpty": "Enable languages from settings",
@@ -119,13 +130,14 @@
},
"noSource": "Your library does not have any novels from this source",
"pinned": "Pinned",
"pluginsHostError": "Plugins host error",
"removeFromLibrary": "Removed from Library",
"searchbar": "Search sources",
"selectNovel": "Select Novel",
"tryAgain": "Try again in a moment",
"uninstalledPlugin": "Uninstalled %{name}",
"updatedTo": "Updated to %{version}",
"updateFailed": "Update failed"
"updateFailed": "Update failed",
"updatedTo": "Updated to %{version}"
},
"browseSettings": "Browse Settings",
"browseSettingsScreen": {
@@ -176,6 +188,7 @@
"name": "Name",
"newUpdateAvailable": "New update available",
"ok": "Ok",
"parsing": "Parsing",
"pause": "Pause",
"preparing": "Preparing",
"remove": "Remove",
@@ -474,6 +487,7 @@
"newChapters": "new Chapters",
"novelsUpdated": "%{num} novels updated",
"searchbar": "Search updates",
"unableToGetNovel": "Unable to get novel",
"updatesLower": "updates",
"updatingLibrary": "Updating library"
}
+24 -7
View File
@@ -2,7 +2,7 @@
"aboutScreen": {
"discord": "Discord",
"github": "Github",
"helpTranslate": "帮助翻译",
"helpTranslate": "协助翻译",
"sources": "源",
"version": "版本",
"whatsNew": "新增内容"
@@ -10,6 +10,7 @@
"advancedSettings": "高级",
"advancedSettingsScreen": {
"cachedNovelsDeletedToast": "缓存的小说已删除",
"chapterInsertFailed": "章节插入失败",
"clearCachedNovels": "清除缓存的小说",
"clearCachedNovelsDesc": "删除不在您的书库中的缓存小说",
"clearDatabaseWarning": "您确定吗?非书库小说的阅读,已下载章节和进度将会丢失。",
@@ -24,6 +25,8 @@
"importError": "导入出错",
"importNovel": "导入小说",
"importStaticFiles": "导入静态文件",
"novelInsertFailed": "小说插入失败",
"parseEpub": "解析 EPUB",
"useFAB": "使用浮动操作按钮",
"userAgent": "用户代理"
},
@@ -38,7 +41,7 @@
"navbar": "导航栏",
"novelInfo": "小说信息",
"pureBlackDarkMode": "纯黑深色模式",
"showHistoryInTheNav": "在导航中显示历史记录",
"showHistoryInTheNav": "在导航中显示历史",
"showUpdatesInTheNav": "在导航中显示更新",
"theme": {
"default": "默认",
@@ -56,6 +59,8 @@
"createBackup": "创建备份",
"createBackupDesc": "可用于恢复当前书库",
"createBackupWarning": "创建备份可能无法在 Android 9 或更低版本的设备上运行。",
"downloadingData": "下载数据",
"downloadingDownloadedFiles": "下载已下载文件",
"drive": {
"backup": "云端硬盘备份",
"backupInterruped": "云端硬盘备份中断",
@@ -65,6 +70,7 @@
},
"googeDrive": "Google 云端硬盘",
"googeDriveDesc": "备份到您的 Google 云端硬盘",
"invalidBackupFolder": "备份文件夹有误",
"legacy": {
"backupCreated": "备份已创建 %{fileName}",
"libraryRestored": "书库已恢复",
@@ -76,6 +82,8 @@
},
"legacyBackup": "旧版备份",
"noBackupFound": "没有找到备份",
"noDataProvided": "未提供数据",
"preparingData": "准备数据",
"remote": {
"backup": "自托管备份",
"backupInterruped": "自托管备份中断",
@@ -91,8 +99,11 @@
"restoreErrorDesc": "用这个来恢复剩余的。节省您的时间。",
"restoreLargeBackupsWarning": "恢复大量备份可能会冻结应用程序,直到恢复完成",
"restorinBackup": "恢复备份",
"restoringData": "恢复数据",
"selfHost": "自托管",
"selfHostDesc": "备份到您的服务器"
"selfHostDesc": "备份到您的服务器",
"uploadingData": "上传数据",
"uploadingDownloadedFiles": "上传已下载文件"
},
"browse": "浏览",
"browseScreen": {
@@ -100,6 +111,7 @@
"available": "可用",
"discover": "发现",
"globalSearch": "全局搜索",
"installFailed": "安装失败:%{name}",
"installed": "已安装",
"installedPlugin": "已安装 %{name}",
"installedPlugins": "已安装插件",
@@ -118,10 +130,13 @@
},
"noSource": "您的图书馆没有该源的任何小说",
"pinned": "已固定",
"pluginsHostError": "获取插件列表失败",
"removeFromLibrary": "已从书库中删除",
"searchbar": "搜索资源",
"selectNovel": "选择小说",
"tryAgain": "请稍后再试",
"uninstalledPlugin": "已卸载 %{name}",
"updateFailed": "更新失败",
"updatedTo": "已更新至 %{version}"
},
"browseSettings": "浏览设置",
@@ -173,6 +188,7 @@
"name": "名称",
"newUpdateAvailable": "新版本可用",
"ok": "确定",
"parsing": "解析",
"pause": "暂停",
"preparing": "准备中",
"remove": "移除",
@@ -273,8 +289,8 @@
"downloadBadges": "下载徽章",
"list": "列表",
"noTitle": "仅封面网格",
"numberOfItems": "条目数量",
"showNoOfItems": "显示条目数量",
"numberOfItems": "小说数",
"showNoOfItems": "显示小说数",
"unread": "未读",
"unreadBadges": "未读徽章"
},
@@ -294,13 +310,13 @@
"unread": "未读"
}
},
"empty": "您的库是空的。从浏览添加丛书到您的库里。",
"empty": "您的书库是空的。请从浏览将小说添加到您的书库中。",
"searchbar": "搜索书库"
},
"more": "更多",
"moreScreen": {
"downloadOnly": "仅已下载",
"downloadOnlyDesc": "过滤您书库中的所有小说",
"downloadOnlyDesc": "筛选您书库中的全部小说",
"downloadQueue": "下载队列",
"incognitoMode": "无痕模式",
"incognitoModeDesc": "暂停阅读历史记录"
@@ -471,6 +487,7 @@
"newChapters": "新章节",
"novelsUpdated": "已更新 %{num} 部小说",
"searchbar": "搜索更新",
"unableToGetNovel": "无法获取小说",
"updatesLower": "更新",
"updatingLibrary": "更新书库"
}
+16 -2
View File
@@ -11,6 +11,7 @@ export interface StringMap {
'aboutScreen.whatsNew': 'string';
'advancedSettings': 'string';
'advancedSettingsScreen.cachedNovelsDeletedToast': 'string';
'advancedSettingsScreen.chapterInsertFailed': 'string';
'advancedSettingsScreen.clearCachedNovels': 'string';
'advancedSettingsScreen.clearCachedNovelsDesc': 'string';
'advancedSettingsScreen.clearDatabaseWarning': 'string';
@@ -25,6 +26,8 @@ export interface StringMap {
'advancedSettingsScreen.importError': 'string';
'advancedSettingsScreen.importNovel': 'string';
'advancedSettingsScreen.importStaticFiles': 'string';
'advancedSettingsScreen.novelInsertFailed': 'string';
'advancedSettingsScreen.parseEpub': 'string';
'advancedSettingsScreen.useFAB': 'string';
'advancedSettingsScreen.userAgent': 'string';
'appearance': 'string';
@@ -51,6 +54,8 @@ export interface StringMap {
'backupScreen.createBackup': 'string';
'backupScreen.createBackupDesc': 'string';
'backupScreen.createBackupWarning': 'string';
'backupScreen.downloadingData': 'string';
'backupScreen.downloadingDownloadedFiles': 'string';
'backupScreen.drive.backup': 'string';
'backupScreen.drive.backupInterruped': 'string';
'backupScreen.drive.googleDriveBackup': 'string';
@@ -58,6 +63,7 @@ export interface StringMap {
'backupScreen.drive.restoreInterruped': 'string';
'backupScreen.googeDrive': 'string';
'backupScreen.googeDriveDesc': 'string';
'backupScreen.invalidBackupFolder': 'string';
'backupScreen.legacy.backupCreated': 'string';
'backupScreen.legacy.libraryRestored': 'string';
'backupScreen.legacy.noAvailableBackup': 'string';
@@ -67,6 +73,8 @@ export interface StringMap {
'backupScreen.legacy.pluginNotExist': 'string';
'backupScreen.legacyBackup': 'string';
'backupScreen.noBackupFound': 'string';
'backupScreen.noDataProvided': 'string';
'backupScreen.preparingData': 'string';
'backupScreen.remote.backup': 'string';
'backupScreen.remote.backupInterruped': 'string';
'backupScreen.remote.host': 'string';
@@ -80,17 +88,20 @@ export interface StringMap {
'backupScreen.restoreErrorDesc': 'string';
'backupScreen.restoreLargeBackupsWarning': 'string';
'backupScreen.restorinBackup': 'string';
'backupScreen.restoringData': 'string';
'backupScreen.selfHost': 'string';
'backupScreen.selfHostDesc': 'string';
'backupScreen.uploadingData': 'string';
'backupScreen.uploadingDownloadedFiles': 'string';
'browse': 'string';
'browseScreen.addedToLibrary': 'string';
'browseScreen.available': 'string';
'browseScreen.discover': 'string';
'browseScreen.globalSearch': 'string';
'browseScreen.installFailed': 'string';
'browseScreen.installed': 'string';
'browseScreen.installedPlugin': 'string';
'browseScreen.installedPlugins': 'string';
'browseScreen.installFailed': 'string';
'browseScreen.lastUsed': 'string';
'browseScreen.latest': 'string';
'browseScreen.listEmpty': 'string';
@@ -104,13 +115,14 @@ export interface StringMap {
'browseScreen.migration.selectSourceDesc': 'string';
'browseScreen.noSource': 'string';
'browseScreen.pinned': 'string';
'browseScreen.pluginsHostError': 'string';
'browseScreen.removeFromLibrary': 'string';
'browseScreen.searchbar': 'string';
'browseScreen.selectNovel': 'string';
'browseScreen.tryAgain': 'string';
'browseScreen.uninstalledPlugin': 'string';
'browseScreen.updatedTo': 'string';
'browseScreen.updateFailed': 'string';
'browseScreen.updatedTo': 'string';
'browseSettings': 'string';
'browseSettingsScreen.languages': 'string';
'browseSettingsScreen.onlyShowPinnedSources': 'string';
@@ -153,6 +165,7 @@ export interface StringMap {
'common.name': 'string';
'common.newUpdateAvailable': 'string';
'common.ok': 'string';
'common.parsing': 'string';
'common.pause': 'string';
'common.preparing': 'string';
'common.remove': 'string';
@@ -389,6 +402,7 @@ export interface StringMap {
'updatesScreen.newChapters': 'string';
'updatesScreen.novelsUpdated': 'string';
'updatesScreen.searchbar': 'string';
'updatesScreen.unableToGetNovel': 'string';
'updatesScreen.updatesLower': 'string';
'updatesScreen.updatingLibrary': 'string';
}