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

Refactor news components #6060

Merged
merged 7 commits into from
May 16, 2022
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
19 changes: 1 addition & 18 deletions eslint-problems
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -134,23 +134,6 @@
./source/views/menus/types.ts ./source/views/menus/types.ts
35:29 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any 35:29 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any


./source/views/news/news-container.tsx
28:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
34:14 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
59:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types

./source/views/news/news-list.tsx
22:19 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
29:16 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
33:20 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
39:15 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
47:17 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
49:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types

./source/views/news/news-row.tsx
14:13 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
22:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types

./source/views/settings/components/logo.tsx ./source/views/settings/components/logo.tsx
26:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types 26:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
32:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types 32:2 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
Expand Down Expand Up @@ -307,5 +290,5 @@
./source/views/student-orgs/util.ts ./source/views/student-orgs/util.ts
3:8 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types 3:8 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types


192 problems (0 errors, 192 warnings) 181 problems (0 errors, 181 warnings)


4 changes: 4 additions & 0 deletions images/news-sources/index.ts
Original file line number Original file line Diff line number Diff line change
@@ -1 +1,5 @@
export {ksto} from '../streaming' export {ksto} from '../streaming'

export * as mess from './mess.png'
export * as oleville from './oleville.png'
export * as stolaf from './stolaf.png'
10 changes: 8 additions & 2 deletions source/navigation/routes.tsx
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
MenuItemDetailView, MenuItemDetailView,
DetailNavigationOptions, DetailNavigationOptions,
} from '@frogpond/food-menu/food-item-detail' } from '@frogpond/food-menu/food-item-detail'
// import NewsView from '../views/news' import * as news from '../views/news'
import * as settings from '../views/settings/' import * as settings from '../views/settings/'
// import SISView from '../views/sis' // import SISView from '../views/sis'
import * as streaming from '../views/streaming' import * as streaming from '../views/streaming'
Expand Down Expand Up @@ -214,10 +214,16 @@ export function RootStack(): JSX.Element {
options={orgs.DetailNavigationOptions} options={orgs.DetailNavigationOptions}
/> />
</Stack.Group> </Stack.Group>
<Stack.Group>
<Stack.Screen
component={news.View}
name="News"
options={news.NavigationOptions}
/>
</Stack.Group>
{/* {/*
<Stack.Screen component={JobDetail} name="JobDetail" /> <Stack.Screen component={JobDetail} name="JobDetail" />
<Stack.Screen component={Menus} name="Menus" /> <Stack.Screen component={Menus} name="Menus" />
<Stack.Screen component={News} name="News" />
<Stack.Screen component={SIS} name="SIS" /> <Stack.Screen component={SIS} name="SIS" />
<Stack.Screen <Stack.Screen
component={CourseSearchResults} component={CourseSearchResults}
Expand Down
105 changes: 57 additions & 48 deletions source/views/news/index.tsx
Original file line number Original file line Diff line number Diff line change
@@ -1,57 +1,66 @@
import * as React from 'react' import * as React from 'react'
import {TabNavigator, TabBarIcon} from '@frogpond/navigation-tabs'

import {TabBarIcon} from '@frogpond/navigation-tabs'
import * as newsImages from '../../../images/news-sources' import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'
import NewsContainer from './news-container' import {NativeStackNavigationOptions} from '@react-navigation/native-stack'


const NewsView = TabNavigator({ import * as newsImages from '../../../images/news-sources/index'
StOlafNewsView: { import {NewsList} from './news-list'
screen: ({navigation}) => (
<NewsContainer type Params = {
navigation={navigation} StOlafNewsView: undefined
drewvolz marked this conversation as resolved.
Show resolved Hide resolved
source="stolaf" MessNewsView: undefined
thumbnail={newsImages.stolaf} OlevilleNewsView: undefined
title="St. Olaf" }
/>
), const Tabs = createBottomTabNavigator<Params>()
navigationOptions: {
const StOlafNewsView = () => (
<NewsList source="stolaf" thumbnail={newsImages.stolaf.default} />
)
const MessNewsView = () => (
<NewsList source="mess" thumbnail={newsImages.mess.default} />
)
const OlevilleNewsView = () => (
<NewsList source="oleville" thumbnail={newsImages.oleville.default} />
)

const NewsView = (): JSX.Element => {
return (
<Tabs.Navigator>
<Tabs.Screen
component={StOlafNewsView}
name="StOlafNewsView"
options={{
tabBarLabel: 'St. Olaf', tabBarLabel: 'St. Olaf',
tabBarIcon: TabBarIcon('school'), tabBarIcon: TabBarIcon('school'),
}, headerShown: false,
}, }}

OlevilleNewsView: {
screen: ({navigation}) => (
<NewsContainer
navigation={navigation}
source="oleville"
thumbnail={newsImages.oleville}
title="Oleville"
/> />
), <Tabs.Screen
navigationOptions: { component={MessNewsView}
name="MessNewsView"
options={{
tabBarLabel: 'The Mess',
tabBarIcon: TabBarIcon('newspaper'),
headerShown: false,
}}
/>
<Tabs.Screen
component={OlevilleNewsView}
name="OlevilleNewsView"
options={{
tabBarLabel: 'Oleville', tabBarLabel: 'Oleville',
tabBarIcon: TabBarIcon('happy'), tabBarIcon: TabBarIcon('happy'),
}, headerShown: false,
}, }}

MessNewsView: {
screen: ({navigation}) => (
<NewsContainer
navigation={navigation}
source="mess"
thumbnail={newsImages.mess}
title="The Mess"
/> />
), </Tabs.Navigator>
navigationOptions: { )
tabBarLabel: 'The Mess',
tabBarIcon: TabBarIcon('paper'),
},
},
})
NewsView.navigationOptions = {
title: 'News',
} }


export default NewsView export {NewsView as View}

export const NavigationOptions: NativeStackNavigationOptions = {
title: 'News',
}
75 changes: 0 additions & 75 deletions source/views/news/news-container.tsx

This file was deleted.

100 changes: 62 additions & 38 deletions source/views/news/news-list.tsx
Original file line number Original file line Diff line number Diff line change
@@ -1,12 +1,18 @@
import * as React from 'react' import * as React from 'react'
import {StyleSheet, FlatList} from 'react-native' import {FlatList, StyleSheet} from 'react-native'
import * as c from '@frogpond/colors'
import type {StoryType} from './types' import type {StoryType} from './types'
import {API} from '@frogpond/api'
import * as c from '@frogpond/colors'
import {useFetch} from 'react-async'
import {ListSeparator} from '@frogpond/lists' import {ListSeparator} from '@frogpond/lists'
import {NoticeView} from '@frogpond/notice' import {LoadingView, NoticeView} from '@frogpond/notice'
import type {TopLevelViewPropsType} from '../types'
import {NewsRow} from './news-row'
import {openUrl} from '@frogpond/open-url' import {openUrl} from '@frogpond/open-url'
import {NewsRow} from './news-row'

type Props = {
source: string | {url: string; type: 'rss' | 'wp-json'}
thumbnail: false | number
}


const styles = StyleSheet.create({ const styles = StyleSheet.create({
listContainer: { listContainer: {
Expand All @@ -17,54 +23,72 @@ const styles = StyleSheet.create({
}, },
}) })


type Props = TopLevelViewPropsType & { const useNews = (source: Props['source']) => {
name: string let url
onRefresh: () => any if (typeof source === 'string') {
entries: StoryType[] url = API(`/news/named/${source}`)
loading: boolean } else if (source.type === 'rss') {
thumbnail: false | number url = API('/news/rss', {url: source.url})
} else if (source.type === 'wp-json') {
url = API('/news/wpjson', {url: source.url})
} else {
throw new Error('invalid news source type!')
} }


export class NewsList extends React.PureComponent<Props> { return useFetch<StoryType[]>(url, {
onPressNews = (url: string) => { headers: {accept: 'application/json'},
return openUrl(url) })
} }


renderSeparator = () => ( export const NewsList = (props: Props): JSX.Element => {
<ListSeparator let {
spacing={{left: this.props.thumbnail === false ? undefined : 101}} data = [],
/> error,
) reload,

isPending,
renderItem = ({item}: {item: StoryType}) => ( isInitial,
<NewsRow isLoading,
onPress={this.onPressNews} } = useNews(props.source)
story={item}
thumbnail={this.props.thumbnail}
/>
)

keyExtractor = (item: StoryType) => item.title


render() {
// remove all entries with blank excerpts // remove all entries with blank excerpts
// remove all entries with a <form from the list // remove all entries with a <form from the list
let entries = this.props.entries let entries = data
.filter((entry) => entry.excerpt.trim() !== '') .filter((entry) => entry.excerpt.trim() !== '')
.filter((entry) => !entry.content.includes('<form')) .filter((entry) => !entry.content.includes('<form'))


if (error) {
return (
<NoticeView
buttonText="Try Again"
onPress={reload}
text="A problem occured while loading the news stories"
/>
)
}

return ( return (
<FlatList <FlatList
ItemSeparatorComponent={this.renderSeparator} ItemSeparatorComponent={() => (
ListEmptyComponent={<NoticeView text="No news." />} <ListSeparator
spacing={{left: props.thumbnail === false ? undefined : 101}}
/>
)}
ListEmptyComponent={
isLoading ? <LoadingView /> : <NoticeView text="No news." />
}
contentContainerStyle={styles.contentContainer} contentContainerStyle={styles.contentContainer}
data={entries} data={entries}
keyExtractor={this.keyExtractor} keyExtractor={(item: StoryType) => item.title}
onRefresh={this.props.onRefresh} onRefresh={reload}
refreshing={this.props.loading} refreshing={isPending && !isInitial}
renderItem={this.renderItem} renderItem={({item}: {item: StoryType}) => (
<NewsRow
onPress={(url: string) => openUrl(url)}
story={item}
thumbnail={props.thumbnail}
/>
)}
style={styles.listContainer} style={styles.listContainer}
/> />
) )
} }
}
Loading