📓 Bookmarks (#8976)

* Add button to controls, respace

* Hook up shadow and mutation

* Add Bookmarks screen

* Build out Bookmarks screen

* Handle removals via shadow

* Use truncateAndInvalidate strategy

* Add empty state

* Add toasts

* Add undo buttons to toasts

* Stage NUX, needs image

* Finesse post controls

* New reply icon

* Use curvier variant of repost icon

* Prevent layout shift with align_start

* Update api pkg

* Swap in new image

* Limit spacing on desktop

* Rm decimals over 10k

* Better optimistic adding/removing

* Add metrics

* Comment

* Remove unused code block

* Remove debug limit

* Fork shadow for web/native

* Tweak alt

* add preventExpansion: true

* Refine hitslop

* Add count to anchor

* Reduce space in compact mode

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
Eric Bailey
2025-09-04 17:30:15 -05:00
committed by GitHub
parent 04b869714e
commit 535d4d6cf7
38 changed files with 1251 additions and 163 deletions
+37
View File
@@ -30,6 +30,7 @@ import {
Bell_Filled_Corner0_Rounded as BellFilled,
Bell_Stroke2_Corner0_Rounded as Bell,
} from '#/components/icons/Bell'
import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark'
import {BulletList_Stroke2_Corner0_Rounded as List} from '#/components/icons/BulletList'
import {
Hashtag_Filled_Corner0_Rounded as HashtagFilled,
@@ -150,6 +151,7 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
isAtHome,
isAtSearch,
isAtFeeds,
isAtBookmarks,
isAtNotifications,
isAtMyProfile,
isAtMessages,
@@ -231,6 +233,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
setDrawerOpen(false)
}, [navigation, setDrawerOpen])
const onPressBookmarks = React.useCallback(() => {
navigation.navigate('Bookmarks')
setDrawerOpen(false)
}, [navigation, setDrawerOpen])
const onPressSettings = React.useCallback(() => {
navigation.navigate('Settings')
setDrawerOpen(false)
@@ -292,6 +299,10 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
/>
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
<ListsMenuItem onPress={onPressLists} />
<BookmarksMenuItem
isActive={isAtBookmarks}
onPress={onPressBookmarks}
/>
<ProfileMenuItem
isActive={isAtMyProfile}
onPress={onPressProfile}
@@ -538,6 +549,32 @@ let ListsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
}
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 = ({
isActive,
onPress,
+19
View File
@@ -40,6 +40,7 @@ import {
Bell_Filled_Corner0_Rounded as BellFilled,
Bell_Stroke2_Corner0_Rounded as Bell,
} from '#/components/icons/Bell'
import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark'
import {
BulletList_Filled_Corner0_Rounded as ListFilled,
BulletList_Stroke2_Corner0_Rounded as List,
@@ -743,6 +744,24 @@ export function DesktopLeftNav() {
}
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
href={currentAccount ? makeProfileLink(currentAccount) : '/'}
icon={