Skip to content

Commit

Permalink
Merge branch 'bluesky-social:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
kaytwo authored Jan 21, 2025
2 parents d261e71 + 99d23d6 commit 25c5c05
Show file tree
Hide file tree
Showing 24 changed files with 445 additions and 617 deletions.
10 changes: 7 additions & 3 deletions app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ module.exports = function (config) {
'tr',
'uk',
'vi',
'yue-Hant',
'yue',
'zh-Hans',
'zh-Hant',
],
Expand Down Expand Up @@ -226,8 +226,12 @@ module.exports = function (config) {
},
],
'react-native-compressor',
// TODO: Reenable when the build issue is fixed.
// '@bitdrift/react-native',
[
'@bitdrift/react-native',
{
networkInstrumentation: true,
},
],
'./plugins/starterPackAppClipExtension/withStarterPackAppClip.js',
'./plugins/withAndroidManifestPlugin.js',
'./plugins/withAndroidManifestFCMIconPlugin.js',
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bsky.app",
"version": "1.96.7",
"version": "1.97.0",
"private": true,
"engines": {
"node": ">=20"
Expand Down Expand Up @@ -55,6 +55,7 @@
},
"dependencies": {
"@atproto/api": "^0.13.28",
"@bitdrift/react-native": "^0.6.2",
"@braintree/sanitize-url": "^6.0.2",
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
"@emoji-mart/react": "^1.1.1",
Expand Down
2 changes: 2 additions & 0 deletions src/components/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const Content = React.memo(function Content({
contentContainerStyle,
...props
}: ContentProps) {
const t = useTheme()
const {footerHeight} = useShellLayout()
const animatedProps = useAnimatedProps(() => {
return {
Expand All @@ -73,6 +74,7 @@ export const Content = React.memo(function Content({
<Animated.ScrollView
id="content"
automaticallyAdjustsScrollIndicatorInsets={false}
indicatorStyle={t.scheme === 'dark' ? 'white' : 'black'}
// sets the scroll inset to the height of the footer
animatedProps={animatedProps}
style={[scrollViewStyles.common, style]}
Expand Down
126 changes: 108 additions & 18 deletions src/components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
linkRequiresWarning,
} from '#/lib/strings/url-helpers'
import {isNative, isWeb} from '#/platform/detection'
import {shouldClickOpenNewTab} from '#/platform/urls'
import {useModalControls} from '#/state/modals'
import {atoms as a, flatten, TextStyleProp, useTheme, web} from '#/alf'
import {Button, ButtonProps} from '#/components/Button'
Expand Down Expand Up @@ -55,6 +54,12 @@ type BaseLinkProps = Pick<
*/
onPress?: (e: GestureResponderEvent) => void | false

/**
* Callback for when the link is long pressed (on native). Prevent default
* and return `false` to exit early and prevent default long press hander.
*/
onLongPress?: (e: GestureResponderEvent) => void | false

/**
* Web-only attribute. Sets `download` attr on web.
*/
Expand All @@ -72,6 +77,7 @@ export function useLink({
action = 'push',
disableMismatchWarning,
onPress: outerOnPress,
onLongPress: outerOnLongPress,
shareOnLongPress,
}: BaseLinkProps & {
displayText: string
Expand Down Expand Up @@ -175,8 +181,14 @@ export function useLink({
}
}, [disableMismatchWarning, displayText, href, isExternal, openModal])

const onLongPress =
isNative && isExternal && shareOnLongPress ? handleLongPress : undefined
const onLongPress = React.useCallback(
(e: GestureResponderEvent) => {
const exitEarlyIfFalse = outerOnLongPress?.(e)
if (exitEarlyIfFalse === false) return
return isNative && shareOnLongPress ? handleLongPress() : undefined
},
[outerOnLongPress, handleLongPress, shareOnLongPress],
)

return {
isExternal,
Expand All @@ -202,14 +214,16 @@ export function Link({
to,
action = 'push',
onPress: outerOnPress,
onLongPress: outerOnLongPress,
download,
...rest
}: LinkProps) {
const {href, isExternal, onPress} = useLink({
const {href, isExternal, onPress, onLongPress} = useLink({
to,
displayText: typeof children === 'string' ? children : '',
action,
onPress: outerOnPress,
onLongPress: outerOnLongPress,
})

return (
Expand All @@ -220,6 +234,7 @@ export function Link({
accessibilityRole="link"
href={href}
onPress={download ? undefined : onPress}
onLongPress={onLongPress}
{...web({
hrefAttrs: {
target: download ? undefined : isExternal ? 'blank' : undefined,
Expand All @@ -241,7 +256,7 @@ export type InlineLinkProps = React.PropsWithChildren<
TextStyleProp &
Pick<TextProps, 'selectable' | 'numberOfLines'>
> &
Pick<ButtonProps, 'label'> & {
Pick<ButtonProps, 'label' | 'accessibilityHint'> & {
disableUnderline?: boolean
title?: TextProps['title']
}
Expand All @@ -253,6 +268,7 @@ export function InlineLinkText({
disableMismatchWarning,
style,
onPress: outerOnPress,
onLongPress: outerOnLongPress,
download,
selectable,
label,
Expand All @@ -268,6 +284,7 @@ export function InlineLinkText({
action,
disableMismatchWarning,
onPress: outerOnPress,
onLongPress: outerOnLongPress,
shareOnLongPress,
})
const {
Expand Down Expand Up @@ -319,6 +336,21 @@ export function InlineLinkText({
)
}

export function WebOnlyInlineLinkText({
children,
to,
onPress,
...props
}: Omit<InlineLinkProps, 'onLongPress'>) {
return isWeb ? (
<InlineLinkText {...props} to={to} onPress={onPress}>
{children}
</InlineLinkText>
) : (
<Text {...props}>{children}</Text>
)
}

/**
* Utility to create a static `onPress` handler for a `Link` that would otherwise link to a URI
*
Expand All @@ -327,7 +359,10 @@ export function InlineLinkText({
*/
export function createStaticClick(
onPressHandler: Exclude<BaseLinkProps['onPress'], undefined>,
): Pick<BaseLinkProps, 'to' | 'onPress'> {
): {
to: BaseLinkProps['to']
onPress: Exclude<BaseLinkProps['onPress'], undefined>
} {
return {
to: '#',
onPress(e: GestureResponderEvent) {
Expand All @@ -338,17 +373,72 @@ export function createStaticClick(
}
}

export function WebOnlyInlineLinkText({
children,
to,
onPress,
...props
}: InlineLinkProps) {
return isWeb ? (
<InlineLinkText {...props} to={to} onPress={onPress}>
{children}
</InlineLinkText>
) : (
<Text {...props}>{children}</Text>
/**
* Utility to create a static `onPress` handler for a `Link`, but only if the
* click was not modified in some way e.g. `Cmd` or a middle click.
*
* On native, this behaves the same as `createStaticClick` because there are no
* options to "modify" the click in this sense.
*
* Example:
* `<Link {...createStaticClick(e => {...})} />`
*/
export function createStaticClickIfUnmodified(
onPressHandler: Exclude<BaseLinkProps['onPress'], undefined>,
): {onPress: Exclude<BaseLinkProps['onPress'], undefined>} {
return {
onPress(e: GestureResponderEvent) {
if (!isWeb || !isModifiedClickEvent(e)) {
e.preventDefault()
onPressHandler(e)
return false
}
},
}
}

/**
* Determines if the click event has a meta key pressed, indicating the user
* intends to deviate from default behavior.
*/
export function isClickEventWithMetaKey(e: GestureResponderEvent) {
if (!isWeb) return false
const event = e as unknown as MouseEvent
return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey
}

/**
* Determines if the web click target is anything other than `_self`
*/
export function isClickTargetExternal(e: GestureResponderEvent) {
if (!isWeb) return false
const event = e as unknown as MouseEvent
const el = event.currentTarget as HTMLAnchorElement
return el && el.target && el.target !== '_self'
}

/**
* Determines if a click event has been modified in some way from its default
* behavior, e.g. `Cmd` or a middle click.
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button}
*/
export function isModifiedClickEvent(e: GestureResponderEvent): boolean {
if (!isWeb) return false
const event = e as unknown as MouseEvent
const isPrimaryButton = event.button === 0
return (
isClickEventWithMetaKey(e) || isClickTargetExternal(e) || !isPrimaryButton
)
}

/**
* Determines if a click event has been modified in a way that should indiciate
* that the user intends to open a new tab.
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button}
*/
export function shouldClickOpenNewTab(e: GestureResponderEvent) {
if (!isWeb) return false
const event = e as unknown as MouseEvent
const isMiddleClick = isWeb && event.button === 1
return isClickEventWithMetaKey(e) || isClickTargetExternal(e) || isMiddleClick
}
9 changes: 8 additions & 1 deletion src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ export function Root({
return <Context.Provider value={context}>{children}</Context.Provider>
}

export function Trigger({children, label, role = 'button'}: TriggerProps) {
export function Trigger({
children,
label,
role = 'button',
hint,
}: TriggerProps) {
const context = useMenuContext()
const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState()
const {
Expand All @@ -65,11 +70,13 @@ export function Trigger({children, label, role = 'button'}: TriggerProps) {
pressed,
},
props: {
ref: null,
onPress: context.control.open,
onFocus,
onBlur,
onPressIn,
onPressOut,
accessibilityHint: hint,
accessibilityLabel: label,
accessibilityRole: role,
},
Expand Down
8 changes: 7 additions & 1 deletion src/components/Menu/index.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,12 @@ const RadixTriggerPassThrough = React.forwardRef(
)
RadixTriggerPassThrough.displayName = 'RadixTriggerPassThrough'

export function Trigger({children, label, role = 'button'}: TriggerProps) {
export function Trigger({
children,
label,
role = 'button',
hint,
}: TriggerProps) {
const {control} = useMenuContext()
const {
state: hovered,
Expand Down Expand Up @@ -153,6 +158,7 @@ export function Trigger({children, label, role = 'button'}: TriggerProps) {
onBlur: onBlur,
onMouseEnter,
onMouseLeave,
accessibilityHint: hint,
accessibilityLabel: label,
accessibilityRole: role,
},
Expand Down
5 changes: 5 additions & 0 deletions src/components/Menu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type ItemContextType = {
}

export type RadixPassThroughTriggerProps = {
ref: React.RefObject<any>
id: string
type: 'button'
disabled: boolean
Expand All @@ -37,6 +38,7 @@ export type RadixPassThroughTriggerProps = {
export type TriggerProps = {
children(props: TriggerChildProps): React.ReactNode
label: string
hint?: string
role?: AccessibilityRole
}
export type TriggerChildProps =
Expand All @@ -59,11 +61,13 @@ export type TriggerChildProps =
* object is empty.
*/
props: {
ref: null
onPress: () => void
onFocus: () => void
onBlur: () => void
onPressIn: () => void
onPressOut: () => void
accessibilityHint?: string
accessibilityLabel: string
accessibilityRole: AccessibilityRole
}
Expand All @@ -85,6 +89,7 @@ export type TriggerChildProps =
onBlur: () => void
onMouseEnter: () => void
onMouseLeave: () => void
accessibilityHint?: string
accessibilityLabel: string
accessibilityRole: AccessibilityRole
}
Expand Down
Loading

0 comments on commit 25c5c05

Please sign in to comment.