Add button to controls, respace
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" d="M9.7 16.895a4 4 0 0 1 4.6 0l3.7 2.6V6.5a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v12.995l3.7-2.6Zm10.3 2.6c0 1.62-1.825 2.567-3.15 1.636l-3.7-2.6a2 2 0 0 0-2.3 0l-3.7 2.6C5.825 22.062 4 21.115 4 19.495V6.5a4 4 0 0 1 4-4h8a4 4 0 0 1 4 4v12.995Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 334 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#006AFF" d="M16 2.5a4 4 0 0 1 4 4v12.995c0 1.62-1.825 2.567-3.15 1.636l-3.7-2.6a2 2 0 0 0-2.3 0l-3.7 2.6C5.825 22.062 4 21.115 4 19.495V6.5a4 4 0 0 1 4-4h8Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 250 B |
@@ -0,0 +1,28 @@
|
|||||||
|
import {memo} from 'react'
|
||||||
|
import {type AppBskyFeedDefs, type AppBskyFeedPost} from '@atproto/api'
|
||||||
|
import {msg} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
import type React from 'react'
|
||||||
|
|
||||||
|
import {type Shadow} from '#/state/cache/post-shadow'
|
||||||
|
import {Bookmark} from '#/components/icons/Bookmark'
|
||||||
|
import {PostControlButton, PostControlButtonIcon} from './PostControlButton'
|
||||||
|
|
||||||
|
export const BookmarkButton = memo(function BookmarkButton({
|
||||||
|
big,
|
||||||
|
}: {
|
||||||
|
post: Shadow<AppBskyFeedDefs.PostView>
|
||||||
|
big?: boolean
|
||||||
|
record: AppBskyFeedPost.Record
|
||||||
|
}): React.ReactNode {
|
||||||
|
const {_} = useLingui()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PostControlButton
|
||||||
|
testID="postBookmarkBtn"
|
||||||
|
big={big}
|
||||||
|
label={_(msg`Bookmark this post`)}>
|
||||||
|
<PostControlButtonIcon icon={Bookmark} />
|
||||||
|
</PostControlButton>
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -26,8 +26,9 @@ import {
|
|||||||
} from '#/state/shell/progress-guide'
|
} from '#/state/shell/progress-guide'
|
||||||
import {formatCount} from '#/view/com/util/numeric/format'
|
import {formatCount} from '#/view/com/util/numeric/format'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
import {atoms as a, useBreakpoints} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
|
import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
|
||||||
|
import {BookmarkButton} from './BookmarkButton'
|
||||||
import {
|
import {
|
||||||
PostControlButton,
|
PostControlButton,
|
||||||
PostControlButtonIcon,
|
PostControlButtonIcon,
|
||||||
@@ -67,7 +68,6 @@ let PostControls = ({
|
|||||||
viaRepost?: {uri: string; cid: string}
|
viaRepost?: {uri: string; cid: string}
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_, i18n} = useLingui()
|
const {_, i18n} = useLingui()
|
||||||
const {gtMobile} = useBreakpoints()
|
|
||||||
const {openComposer} = useOpenComposer()
|
const {openComposer} = useOpenComposer()
|
||||||
const {feedDescriptor} = useFeedFeedbackContext()
|
const {feedDescriptor} = useFeedFeedbackContext()
|
||||||
const [queueLike, queueUnlike] = usePostLikeMutationQueue(
|
const [queueLike, queueUnlike] = usePostLikeMutationQueue(
|
||||||
@@ -193,102 +193,108 @@ let PostControls = ({
|
|||||||
!big && a.pt_2xs,
|
!big && a.pt_2xs,
|
||||||
style,
|
style,
|
||||||
]}>
|
]}>
|
||||||
<View
|
<View style={[a.flex_row, a.justify_between, a.flex_1]}>
|
||||||
style={[
|
<View
|
||||||
big ? a.align_center : [a.flex_1, a.align_start, {marginLeft: -6}],
|
style={[
|
||||||
replyDisabled ? {opacity: 0.5} : undefined,
|
big ? a.align_center : [a.flex_1, a.align_start, {marginLeft: -6}],
|
||||||
]}>
|
replyDisabled ? {opacity: 0.5} : undefined,
|
||||||
<PostControlButton
|
]}>
|
||||||
testID="replyBtn"
|
<PostControlButton
|
||||||
onPress={
|
testID="replyBtn"
|
||||||
!replyDisabled ? () => requireAuth(() => onPressReply()) : undefined
|
onPress={
|
||||||
}
|
!replyDisabled
|
||||||
label={_(
|
? () => requireAuth(() => onPressReply())
|
||||||
msg({
|
: undefined
|
||||||
message: `Reply (${plural(post.replyCount || 0, {
|
}
|
||||||
one: '# reply',
|
label={_(
|
||||||
other: '# replies',
|
msg({
|
||||||
})})`,
|
message: `Reply (${plural(post.replyCount || 0, {
|
||||||
comment:
|
one: '# reply',
|
||||||
'Accessibility label for the reply button, verb form followed by number of replies and noun form',
|
other: '# replies',
|
||||||
}),
|
})})`,
|
||||||
)}
|
comment:
|
||||||
big={big}>
|
'Accessibility label for the reply button, verb form followed by number of replies and noun form',
|
||||||
<PostControlButtonIcon icon={Bubble} />
|
}),
|
||||||
{typeof post.replyCount !== 'undefined' && post.replyCount > 0 && (
|
)}
|
||||||
<PostControlButtonText>
|
big={big}>
|
||||||
{formatCount(i18n, post.replyCount)}
|
<PostControlButtonIcon icon={Bubble} />
|
||||||
</PostControlButtonText>
|
{typeof post.replyCount !== 'undefined' && post.replyCount > 0 && (
|
||||||
)}
|
<PostControlButtonText>
|
||||||
</PostControlButton>
|
{formatCount(i18n, post.replyCount)}
|
||||||
</View>
|
</PostControlButtonText>
|
||||||
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
|
)}
|
||||||
<RepostButton
|
</PostControlButton>
|
||||||
isReposted={!!post.viewer?.repost}
|
</View>
|
||||||
repostCount={(post.repostCount ?? 0) + (post.quoteCount ?? 0)}
|
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
|
||||||
onRepost={onRepost}
|
<RepostButton
|
||||||
onQuote={onQuote}
|
isReposted={!!post.viewer?.repost}
|
||||||
big={big}
|
repostCount={(post.repostCount ?? 0) + (post.quoteCount ?? 0)}
|
||||||
embeddingDisabled={Boolean(post.viewer?.embeddingDisabled)}
|
onRepost={onRepost}
|
||||||
/>
|
onQuote={onQuote}
|
||||||
</View>
|
|
||||||
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
|
|
||||||
<PostControlButton
|
|
||||||
testID="likeBtn"
|
|
||||||
big={big}
|
|
||||||
onPress={() => requireAuth(() => onPressToggleLike())}
|
|
||||||
label={
|
|
||||||
post.viewer?.like
|
|
||||||
? _(
|
|
||||||
msg({
|
|
||||||
message: `Unlike (${plural(post.likeCount || 0, {
|
|
||||||
one: '# like',
|
|
||||||
other: '# likes',
|
|
||||||
})})`,
|
|
||||||
comment:
|
|
||||||
'Accessibility label for the like button when the post has been liked, verb followed by number of likes and noun',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
: _(
|
|
||||||
msg({
|
|
||||||
message: `Like (${plural(post.likeCount || 0, {
|
|
||||||
one: '# like',
|
|
||||||
other: '# likes',
|
|
||||||
})})`,
|
|
||||||
comment:
|
|
||||||
'Accessibility label for the like button when the post has not been liked, verb form followed by number of likes and noun form',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}>
|
|
||||||
<AnimatedLikeIcon
|
|
||||||
isLiked={Boolean(post.viewer?.like)}
|
|
||||||
big={big}
|
big={big}
|
||||||
hasBeenToggled={hasLikeIconBeenToggled}
|
embeddingDisabled={Boolean(post.viewer?.embeddingDisabled)}
|
||||||
/>
|
/>
|
||||||
<CountWheel
|
</View>
|
||||||
likeCount={post.likeCount ?? 0}
|
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
|
||||||
|
<PostControlButton
|
||||||
|
testID="likeBtn"
|
||||||
big={big}
|
big={big}
|
||||||
isLiked={Boolean(post.viewer?.like)}
|
onPress={() => requireAuth(() => onPressToggleLike())}
|
||||||
hasBeenToggled={hasLikeIconBeenToggled}
|
label={
|
||||||
/>
|
post.viewer?.like
|
||||||
</PostControlButton>
|
? _(
|
||||||
</View>
|
msg({
|
||||||
<View style={big ? a.align_center : [a.flex_1, a.align_start]}>
|
message: `Unlike (${plural(post.likeCount || 0, {
|
||||||
<View style={[!big && a.ml_sm]}>
|
one: '# like',
|
||||||
<ShareMenuButton
|
other: '# likes',
|
||||||
testID="postShareBtn"
|
})})`,
|
||||||
post={post}
|
comment:
|
||||||
big={big}
|
'Accessibility label for the like button when the post has been liked, verb followed by number of likes and noun',
|
||||||
record={record}
|
}),
|
||||||
richText={richText}
|
)
|
||||||
timestamp={post.indexedAt}
|
: _(
|
||||||
threadgateRecord={threadgateRecord}
|
msg({
|
||||||
onShare={onShare}
|
message: `Like (${plural(post.likeCount || 0, {
|
||||||
/>
|
one: '# like',
|
||||||
|
other: '# likes',
|
||||||
|
})})`,
|
||||||
|
comment:
|
||||||
|
'Accessibility label for the like button when the post has not been liked, verb form followed by number of likes and noun form',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}>
|
||||||
|
<AnimatedLikeIcon
|
||||||
|
isLiked={Boolean(post.viewer?.like)}
|
||||||
|
big={big}
|
||||||
|
hasBeenToggled={hasLikeIconBeenToggled}
|
||||||
|
/>
|
||||||
|
<CountWheel
|
||||||
|
likeCount={post.likeCount ?? 0}
|
||||||
|
big={big}
|
||||||
|
isLiked={Boolean(post.viewer?.like)}
|
||||||
|
hasBeenToggled={hasLikeIconBeenToggled}
|
||||||
|
/>
|
||||||
|
</PostControlButton>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
style={big ? a.align_center : [gtMobile && a.flex_1, a.align_start]}>
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.justify_end,
|
||||||
|
a.flex_1,
|
||||||
|
big ? a.gap_sm : a.gap_xs,
|
||||||
|
]}>
|
||||||
|
<BookmarkButton post={post} big={big} record={record} />
|
||||||
|
<ShareMenuButton
|
||||||
|
testID="postShareBtn"
|
||||||
|
post={post}
|
||||||
|
big={big}
|
||||||
|
record={record}
|
||||||
|
richText={richText}
|
||||||
|
timestamp={post.indexedAt}
|
||||||
|
threadgateRecord={threadgateRecord}
|
||||||
|
onShare={onShare}
|
||||||
|
/>
|
||||||
<PostMenuButton
|
<PostMenuButton
|
||||||
testID="postDropdownBtn"
|
testID="postDropdownBtn"
|
||||||
post={post}
|
post={post}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import {createSinglePathSVG} from './TEMPLATE'
|
||||||
|
|
||||||
|
// custom, not part of icon library
|
||||||
|
export const Bookmark = createSinglePathSVG({
|
||||||
|
path: 'M9.7 16.895a4 4 0 0 1 4.6 0l3.7 2.6V6.5a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v12.995l3.7-2.6Zm10.3 2.6c0 1.62-1.825 2.567-3.15 1.636l-3.7-2.6a2.001 2.001 0 0 0-2.3 0l-3.7 2.6C5.825 22.062 4 21.115 4 19.495V6.5a4 4 0 0 1 4-4h8a4 4 0 0 1 4 4v12.995Z',
|
||||||
|
})
|
||||||
|
|
||||||
|
// custom, not part of icon library
|
||||||
|
export const BookmarkFilled = createSinglePathSVG({
|
||||||
|
path: 'M16 2.5a4 4 0 0 1 4 4v12.995c0 1.62-1.825 2.567-3.15 1.636l-3.7-2.6a2.001 2.001 0 0 0-2.3 0l-3.7 2.6C5.825 22.062 4 21.115 4 19.495V6.5a4 4 0 0 1 4-4h8Z',
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user