diff options
-rw-r--r-- | assets/icons/closeQuote_filled_stroke2_corner0_rounded.svg | 1 | ||||
-rw-r--r-- | assets/icons/closeQuote_stroke2_corner0_rounded.svg | 1 | ||||
-rw-r--r-- | assets/icons/closeQuote_stroke2_corner1_rounded.svg | 1 | ||||
-rw-r--r-- | assets/icons/openQuote_filled_stroke2_corner0_rounded.svg | 1 | ||||
-rw-r--r-- | assets/icons/openQuote_stroke2_corner0_rounded.svg | 1 | ||||
-rw-r--r-- | assets/icons/repost_stroke2_corner0_rounded.svg | 1 | ||||
-rw-r--r-- | assets/icons/repost_stroke2_corner3_rounded.svg | 1 | ||||
-rw-r--r-- | src/alf/atoms.ts | 11 | ||||
-rw-r--r-- | src/components/Button.tsx | 6 | ||||
-rw-r--r-- | src/components/icons/Quote.tsx | 21 | ||||
-rw-r--r-- | src/components/icons/Repost.tsx | 13 | ||||
-rw-r--r-- | src/view/com/post-thread/PostThreadItem.tsx | 4 | ||||
-rw-r--r-- | src/view/com/util/LoadingPlaceholder.tsx | 64 | ||||
-rw-r--r-- | src/view/com/util/forms/PostDropdownBtn.tsx | 20 | ||||
-rw-r--r-- | src/view/com/util/post-ctrls/PostCtrls.tsx | 147 | ||||
-rw-r--r-- | src/view/com/util/post-ctrls/RepostButton.tsx | 174 | ||||
-rw-r--r-- | src/view/com/util/post-ctrls/RepostButton.web.tsx | 194 |
17 files changed, 376 insertions, 285 deletions
diff --git a/assets/icons/closeQuote_filled_stroke2_corner0_rounded.svg b/assets/icons/closeQuote_filled_stroke2_corner0_rounded.svg new file mode 100644 index 000000000..41e75887c --- /dev/null +++ b/assets/icons/closeQuote_filled_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" d="M3.004 4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2v5a1 1 0 0 0 .43.822c.57.395 1.176.031 1.685-.255.428-.24.998-.614 1.569-1.15 1.154-1.082 2.316-2.832 2.316-5.417V5a1 1 0 0 0-1-1h-7ZM14.004 4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2v5a1 1 0 0 0 .43.822c.57.395 1.176.031 1.685-.255.428-.24.998-.614 1.569-1.15 1.154-1.082 2.316-2.832 2.316-5.417V5a1 1 0 0 0-1-1h-7Z"/></svg> diff --git a/assets/icons/closeQuote_stroke2_corner0_rounded.svg b/assets/icons/closeQuote_stroke2_corner0_rounded.svg new file mode 100644 index 000000000..3c76c7392 --- /dev/null +++ b/assets/icons/closeQuote_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M2.004 5a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v8c0 2.585-1.162 4.335-2.316 5.417-.571.536-1.14.91-1.569 1.15a7.01 7.01 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001L6.004 19l.351.936A1 1 0 0 1 5.004 19v-5h-2a1 1 0 0 1-1-1V5Zm5 12.234c.104-.085.21-.177.316-.276.846-.793 1.684-2.043 1.684-3.958V6h-5v6h2a1 1 0 0 1 1 1v4.234Zm6-12.234a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v8c0 2.585-1.162 4.335-2.316 5.417-.571.536-1.14.91-1.569 1.15a7.018 7.018 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001-.352-.936.351.936A1 1 0 0 1 16.004 19v-5h-2a1 1 0 0 1-1-1V5Zm5 12.234V13a1 1 0 0 0-1-1h-2V6h5v7c0 1.915-.838 3.165-1.684 3.958-.106.1-.212.191-.316.276Z" clip-rule="evenodd"/></svg> \ No newline at end of file diff --git a/assets/icons/closeQuote_stroke2_corner1_rounded.svg b/assets/icons/closeQuote_stroke2_corner1_rounded.svg new file mode 100644 index 000000000..b27eb94f2 --- /dev/null +++ b/assets/icons/closeQuote_stroke2_corner1_rounded.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M2.003 5.999a2 2 0 0 1 2-1.999h5c1.104 0 2 .893 2 1.999V13c0 2.585-1.16 4.335-2.315 5.417-.571.536-1.14.91-1.569 1.15a7.01 7.01 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001L6.004 19l.351.936a1 1 0 0 1-1.351-.935L5 14H4a2 2 0 0 1-2-2.001l.002-6Zm5 11.236L7 12.999A1 1 0 0 0 6 12H4l.003-6h5v7c0 1.915-.837 3.165-1.683 3.958-.106.1-.213.192-.317.277Zm6-11.235a2 2 0 0 1 2-2h5c1.104 0 2 .893 2 1.999V13c0 2.585-1.16 4.335-2.315 5.417-.571.536-1.14.91-1.569 1.15a7.018 7.018 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001-.352-.936.351.936A1 1 0 0 1 16.004 19v-5h-1a2 2 0 0 1-2-2V6Zm7 0h-5v6h2a1 1 0 0 1 1 1v4.234c.105-.085.211-.177.317-.276.846-.793 1.684-2.043 1.684-3.958V6Z" clip-rule="evenodd"/></svg> diff --git a/assets/icons/openQuote_filled_stroke2_corner0_rounded.svg b/assets/icons/openQuote_filled_stroke2_corner0_rounded.svg new file mode 100644 index 000000000..e8141a112 --- /dev/null +++ b/assets/icons/openQuote_filled_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" d="M8.004 5a1 1 0 0 0-.43-.822c-.57-.395-1.176-.031-1.685.255-.428.24-.998.614-1.569 1.15C3.166 6.665 2.004 8.415 2.004 11v8a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-2V5ZM19.004 5a1 1 0 0 0-.43-.822c-.57-.395-1.176-.031-1.685.255-.428.24-.998.614-1.569 1.15-1.154 1.082-2.316 2.832-2.316 5.417v8a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-2V5Z"/></svg> diff --git a/assets/icons/openQuote_stroke2_corner0_rounded.svg b/assets/icons/openQuote_stroke2_corner0_rounded.svg new file mode 100644 index 000000000..eee6344ce --- /dev/null +++ b/assets/icons/openQuote_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M7.574 4.178a1 1 0 0 1 .43.822v5h2a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-8c0-2.585 1.162-4.335 2.316-5.417a8.163 8.163 0 0 1 1.569-1.15 7.029 7.029 0 0 1 .738-.36l.016-.005.005-.003h.003v-.001c.001 0 .002 0 .353.936l-.351-.936a1 1 0 0 1 .92.114Zm-1.57 2.588a5.99 5.99 0 0 0-.316.276C4.842 7.835 4.004 9.085 4.004 11v7h5v-6h-2a1 1 0 0 1-1-1V6.766Zm12.57-2.588a1 1 0 0 1 .43.822v5h2a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-8c0-2.585 1.162-4.335 2.316-5.417a8.166 8.166 0 0 1 1.569-1.15 7.038 7.038 0 0 1 .738-.36l.016-.005.005-.003h.003v-.001c.001 0 .002 0 .353.936l-.351-.936a1 1 0 0 1 .92.114Zm-1.57 2.588c-.105.085-.21.177-.316.276-.846.793-1.684 2.043-1.684 3.958v7h5v-6h-2a1 1 0 0 1-1-1V6.766Z" clip-rule="evenodd"/></svg> diff --git a/assets/icons/repost_stroke2_corner0_rounded.svg b/assets/icons/repost_stroke2_corner0_rounded.svg new file mode 100644 index 000000000..a3cff9c62 --- /dev/null +++ b/assets/icons/repost_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M16.293 2.293a1 1 0 0 1 1.414 0l3 3a1 1 0 0 1 0 1.414l-3 3a1 1 0 0 1-1.414-1.414L17.586 7H5v4a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1h13.586l-1.293-1.293a1 1 0 0 1 0-1.414ZM21 13v5a1 1 0 0 1-1 1H6.414l1.293 1.293a1 1 0 1 1-1.414 1.414l-3-3a1 1 0 0 1 0-1.414l3-3a1 1 0 0 1 1.414 1.414L6.414 17H19v-4a1 1 0 1 1 2 0Z" clip-rule="evenodd"/></svg> diff --git a/assets/icons/repost_stroke2_corner3_rounded.svg b/assets/icons/repost_stroke2_corner3_rounded.svg new file mode 100644 index 000000000..8aa7f727b --- /dev/null +++ b/assets/icons/repost_stroke2_corner3_rounded.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M16.793 2.293a1 1 0 0 1 1.414 0L20.5 4.586a2 2 0 0 1 0 2.828l-2.293 2.293a1 1 0 0 1-1.414-1.414L18.086 7H7a2 2 0 0 0-2 2v2a1 1 0 1 1-2 0V9a4 4 0 0 1 4-4h11.086l-1.293-1.293a1 1 0 0 1 0-1.414ZM20 12a1 1 0 0 1 1 1v2a4 4 0 0 1-4 4H5.914l1.293 1.293a1 1 0 1 1-1.414 1.414L3.5 19.414a2 2 0 0 1 0-2.828l2.293-2.293a1 1 0 0 1 1.414 1.414L5.914 17H17a2 2 0 0 0 2-2v-2a1 1 0 0 1 1-1Z" clip-rule="evenodd"/></svg> diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index 3e5ddf049..158bb6ec5 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -841,7 +841,7 @@ export const atoms = { marginRight: 'auto', }, /* - * Pointer events + * Pointer events & user select */ pointer_events_none: { pointerEvents: 'none', @@ -849,6 +849,15 @@ export const atoms = { pointer_events_auto: { pointerEvents: 'auto', }, + user_select_none: { + userSelect: 'none', + }, + user_select_text: { + userSelect: 'text', + }, + user_select_all: { + userSelect: 'all', + }, /* * Text decoration */ diff --git a/src/components/Button.tsx b/src/components/Button.tsx index a008c8605..3db803399 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -71,6 +71,7 @@ export type ButtonProps = Pick< testID?: string label: string style?: StyleProp<ViewStyle> + hoverStyle?: StyleProp<ViewStyle> children: NonTextElements | ((context: ButtonContext) => NonTextElements) } @@ -96,6 +97,7 @@ export function Button({ label, disabled = false, style, + hoverStyle: hoverStyleProp, ...rest }: ButtonProps) { const t = useTheme() @@ -374,7 +376,9 @@ export function Button({ a.align_center, a.justify_center, flattenedBaseStyles, - ...(state.hovered || state.pressed ? hoverStyles : []), + ...(state.hovered || state.pressed + ? [hoverStyles, flatten(hoverStyleProp)] + : []), flatten(style), ]} onPressIn={onPressIn} diff --git a/src/components/icons/Quote.tsx b/src/components/icons/Quote.tsx new file mode 100644 index 000000000..ec53cfc46 --- /dev/null +++ b/src/components/icons/Quote.tsx @@ -0,0 +1,21 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const OpenQuote_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M7.574 4.178a1 1 0 0 1 .43.822v5h2a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-8c0-2.585 1.162-4.335 2.316-5.417a8.163 8.163 0 0 1 1.569-1.15 7.029 7.029 0 0 1 .738-.36l.016-.005.005-.003h.003v-.001c.001 0 .002 0 .353.936l-.351-.936a1 1 0 0 1 .92.114Zm-1.57 2.588a5.99 5.99 0 0 0-.316.276C4.842 7.835 4.004 9.085 4.004 11v7h5v-6h-2a1 1 0 0 1-1-1V6.766Zm12.57-2.588a1 1 0 0 1 .43.822v5h2a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1v-8c0-2.585 1.162-4.335 2.316-5.417a8.166 8.166 0 0 1 1.569-1.15 7.038 7.038 0 0 1 .738-.36l.016-.005.005-.003h.003v-.001c.001 0 .002 0 .353.936l-.351-.936a1 1 0 0 1 .92.114Zm-1.57 2.588c-.105.085-.21.177-.316.276-.846.793-1.684 2.043-1.684 3.958v7h5v-6h-2a1 1 0 0 1-1-1V6.766Z', +}) + +export const OpenQuote_Filled_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M8.004 5a1 1 0 0 0-.43-.822c-.57-.395-1.176-.031-1.685.255-.428.24-.998.614-1.569 1.15C3.166 6.665 2.004 8.415 2.004 11v8a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-2V5ZM19.004 5a1 1 0 0 0-.43-.822c-.57-.395-1.176-.031-1.685.255-.428.24-.998.614-1.569 1.15-1.154 1.082-2.316 2.832-2.316 5.417v8a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1v-8a1 1 0 0 0-1-1h-2V5Z', +}) + +export const CloseQuote_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M2.004 5a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v8c0 2.585-1.162 4.335-2.316 5.417-.571.536-1.14.91-1.569 1.15a7.01 7.01 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001L6.004 19l.351.936A1 1 0 0 1 5.004 19v-5h-2a1 1 0 0 1-1-1V5Zm5 12.234c.104-.085.21-.177.316-.276.846-.793 1.684-2.043 1.684-3.958V6h-5v6h2a1 1 0 0 1 1 1v4.234Zm6-12.234a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v8c0 2.585-1.162 4.335-2.316 5.417-.571.536-1.14.91-1.569 1.15a7.018 7.018 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001-.352-.936.351.936A1 1 0 0 1 16.004 19v-5h-2a1 1 0 0 1-1-1V5Zm5 12.234V13a1 1 0 0 0-1-1h-2V6h5v7c0 1.915-.838 3.165-1.684 3.958-.106.1-.212.191-.316.276Z', +}) + +export const CloseQuote_Stroke2_Corner1_Rounded = createSinglePathSVG({ + path: 'M2.003 5.999a2 2 0 0 1 2-1.999h5c1.104 0 2 .893 2 1.999V13c0 2.585-1.16 4.335-2.315 5.417-.571.536-1.14.91-1.569 1.15a7.01 7.01 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001L6.004 19l.351.936a1 1 0 0 1-1.351-.935L5 14H4a2 2 0 0 1-2-2.001l.002-6Zm5 11.236L7 12.999A1 1 0 0 0 6 12H4l.003-6h5v7c0 1.915-.837 3.165-1.683 3.958-.106.1-.213.192-.317.277Zm6-11.235a2 2 0 0 1 2-2h5c1.104 0 2 .893 2 1.999V13c0 2.585-1.16 4.335-2.315 5.417-.571.536-1.14.91-1.569 1.15a7.018 7.018 0 0 1-.738.36l-.016.006-.006.002h-.002l-.001.001-.352-.936.351.936A1 1 0 0 1 16.004 19v-5h-1a2 2 0 0 1-2-2V6Zm7 0h-5v6h2a1 1 0 0 1 1 1v4.234c.105-.085.211-.177.317-.276.846-.793 1.684-2.043 1.684-3.958V6Z', +}) + +export const CloseQuote_Filled_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M3.004 4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2v5a1 1 0 0 0 .43.822c.57.395 1.176.031 1.685-.255.428-.24.998-.614 1.569-1.15 1.154-1.082 2.316-2.832 2.316-5.417V5a1 1 0 0 0-1-1h-7ZM14.004 4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2v5a1 1 0 0 0 .43.822c.57.395 1.176.031 1.685-.255.428-.24.998-.614 1.569-1.15 1.154-1.082 2.316-2.832 2.316-5.417V5a1 1 0 0 0-1-1h-7Z', +}) diff --git a/src/components/icons/Repost.tsx b/src/components/icons/Repost.tsx new file mode 100644 index 000000000..01214bca7 --- /dev/null +++ b/src/components/icons/Repost.tsx @@ -0,0 +1,13 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const Repost_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M16.293 2.293a1 1 0 0 1 1.414 0l3 3a1 1 0 0 1 0 1.414l-3 3a1 1 0 0 1-1.414-1.414L17.586 7H5v4a1 1 0 1 1-2 0V6a1 1 0 0 1 1-1h13.586l-1.293-1.293a1 1 0 0 1 0-1.414ZM21 13v5a1 1 0 0 1-1 1H6.414l1.293 1.293a1 1 0 1 1-1.414 1.414l-3-3a1 1 0 0 1 0-1.414l3-3a1 1 0 0 1 1.414 1.414L6.414 17H19v-4a1 1 0 1 1 2 0Z', +}) + +export const Repost_Stroke2_Corner2_Rounded = createSinglePathSVG({ + path: 'M17.957 2.293a1 1 0 1 0-1.414 1.414L17.836 5H6a3 3 0 0 0-3 3v3a1 1 0 1 0 2 0V8a1 1 0 0 1 1-1h11.836l-1.293 1.293a1 1 0 0 0 1.414 1.414l2.47-2.47a1.75 1.75 0 0 0 0-2.474l-2.47-2.47ZM20 12a1 1 0 0 1 1 1v3a3 3 0 0 1-3 3H6.164l1.293 1.293a1 1 0 1 1-1.414 1.414l-2.47-2.47a1.75 1.75 0 0 1 0-2.474l2.47-2.47a1 1 0 0 1 1.414 1.414L6.164 17H18a1 1 0 0 0 1-1v-3a1 1 0 0 1 1-1Z', +}) + +export const Repost_Stroke2_Corner3_Rounded = createSinglePathSVG({ + path: 'M16.793 2.293a1 1 0 0 1 1.414 0L20.5 4.586a2 2 0 0 1 0 2.828l-2.293 2.293a1 1 0 0 1-1.414-1.414L18.086 7H7a2 2 0 0 0-2 2v2a1 1 0 1 1-2 0V9a4 4 0 0 1 4-4h11.086l-1.293-1.293a1 1 0 0 1 0-1.414ZM20 12a1 1 0 0 1 1 1v2a4 4 0 0 1-4 4H5.914l1.293 1.293a1 1 0 1 1-1.414 1.414L3.5 19.414a2 2 0 0 1 0-2.828l2.293-2.293a1 1 0 0 1 1.414 1.414L5.914 17H17a2 2 0 0 0 2-2v-2a1 1 0 0 1 1-1Z', +}) diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index 548b73af6..0ff040b9c 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -367,7 +367,7 @@ let PostThreadItemLoaded = ({ ) : null} </View> ) : null} - <View style={[s.pl10, s.pr10, s.pb5]}> + <View style={[s.pl10, s.pr10]}> <PostCtrls big post={post} @@ -733,7 +733,7 @@ const styles = StyleSheet.create({ borderTopWidth: 1, borderBottomWidth: 1, marginTop: 5, - marginBottom: 15, + marginBottom: 10, }, expandedInfoItem: { marginRight: 10, diff --git a/src/view/com/util/LoadingPlaceholder.tsx b/src/view/com/util/LoadingPlaceholder.tsx index 6dfe12598..882f7216b 100644 --- a/src/view/com/util/LoadingPlaceholder.tsx +++ b/src/view/com/util/LoadingPlaceholder.tsx @@ -1,20 +1,20 @@ import React from 'react' import { - StyleSheet, + DimensionValue, StyleProp, + StyleSheet, View, ViewStyle, - DimensionValue, } from 'react-native' -import { - HeartIcon, - HeartIconSolid, - CommentBottomArrow, - RepostIcon, -} from 'lib/icons' + +import {usePalette} from 'lib/hooks/usePalette' +import {HeartIconSolid} from 'lib/icons' import {s} from 'lib/styles' import {useTheme} from 'lib/ThemeContext' -import {usePalette} from 'lib/hooks/usePalette' +import {useTheme as useTheme_NEW} from '#/alf' +import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' +import {Heart2_Stroke2_Corner0_Rounded as HeartIconOutline} from '#/components/icons/Heart2' +import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost' export function LoadingPlaceholder({ width, @@ -46,7 +46,7 @@ export function PostLoadingPlaceholder({ }: { style?: StyleProp<ViewStyle> }) { - const theme = useTheme() + const t = useTheme_NEW() const pal = usePalette('default') return ( <View style={[styles.post, pal.view, style]}> @@ -67,35 +67,47 @@ export function PostLoadingPlaceholder({ <LoadingPlaceholder width="95%" height={6} style={{marginBottom: 8}} /> <LoadingPlaceholder width="80%" height={6} style={{marginBottom: 11}} /> <View style={styles.postCtrls}> - <View style={styles.postCtrl}> - <View style={[styles.postBtn, {paddingLeft: 0}]}> - <CommentBottomArrow - style={[{color: theme.palette.default.icon, marginTop: 1}]} - strokeWidth={3} - size={15} + <View style={[styles.postCtrl, {marginLeft: -5}]}> + <View style={styles.postBtn}> + <Bubble + style={[ + { + color: t.palette.contrast_500, + }, + {pointerEvents: 'none'}, + ]} + width={18} /> </View> </View> <View style={styles.postCtrl}> <View style={styles.postBtn}> - <RepostIcon - style={{color: theme.palette.default.icon}} - strokeWidth={3} - size={20} + <Repost + style={[ + { + color: t.palette.contrast_500, + }, + {pointerEvents: 'none'}, + ]} + width={18} /> </View> </View> <View style={styles.postCtrl}> <View style={styles.postBtn}> - <HeartIcon - style={{color: theme.palette.default.icon} as ViewStyle} - size={16} - strokeWidth={3} + <HeartIconOutline + style={[ + { + color: t.palette.contrast_500, + }, + {pointerEvents: 'none'}, + ]} + width={18} /> </View> </View> <View style={styles.postCtrl}> - <View style={styles.postBtn} /> + <View style={[styles.postBtn, {minHeight: 30}]} /> </View> </View> </View> @@ -290,10 +302,10 @@ const styles = StyleSheet.create({ flex: 1, }, postBtn: { - padding: 5, flex: 1, flexDirection: 'row', alignItems: 'center', + padding: 5, }, avatar: { borderRadius: 26, diff --git a/src/view/com/util/forms/PostDropdownBtn.tsx b/src/view/com/util/forms/PostDropdownBtn.tsx index 50677ee8a..cd82ec98f 100644 --- a/src/view/com/util/forms/PostDropdownBtn.tsx +++ b/src/view/com/util/forms/PostDropdownBtn.tsx @@ -1,5 +1,10 @@ import React, {memo} from 'react' -import {Pressable, PressableProps, StyleProp, ViewStyle} from 'react-native' +import { + Pressable, + type PressableProps, + type StyleProp, + type ViewStyle, +} from 'react-native' import * as Clipboard from 'expo-clipboard' import { AppBskyActorDefs, @@ -7,7 +12,6 @@ import { AtUri, RichText as RichTextAPI, } from '@atproto/api' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' @@ -37,6 +41,7 @@ import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons import {BubbleQuestion_Stroke2_Corner0_Rounded as Translate} from '#/components/icons/Bubble' import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard' import {CodeBrackets_Stroke2_Corner0_Rounded as CodeBrackets} from '#/components/icons/CodeBrackets' +import {DotGrid_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid' import { EmojiSad_Stroke2_Corner0_Rounded as EmojiSad, EmojiSmile_Stroke2_Corner0_Rounded as EmojiSmile, @@ -68,6 +73,7 @@ let PostDropdownBtn = ({ richText, style, hitSlop, + size, timestamp, }: { testID: string @@ -79,6 +85,7 @@ let PostDropdownBtn = ({ richText: RichTextAPI style?: StyleProp<ViewStyle> hitSlop?: PressableProps['hitSlop'] + size?: 'lg' | 'md' | 'sm' timestamp: string }): React.ReactNode => { const {hasSession, currentAccount} = useSession() @@ -238,14 +245,13 @@ let PostDropdownBtn = ({ style, a.rounded_full, (state.hovered || state.pressed) && [ - alf.atoms.bg_contrast_50, + alf.atoms.bg_contrast_25, ], ]}> - <FontAwesomeIcon - icon="ellipsis" - size={20} - color={defaultCtrlColor} + <DotsHorizontal + fill={defaultCtrlColor} style={{pointerEvents: 'none'}} + size={size} /> </Pressable> ) diff --git a/src/view/com/util/post-ctrls/PostCtrls.tsx b/src/view/com/util/post-ctrls/PostCtrls.tsx index b6c07d573..2b0220842 100644 --- a/src/view/com/util/post-ctrls/PostCtrls.tsx +++ b/src/view/com/util/post-ctrls/PostCtrls.tsx @@ -1,10 +1,10 @@ import React, {memo, useCallback} from 'react' import { - StyleProp, - StyleSheet, - TouchableOpacity, + Pressable, + type PressableStateCallbackType, + type StyleProp, View, - ViewStyle, + type ViewStyle, } from 'react-native' import { AppBskyFeedDefs, @@ -16,12 +16,11 @@ import {msg, plural} from '@lingui/macro' import {useLingui} from '@lingui/react' import {HITSLOP_10, HITSLOP_20} from '#/lib/constants' -import {CommentBottomArrow, HeartIcon, HeartIconSolid} from '#/lib/icons' +import {useHaptics} from '#/lib/haptics' import {makeProfileLink} from '#/lib/routes/links' import {shareUrl} from '#/lib/sharing' import {toShareUrl} from '#/lib/strings/url-helpers' import {s} from '#/lib/styles' -import {useTheme} from '#/lib/ThemeContext' import {Shadow} from '#/state/cache/types' import {useFeedFeedbackContext} from '#/state/feed-feedback' import {useModalControls} from '#/state/modals' @@ -31,9 +30,14 @@ import { } from '#/state/queries/post' import {useRequireAuth} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' -import {useHaptics} from 'lib/haptics' +import {atoms as a, useTheme} from '#/alf' import {useDialogControl} from '#/components/Dialog' import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox' +import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' +import { + Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled, + Heart2_Stroke2_Corner0_Rounded as HeartIconOutline, +} from '#/components/icons/Heart2' import * as Prompt from '#/components/Prompt' import {PostDropdownBtn} from '../forms/PostDropdownBtn' import {Text} from '../text/Text' @@ -58,7 +62,7 @@ let PostCtrls = ({ onPressReply: () => void logContext: 'FeedItem' | 'PostThreadItem' | 'Post' }): React.ReactNode => { - const theme = useTheme() + const t = useTheme() const {_} = useLingui() const {openComposer} = useComposerControls() const {closeModal} = useModalControls() @@ -80,9 +84,9 @@ let PostCtrls = ({ const defaultCtrlColor = React.useMemo( () => ({ - color: theme.palette.default.postCtrl, + color: t.palette.contrast_500, }), - [theme], + [t], ) as StyleProp<ViewStyle> const onPressToggleLike = React.useCallback(async () => { @@ -185,57 +189,70 @@ let PostCtrls = ({ }) }, [post.uri, post.author, sendInteraction, feedContext]) + const btnStyle = React.useCallback( + ({pressed, hovered}: PressableStateCallbackType) => [ + a.gap_xs, + a.rounded_full, + a.flex_row, + a.align_center, + a.justify_center, + {padding: 5}, + (pressed || hovered) && t.atoms.bg_contrast_25, + ], + [t.atoms.bg_contrast_25], + ) + return ( - <View style={[styles.ctrls, style]}> + <View style={[a.flex_row, a.justify_between, a.align_center, style]}> <View style={[ - big ? styles.ctrlBig : styles.ctrl, + big ? a.align_center : [a.flex_1, a.align_start, {marginLeft: -5}], post.viewer?.replyDisabled ? {opacity: 0.5} : undefined, ]}> - <TouchableOpacity + <Pressable testID="replyBtn" - style={[styles.btn, !big && styles.btnPad, {paddingLeft: 0}]} + style={btnStyle} onPress={() => { if (!post.viewer?.replyDisabled) { requireAuth(() => onPressReply()) } }} - accessibilityRole="button" accessibilityLabel={plural(post.replyCount || 0, { one: 'Reply (# reply)', other: 'Reply (# replies)', })} accessibilityHint="" hitSlop={big ? HITSLOP_20 : HITSLOP_10}> - <CommentBottomArrow - style={[defaultCtrlColor, big ? s.mt2 : styles.mt1]} - strokeWidth={3} - size={big ? 20 : 15} + <Bubble + style={[defaultCtrlColor, {pointerEvents: 'none'}]} + width={big ? 22 : 18} /> {typeof post.replyCount !== 'undefined' && post.replyCount > 0 ? ( - <Text style={[defaultCtrlColor, s.ml5, s.f15]}> + <Text + style={[ + defaultCtrlColor, + big ? a.text_md : {fontSize: 15}, + a.user_select_none, + ]}> {post.replyCount} </Text> ) : undefined} - </TouchableOpacity> + </Pressable> </View> - <View style={big ? styles.ctrlBig : styles.ctrl}> + <View style={big ? a.align_center : [a.flex_1, a.align_start]}> <RepostButton - big={big} isReposted={!!post.viewer?.repost} repostCount={post.repostCount} onRepost={onRepost} onQuote={onQuote} + big={big} /> </View> - <View style={big ? styles.ctrlBig : styles.ctrl}> - <TouchableOpacity + <View style={big ? a.align_center : [a.flex_1, a.align_start]}> + <Pressable testID="likeBtn" - style={[styles.btn, !big && styles.btnPad]} - onPress={() => { - requireAuth(() => onPressToggleLike()) - }} - accessibilityRole="button" + style={btnStyle} + onPress={() => requireAuth(() => onPressToggleLike())} accessibilityLabel={ post.viewer?.like ? plural(post.likeCount || 0, { @@ -250,33 +267,36 @@ let PostCtrls = ({ accessibilityHint="" hitSlop={big ? HITSLOP_20 : HITSLOP_10}> {post.viewer?.like ? ( - <HeartIconSolid style={s.likeColor} size={big ? 22 : 16} /> + <HeartIconFilled style={s.likeColor} width={big ? 22 : 18} /> ) : ( - <HeartIcon - style={[defaultCtrlColor, big ? styles.mt1 : undefined]} - strokeWidth={3} - size={big ? 20 : 16} + <HeartIconOutline + style={[defaultCtrlColor, {pointerEvents: 'none'}]} + width={big ? 22 : 18} /> )} {typeof post.likeCount !== 'undefined' && post.likeCount > 0 ? ( <Text testID="likeCount" - style={ - post.viewer?.like - ? [s.bold, s.likeColor, s.f15, s.ml5] - : [defaultCtrlColor, s.f15, s.ml5] - }> + style={[ + [ + big ? a.text_md : {fontSize: 15}, + a.user_select_none, + post.viewer?.like + ? [a.font_bold, s.likeColor] + : defaultCtrlColor, + ], + ]}> {post.likeCount} </Text> ) : undefined} - </TouchableOpacity> + </Pressable> </View> {big && ( <> - <View style={styles.ctrlBig}> - <TouchableOpacity + <View style={a.align_center}> + <Pressable testID="shareBtn" - style={[styles.btn]} + style={btnStyle} onPress={() => { if (shouldShowLoggedOutWarning) { loggedOutWarningPromptControl.open() @@ -284,15 +304,14 @@ let PostCtrls = ({ onShare() } }} - accessibilityRole="button" - accessibilityLabel={`${_(msg`Share`)}`} + accessibilityLabel={_(msg`Share`)} accessibilityHint="" hitSlop={big ? HITSLOP_20 : HITSLOP_10}> <ArrowOutOfBox - style={[defaultCtrlColor, styles.mt1]} + style={[defaultCtrlColor, {pointerEvents: 'none'}]} width={22} /> - </TouchableOpacity> + </Pressable> </View> <Prompt.Basic control={loggedOutWarningPromptControl} @@ -305,7 +324,7 @@ let PostCtrls = ({ /> </> )} - <View style={big ? styles.ctrlBig : styles.ctrl}> + <View style={big ? a.align_center : [a.flex_1, a.align_start]}> <PostDropdownBtn testID="postDropdownBtn" postAuthor={post.author} @@ -314,7 +333,7 @@ let PostCtrls = ({ postFeedContext={feedContext} record={record} richText={richText} - style={styles.btnPad} + style={{padding: 5}} hitSlop={big ? HITSLOP_20 : HITSLOP_10} timestamp={post.indexedAt} /> @@ -324,31 +343,3 @@ let PostCtrls = ({ } PostCtrls = memo(PostCtrls) export {PostCtrls} - -const styles = StyleSheet.create({ - ctrls: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - }, - ctrl: { - flex: 1, - alignItems: 'flex-start', - }, - ctrlBig: { - alignItems: 'center', - }, - btn: { - flexDirection: 'row', - alignItems: 'center', - }, - btnPad: { - paddingTop: 5, - paddingBottom: 5, - paddingLeft: 5, - paddingRight: 5, - }, - mt1: { - marginTop: 1, - }, -}) diff --git a/src/view/com/util/post-ctrls/RepostButton.tsx b/src/view/com/util/post-ctrls/RepostButton.tsx index f58417887..1124cb405 100644 --- a/src/view/com/util/post-ctrls/RepostButton.tsx +++ b/src/view/com/util/post-ctrls/RepostButton.tsx @@ -1,108 +1,132 @@ import React, {memo, useCallback} from 'react' -import {StyleProp, StyleSheet, TouchableOpacity, ViewStyle} from 'react-native' +import {View} from 'react-native' import {msg, plural} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useModalControls} from '#/state/modals' import {useRequireAuth} from '#/state/session' -import {HITSLOP_10, HITSLOP_20} from 'lib/constants' -import {RepostIcon} from 'lib/icons' -import {colors, s} from 'lib/styles' -import {useTheme} from 'lib/ThemeContext' -import {Text} from '../text/Text' +import {atoms as a, useTheme} from '#/alf' +import {Button, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {CloseQuote_Stroke2_Corner1_Rounded as Quote} from '#/components/icons/Quote' +import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost' +import {Text} from '#/components/Typography' interface Props { isReposted: boolean repostCount?: number - big?: boolean onRepost: () => void onQuote: () => void + big?: boolean } let RepostButton = ({ isReposted, repostCount, - big, onRepost, onQuote, + big, }: Props): React.ReactNode => { - const theme = useTheme() + const t = useTheme() const {_} = useLingui() - const {openModal} = useModalControls() const requireAuth = useRequireAuth() + const dialogControl = Dialog.useDialogControl() - const defaultControlColor = React.useMemo( + const color = React.useMemo( () => ({ - color: theme.palette.default.postCtrl, + color: isReposted ? t.palette.positive_600 : t.palette.contrast_500, }), - [theme], + [t, isReposted], ) - const onPressToggleRepostWrapper = useCallback(() => { - openModal({ - name: 'repost', - onRepost: onRepost, - onQuote: onQuote, - isReposted, - }) - }, [onRepost, onQuote, isReposted, openModal]) + const close = useCallback(() => dialogControl.close(), [dialogControl]) return ( - <TouchableOpacity - testID="repostBtn" - onPress={() => { - requireAuth(() => onPressToggleRepostWrapper()) - }} - style={[styles.btn, !big && styles.btnPad]} - accessibilityRole="button" - accessibilityLabel={`${ - isReposted - ? _(msg`Undo repost`) - : _(msg({message: 'Repost', context: 'action'})) - } (${plural(repostCount || 0, {one: '# repost', other: '# reposts'})})`} - accessibilityHint="" - hitSlop={big ? HITSLOP_20 : HITSLOP_10}> - <RepostIcon - style={ + <> + <Button + testID="repostBtn" + onPress={() => { + requireAuth(() => dialogControl.open()) + }} + style={[a.flex_row, a.align_center, a.gap_xs, {padding: 5}]} + hoverStyle={t.atoms.bg_contrast_25} + label={`${ isReposted - ? (styles.reposted as StyleProp<ViewStyle>) - : defaultControlColor - } - strokeWidth={2.4} - size={big ? 24 : 20} - /> - {typeof repostCount !== 'undefined' && repostCount > 0 ? ( - <Text - testID="repostCount" - style={ - isReposted - ? [s.bold, s.green3, s.f15, s.ml5] - : [defaultControlColor, s.f15, s.ml5] - }> - {repostCount} - </Text> - ) : undefined} - </TouchableOpacity> + ? _(msg`Undo repost`) + : _(msg({message: 'Repost', context: 'action'})) + } (${plural(repostCount || 0, {one: '# repost', other: '# reposts'})})`} + shape="round" + variant="ghost" + color="secondary"> + <Repost style={color} width={big ? 22 : 18} /> + {typeof repostCount !== 'undefined' && repostCount > 0 ? ( + <Text + testID="repostCount" + style={[ + color, + big ? a.text_md : {fontSize: 15}, + isReposted && a.font_bold, + ]}> + {repostCount} + </Text> + ) : undefined} + </Button> + <Dialog.Outer control={dialogControl}> + <Dialog.Handle /> + <Dialog.Inner label={_(msg`Repost or quote post`)}> + <View style={a.gap_xl}> + <View style={a.gap_xs}> + <Button + style={[a.justify_start, a.px_md]} + label={ + isReposted + ? _(msg`Remove repost`) + : _(msg({message: `Repost`, context: 'action'})) + } + onPress={() => { + dialogControl.close() + onRepost() + }} + size="large" + variant="ghost" + color="primary"> + <Repost size="lg" fill={t.palette.primary_500} /> + <Text style={[a.font_bold, a.text_xl]}> + {isReposted + ? _(msg`Remove repost`) + : _(msg({message: `Repost`, context: 'action'}))} + </Text> + </Button> + <Button + style={[a.justify_start, a.px_md]} + label={_(msg`Quote post`)} + onPress={() => { + dialogControl.close(() => { + onQuote() + }) + }} + size="large" + variant="ghost" + color="primary"> + <Quote size="lg" fill={t.palette.primary_500} /> + <Text style={[a.font_bold, a.text_xl]}> + {_(msg`Quote post`)} + </Text> + </Button> + </View> + <Button + label={_(msg`Cancel quote post`)} + onAccessibilityEscape={close} + onPress={close} + size="medium" + variant="solid" + color="primary"> + <ButtonText>{_(msg`Cancel`)}</ButtonText> + </Button> + </View> + </Dialog.Inner> + </Dialog.Outer> + </> ) } RepostButton = memo(RepostButton) export {RepostButton} - -const styles = StyleSheet.create({ - btn: { - flexDirection: 'row', - alignItems: 'center', - }, - btnPad: { - paddingTop: 5, - paddingBottom: 5, - paddingLeft: 5, - paddingRight: 5, - }, - reposted: { - color: colors.green3, - }, - repostCount: { - color: 'currentColor', - }, -}) diff --git a/src/view/com/util/post-ctrls/RepostButton.web.tsx b/src/view/com/util/post-ctrls/RepostButton.web.tsx index bbe5869fe..089898141 100644 --- a/src/view/com/util/post-ctrls/RepostButton.web.tsx +++ b/src/view/com/util/post-ctrls/RepostButton.web.tsx @@ -1,130 +1,134 @@ import React from 'react' -import {StyleProp, StyleSheet, View, ViewStyle, Pressable} from 'react-native' -import {RepostIcon} from 'lib/icons' -import {colors} from 'lib/styles' -import {useTheme} from 'lib/ThemeContext' -import {Text} from '../text/Text' - -import { - NativeDropdown, - DropdownItem as NativeDropdownItem, -} from '../forms/NativeDropdown' -import {EventStopper} from '../EventStopper' -import {useLingui} from '@lingui/react' +import {Pressable, View} from 'react-native' import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' + import {useRequireAuth} from '#/state/session' import {useSession} from '#/state/session' +import {atoms as a, useTheme} from '#/alf' +import {Button} from '#/components/Button' +import {CloseQuote_Stroke2_Corner1_Rounded as Quote} from '#/components/icons/Quote' +import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost' +import * as Menu from '#/components/Menu' +import {Text} from '#/components/Typography' +import {EventStopper} from '../EventStopper' interface Props { isReposted: boolean repostCount?: number - big?: boolean onRepost: () => void onQuote: () => void - style?: StyleProp<ViewStyle> + big?: boolean } export const RepostButton = ({ isReposted, repostCount, - big, onRepost, onQuote, + big, }: Props) => { - const theme = useTheme() + const t = useTheme() const {_} = useLingui() const {hasSession} = useSession() const requireAuth = useRequireAuth() - const defaultControlColor = React.useMemo( + const color = React.useMemo( () => ({ - color: theme.palette.default.postCtrl, + color: isReposted ? t.palette.positive_600 : t.palette.contrast_500, }), - [theme], - ) - - const dropdownItems: NativeDropdownItem[] = [ - { - label: isReposted ? _(msg`Undo repost`) : _(msg`Repost`), - testID: 'repostDropdownRepostBtn', - icon: { - ios: {name: 'repeat'}, - android: '', - web: 'retweet', - }, - onPress: onRepost, - }, - { - label: _(msg`Quote post`), - testID: 'repostDropdownQuoteBtn', - icon: { - ios: {name: 'quote.bubble'}, - android: '', - web: 'quote-left', - }, - onPress: onQuote, - }, - ] - - const inner = ( - <View - style={[ - styles.btn, - !big && styles.btnPad, - (isReposted - ? styles.reposted - : defaultControlColor) as StyleProp<ViewStyle>, - ]}> - <RepostIcon strokeWidth={2.2} size={big ? 24 : 20} /> - {typeof repostCount !== 'undefined' && repostCount > 0 ? ( - <Text - testID="repostCount" - type={isReposted ? 'md-bold' : 'md'} - style={styles.repostCount}> - {repostCount} - </Text> - ) : undefined} - </View> + [t, isReposted], ) return hasSession ? ( - <EventStopper> - <NativeDropdown - items={dropdownItems} - accessibilityLabel={_(msg`Repost or quote post`)} - accessibilityHint=""> - {inner} - </NativeDropdown> + <EventStopper onKeyDown={false}> + <Menu.Root> + <Menu.Trigger label={_(msg`Repost or quote post`)}> + {({props, state}) => { + return ( + <Pressable + {...props} + style={[ + a.rounded_full, + (state.hovered || state.pressed) && { + backgroundColor: t.palette.contrast_25, + }, + ]}> + <RepostInner + isReposted={isReposted} + color={color} + repostCount={repostCount} + big={big} + /> + </Pressable> + ) + }} + </Menu.Trigger> + <Menu.Outer style={{minWidth: 170}}> + <Menu.Item + label={isReposted ? _(msg`Undo repost`) : _(msg`Repost`)} + testID="repostDropdownRepostBtn" + onPress={onRepost}> + <Menu.ItemText> + {isReposted ? _(msg`Undo repost`) : _(msg`Repost`)} + </Menu.ItemText> + <Menu.ItemIcon icon={Repost} position="right" /> + </Menu.Item> + <Menu.Item + label={_(msg`Quote post`)} + testID="repostDropdownQuoteBtn" + onPress={onQuote}> + <Menu.ItemText>{_(msg`Quote post`)}</Menu.ItemText> + <Menu.ItemIcon icon={Quote} position="right" /> + </Menu.Item> + </Menu.Outer> + </Menu.Root> </EventStopper> ) : ( - <Pressable - accessibilityRole="button" + <Button onPress={() => { requireAuth(() => {}) }} - accessibilityLabel={_(msg`Repost or quote post`)} - accessibilityHint=""> - {inner} - </Pressable> + label={_(msg`Repost or quote post`)} + style={{padding: 0}} + hoverStyle={t.atoms.bg_contrast_25} + shape="round" + variant="ghost" + color="secondary"> + <RepostInner + isReposted={isReposted} + color={color} + repostCount={repostCount} + big={big} + /> + </Button> ) } -const styles = StyleSheet.create({ - btn: { - flexDirection: 'row', - alignItems: 'center', - gap: 4, - }, - btnPad: { - paddingTop: 5, - paddingBottom: 5, - paddingLeft: 5, - paddingRight: 5, - }, - reposted: { - color: colors.green3, - }, - repostCount: { - color: 'currentColor', - }, -}) +const RepostInner = ({ + isReposted, + color, + repostCount, + big, +}: { + isReposted: boolean + color: {color: string} + repostCount?: number + big?: boolean +}) => ( + <View style={[a.flex_row, a.align_center, a.gap_xs, {padding: 5}]}> + <Repost style={color} width={big ? 22 : 18} /> + {typeof repostCount !== 'undefined' && repostCount > 0 ? ( + <Text + testID="repostCount" + style={[ + color, + big ? a.text_md : {fontSize: 15}, + isReposted && [a.font_bold], + a.user_select_none, + ]}> + {repostCount} + </Text> + ) : undefined} + </View> +) |