📓 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
+16
View File
@@ -25,6 +25,7 @@ export interface PostShadow {
embed: AppBskyEmbedRecord.View | AppBskyEmbedRecordWithMedia.View | undefined
pinned: boolean
optimisticReplyCount: number | undefined
bookmarked: boolean | undefined
}
export const POST_TOMBSTONE = Symbol('PostTombstone')
@@ -92,6 +93,18 @@ function mergeShadow(
likeCount = Math.max(0, likeCount)
}
let bookmarkCount = post.bookmarkCount ?? 0
if ('bookmarked' in shadow) {
const wasBookmarked = !!post.viewer?.bookmarked
const isBookmarked = !!shadow.bookmarked
if (wasBookmarked && !isBookmarked) {
bookmarkCount--
} else if (!wasBookmarked && isBookmarked) {
bookmarkCount++
}
bookmarkCount = Math.max(0, bookmarkCount)
}
let repostCount = post.repostCount ?? 0
if ('repostUri' in shadow) {
const wasReposted = !!post.viewer?.repost
@@ -127,11 +140,14 @@ function mergeShadow(
likeCount: likeCount,
repostCount: repostCount,
replyCount: replyCount,
bookmarkCount: bookmarkCount,
viewer: {
...(post.viewer || {}),
like: 'likeUri' in shadow ? shadow.likeUri : post.viewer?.like,
repost: 'repostUri' in shadow ? shadow.repostUri : post.viewer?.repost,
pinned: 'pinned' in shadow ? shadow.pinned : post.viewer?.pinned,
bookmarked:
'bookmarked' in shadow ? shadow.bookmarked : post.viewer?.bookmarked,
},
})
}