Add Bookmarks screen
This commit is contained in:
@@ -331,6 +331,9 @@ func serve(cctx *cli.Context) error {
|
|||||||
e.GET("/starter-pack-short/:code", server.WebGeneric)
|
e.GET("/starter-pack-short/:code", server.WebGeneric)
|
||||||
e.GET("/start/:handleOrDID/:rkey", server.WebStarterPack)
|
e.GET("/start/:handleOrDID/:rkey", server.WebStarterPack)
|
||||||
|
|
||||||
|
// bookmarks
|
||||||
|
e.GET("/saved", server.WebGeneric)
|
||||||
|
|
||||||
// ipcc
|
// ipcc
|
||||||
e.GET("/ipcc", server.WebIpCC)
|
e.GET("/ipcc", server.WebIpCC)
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ import {SupportScreen} from '#/view/screens/Support'
|
|||||||
import {TermsOfServiceScreen} from '#/view/screens/TermsOfService'
|
import {TermsOfServiceScreen} from '#/view/screens/TermsOfService'
|
||||||
import {BottomBar} from '#/view/shell/bottom-bar/BottomBar'
|
import {BottomBar} from '#/view/shell/bottom-bar/BottomBar'
|
||||||
import {createNativeStackNavigatorWithAuth} from '#/view/shell/createNativeStackNavigatorWithAuth'
|
import {createNativeStackNavigatorWithAuth} from '#/view/shell/createNativeStackNavigatorWithAuth'
|
||||||
|
import {BookmarksScreen} from '#/screens/Bookmarks'
|
||||||
import {SharedPreferencesTesterScreen} from '#/screens/E2E/SharedPreferencesTesterScreen'
|
import {SharedPreferencesTesterScreen} from '#/screens/E2E/SharedPreferencesTesterScreen'
|
||||||
import HashtagScreen from '#/screens/Hashtag'
|
import HashtagScreen from '#/screens/Hashtag'
|
||||||
import {LogScreen} from '#/screens/Log'
|
import {LogScreen} from '#/screens/Log'
|
||||||
@@ -600,6 +601,14 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) {
|
|||||||
requireAuth: true,
|
requireAuth: true,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Bookmarks"
|
||||||
|
getComponent={() => BookmarksScreen}
|
||||||
|
options={{
|
||||||
|
title: title(msg`Saved Posts`),
|
||||||
|
requireAuth: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export function useNavigationTabState() {
|
|||||||
isAtSearch: getTabState(state, 'Search') !== TabState.Outside,
|
isAtSearch: getTabState(state, 'Search') !== TabState.Outside,
|
||||||
// FeedsTab no longer exists, but this check works for `Feeds` screen as well
|
// FeedsTab no longer exists, but this check works for `Feeds` screen as well
|
||||||
isAtFeeds: getTabState(state, 'Feeds') !== TabState.Outside,
|
isAtFeeds: getTabState(state, 'Feeds') !== TabState.Outside,
|
||||||
|
isAtBookmarks: getTabState(state, 'Bookmarks') !== TabState.Outside,
|
||||||
isAtNotifications:
|
isAtNotifications:
|
||||||
getTabState(state, 'Notifications') !== TabState.Outside,
|
getTabState(state, 'Notifications') !== TabState.Outside,
|
||||||
isAtMyProfile: getTabState(state, 'MyProfile') !== TabState.Outside,
|
isAtMyProfile: getTabState(state, 'MyProfile') !== TabState.Outside,
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export type CommonNavigatorParams = {
|
|||||||
}
|
}
|
||||||
StarterPackEdit: {rkey?: string}
|
StarterPackEdit: {rkey?: string}
|
||||||
VideoFeed: VideoFeedSourceContext
|
VideoFeed: VideoFeedSourceContext
|
||||||
|
Bookmarks: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BottomTabNavigatorParams = CommonNavigatorParams & {
|
export type BottomTabNavigatorParams = CommonNavigatorParams & {
|
||||||
|
|||||||
@@ -90,4 +90,5 @@ export const router = new Router<AllNavigatableRoutes>({
|
|||||||
StarterPackShort: '/starter-pack-short/:code',
|
StarterPackShort: '/starter-pack-short/:code',
|
||||||
StarterPackWizard: '/starter-pack/create',
|
StarterPackWizard: '/starter-pack/create',
|
||||||
VideoFeed: '/video-feed',
|
VideoFeed: '/video-feed',
|
||||||
|
Bookmarks: '/saved',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
|
||||||
|
import {
|
||||||
|
type CommonNavigatorParams,
|
||||||
|
type NativeStackScreenProps,
|
||||||
|
} from '#/lib/routes/types'
|
||||||
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
|
import * as Layout from '#/components/Layout'
|
||||||
|
|
||||||
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Bookmarks'>
|
||||||
|
|
||||||
|
export function BookmarksScreen({}: Props) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => {
|
||||||
|
setMinimalShellMode(false)
|
||||||
|
}, [setMinimalShellMode]),
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout.Screen testID="bookmarksScreen">
|
||||||
|
<Layout.Header.Outer>
|
||||||
|
<Layout.Header.BackButton />
|
||||||
|
<Layout.Header.Content>
|
||||||
|
<Layout.Header.TitleText>
|
||||||
|
<Trans>Saved Posts</Trans>
|
||||||
|
</Layout.Header.TitleText>
|
||||||
|
</Layout.Header.Content>
|
||||||
|
<Layout.Header.Slot />
|
||||||
|
</Layout.Header.Outer>
|
||||||
|
</Layout.Screen>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ import {
|
|||||||
Bell_Filled_Corner0_Rounded as BellFilled,
|
Bell_Filled_Corner0_Rounded as BellFilled,
|
||||||
Bell_Stroke2_Corner0_Rounded as Bell,
|
Bell_Stroke2_Corner0_Rounded as Bell,
|
||||||
} from '#/components/icons/Bell'
|
} from '#/components/icons/Bell'
|
||||||
|
import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark'
|
||||||
import {BulletList_Stroke2_Corner0_Rounded as List} from '#/components/icons/BulletList'
|
import {BulletList_Stroke2_Corner0_Rounded as List} from '#/components/icons/BulletList'
|
||||||
import {
|
import {
|
||||||
Hashtag_Filled_Corner0_Rounded as HashtagFilled,
|
Hashtag_Filled_Corner0_Rounded as HashtagFilled,
|
||||||
@@ -150,6 +151,7 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
|||||||
isAtHome,
|
isAtHome,
|
||||||
isAtSearch,
|
isAtSearch,
|
||||||
isAtFeeds,
|
isAtFeeds,
|
||||||
|
isAtBookmarks,
|
||||||
isAtNotifications,
|
isAtNotifications,
|
||||||
isAtMyProfile,
|
isAtMyProfile,
|
||||||
isAtMessages,
|
isAtMessages,
|
||||||
@@ -231,6 +233,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
|||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
}, [navigation, setDrawerOpen])
|
}, [navigation, setDrawerOpen])
|
||||||
|
|
||||||
|
const onPressBookmarks = React.useCallback(() => {
|
||||||
|
navigation.navigate('Bookmarks')
|
||||||
|
setDrawerOpen(false)
|
||||||
|
}, [navigation, setDrawerOpen])
|
||||||
|
|
||||||
const onPressSettings = React.useCallback(() => {
|
const onPressSettings = React.useCallback(() => {
|
||||||
navigation.navigate('Settings')
|
navigation.navigate('Settings')
|
||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
@@ -292,6 +299,10 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
|||||||
/>
|
/>
|
||||||
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||||
<ListsMenuItem onPress={onPressLists} />
|
<ListsMenuItem onPress={onPressLists} />
|
||||||
|
<BookmarksMenuItem
|
||||||
|
isActive={isAtBookmarks}
|
||||||
|
onPress={onPressBookmarks}
|
||||||
|
/>
|
||||||
<ProfileMenuItem
|
<ProfileMenuItem
|
||||||
isActive={isAtMyProfile}
|
isActive={isAtMyProfile}
|
||||||
onPress={onPressProfile}
|
onPress={onPressProfile}
|
||||||
@@ -538,6 +549,32 @@ let ListsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
|||||||
}
|
}
|
||||||
ListsMenuItem = React.memo(ListsMenuItem)
|
ListsMenuItem = React.memo(ListsMenuItem)
|
||||||
|
|
||||||
|
let BookmarksMenuItem = ({
|
||||||
|
isActive,
|
||||||
|
onPress,
|
||||||
|
}: {
|
||||||
|
isActive: boolean
|
||||||
|
onPress: () => void
|
||||||
|
}): React.ReactNode => {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
icon={
|
||||||
|
isActive ? (
|
||||||
|
<BookmarkFilled style={[t.atoms.text]} width={iconWidth} />
|
||||||
|
) : (
|
||||||
|
<Bookmark style={[t.atoms.text]} width={iconWidth} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
label={_(msg`Saved`)}
|
||||||
|
onPress={onPress}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
BookmarksMenuItem = React.memo(BookmarksMenuItem)
|
||||||
|
|
||||||
let ProfileMenuItem = ({
|
let ProfileMenuItem = ({
|
||||||
isActive,
|
isActive,
|
||||||
onPress,
|
onPress,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import {
|
|||||||
Bell_Filled_Corner0_Rounded as BellFilled,
|
Bell_Filled_Corner0_Rounded as BellFilled,
|
||||||
Bell_Stroke2_Corner0_Rounded as Bell,
|
Bell_Stroke2_Corner0_Rounded as Bell,
|
||||||
} from '#/components/icons/Bell'
|
} from '#/components/icons/Bell'
|
||||||
|
import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark'
|
||||||
import {
|
import {
|
||||||
BulletList_Filled_Corner0_Rounded as ListFilled,
|
BulletList_Filled_Corner0_Rounded as ListFilled,
|
||||||
BulletList_Stroke2_Corner0_Rounded as List,
|
BulletList_Stroke2_Corner0_Rounded as List,
|
||||||
@@ -743,6 +744,24 @@ export function DesktopLeftNav() {
|
|||||||
}
|
}
|
||||||
label={_(msg`Lists`)}
|
label={_(msg`Lists`)}
|
||||||
/>
|
/>
|
||||||
|
<NavItem
|
||||||
|
href="/saved"
|
||||||
|
icon={
|
||||||
|
<Bookmark
|
||||||
|
style={pal.text}
|
||||||
|
aria-hidden={true}
|
||||||
|
width={NAV_ICON_WIDTH}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
iconFilled={
|
||||||
|
<BookmarkFilled
|
||||||
|
style={pal.text}
|
||||||
|
aria-hidden={true}
|
||||||
|
width={NAV_ICON_WIDTH}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={_(msg`Saved`)}
|
||||||
|
/>
|
||||||
<NavItem
|
<NavItem
|
||||||
href={currentAccount ? makeProfileLink(currentAccount) : '/'}
|
href={currentAccount ? makeProfileLink(currentAccount) : '/'}
|
||||||
icon={
|
icon={
|
||||||
|
|||||||
Reference in New Issue
Block a user