diff --git a/src/components/NovelCover.tsx b/src/components/NovelCover.tsx index 95c87f97..27debc47 100644 --- a/src/components/NovelCover.tsx +++ b/src/components/NovelCover.tsx @@ -112,9 +112,9 @@ function NovelCover({ }, styles.standardNovelCover, isSelected && { - backgroundColor: theme.primary, - } && - styles.selectedNovelCover, + backgroundColor: theme.primary, + ...styles.selectedNovelCover, + }, ]} > ( - + diff --git a/src/navigators/types/index.ts b/src/navigators/types/index.ts index f24353a6..82f7f7c1 100644 --- a/src/navigators/types/index.ts +++ b/src/navigators/types/index.ts @@ -65,7 +65,7 @@ export type MoreStackScreenProps = CompositeScreenProps< export type MoreStackParamList = { SettingsStack: NavigatorScreenParams; About: undefined; - DownloadQueue: undefined; + TaskQueue: undefined; Downloads: undefined; Categories: undefined; Statistics: undefined; @@ -94,9 +94,9 @@ export type DownloadsScreenProps = StackScreenProps< MoreStackParamList, 'Downloads' >; -export type DownloadQueueScreenProps = StackScreenProps< +export type TaskQueueScreenProps = StackScreenProps< MoreStackParamList, - 'DownloadQueue' + 'TaskQueue' >; export type BrowseSourceScreenProps = StackScreenProps< RootStackParamList, diff --git a/src/screens/more/MoreScreen.tsx b/src/screens/more/MoreScreen.tsx index 950454c0..6606ee4b 100644 --- a/src/screens/more/MoreScreen.tsx +++ b/src/screens/more/MoreScreen.tsx @@ -5,13 +5,17 @@ import { getString } from '@strings/translations'; import { List } from '@components'; import { MoreHeader } from './components/MoreHeader'; -import { useDownload, useLibrarySettings, useTheme } from '@hooks/persisted'; +import { useLibrarySettings, useTheme } from '@hooks/persisted'; import { MoreStackScreenProps } from '@navigators/types'; import Switch from '@components/Switch/Switch'; +import { useMMKVObject } from 'react-native-mmkv'; +import ServiceManager, { BackgroundTask } from '@services/ServiceManager'; const MoreScreen = ({ navigation }: MoreStackScreenProps) => { const theme = useTheme(); - const { downloadQueue } = useDownload(); + const [taskQueue] = useMMKVObject( + ServiceManager.manager.STORE_KEY, + ); const { incognitoMode = false, downloadedOnlyMode = false, @@ -107,14 +111,16 @@ const MoreScreen = ({ navigation }: MoreStackScreenProps) => { 0 ? downloadQueue.length + ' remaining' : '' + taskQueue && taskQueue.length > 0 + ? taskQueue.length + ' remaining' + : '' } icon="progress-download" onPress={() => navigation.navigate('MoreStack', { - screen: 'DownloadQueue', + screen: 'TaskQueue', }) } theme={theme} diff --git a/src/screens/more/DownloadQueueScreen.tsx b/src/screens/more/TaskQueueScreen.tsx similarity index 61% rename from src/screens/more/DownloadQueueScreen.tsx rename to src/screens/more/TaskQueueScreen.tsx index 64bed14c..1db4af5b 100644 --- a/src/screens/more/DownloadQueueScreen.tsx +++ b/src/screens/more/TaskQueueScreen.tsx @@ -8,36 +8,36 @@ import { overlay, } from 'react-native-paper'; -import { useDownload, useTheme } from '@hooks/persisted'; +import { useTheme } from '@hooks/persisted'; import { showToast } from '../../utils/showToast'; import { getString } from '@strings/translations'; import { Appbar, EmptyView } from '@components'; -import { DownloadQueueScreenProps } from '@navigators/types'; -import ServiceManager from '@services/ServiceManager'; +import { TaskQueueScreenProps } from '@navigators/types'; +import ServiceManager, { BackgroundTask } from '@services/ServiceManager'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useMMKVObject } from 'react-native-mmkv'; -const DownloadQueue = ({ navigation }: DownloadQueueScreenProps) => { +const DownloadQueue = ({ navigation }: TaskQueueScreenProps) => { const theme = useTheme(); const { bottom } = useSafeAreaInsets(); - const { downloadQueue, resumeDowndload, pauseDownload, cancelDownload } = - useDownload(); - const [isDownloading, setIsDownloading] = useState( - ServiceManager.manager.isRunning, + const [taskQueue] = useMMKVObject( + ServiceManager.manager.STORE_KEY, ); + const [isRunning, setIsRunning] = useState(ServiceManager.manager.isRunning); const [visible, setVisible] = useState(false); const openMenu = () => setVisible(true); const closeMenu = () => setVisible(false); useEffect(() => { - if (downloadQueue.length === 0) { - setIsDownloading(false); + if (taskQueue?.length === 0) { + setIsRunning(false); } - }, [downloadQueue]); + }, [taskQueue]); return ( <> @@ -45,7 +45,7 @@ const DownloadQueue = ({ navigation }: DownloadQueueScreenProps) => { visible={visible} onDismiss={closeMenu} anchor={ - downloadQueue.length ? ( + taskQueue?.length ? ( { > { - cancelDownload(); - setIsDownloading(false); + ServiceManager.manager.stop(); + setIsRunning(false); showToast(getString('downloadScreen.cancelled')); closeMenu(); }} @@ -69,19 +69,15 @@ const DownloadQueue = ({ navigation }: DownloadQueueScreenProps) => { 'download_chapter_' + item.data.chapterId} - data={downloadQueue} - renderItem={({ item }) => ( + keyExtractor={(item, index) => 'task_' + index} + data={taskQueue || []} + renderItem={({ item, index }) => ( - {item.data.chapterName} + {item.name} - {ServiceManager.manager.getTaskDescription(item)} 0 && - downloadQueue[0].data.chapterId === item.data.chapterId - } + indeterminate={taskQueue && taskQueue.length > 0 && index === 0} color={theme.primary} style={{ marginTop: 8 }} /> @@ -90,29 +86,27 @@ const DownloadQueue = ({ navigation }: DownloadQueueScreenProps) => { ListEmptyComponent={ } /> - {downloadQueue.length > 0 ? ( + {taskQueue && taskQueue.length > 0 ? ( { - if (isDownloading) { - pauseDownload(); - setIsDownloading(false); + if (isRunning) { + ServiceManager.manager.pause(); + setIsRunning(false); } else { - resumeDowndload(); - setIsDownloading(true); + ServiceManager.manager.resume(); + setIsRunning(true); } }} /> diff --git a/src/services/ServiceManager.ts b/src/services/ServiceManager.ts index 69e442c0..7b49c5d6 100644 --- a/src/services/ServiceManager.ts +++ b/src/services/ServiceManager.ts @@ -50,6 +50,13 @@ export default class ServiceManager { get isRunning() { return BackgroundService.isRunning(); } + isMultiplicableTask(task: BackgroundTask) { + return ( + ['DOWNLOAD_CHAPTER', 'IMPORT_EPUB', 'MIGRATE_NOVEL'] as Array< + BackgroundTask['name'] + > + ).includes(task.name); + } start() { if (!this.isRunning) { BackgroundService.start(ServiceManager.lauch, { @@ -141,12 +148,32 @@ export default class ServiceManager { }); } } + getTaskDescription(task: BackgroundTask) { + switch (task.name) { + case 'DOWNLOAD_CHAPTER': + return task.data.chapterName; + case 'IMPORT_EPUB': + return task.data.filename; + case 'MIGRATE_NOVEL': + return task.data.fromNovel.name; + default: + return task.data?.toString() || 'No data'; + } + } getTaskList() { return getMMKVObject>(this.STORE_KEY) || []; } addTask(tasks: BackgroundTask | BackgroundTask[]) { - setMMKVObject(this.STORE_KEY, this.getTaskList().concat(tasks)); - this.start(); + const currentTasks = this.getTaskList(); + const addableTasks = (Array.isArray(tasks) ? tasks : [tasks]).filter( + task => + this.isMultiplicableTask(task) || + !currentTasks.some(_t => _t.name === task.name), + ); + if (addableTasks.length) { + setMMKVObject(this.STORE_KEY, currentTasks.concat(addableTasks)); + this.start(); + } } removeTasksByName(name: BackgroundTask['name']) { const taskList = this.getTaskList();