Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues reported by pre-alpha users #905

Merged
merged 8 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/database/queries/CategoryQueries.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as SQLite from 'expo-sqlite';
import { noop } from 'lodash-es';
import { BackupCategory, Category, NovelCategory } from '../types';
import { BackupCategory, Category, NovelCategory, CCategory } from '../types';
import { showToast } from '@utils/showToast';
import { txnErrorCallback } from '../utils/helpers';
const db = SQLite.openDatabase('lnreader.db');
Expand All @@ -22,6 +22,33 @@ export const getCategoriesFromDb = async (): Promise<Category[]> => {
);
};

export const getCategoriesWithCount = async (
novelIds: number[],
): Promise<CCategory[]> => {
const getCategoriesWithCountQuery = `
SELECT *, novelsCount
FROM Category LEFT JOIN
(
SELECT categoryId, COUNT(novelId) as novelsCount
FROM NovelCategory WHERE novelId in (${novelIds.join(
',',
)}) GROUP BY categoryId
) as NC ON Category.id = NC.categoryId
ORDER BY sort
`;

return new Promise(resolve =>
db.transaction(tx => {
tx.executeSql(
getCategoriesWithCountQuery,
[],
(txObj, { rows }) => resolve((rows as any)._array),
txnErrorCallback,
);
}),
);
};

const createCategoryQuery = 'INSERT INTO Category (name) VALUES (?)';

export const createCategory = (categoryName: string): void =>
Expand Down Expand Up @@ -94,7 +121,11 @@ export const isCategoryNameDuplicate = (

const updateCategoryOrderQuery = 'UPDATE Category SET sort = ? WHERE id = ?';

export const updateCategoryOrderInDb = (categories: Category[]): void =>
export const updateCategoryOrderInDb = (categories: Category[]): void => {
// Do not set local as default one
if (categories.length && categories[0].id == 2) {
return;
}
db.transaction(tx => {
categories.map(category => {
tx.executeSql(
Expand All @@ -105,6 +136,7 @@ export const updateCategoryOrderInDb = (categories: Category[]): void =>
);
});
});
};

export const getAllNovelCategories = (): Promise<NovelCategory[]> => {
return new Promise(resolve =>
Expand Down
53 changes: 15 additions & 38 deletions src/database/queries/NovelQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,6 @@ export const switchNovelToLibrary = async (
) => {
const novel = await getNovel(novelUrl);
if (novel) {
if (novel.isLocal) {
return;
}
db.transaction(tx => {
tx.executeSql(
'UPDATE Novel SET inLibrary = ? WHERE id = ?',
Expand Down Expand Up @@ -288,45 +285,25 @@ export const updateNovelCategoryById = async (
export const updateNovelCategories = async (
novelIds: number[],
categoryIds: number[],
option: string,
): Promise<void> => {
let queries: string[] = [];
// allow local novels have other categories, but not the revesre
// not allow others have local id;
categoryIds = categoryIds.filter(id => id !== 2);
if (option === 'KEEP_OLD') {
novelIds.forEach(novelId => {
categoryIds.forEach(categoryId =>
queries.push(
`INSERT OR REPLACE INTO NovelCategory (novelId, categoryId) VALUES (${novelId}, ${categoryId})`,
),
);
});
} else {
novelIds.forEach(novelId =>
queries.push(`DELETE FROM NovelCategory WHERE novelId = ${novelId}`),
queries.push(
`DELETE FROM NovelCategory WHERE novelId IN (${novelIds.join(
',',
)}) AND categoryId != 2`,
);
novelIds.forEach(novelId => {
categoryIds.forEach(categoryId =>
queries.push(
`INSERT INTO NovelCategory (novelId, categoryId) VALUES (${novelId}, ${categoryId})`,
),
);
novelIds.forEach(novelId => {
categoryIds.forEach(categoryId =>
queries.push(
`INSERT INTO NovelCategory (novelId, categoryId) VALUES (${novelId}, ${categoryId})`,
),
);
});
}
return new Promise(resolve => {
db.transaction(tx => {
queries.forEach((query, index) => {
tx.executeSql(
query,
[],
() => {
if (index === queries.length - 1) {
resolve();
}
},
txnErrorCallback,
);
});
});
db.transaction(tx => {
queries.forEach(query => {
tx.executeSql(query);
});
});
};
Expand Down
4 changes: 4 additions & 0 deletions src/database/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export interface NovelCategory {
categoryId: number;
}

export interface CCategory extends Category {
novelsCount: number;
}

export interface LibraryStats {
novelsCount?: number;
chaptersCount?: number;
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/common/githubUpdateChecker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState, useEffect } from 'react';
import { appVersion } from '../../utils/versionUtils';
import { newer } from '@utils/compareVersion';

interface GithubUpdate {
isNewVersion: boolean;
Expand Down Expand Up @@ -32,9 +33,8 @@ export const useGithubUpdateChecker = (): GithubUpdate => {
const regex = /[^\\d.]/;

let newVersion = versionTag.replace(regex, '');
currentVersion = currentVersion;

return newVersion !== currentVersion;
return newer(newVersion, currentVersion);
};

useEffect(() => {
Expand Down
15 changes: 10 additions & 5 deletions src/hooks/persisted/usePlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export default function usePlugins() {
if (newer(plg.version, finded.version)) {
finded.hasUpdate = true;
finded.iconUrl = plg.iconUrl;
finded.url = plg.url;
if (finded.id === lastUsedPlugin?.id) {
setLastUsedPlugin(finded);
}
}
return false;
}
Expand Down Expand Up @@ -161,16 +165,17 @@ export default function usePlugins() {
if (plugin.id !== plg.id) {
return plg;
}
return {
id: plugin.id,
url: plugin.url,
lang: plugin.lang,
iconUrl: plugin.iconUrl,
const newPlugin: PluginItem = {
...plugin,
site: _plg.site,
name: _plg.name,
version: _plg.version,
hasUpdate: false,
};
if (newPlugin.id === lastUsedPlugin?.id) {
setLastUsedPlugin(newPlugin);
}
return newPlugin;
}),
);
filterPlugins(languagesFilter);
Expand Down
3 changes: 1 addition & 2 deletions src/plugins/pluginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ const installPlugin = async (url: string): Promise<Plugin | undefined> => {
const oldPlugin = plugins[plugin.id];
if (oldPlugin) {
if (newer(plugin.version, oldPlugin.version)) {
delete plugins[oldPlugin.id];
plugins[plugin.id] = plugin;
plugins[oldPlugin.id] = plugin;
await RNFS.writeFile(plugin.path, rawCode, 'utf8');
return plugin;
} else {
Expand Down
14 changes: 13 additions & 1 deletion src/screens/Categories/CategoriesScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,22 @@ const CategoriesScreen = () => {
getCategories();
}, []);
const updateCategorySort = (currentIndex: number, newIndex: number) => {
// Do not set local as default one
if (
(newIndex === 0 &&
currentIndex == 1 &&
categories?.[currentIndex].id === 2) ||
(newIndex === 1 && currentIndex == 0 && categories?.[newIndex].id === 2)
) {
return;
}
const updatedOrderCategories = orderBy(
categories?.map((category, index) => {
// + 1 because in db, sort start from 1

// swap adjacent cards
if (index === currentIndex) {
return { ...category, sort: newIndex + 1 }; // + 1 because in db, sort start from 1
return { ...category, sort: newIndex + 1 };
}
if (index === newIndex) {
return { ...category, sort: currentIndex + 1 };
Expand Down
13 changes: 8 additions & 5 deletions src/screens/Categories/components/CategoryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,14 @@ const CategoryCard: React.FC<CategoryCardProps> = ({
style={[
styles.cardCtn,
{
backgroundColor: theme.isDark
? overlay(2, category.sort === 1 ? theme.surface2 : theme.surface)
: category.sort === 1
? theme.primaryContainer
: theme.secondaryContainer,
backgroundColor:
category.sort === 1
? theme.isDark
? overlay(2, theme.surface2)
: theme.primaryContainer
: category.id === 2
? theme.tertiaryContainer
: theme.secondaryContainer,
},
]}
>
Expand Down
2 changes: 1 addition & 1 deletion src/screens/novel/components/ChapterItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const ChapterItem: React.FC<ChapterItemProps> = ({
]}
numberOfLines={1}
>
{showChapterTitles ? name : `Chapter ${chapNum} • ID: ${id}`}
{showChapterTitles ? name : `Chapter ${chapNum}`}
</Text>
</Row>
<View style={styles.textRow}>
Expand Down
45 changes: 11 additions & 34 deletions src/screens/novel/components/SetCategoriesModal.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import React, { useEffect, useState } from 'react';
import { Dimensions, FlatList, StyleSheet, Text, View } from 'react-native';
import { Divider, Modal, overlay, Portal } from 'react-native-paper';
import { useNavigation } from '@react-navigation/native';
import { NavigationProp, useNavigation } from '@react-navigation/native';

import { Button } from '@components/index';

import { useTheme } from '@hooks/persisted';

import { getString } from '@strings/translations';
import { getCategoriesFromDb } from '@database/queries/CategoryQueries';
import { getCategoriesWithCount } from '@database/queries/CategoryQueries';
import { updateNovelCategories } from '@database/queries/NovelQueries';
import { Category } from '@database/types';
import { CCategory, Category } from '@database/types';
import { Checkbox } from '@components/Checkbox/Checkbox';
import { xor } from 'lodash-es';
import { RootStackParamList } from '@navigators/types';

interface SetCategoryModalProps {
novelIds: number[];
Expand All @@ -30,15 +31,14 @@ const SetCategoryModal: React.FC<SetCategoryModalProps> = ({
onEditCategories,
}) => {
const theme = useTheme();
const { navigate } = useNavigation();
const [option, setOption] = useState<string>('KEEP_OLD');
const { navigate } = useNavigation<NavigationProp<RootStackParamList>>();
const [selectedCategories, setSelectedCategories] = useState<Category[]>([]);
const [categories = [], setCategories] = useState<Category[]>();
const [categories = [], setCategories] = useState<CCategory[]>();

const getCategories = async () => {
const res = await getCategoriesFromDb();

const res = await getCategoriesWithCount(novelIds);
setCategories(res);
setSelectedCategories(res.filter(c => c.novelsCount));
};

useEffect(() => {
Expand Down Expand Up @@ -95,35 +95,13 @@ const SetCategoryModal: React.FC<SetCategoryModalProps> = ({
backgroundColor: theme.onSurfaceDisabled,
}}
/>
<View>
<Text style={[styles.modelOption, { color: theme.onSurface }]}>
{'Option'}
</Text>
<Checkbox
status={option === 'KEEP_OLD'}
label={'Keep old categories'}
onPress={() => setOption('KEEP_OLD')}
viewStyle={styles.checkboxView}
theme={theme}
/>
<Checkbox
status={option === 'REMOVE_OLD'}
label={'Remove old categories (not selected)'}
onPress={() => setOption('REMOVE_OLD')}
viewStyle={styles.checkboxView}
theme={theme}
/>
</View>
<View style={styles.btnContainer}>
<Button
title={getString('common.edit')}
onPress={() => {
navigate(
'MoreStack' as never,
{
screen: 'Categories',
} as never,
);
navigate('MoreStack', {
screen: 'Categories',
});
closeModal();
onEditCategories?.();
}}
Expand All @@ -142,7 +120,6 @@ const SetCategoryModal: React.FC<SetCategoryModalProps> = ({
await updateNovelCategories(
novelIds,
selectedCategories.map(category => category.id),
option,
);
closeModal();
setSelectedCategories([]);
Expand Down
Loading
Loading