From e650d98924051abfee40ff956f7348e2e47e7cd7 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 7 Nov 2022 16:24:06 -0600 Subject: [PATCH] Add search view; factor out SuggestedFollows component; add suggested follows to search --- src/state/models/onboard.ts | 2 +- src/view/com/discover/SuggestedFollows.tsx | 177 +++++++++++++++++++++ src/view/com/onboard/Follows.tsx | 160 +------------------ src/view/lib/icons.tsx | 27 ++++ src/view/screens/Search.tsx | 56 ++++++- src/view/shell/mobile/index.tsx | 17 +- 6 files changed, 278 insertions(+), 161 deletions(-) create mode 100644 src/view/com/discover/SuggestedFollows.tsx diff --git a/src/state/models/onboard.ts b/src/state/models/onboard.ts index 77a06633..20e6ecda 100644 --- a/src/state/models/onboard.ts +++ b/src/state/models/onboard.ts @@ -9,7 +9,7 @@ export const OnboardStage = { export const OnboardStageOrder = [OnboardStage.Explainers, OnboardStage.Follows] export class OnboardModel { - isOnboarding: boolean = true + isOnboarding: boolean = false stage: string = OnboardStageOrder[0] constructor() { diff --git a/src/view/com/discover/SuggestedFollows.tsx b/src/view/com/discover/SuggestedFollows.tsx new file mode 100644 index 00000000..e73d9a7d --- /dev/null +++ b/src/view/com/discover/SuggestedFollows.tsx @@ -0,0 +1,177 @@ +import React, {useMemo, useEffect} from 'react' +import { + ActivityIndicator, + FlatList, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native' +import LinearGradient from 'react-native-linear-gradient' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {observer} from 'mobx-react-lite' +import {ErrorScreen} from '../util/ErrorScreen' +import {UserAvatar} from '../util/UserAvatar' +import {useStores} from '../../../state' +import { + SuggestedActorsViewModel, + SuggestedActor, +} from '../../../state/models/suggested-actors-view' +import {s, colors, gradients} from '../../lib/styles' + +export const SuggestedFollows = observer( + ({onNoSuggestions}: {onNoSuggestions?: () => void}) => { + const store = useStores() + + const view = useMemo( + () => new SuggestedActorsViewModel(store), + [], + ) + + useEffect(() => { + console.log('Fetching suggested actors') + view + .setup() + .catch((err: any) => console.error('Failed to fetch suggestions', err)) + }, [view]) + + useEffect(() => { + if (!view.isLoading && !view.hasError && !view.hasContent) { + onNoSuggestions?.() + } + }, [view, view.isLoading, view.hasError, view.hasContent]) + + const onPressTryAgain = () => + view + .setup() + .catch((err: any) => console.error('Failed to fetch suggestions', err)) + + const renderItem = ({item}: {item: SuggestedActor}) => + return ( + + {view.isLoading ? ( + + + + ) : view.hasError ? ( + + ) : ( + + item._reactKey} + renderItem={renderItem} + style={s.flex1} + /> + + )} + + ) + }, +) + +const User = ({item}: {item: SuggestedActor}) => { + return ( + + + + + + + + {item.displayName} + + + @{item.handle} + + + + + + + Follow + + + + + {item.description ? ( + + + {item.description} + + + ) : undefined} + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + + suggestionsContainer: { + flex: 1, + backgroundColor: colors.gray1, + }, + + actor: { + backgroundColor: colors.white, + borderRadius: 6, + margin: 2, + marginBottom: 0, + }, + actorMeta: { + flexDirection: 'row', + }, + actorAvi: { + width: 60, + paddingLeft: 10, + paddingTop: 10, + paddingBottom: 10, + }, + actorContent: { + flex: 1, + paddingRight: 10, + paddingTop: 10, + }, + actorBtn: { + paddingRight: 10, + paddingTop: 10, + }, + actorDetails: { + paddingLeft: 60, + paddingRight: 10, + paddingBottom: 10, + }, + + gradientBtn: { + paddingHorizontal: 24, + paddingVertical: 6, + }, + secondaryBtn: { + paddingHorizontal: 14, + }, + btn: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 7, + borderRadius: 50, + backgroundColor: colors.gray1, + marginLeft: 6, + }, +}) diff --git a/src/view/com/onboard/Follows.tsx b/src/view/com/onboard/Follows.tsx index c4853152..ab65cd45 100644 --- a/src/view/com/onboard/Follows.tsx +++ b/src/view/com/onboard/Follows.tsx @@ -1,78 +1,29 @@ -import React, {useMemo, useEffect} from 'react' +import React from 'react' import { - ActivityIndicator, - FlatList, SafeAreaView, StyleSheet, Text, TouchableOpacity, View, } from 'react-native' -import LinearGradient from 'react-native-linear-gradient' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {observer} from 'mobx-react-lite' -import {ErrorScreen} from '../util/ErrorScreen' -import {UserAvatar} from '../util/UserAvatar' +import {SuggestedFollows} from '../discover/SuggestedFollows' import {useStores} from '../../../state' -import { - SuggestedActorsViewModel, - SuggestedActor, -} from '../../../state/models/suggested-actors-view' -import {s, colors, gradients} from '../../lib/styles' +import {s} from '../../lib/styles' export const Follows = observer(() => { const store = useStores() - const view = useMemo( - () => new SuggestedActorsViewModel(store), - [], - ) - - useEffect(() => { - console.log('Fetching suggested actors') - view - .setup() - .catch((err: any) => console.error('Failed to fetch suggestions', err)) - }, [view]) - - useEffect(() => { - if (!view.isLoading && !view.hasError && !view.hasContent) { - // no suggestions, bounce from this view - store.onboard.next() - } - }, [view, view.isLoading, view.hasError, view.hasContent]) - - const onPressTryAgain = () => - view - .setup() - .catch((err: any) => console.error('Failed to fetch suggestions', err)) + const onNoSuggestions = () => { + // no suggestions, bounce from this view + store.onboard.next() + } const onPressNext = () => store.onboard.next() - const renderItem = ({item}: {item: SuggestedActor}) => return ( Suggested follows - {view.isLoading ? ( - - - - ) : view.hasError ? ( - - ) : ( - - item._reactKey} - renderItem={renderItem} - style={s.flex1} - /> - - )} + Skip @@ -86,49 +37,6 @@ export const Follows = observer(() => { ) }) -const User = ({item}: {item: SuggestedActor}) => { - return ( - - - - - - - - {item.displayName} - - - @{item.handle} - - - - - - - Follow - - - - - {item.description ? ( - - - {item.description} - - - ) : undefined} - - ) -} - const styles = StyleSheet.create({ container: { flex: 1, @@ -141,58 +49,6 @@ const styles = StyleSheet.create({ paddingBottom: 12, }, - suggestionsContainer: { - flex: 1, - backgroundColor: colors.gray1, - }, - - actor: { - backgroundColor: colors.white, - borderRadius: 6, - margin: 2, - marginBottom: 0, - }, - actorMeta: { - flexDirection: 'row', - }, - actorAvi: { - width: 60, - paddingLeft: 10, - paddingTop: 10, - paddingBottom: 10, - }, - actorContent: { - flex: 1, - paddingRight: 10, - paddingTop: 10, - }, - actorBtn: { - paddingRight: 10, - paddingTop: 10, - }, - actorDetails: { - paddingLeft: 60, - paddingRight: 10, - paddingBottom: 10, - }, - - gradientBtn: { - paddingHorizontal: 24, - paddingVertical: 6, - }, - secondaryBtn: { - paddingHorizontal: 14, - }, - btn: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - paddingVertical: 7, - borderRadius: 50, - backgroundColor: colors.gray1, - marginLeft: 6, - }, - footer: { flexDirection: 'row', paddingHorizontal: 32, diff --git a/src/view/lib/icons.tsx b/src/view/lib/icons.tsx index bf4d242f..b42fc6fc 100644 --- a/src/view/lib/icons.tsx +++ b/src/view/lib/icons.tsx @@ -53,6 +53,33 @@ export function HomeIcon({ ) } +// Copyright (c) 2020 Refactoring UI Inc. +// https://github.com/tailwindlabs/heroicons/blob/master/LICENSE +export function MangifyingGlassIcon({ + style, + size, +}: { + style?: StyleProp + size?: string | number +}) { + return ( + + + + ) +} + // https://github.com/Remix-Design/RemixIcon/blob/master/License export function BellIcon({ style, diff --git a/src/view/screens/Search.tsx b/src/view/screens/Search.tsx index aea54051..73532602 100644 --- a/src/view/screens/Search.tsx +++ b/src/view/screens/Search.tsx @@ -1,11 +1,57 @@ -import React from 'react' -import {Text, View} from 'react-native' +import React, {useEffect} from 'react' +import {StyleSheet, Text, View} from 'react-native' +import {ViewHeader} from '../com/util/ViewHeader' +import {SuggestedFollows} from '../com/discover/SuggestedFollows' import {ScreenParams} from '../routes' +import {useStores} from '../../state' +import {colors} from '../lib/styles' + +export const Search = ({visible, params}: ScreenParams) => { + const store = useStores() + const {name} = params + + useEffect(() => { + if (visible) { + store.nav.setTitle(`Search`) + } + }, [store, visible, name]) -export const Search = ({params}: ScreenParams) => { return ( - - Search + + + + + Search is still being implemented. Check back soon! + + + Suggested follows + ) } + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.white, + }, + + todoContainer: { + backgroundColor: colors.pink1, + margin: 10, + padding: 10, + borderRadius: 6, + }, + todoLabel: { + color: colors.pink5, + textAlign: 'center', + }, + + heading: { + fontSize: 16, + fontWeight: 'bold', + paddingTop: 12, + paddingBottom: 6, + paddingHorizontal: 12, + }, +}) diff --git a/src/view/shell/mobile/index.tsx b/src/view/shell/mobile/index.tsx index b359bdcb..49b18a48 100644 --- a/src/view/shell/mobile/index.tsx +++ b/src/view/shell/mobile/index.tsx @@ -33,7 +33,12 @@ import {MainMenu} from './MainMenu' import {TabsSelector} from './TabsSelector' import {Composer} from './Composer' import {s, colors} from '../../lib/styles' -import {GridIcon, HomeIcon, BellIcon} from '../../lib/icons' +import { + GridIcon, + HomeIcon, + MangifyingGlassIcon, + BellIcon, +} from '../../lib/icons' const SWIPE_GESTURE_DIST_TRIGGER = 0.5 const SWIPE_GESTURE_VEL_TRIGGER = 2500 @@ -45,7 +50,7 @@ const Btn = ({ onPress, onLongPress, }: { - icon: IconProp | 'menu' | 'house' | 'bell' + icon: IconProp | 'menu' | 'house' | 'bell' | 'search' inactive?: boolean notificationCount?: number onPress?: (event: GestureResponderEvent) => void @@ -58,6 +63,11 @@ const Btn = ({ IconEl = GridIcon } else if (icon === 'house') { IconEl = HomeIcon + size = 24 + } else if (icon === 'search') { + IconEl = MangifyingGlassIcon + size = 24 + addedStyles = {position: 'relative', top: -1} as ViewStyle } else if (icon === 'bell') { IconEl = BellIcon size = 24 @@ -114,6 +124,7 @@ export const MobileShell: React.FC = observer(() => { store.nav.navigate('/') } } + const onPressSearch = () => store.nav.navigate('/search') const onPressMenu = () => setMainMenuActive(true) const onPressNotifications = () => store.nav.navigate('/notifications') const onPressTabs = () => setTabsSelectorActive(true) @@ -210,7 +221,7 @@ export const MobileShell: React.FC = observer(() => { - {} /* TODO */} /> +