Add copy to feeds page (#2852)
* move `IconCircle` to `components` for reuse * add copy to feeds page * start of a header * saveit * add lg size * add your feeds * don't show Your Feeds if you don't have any * Minor ui tweaks * cleanup * remove unused activity indicator --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>zio/stable
parent
36e1da1006
commit
d8245e96ea
|
@ -30,8 +30,8 @@ export function IconCircle({
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.rounded_full,
|
a.rounded_full,
|
||||||
{
|
{
|
||||||
width: 64,
|
width: size === 'lg' ? 52 : 64,
|
||||||
height: 64,
|
height: size === 'lg' ? 52 : 64,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
t.name === 'light' ? t.palette.primary_50 : t.palette.primary_950,
|
t.name === 'light' ? t.palette.primary_50 : t.palette.primary_950,
|
||||||
},
|
},
|
|
@ -20,7 +20,7 @@ import {
|
||||||
OnboardingControls,
|
OnboardingControls,
|
||||||
} from '#/screens/Onboarding/Layout'
|
} from '#/screens/Onboarding/Layout'
|
||||||
import {FeedCard} from '#/screens/Onboarding/StepAlgoFeeds/FeedCard'
|
import {FeedCard} from '#/screens/Onboarding/StepAlgoFeeds/FeedCard'
|
||||||
import {IconCircle} from '#/screens/Onboarding/IconCircle'
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
|
|
||||||
export type FeedConfig = {
|
export type FeedConfig = {
|
||||||
default: boolean
|
default: boolean
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {
|
||||||
Description,
|
Description,
|
||||||
OnboardingControls,
|
OnboardingControls,
|
||||||
} from '#/screens/Onboarding/Layout'
|
} from '#/screens/Onboarding/Layout'
|
||||||
import {IconCircle} from '#/screens/Onboarding/IconCircle'
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
import {
|
import {
|
||||||
bulkWriteFollows,
|
bulkWriteFollows,
|
||||||
sortPrimaryAlgorithmFeeds,
|
sortPrimaryAlgorithmFeeds,
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {
|
||||||
usePreferencesQuery,
|
usePreferencesQuery,
|
||||||
useSetFeedViewPreferencesMutation,
|
useSetFeedViewPreferencesMutation,
|
||||||
} from 'state/queries/preferences'
|
} from 'state/queries/preferences'
|
||||||
import {IconCircle} from '#/screens/Onboarding/IconCircle'
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
|
|
||||||
export function StepFollowingFeed() {
|
export function StepFollowingFeed() {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
|
@ -26,7 +26,7 @@ import {
|
||||||
OnboardingControls,
|
OnboardingControls,
|
||||||
} from '#/screens/Onboarding/Layout'
|
} from '#/screens/Onboarding/Layout'
|
||||||
import {InterestButton} from '#/screens/Onboarding/StepInterests/InterestButton'
|
import {InterestButton} from '#/screens/Onboarding/StepInterests/InterestButton'
|
||||||
import {IconCircle} from '#/screens/Onboarding/IconCircle'
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
|
|
||||||
export function StepInterests() {
|
export function StepInterests() {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
|
@ -26,7 +26,7 @@ import {
|
||||||
import {ModerationOption} from '#/screens/Onboarding/StepModeration/ModerationOption'
|
import {ModerationOption} from '#/screens/Onboarding/StepModeration/ModerationOption'
|
||||||
import {AdultContentEnabledPref} from '#/screens/Onboarding/StepModeration/AdultContentEnabledPref'
|
import {AdultContentEnabledPref} from '#/screens/Onboarding/StepModeration/AdultContentEnabledPref'
|
||||||
import {Context} from '#/screens/Onboarding/state'
|
import {Context} from '#/screens/Onboarding/state'
|
||||||
import {IconCircle} from '#/screens/Onboarding/IconCircle'
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
|
|
||||||
function AnimatedDivider() {
|
function AnimatedDivider() {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
SuggestedAccountCardPlaceholder,
|
SuggestedAccountCardPlaceholder,
|
||||||
} from '#/screens/Onboarding/StepSuggestedAccounts/SuggestedAccountCard'
|
} from '#/screens/Onboarding/StepSuggestedAccounts/SuggestedAccountCard'
|
||||||
import {aggregateInterestItems} from '#/screens/Onboarding/util'
|
import {aggregateInterestItems} from '#/screens/Onboarding/util'
|
||||||
import {IconCircle} from '#/screens/Onboarding/IconCircle'
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
|
|
||||||
export function Inner({
|
export function Inner({
|
||||||
profiles,
|
profiles,
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
} from '#/screens/Onboarding/Layout'
|
} from '#/screens/Onboarding/Layout'
|
||||||
import {FeedCard} from '#/screens/Onboarding/StepAlgoFeeds/FeedCard'
|
import {FeedCard} from '#/screens/Onboarding/StepAlgoFeeds/FeedCard'
|
||||||
import {aggregateInterestItems} from '#/screens/Onboarding/util'
|
import {aggregateInterestItems} from '#/screens/Onboarding/util'
|
||||||
import {IconCircle} from '#/screens/Onboarding/IconCircle'
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
|
|
||||||
export function StepTopicalFeeds() {
|
export function StepTopicalFeeds() {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {ComposeIcon2, CogIcon, MagnifyingGlassIcon2} from 'lib/icons'
|
import {ComposeIcon2, CogIcon, MagnifyingGlassIcon2} from 'lib/icons'
|
||||||
import {s} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {SearchInput, SearchInputRef} from 'view/com/util/forms/SearchInput'
|
import {SearchInput, SearchInputRef} from 'view/com/util/forms/SearchInput'
|
||||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||||
import {
|
import {
|
||||||
|
@ -41,8 +42,11 @@ import {
|
||||||
import {cleanError} from 'lib/strings/errors'
|
import {cleanError} from 'lib/strings/errors'
|
||||||
import {useComposerControls} from '#/state/shell/composer'
|
import {useComposerControls} from '#/state/shell/composer'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {isNative} from '#/platform/detection'
|
import {isNative, isWeb} from '#/platform/detection'
|
||||||
import {HITSLOP_10} from 'lib/constants'
|
import {HITSLOP_10} from 'lib/constants'
|
||||||
|
import {IconCircle} from '#/components/IconCircle'
|
||||||
|
import {ListSparkle_Stroke2_Corner0_Rounded} from '#/components/icons/ListSparkle'
|
||||||
|
import {ListMagnifyingGlass_Stroke2_Corner0_Rounded} from '#/components/icons/ListMagnifyingGlass'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
type Props = NativeStackScreenProps<FeedsTabNavigatorParams, 'Feeds'>
|
||||||
|
|
||||||
|
@ -215,12 +219,7 @@ export function FeedsScreen(_props: Props) {
|
||||||
// pendingItems: this.rootStore.preferences.savedFeeds.length || 3,
|
// pendingItems: this.rootStore.preferences.savedFeeds.length || 3,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (preferences?.feeds?.saved.length === 0) {
|
if (preferences?.feeds?.saved.length !== 0) {
|
||||||
slices.push({
|
|
||||||
key: 'savedFeedNoResults',
|
|
||||||
type: 'savedFeedNoResults',
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const {saved, pinned} = preferences.feeds
|
const {saved, pinned} = preferences.feeds
|
||||||
|
|
||||||
slices = slices.concat(
|
slices = slices.concat(
|
||||||
|
@ -400,46 +399,48 @@ export function FeedsScreen(_props: Props) {
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<View style={s.p10}>
|
<View style={s.p10}>
|
||||||
<ActivityIndicator />
|
<ActivityIndicator size="large" />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
} else if (item.type === 'savedFeedsHeader') {
|
} else if (item.type === 'savedFeedsHeader') {
|
||||||
if (!isMobile) {
|
return (
|
||||||
return (
|
<>
|
||||||
<View
|
{!isMobile && (
|
||||||
style={[
|
<View
|
||||||
pal.view,
|
style={[
|
||||||
styles.header,
|
pal.view,
|
||||||
pal.border,
|
styles.header,
|
||||||
{
|
pal.border,
|
||||||
borderBottomWidth: 1,
|
{
|
||||||
},
|
borderBottomWidth: 1,
|
||||||
]}>
|
},
|
||||||
<Text type="title-lg" style={[pal.text, s.bold]}>
|
]}>
|
||||||
<Trans>My Feeds</Trans>
|
<Text type="title-lg" style={[pal.text, s.bold]}>
|
||||||
</Text>
|
<Trans>Feeds</Trans>
|
||||||
<View style={styles.headerBtnGroup}>
|
</Text>
|
||||||
<Pressable
|
<View style={styles.headerBtnGroup}>
|
||||||
accessibilityRole="button"
|
<Pressable
|
||||||
hitSlop={HITSLOP_10}
|
accessibilityRole="button"
|
||||||
onPress={searchInputRef.current?.focus}>
|
hitSlop={HITSLOP_10}
|
||||||
<MagnifyingGlassIcon2
|
onPress={searchInputRef.current?.focus}>
|
||||||
size={22}
|
<MagnifyingGlassIcon2
|
||||||
strokeWidth={2}
|
size={22}
|
||||||
style={pal.icon}
|
strokeWidth={2}
|
||||||
/>
|
style={pal.icon}
|
||||||
</Pressable>
|
/>
|
||||||
<Link
|
</Pressable>
|
||||||
href="/settings/saved-feeds"
|
<Link
|
||||||
accessibilityLabel={_(msg`Edit My Feeds`)}
|
href="/settings/saved-feeds"
|
||||||
accessibilityHint="">
|
accessibilityLabel={_(msg`Edit My Feeds`)}
|
||||||
<CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
|
accessibilityHint="">
|
||||||
</Link>
|
<CogIcon strokeWidth={1.5} style={pal.icon} size={28} />
|
||||||
|
</Link>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
)}
|
||||||
)
|
{preferences?.feeds?.saved?.length !== 0 && <FeedsSavedHeader />}
|
||||||
}
|
</>
|
||||||
return <View />
|
)
|
||||||
} else if (item.type === 'savedFeedNoResults') {
|
} else if (item.type === 'savedFeedNoResults') {
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
@ -457,47 +458,17 @@ export function FeedsScreen(_props: Props) {
|
||||||
} else if (item.type === 'popularFeedsHeader') {
|
} else if (item.type === 'popularFeedsHeader') {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View
|
<FeedsAboutHeader />
|
||||||
style={[
|
<View style={{paddingHorizontal: 12, paddingBottom: 12}}>
|
||||||
pal.view,
|
<SearchInput
|
||||||
styles.header,
|
ref={searchInputRef}
|
||||||
{
|
query={query}
|
||||||
// This is first in the flatlist without a session -esb
|
onChangeQuery={onChangeQuery}
|
||||||
marginTop: hasSession ? 16 : 0,
|
onPressCancelSearch={onPressCancelSearch}
|
||||||
paddingLeft: isMobile ? 12 : undefined,
|
onSubmitQuery={onSubmitQuery}
|
||||||
paddingRight: 10,
|
setIsInputFocused={onChangeSearchFocus}
|
||||||
paddingBottom: isMobile ? 6 : undefined,
|
/>
|
||||||
},
|
|
||||||
]}>
|
|
||||||
<Text type="title-lg" style={[pal.text, s.bold]}>
|
|
||||||
<Trans>Discover new feeds</Trans>
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
{!isMobile && (
|
|
||||||
<SearchInput
|
|
||||||
ref={searchInputRef}
|
|
||||||
query={query}
|
|
||||||
onChangeQuery={onChangeQuery}
|
|
||||||
onPressCancelSearch={onPressCancelSearch}
|
|
||||||
onSubmitQuery={onSubmitQuery}
|
|
||||||
setIsInputFocused={onChangeSearchFocus}
|
|
||||||
style={{flex: 1, maxWidth: 250}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{isMobile && (
|
|
||||||
<View style={{paddingHorizontal: 8, paddingBottom: 10}}>
|
|
||||||
<SearchInput
|
|
||||||
ref={searchInputRef}
|
|
||||||
query={query}
|
|
||||||
onChangeQuery={onChangeQuery}
|
|
||||||
onPressCancelSearch={onPressCancelSearch}
|
|
||||||
onSubmitQuery={onSubmitQuery}
|
|
||||||
setIsInputFocused={onChangeSearchFocus}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
} else if (item.type === 'popularFeedsLoading') {
|
} else if (item.type === 'popularFeedsLoading') {
|
||||||
|
@ -529,15 +500,20 @@ export function FeedsScreen(_props: Props) {
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
_,
|
|
||||||
hasSession,
|
|
||||||
isMobile,
|
isMobile,
|
||||||
pal,
|
pal.view,
|
||||||
|
pal.border,
|
||||||
|
pal.text,
|
||||||
|
pal.icon,
|
||||||
|
pal.textLight,
|
||||||
|
_,
|
||||||
|
preferences?.feeds?.saved?.length,
|
||||||
query,
|
query,
|
||||||
onChangeQuery,
|
onChangeQuery,
|
||||||
onPressCancelSearch,
|
onPressCancelSearch,
|
||||||
onSubmitQuery,
|
onSubmitQuery,
|
||||||
onChangeSearchFocus,
|
onChangeSearchFocus,
|
||||||
|
hasSession,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -552,8 +528,6 @@ export function FeedsScreen(_props: Props) {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{preferences ? <View /> : <ActivityIndicator />}
|
|
||||||
|
|
||||||
<List
|
<List
|
||||||
ref={listRef}
|
ref={listRef}
|
||||||
style={[!isTabletOrDesktop && s.flex1, styles.list]}
|
style={[!isTabletOrDesktop && s.flex1, styles.list]}
|
||||||
|
@ -660,6 +634,64 @@ function SavedFeedLoadingPlaceholder() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function FeedsSavedHeader() {
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.px_md,
|
||||||
|
a.pt_2xl,
|
||||||
|
a.gap_md,
|
||||||
|
isWeb ? a.pb_2xl : a.pb_xl,
|
||||||
|
a.border_b,
|
||||||
|
t.atoms.border_contrast_low,
|
||||||
|
]}>
|
||||||
|
<IconCircle icon={ListSparkle_Stroke2_Corner0_Rounded} size="lg" />
|
||||||
|
<View style={[a.flex_1, a.gap_sm]}>
|
||||||
|
<Text style={[a.flex_1, a.text_2xl, a.font_bold, t.atoms.text]}>
|
||||||
|
<Trans>My Feeds</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text style={[t.atoms.text_contrast_high]}>
|
||||||
|
<Trans>All the feeds you've saved, right in one place.</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function FeedsAboutHeader() {
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.px_md,
|
||||||
|
a.pt_2xl,
|
||||||
|
a.gap_md,
|
||||||
|
isWeb ? a.pb_2xl : a.pb_xl,
|
||||||
|
]}>
|
||||||
|
<IconCircle
|
||||||
|
icon={ListMagnifyingGlass_Stroke2_Corner0_Rounded}
|
||||||
|
size="lg"
|
||||||
|
/>
|
||||||
|
<View style={[a.flex_1, a.gap_sm]}>
|
||||||
|
<Text style={[a.flex_1, a.text_2xl, a.font_bold, t.atoms.text]}>
|
||||||
|
<Trans>Discover New Feeds</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text style={[t.atoms.text_contrast_high]}>
|
||||||
|
<Trans>
|
||||||
|
Custom feeds built by the community bring you new experiences and
|
||||||
|
help you find the content you love.
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|
Loading…
Reference in New Issue