Fix app logics (#1001)

* fix: DocumentPicker apis

* fix: retry on browse source screen

* fix: set categories logic

* fix: dont fire noti when pausing downloading
This commit is contained in:
nyagami
2024-03-14 00:28:23 +07:00
committed by GitHub
parent a54ed6de0e
commit aeaecda0cd
8 changed files with 74 additions and 48 deletions
+1
View File
@@ -35,6 +35,7 @@ export const getCategoriesWithCount = async (
',',
)}) GROUP BY categoryId
) as NC ON Category.id = NC.categoryId
WHERE Category.id != 2
ORDER BY sort
`;
+22 -10
View File
@@ -270,11 +270,11 @@ export const updateNovelInfo = async (info: NovelInfo) => {
export const pickCustomNovelCover = async (novel: NovelInfo) => {
const image = await DocumentPicker.getDocumentAsync({ type: 'image/*' });
if (image.type === 'success' && image.uri) {
if (image.assets && image.assets[0]) {
const novelDir =
NovelDownloadFolder + '/' + novel.pluginId + '/' + novel.id;
let novelCoverUri = 'file://' + novelDir + '/cover.png';
RNFS.copyFile(image.uri, novelCoverUri);
RNFS.copyFile(image.assets[0].uri, novelCoverUri);
novelCoverUri += '?' + Date.now();
db.transaction(tx => {
tx.executeSql(
@@ -309,20 +309,32 @@ export const updateNovelCategories = async (
categoryIds: number[],
): Promise<void> => {
let queries: string[] = [];
// not allow others have local id;
categoryIds = categoryIds.filter(id => id !== 2);
queries.push(
`DELETE FROM NovelCategory WHERE novelId IN (${novelIds.join(
',',
)}) AND categoryId != 2`,
);
novelIds.forEach(novelId => {
categoryIds.forEach(categoryId =>
// if no category is selected => set to the default category
if (categoryIds.length) {
novelIds.forEach(novelId => {
categoryIds.forEach(categoryId =>
queries.push(
`INSERT INTO NovelCategory (novelId, categoryId) VALUES (${novelId}, ${categoryId})`,
),
);
});
} else {
novelIds.forEach(novelId => {
// hacky: insert local novel category -> failed -> ignored
queries.push(
`INSERT INTO NovelCategory (novelId, categoryId) VALUES (${novelId}, ${categoryId})`,
),
);
});
`INSERT OR IGNORE INTO NovelCategory (novelId, categoryId)
VALUES (
${novelId},
IFNULL((SELECT categoryId FROM NovelCategory WHERE novelId = ${novelId}), (SELECT id FROM Category WHERE sort = 1))
)`,
);
});
}
db.transaction(tx => {
queries.forEach(query => {
tx.executeSql(query);
+10 -8
View File
@@ -27,7 +27,7 @@ const downloadChapterAction = async (taskData?: TaskData) => {
try {
MMKVStorage.set(BACKGROUND_ACTION, BackgoundAction.DOWNLOAD_CHAPTER);
let queue = getMMKVObject<DownloadData[]>(DOWNLOAD_QUEUE) || [];
while (queue.length > 0) {
while (queue.length > 0 && BackgroundService.isRunning()) {
const { novel, chapter } = queue[0];
await BackgroundService.updateNotification({
taskTitle: getString('downloadScreen.downloadingNovel', {
@@ -63,13 +63,15 @@ const downloadChapterAction = async (taskData?: TaskData) => {
}
} finally {
MMKVStorage.delete(BACKGROUND_ACTION);
await Notifications.scheduleNotificationAsync({
content: {
title: getString('downloadScreen.downloader'),
body: getString('downloadScreen.completed'),
},
trigger: null,
});
if (getMMKVObject<DownloadData[]>(DOWNLOAD_QUEUE)?.length === 0) {
await Notifications.scheduleNotificationAsync({
content: {
title: getString('downloadScreen.downloader'),
body: getString('downloadScreen.completed'),
},
trigger: null,
});
}
BackgroundService.stop();
}
};
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useRef } from 'react';
import React, { useCallback, useRef } from 'react';
import { FAB } from 'react-native-paper';
import { Container, ErrorScreenV2, SearchbarV2 } from '@components/index';
@@ -7,7 +7,7 @@ import NovelCover from '@components/NovelCover';
import { BottomSheetModal } from '@gorhom/bottom-sheet';
import FilterBottomSheet from './components/FilterBottomSheet';
import { usePreviousRouteName, useSearch } from '@hooks';
import { useSearch } from '@hooks';
import { useTheme } from '@hooks/persisted';
import { useBrowseSource, useSearchSource } from './useBrowseSource';
@@ -23,8 +23,6 @@ import { BrowseSourceScreenProps } from '@navigators/types';
const BrowseSourceScreen = ({ route, navigation }: BrowseSourceScreenProps) => {
const theme = useTheme();
const previousScreen = usePreviousRouteName();
const { pluginId, pluginName, site, showLatestNovels } = route.params;
const {
@@ -62,12 +60,6 @@ const BrowseSourceScreen = ({ route, navigation }: BrowseSourceScreenProps) => {
clearSearchResults();
};
useEffect(() => {
if (previousScreen === 'WebviewScreen') {
refetchNovels();
}
}, [previousScreen]);
const handleOpenWebView = async () => {
navigation.navigate('WebviewScreen', {
name: pluginName,
@@ -111,6 +103,19 @@ const BrowseSourceScreen = ({ route, navigation }: BrowseSourceScreenProps) => {
) : errorMessage || novelList.length === 0 ? (
<ErrorScreenV2
error={errorMessage || getString('sourceScreen.noResultsFound')}
actions={[
{
iconName: 'refresh',
title: getString('common.retry'),
onPress: () => {
if (searchText) {
searchSource(searchText);
} else {
refetchNovels();
}
},
},
]}
/>
) : (
<NovelList
@@ -44,7 +44,10 @@ export const useBrowseSource = (
setHasNextPage(false);
}
})
.catch(error => setError(error.message));
.catch(error => {
setError(error.message);
setHasNextPage(false);
});
setFilterValues(plugin.filters);
} catch (err: unknown) {
setError(`${err}`);
@@ -74,8 +77,11 @@ export const useBrowseSource = (
}, [fetchNovels, currentPage]);
const refetchNovels = () => {
setError('');
setIsLoading(true);
setNovels([]);
setCurrentPage(1);
fetchNovels(1);
fetchNovels(1, selectedFilters);
};
const clearFilters = useCallback(
@@ -113,6 +119,7 @@ export const useSearchSource = (pluginId: string) => {
const searchSource = (searchTerm: string) => {
setSearchResults([]);
setHasNextSearchPage(true);
setCurrentPage(1);
setSearchText(searchTerm);
setIsSearching(true);
@@ -137,6 +144,7 @@ export const useSearchSource = (pluginId: string) => {
}
} catch (err: unknown) {
setSearchError(`${err}`);
setHasNextSearchPage(false);
} finally {
setIsSearching(false);
}
@@ -113,20 +113,18 @@ const SetCategoryModal: React.FC<SetCategoryModalProps> = ({
closeModal();
}}
/>
{selectedCategories.length ? (
<Button
title={getString('common.ok')}
onPress={async () => {
await updateNovelCategories(
novelIds,
selectedCategories.map(category => category.id),
);
closeModal();
setSelectedCategories([]);
onSuccess?.();
}}
/>
) : null}
<Button
title={getString('common.ok')}
onPress={async () => {
await updateNovelCategories(
novelIds,
selectedCategories.map(category => category.id),
);
closeModal();
setSelectedCategories([]);
onSuccess?.();
}}
/>
</View>
</Modal>
</Portal>
@@ -43,9 +43,9 @@ const CustomFileModal: React.FC<CustomFileModal> = ({
type: mimeType,
});
if (file.type === 'success') {
if (file.assets) {
const content = await StorageAccessFramework.readAsStringAsync(
file.uri,
file.assets[0].uri,
);
onSave(content.trim());
+2 -2
View File
@@ -67,8 +67,8 @@ export const restoreBackup = async (filePath?: string) => {
});
let novelsString = '';
if (backup.type === 'success') {
novelsString = await RNFS.readFile(backup.uri);
if (backup.assets && backup.assets[0]) {
novelsString = await RNFS.readFile(backup.assets[0].uri);
} else if (filePath) {
if (!(await RNFS.exists(filePath))) {
showToast(getString('backupScreen.legacy.noErrorNovel'));