Skip to content

Commit

Permalink
[saved] Saved stories page (#73)
Browse files Browse the repository at this point in the history
* initial commit

* Fix width bugs

* styling

* adding preview cards

* merging saved stories into branch

* styling selector bar

* finished styling

* removed unused folders

* Fix title preview card overflow

* Fix featured stories extra space

* Revert and useMemo to cache

* Implement flatlist

* Add default state to saved story button

* Run prettier

* Auto update reading list page

* Finish library screen

---------

Co-authored-by: Kyle Ramachandran <[email protected]>
Co-authored-by: Aditya Pawar <[email protected]>
Co-authored-by: Aditya Pawar <[email protected]>
  • Loading branch information
4 people authored Apr 21, 2024
1 parent b88af9e commit 14dbd0d
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 48 deletions.
Binary file modified assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 7 additions & 10 deletions src/app/(tabs)/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
import { SafeAreaView } from 'react-native-safe-area-context';

import styles from './styles';
import Icon from '../../../../assets/icons';
import ContentCard from '../../../components/ContentCard/ContentCard';
import PreviewCard from '../../../components/PreviewCard/PreviewCard';
import { fetchUsername } from '../../../queries/profiles';
Expand Down Expand Up @@ -146,20 +145,18 @@ function HomeScreen() {
<Text style={globalStyles.h1}>
{username ? `Welcome, ${username}` : 'Welcome!'}
</Text>
<Pressable onPress={() => router.push('/settings')}>
<View>
<Icon type="settings_gear" />
</View>
</Pressable>
</View>

{featuredStories.length > 0 && (
<View>
<Text style={globalStyles.h3}>Featured Stories</Text>
<Text style={[globalStyles.body1, styles.featuredDescription]}>
{featuredStoriesDescription}
</Text>
<View style={{ marginRight: 24 }}>
{featuredStoriesDescription != null &&
featuredStoriesDescription.length > 0 && (
<Text style={[globalStyles.body1, styles.featuredDescription]}>
{featuredStoriesDescription}
</Text>
)}
<View style={{ marginRight: 24, marginTop: 16 }}>
{featuredStories.map(story => (
<PreviewCard
key={story.id}
Expand Down
154 changes: 149 additions & 5 deletions src/app/(tabs)/library/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,157 @@
import { Text } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Text, View, Pressable, ScrollView } from 'react-native';
import { useState, useEffect, useMemo } from 'react';
import { useSession } from '../../../utils/AuthContext';
import { router } from 'expo-router';

import globalStyles from '../../../styles/globalStyles';
import styles from './styles';
import LibraryHeader from '../../../components/LibraryHeader/LibraryHeader';
import PreviewCard from '../../../components/PreviewCard/PreviewCard';
import { StoryPreview } from '../../../queries/types';
import {
fetchUserStoriesFavorites,
fetchUserStoriesReadingList,
} from '../../../queries/savedStories';
import { FlatList } from 'react-native-gesture-handler';
import { usePubSub } from '../../../utils/PubSubContext';

function LibraryScreen() {
const { user } = useSession();
const [favoritesSelected, setFavoritesSelected] = useState(true);
const [readingSelected, setReadingSelected] = useState(false);
const [favoriteStories, setFavoriteStories] = useState<StoryPreview[]>([]);
const [readingListStories, setReadingListStories] = useState<StoryPreview[]>(
[],
);
const { channels } = usePubSub();
let updateReadingListTimeout: NodeJS.Timeout | null = null;

const favoritesPressed = () => {
setFavoritesSelected(true);
setReadingSelected(false);
};

const readingPressed = () => {
setFavoritesSelected(false);
setReadingSelected(true);
};

const renderItem = ({ item }: { item: StoryPreview }) => {
return (
<View style={{ paddingHorizontal: 24 }}>
<PreviewCard
key={item.title}
storyId={item.id}
defaultSavedStoriesState={true}
title={item.title}
image={item.featured_media}
author={item.author_name}
authorImage={item.author_image}
excerpt={item.excerpt}
tags={item.genre_medium.concat(item.tone).concat(item.topic)}
pressFunction={() =>
router.push({
pathname: '/story',
params: { storyId: item.id.toString() },
})
}
/>
</View>
);
};

useEffect(() => {
if (updateReadingListTimeout) {
clearTimeout(updateReadingListTimeout);
}

updateReadingListTimeout = setTimeout(
() =>
fetchUserStoriesReadingList(user?.id).then(readingList => {
setReadingListStories(readingList);
}),
5000,
);
}, [channels]);

useEffect(() => {
(async () => {
await Promise.all([
fetchUserStoriesFavorites(user?.id).then(favorites =>
setFavoriteStories(favorites),
),
fetchUserStoriesReadingList(user?.id).then(readingList => {
setReadingListStories(readingList);
}),
]);
})();
}, [user]);

return (
<SafeAreaView style={globalStyles.tabBarContainer}>
<Text style={globalStyles.h1}>Library</Text>
</SafeAreaView>
<View style={styles.container}>
<View style={styles.header}>
<LibraryHeader />
</View>
<View style={styles.selector}>
<View style={favoritesSelected && styles.selectedButton}>
<Pressable onPress={favoritesPressed}>
<Text
style={[
globalStyles.subHeading1,
favoritesSelected ? styles.selectedText : styles.unselectedText,
]}
>
Favorites
</Text>
</Pressable>
</View>

<View style={readingSelected && styles.selectedButton}>
<Pressable onPress={readingPressed}>
<View>
<Text
style={[
globalStyles.subHeading1,
readingSelected ? styles.selectedText : styles.unselectedText,
]}
>
Reading List
</Text>
</View>
</Pressable>
</View>
</View>

<View style={{ width: '100%', flex: 1, marginBottom: 100 }}>
{favoritesSelected &&
(favoriteStories.length > 0 ? (
<FlatList data={favoriteStories} renderItem={renderItem} />
) : (
<View style={{ paddingBottom: 16 }}>
<Text style={[globalStyles.h3, { textAlign: 'center' }]}>
Favorited stories
</Text>
<Text style={[globalStyles.h3, { textAlign: 'center' }]}>
will appear here.
</Text>
</View>
))}

{readingSelected &&
(readingListStories.length > 0 ? (
<FlatList data={readingListStories} renderItem={renderItem} />
) : (
<View style={{ paddingBottom: 16 }}>
<Text style={[globalStyles.h3, { textAlign: 'center' }]}>
Saved stories
</Text>
<Text style={[globalStyles.h3, { textAlign: 'center' }]}>
will appear here.
</Text>
</View>
))}
</View>
</View>
);
}

Expand Down
40 changes: 39 additions & 1 deletion src/app/(tabs)/library/styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
import { StyleSheet } from 'react-native';
import colors from '../../../styles/colors';

const styles = StyleSheet.create({});
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
alignItems: 'flex-start',
justifyContent: 'flex-start',
},
selector: {
display: 'flex',
width: '100%',
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: '#fbfbfb',
marginBottom: 24,
},
header: {
paddingHorizontal: 24,
marginBottom: 24,
marginTop: 60,
},
selectedText: {
textAlign: 'center',
color: colors.gwnOrange,
paddingVertical: 8,
},
unselectedText: {
textAlign: 'center',
color: colors.black,
paddingVertical: 8,
},
selectedButton: {
borderBottomWidth: 1,
borderBottomColor: colors.gwnOrange,
},
scrollView: {
width: '100%',
},
});

export default styles;
35 changes: 35 additions & 0 deletions src/components/LibraryHeader/LibraryHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { View, Text, Image, Pressable } from 'react-native';
import { router } from 'expo-router';
import { useEffect, useState } from 'react';
import Icon from '../../../assets/icons';

import styles from './styles';
import globalStyles from '../../styles/globalStyles';
import colors from '../../styles/colors';
import { useSession } from '../../utils/AuthContext';

export default function LibraryHeader() {
const { user } = useSession();

return (
<View style={styles.horizontal}>
<View style={styles.textContainer}>
<Image
style={styles.image}
source={require('../../../assets/icon.png')}
/>
<View style={styles.username}>
<Text style={globalStyles.h1}>{user?.user_metadata.username} </Text>
</View>
</View>

<View>
<Pressable onPress={() => router.push('/settings')}>
<View>
<Icon type="settings_gear" />
</View>
</Pressable>
</View>
</View>
);
}
31 changes: 31 additions & 0 deletions src/components/LibraryHeader/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { StyleSheet } from 'react-native';
import colors from '../../styles/colors';

const styles = StyleSheet.create({
container: {
display: 'flex',
flexGrow: 1,
width: '100%',
},
image: {
height: 51,
width: 51,
borderRadius: 51 / 2,
marginBottom: 12,
},
textContainer: {
flexDirection: 'row',
},
username: {
paddingLeft: 12,
},
horizontal: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
width: '100%',
alignContent: 'center',
},
});

export default styles;
11 changes: 9 additions & 2 deletions src/components/PreviewCard/PreviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type PreviewCardProps = {
storyId: number;
author: string;
authorImage: string;
defaultSavedStoriesState?: boolean;
excerpt: { html: string };
tags: string[];
reactions?: string[] | null;
Expand All @@ -40,6 +41,7 @@ function PreviewCard({
authorImage,
excerpt,
tags,
defaultSavedStoriesState = false,
pressFunction,
reactions: preloadedReactions = null,
}: PreviewCardProps) {
Expand Down Expand Up @@ -68,8 +70,13 @@ function PreviewCard({
<Text numberOfLines={1} style={[globalStyles.h3, styles.title]}>
{title}
</Text>
<TouchableOpacity>
<SaveStoryButton storyId={storyId} />
<TouchableOpacity style={{ alignSelf: 'flex-end' }}>
<View>
<SaveStoryButton
storyId={storyId}
defaultState={defaultSavedStoriesState}
/>
</View>
</TouchableOpacity>
</View>
<View style={styles.body}>
Expand Down
7 changes: 4 additions & 3 deletions src/components/PreviewCard/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ const styles = StyleSheet.create({
marginBottom: 12,
},
title: {
marginBottom: 8,
flex: 1,
alignSelf: 'flex-start',
// marginBottom: 8,
},
titleContainer: {
paddingTop: 16,
Expand All @@ -54,8 +56,7 @@ const styles = StyleSheet.create({
borderBottomColor: '#EBEBEB',
borderBottomWidth: StyleSheet.hairlineWidth,
flexDirection: 'row',
flexGrow: 1,
justifyContent: 'space-between',
flex: 1,
},
tag: {
paddingHorizontal: 8,
Expand Down
Loading

0 comments on commit 14dbd0d

Please sign in to comment.