Skip to content

Commit

Permalink
feat: Add Trailing Skeleton Novel Covers (#629)
Browse files Browse the repository at this point in the history
* TS NovelCover

* added some changes to the loading animation
  • Loading branch information
CD-Z authored Jun 7, 2023
1 parent 2d6251b commit 3adc655
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 58 deletions.
123 changes: 79 additions & 44 deletions src/components/NovelCover.js → src/components/NovelCover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
useWindowDimensions,
Pressable,
} from 'react-native';
import color from 'color';

import { LinearGradient } from 'expo-linear-gradient';
import FastImage from 'react-native-fast-image';
Expand All @@ -16,8 +15,22 @@ import { useDeviceOrientation } from '@hooks/useDeviceOrientation';
import { coverPlaceholderColor } from '../theme/colors';
import { useLibrarySettings } from '@hooks/useSettings';
import { DisplayModes } from '@screens/library/constants/constants';
import { LibraryNovelInfo } from '@database/types';
import { SourceNovelItem } from 'src/sources/types';
import { ThemeColors } from '@theme/types';
import SourceScreenSkeletonLoading from '@screens/browse/loadingAnimation/SourceScreenSkeletonLoading';

const NovelCover = ({
interface NovelCoverProps {
item: LibraryNovelInfo;
onPress: () => void;
libraryStatus?: boolean;
theme: ThemeColors;
isSelected?: boolean;
onLongPress: (novelId: number) => void;
selectedNovels?: Array<SourceNovelItem>;
}

const NovelCover: React.FC<NovelCoverProps> = ({
item,
onPress,
libraryStatus,
Expand All @@ -44,26 +57,27 @@ const NovelCover = ({

const coverHeight = useMemo(
() => (window.width / numColumns) * (4 / 3),
// eslint-disable-next-line react-hooks/exhaustive-deps
[numColumns],
);

const selectNovel = () => onLongPress && onLongPress(item.novelId);

const uri = item.novelCover;

return displayMode !== DisplayModes.List ? (
return item.sourceId < 0 ? (
<SourceScreenSkeletonLoading theme={theme} completeRow={item.sourceId} />
) : displayMode !== DisplayModes.List ? (
<View
style={[
{
flex: 1 / numColumns,
borderRadius: 6,
overflow: 'hidden',
margin: 2,
},
styles.standardNovelCover,
isSelected && {
backgroundColor: theme.primary,
opacity: 0.8,
},
backgroundColor: theme.primary,
} &&
styles.selectedNovelCover,
]}
>
<Pressable
Expand Down Expand Up @@ -98,10 +112,10 @@ const NovelCover = ({
style={[
{
height: coverHeight,
borderRadius: 4,
backgroundColor: coverPlaceholderColor,
},
libraryStatus && { opacity: 0.5 },
styles.standardBorderRadius,
libraryStatus && styles.opacityPoint5,
]}
/>
<View style={styles.compactTitleContainer}>
Expand Down Expand Up @@ -152,61 +166,65 @@ const NovelCover = ({

export default memo(NovelCover);

const ComfortableTitle = ({ theme, novelName }) => (
const ComfortableTitle: React.FC<{ theme: ThemeColors; novelName: string }> = ({
theme,
novelName,
}) => (
<Text
numberOfLines={2}
style={[
styles.title,
styles.padding4,
{
color: theme.onSurface,
padding: 4,
},
]}
>
{novelName}
</Text>
);

const CompactTitle = ({ novelName }) => (
const CompactTitle: React.FC<{ novelName: string }> = ({ novelName }) => (
<View style={styles.titleContainer}>
<LinearGradient
colors={['transparent', 'rgba(0,0,0,0.7)']}
style={styles.linearGradient}
>
<Text
numberOfLines={2}
style={[
styles.title,
{
color: 'rgba(255,255,255,1)',
textShadowColor: 'rgba(0, 0, 0, 0.75)',
textShadowOffset: { width: -1, height: 1 },
textShadowRadius: 10,
},
]}
>
<Text numberOfLines={2} style={[styles.title, styles.compactTitle]}>
{novelName}
</Text>
</LinearGradient>
</View>
);

const InLibraryBadge = ({ theme }) => (
const InLibraryBadge: React.FC<{ theme: ThemeColors }> = ({ theme }) => (
<Text
style={[
styles.inLibraryBadge,
{
backgroundColor: theme.primary,
color: theme.onPrimary,
borderRadius: 4,
},
styles.standardBorderRadius,
]}
>
In library
</Text>
);

const UnreadBadge = ({
interface BadgeProps {
chaptersDownloaded: number;
chaptersUnread: number;
theme: ThemeColors;
}
interface UnreadBadgeProps extends BadgeProps {
showDownloadBadges: boolean;
}
interface DownloadBadgeProps extends BadgeProps {
showUnreadBadges: boolean;
}

const UnreadBadge: React.FC<UnreadBadgeProps> = ({
chaptersDownloaded,
chaptersUnread,
showDownloadBadges,
Expand All @@ -215,13 +233,8 @@ const UnreadBadge = ({
<Text
style={[
styles.unreadBadge,
!chaptersDownloaded && {
borderTopLeftRadius: 4,
borderBottomLeftRadius: 4,
},
!showDownloadBadges && {
borderRadius: 4,
},
!chaptersDownloaded && styles.LeftBorderRadius,
!showDownloadBadges && styles.standardBorderRadius,
{
backgroundColor: theme.primary,
color: theme.onPrimary,
Expand All @@ -232,7 +245,7 @@ const UnreadBadge = ({
</Text>
);

const DownloadBadge = ({
const DownloadBadge: React.FC<DownloadBadgeProps> = ({
chaptersDownloaded,
showUnreadBadges,
chaptersUnread,
Expand All @@ -241,13 +254,8 @@ const DownloadBadge = ({
<Text
style={[
styles.downloadBadge,
!chaptersUnread && {
borderTopRightRadius: 4,
borderBottomRightRadius: 4,
},
!showUnreadBadges && {
borderRadius: 4,
},
!chaptersUnread && styles.RightBorderRadius,
!showUnreadBadges && styles.standardBorderRadius,
{
backgroundColor: theme.tertiary,
color: theme.onTertiary,
Expand All @@ -259,6 +267,19 @@ const DownloadBadge = ({
);

const styles = StyleSheet.create({
LeftBorderRadius: {
borderTopLeftRadius: 4,
borderBottomLeftRadius: 4,
},
RightBorderRadius: {
borderTopRightRadius: 4,
borderBottomRightRadius: 4,
},
standardBorderRadius: {
borderRadius: 4,
},
opacityPoint5: { opacity: 0.5 },
padding4: { padding: 4 },
titleContainer: {
flex: 1,
borderRadius: 4,
Expand Down Expand Up @@ -322,4 +343,18 @@ const styles = StyleSheet.create({
left: 10,
flexDirection: 'row',
},
standardNovelCover: {
borderRadius: 6,
overflow: 'hidden',
margin: 2,
},
selectedNovelCover: {
opacity: 0.8,
},
compactTitle: {
color: 'rgba(255,255,255,1)',
textShadowColor: 'rgba(0, 0, 0, 0.75)',
textShadowOffset: { width: -1, height: 1 },
textShadowRadius: 10,
},
});
25 changes: 21 additions & 4 deletions src/components/NovelList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ export type NovelListRenderItem = ListRenderItem<
LibraryNovelInfo | NovelInfo | SourceNovelItem
>;

const NovelList: React.FC<
FlatListProps<LibraryNovelInfo | NovelInfo | SourceNovelItem>
> = props => {
interface NovelListProps
extends FlatListProps<LibraryNovelInfo | NovelInfo | SourceNovelItem> {
inSource?: boolean;
}

const NovelList: React.FC<NovelListProps> = props => {
const { displayMode = DisplayModes.Comfortable, novelsPerRow = 3 } =
useLibrarySettings();

Expand All @@ -37,7 +40,20 @@ const NovelList: React.FC<
}
}, [isListView, orientation, novelsPerRow]);

const keyExtractor = useCallback(item => item.sourceId + item.novelUrl, []);
const keyExtractor = useCallback(
(item: SourceNovelItem) => item.sourceId + item.novelUrl,
[],
);
var extendedNovelList: Array<SourceNovelItem | LibraryNovelInfo> =
props?.data as Array<LibraryNovelInfo>;
if (props.data?.length && props.inSource) {
let remainder = numColumns - (props.data?.length % numColumns);
let extension = [];
if (remainder !== 0 && remainder !== numColumns) {
extension.push({ sourceId: -remainder, novelName: '', novelUrl: '' });
}
extendedNovelList = [...props.data, ...extension];
}

return (
<FlatList
Expand All @@ -49,6 +65,7 @@ const NovelList: React.FC<
key={numColumns}
keyExtractor={keyExtractor}
{...props}
data={extendedNovelList}
/>
);
};
Expand Down
17 changes: 11 additions & 6 deletions src/screens/BrowseSourceScreen/BrowseSourceScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,14 @@ const BrowseSourceScreen: React.FC<BrowseSourceScreenProps> = ({ route }) => {
};

const handleOpenWebView = async () => {
navigate('WebviewScreen', {
sourceId,
name: sourceName,
url: sourceUrl,
});
navigate(
'WebviewScreen' as never,
{
sourceId,
name: sourceName,
url: sourceUrl,
} as never,
);
};

const { library, setLibrary } = useLibraryNovels();
Expand Down Expand Up @@ -127,12 +130,13 @@ const BrowseSourceScreen: React.FC<BrowseSourceScreenProps> = ({ route }) => {
) : (
<NovelList
data={novelList}
inSource
renderItem={({ item }) => {
const inLibrary = novelInLibrary(item.novelUrl);

return (
<NovelCover
item={item}
item={item as LibraryNovelInfo}
theme={theme}
libraryStatus={inLibrary}
onPress={() => navigateToNovel(item)}
Expand Down Expand Up @@ -169,6 +173,7 @@ const BrowseSourceScreen: React.FC<BrowseSourceScreenProps> = ({ route }) => {
fetchNextPage();
}
}}
onEndReachedThreshold={1.5}
ListFooterComponent={
hasNextPage && !searchText ? (
<SourceScreenSkeletonLoading theme={theme} />
Expand Down
2 changes: 1 addition & 1 deletion src/screens/BrowseSourceScreen/useBrowseSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const useBrowseSource = (

const clearFilters = useCallback(() => setSelectedFilters(undefined), []);

const setFilters = (filters: SelectedFilter) => {
const setFilters = (filters?: SelectedFilter) => {
setIsLoading(true);
setCurrentPage(1);
fetchNovels(1, filters);
Expand Down
2 changes: 1 addition & 1 deletion src/screens/browse/loadingAnimation/LoadingNovel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const createStyleSheet = (pictureHeight: number, pictureWidth: number) => {
borderRadius: 4,
},
listLoadingContainer: {
marginHorizontal: 12,
marginHorizontal: 8,
marginVertical: 8,
flexDirection: 'row',
alignItems: 'center',
Expand Down
Loading

0 comments on commit 3adc655

Please sign in to comment.