merge main
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="#FFC404" fill-rule="evenodd" d="M11.183 8.561c0 .544.348.984.892.984.545 0 .893-.44.893-.985V6.985c0-.544-.348-.985-.893-.985-.543 0-.892.44-.892.985v1.576Zm5.94 7.481c0 .539-.438.942-.976.942H8.004c-.538 0-.975-.411-.975-.95 0-2.782 2.264-5.021 5.046-5.021 2.783 0 5.047 2.247 5.047 5.03Zm-.43-4.584a.983.983 0 0 1 0-1.393l1.114-1.114a.985.985 0 0 1 1.393 1.393l-1.114 1.114a.985.985 0 0 1-1.393 0Zm2.897 3.741h1.575c.544 0 .985.349.985.892 0 .544-.44.892-.985.892h-1.67a.872.872 0 0 1-.89-.887c0-.543.44-.897.985-.897Zm-14.045.893c0-.544-.44-.892-.985-.892H2.985c-.544 0-.985.349-.985.892 0 .544.44.892.985.892H4.56c.545 0 .985-.349.985-.892Zm1.913-6.027a.985.985 0 0 1-1.393 1.393L4.95 10.344A.985.985 0 0 1 6.344 8.95l1.114 1.114Z" clip-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 848 B |
@@ -0,0 +1,81 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {AppBskyActorDefs, moderateProfile} from '@atproto/api'
|
||||||
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
import {differenceInSeconds} from 'date-fns'
|
||||||
|
|
||||||
|
import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
||||||
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
|
import {HITSLOP_10} from 'lib/constants'
|
||||||
|
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||||
|
import {atoms as a} from '#/alf'
|
||||||
|
import {Button} from '#/components/Button'
|
||||||
|
import * as Dialog from '#/components/Dialog'
|
||||||
|
import {useDialogControl} from '#/components/Dialog'
|
||||||
|
import {Newskie} from '#/components/icons/Newskie'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
|
export function NewskieDialog({
|
||||||
|
profile,
|
||||||
|
}: {
|
||||||
|
profile: AppBskyActorDefs.ProfileViewDetailed
|
||||||
|
}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const moderationOpts = useModerationOpts()
|
||||||
|
const control = useDialogControl()
|
||||||
|
const profileName = React.useMemo(() => {
|
||||||
|
const name = profile.displayName || profile.handle
|
||||||
|
if (!moderationOpts) return name
|
||||||
|
const moderation = moderateProfile(profile, moderationOpts)
|
||||||
|
return sanitizeDisplayName(name, moderation.ui('displayName'))
|
||||||
|
}, [moderationOpts, profile])
|
||||||
|
const timeAgo = useGetTimeAgo()
|
||||||
|
const createdAt = profile.createdAt as string | undefined
|
||||||
|
const daysOld = React.useMemo(() => {
|
||||||
|
if (!createdAt) return Infinity
|
||||||
|
return differenceInSeconds(new Date(), new Date(createdAt)) / 86400
|
||||||
|
}, [createdAt])
|
||||||
|
|
||||||
|
if (!createdAt || daysOld > 7) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[a.pr_2xs]}>
|
||||||
|
<Button
|
||||||
|
label={_(
|
||||||
|
msg`This user is new here. Press for more info about when they joined.`,
|
||||||
|
)}
|
||||||
|
hitSlop={HITSLOP_10}
|
||||||
|
onPress={control.open}>
|
||||||
|
{({hovered, pressed}) => (
|
||||||
|
<Newskie
|
||||||
|
size="lg"
|
||||||
|
fill="#FFC404"
|
||||||
|
style={{
|
||||||
|
opacity: hovered || pressed ? 0.5 : 1,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Dialog.Outer control={control}>
|
||||||
|
<Dialog.Handle />
|
||||||
|
<Dialog.ScrollableInner
|
||||||
|
label={_(msg`New user info dialog`)}
|
||||||
|
style={[{width: 'auto', maxWidth: 400, minWidth: 200}]}>
|
||||||
|
<View style={[a.gap_sm]}>
|
||||||
|
<Text style={[a.font_bold, a.text_xl]}>
|
||||||
|
<Trans>Say hello!</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text style={[a.text_md]}>
|
||||||
|
<Trans>
|
||||||
|
{profileName} joined Bluesky{' '}
|
||||||
|
{timeAgo(createdAt, {format: 'long'})} ago
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</Dialog.ScrollableInner>
|
||||||
|
</Dialog.Outer>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View} from 'react-native'
|
import {Keyboard, View} from 'react-native'
|
||||||
import DatePicker from 'react-native-date-picker'
|
import DatePicker from 'react-native-date-picker'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -49,7 +49,10 @@ export function DateField({
|
|||||||
<DateFieldButton
|
<DateFieldButton
|
||||||
label={label}
|
label={label}
|
||||||
value={value}
|
value={value}
|
||||||
onPress={control.open}
|
onPress={() => {
|
||||||
|
Keyboard.dismiss()
|
||||||
|
control.open()
|
||||||
|
}}
|
||||||
isInvalid={isInvalid}
|
isInvalid={isInvalid}
|
||||||
accessibilityHint={accessibilityHint}
|
accessibilityHint={accessibilityHint}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,5 @@
|
|||||||
import * as React from 'react'
|
import {createSinglePathSVG} from './TEMPLATE'
|
||||||
import {View} from 'react-native'
|
|
||||||
import Svg, {Path} from 'react-native-svg'
|
export const Newskie = createSinglePathSVG({
|
||||||
export function Newskie({size}: {size: number}) {
|
path: 'M11.183 8.561c0 .544.348.984.892.984.545 0 .893-.44.893-.985V6.985c0-.544-.348-.985-.893-.985-.543 0-.892.44-.892.985v1.576Zm5.94 7.481c0 .539-.438.942-.976.942H8.004c-.538 0-.975-.411-.975-.95 0-2.782 2.264-5.021 5.046-5.021 2.783 0 5.047 2.247 5.047 5.03Zm-.43-4.584a.983.983 0 0 1 0-1.393l1.114-1.114a.985.985 0 0 1 1.393 1.393l-1.114 1.114a.985.985 0 0 1-1.393 0Zm2.897 3.741h1.575c.544 0 .985.349.985.892 0 .544-.44.892-.985.892h-1.67a.872.872 0 0 1-.89-.887c0-.543.44-.897.985-.897Zm-14.045.893c0-.544-.44-.892-.985-.892H2.985c-.544 0-.985.349-.985.892 0 .544.44.892.985.892H4.56c.545 0 .985-.349.985-.892Zm1.913-6.027a.985.985 0 0 1-1.393 1.393L4.95 10.344A.985.985 0 0 1 6.344 8.95l1.114 1.114Z',
|
||||||
return (
|
})
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
height: size,
|
|
||||||
width: size,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}>
|
|
||||||
<Svg fill="none" viewBox="0 0 21 11">
|
|
||||||
<Path
|
|
||||||
fill="#FFC404"
|
|
||||||
d="M14.147 10.984c.538 0 .975-.403.975-.942 0-2.782-2.264-5.03-5.047-5.03-2.782 0-5.046 2.24-5.046 5.022 0 .539.437.95.975.95h8.143Zm-4.072-7.439c-.544 0-.892-.44-.892-.984V.985c0-.544.349-.985.892-.985.545 0 .893.44.893.985V2.56c0 .545-.348.985-.893.985Zm4.618 1.913a.983.983 0 0 1 0-1.393l1.114-1.114A.985.985 0 0 1 17.2 4.344l-1.114 1.114a.985.985 0 0 1-1.393 0ZM19.165 9.2H17.59c-.544 0-.985.353-.985.896a.87.87 0 0 0 .89.887h1.67c.544 0 .985-.348.985-.892 0-.543-.44-.892-.985-.892Zm-15.62.892c0-.544-.44-.892-.985-.892H.985c-.544 0-.985.349-.985.892 0 .544.44.892.985.892H2.56c.545 0 .985-.348.985-.892Zm1.913-4.634a.985.985 0 0 0 0-1.393L4.344 2.95A.985.985 0 0 0 2.95 4.344l1.114 1.114a.983.983 0 0 0 1.393 0Z"
|
|
||||||
/>
|
|
||||||
</Svg>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,11 +7,9 @@ import {Shadow} from '#/state/cache/types'
|
|||||||
import {isInvalidHandle} from 'lib/strings/handles'
|
import {isInvalidHandle} from 'lib/strings/handles'
|
||||||
import {isAndroid} from 'platform/detection'
|
import {isAndroid} from 'platform/detection'
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {NewskieDialog} from '#/components/StarterPack/NewskieDialog'
|
import {NewskieDialog} from '#/components/NewskieDialog'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
const DAYS_TO_SHOW_NEWSKIE = 7
|
|
||||||
|
|
||||||
export function ProfileHeaderHandle({
|
export function ProfileHeaderHandle({
|
||||||
profile,
|
profile,
|
||||||
}: {
|
}: {
|
||||||
@@ -20,23 +18,11 @@ export function ProfileHeaderHandle({
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const invalidHandle = isInvalidHandle(profile.handle)
|
const invalidHandle = isInvalidHandle(profile.handle)
|
||||||
const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy
|
const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy
|
||||||
const createdAt = profile.createdAt
|
|
||||||
? new Date(profile.createdAt).getTime()
|
|
||||||
: 0
|
|
||||||
|
|
||||||
const isNewskie =
|
|
||||||
createdAt > 0 && Date.now() + 60e3 * 24 * DAYS_TO_SHOW_NEWSKIE > createdAt
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[a.flex_row, a.gap_xs, a.align_center]}
|
style={[a.flex_row, a.gap_xs, a.align_center]}
|
||||||
pointerEvents={isAndroid ? 'box-only' : 'auto'}>
|
pointerEvents={isAndroid ? 'box-only' : 'auto'}>
|
||||||
{isNewskie && (
|
<NewskieDialog profile={profile} />
|
||||||
<View style={[a.mr_xs]}>
|
|
||||||
<NewskieDialog profile={profile} />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{profile.viewer?.followedBy && !blockHide ? (
|
{profile.viewer?.followedBy && !blockHide ? (
|
||||||
<View style={[t.atoms.bg_contrast_25, a.rounded_xs, a.px_sm, a.py_xs]}>
|
<View style={[t.atoms.bg_contrast_25, a.rounded_xs, a.px_sm, a.py_xs]}>
|
||||||
<Text style={[t.atoms.text, a.text_sm]}>
|
<Text style={[t.atoms.text, a.text_sm]}>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {ScrollView, StyleSheet, View} from 'react-native'
|
|||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
import {isWeb} from '#/platform/detection'
|
||||||
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||||
|
import {useIsKeyboardVisible} from 'lib/hooks/useIsKeyboardVisible'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
@@ -29,13 +30,18 @@ export const LoggedOutLayout = ({
|
|||||||
borderLeftWidth: 1,
|
borderLeftWidth: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [isKeyboardVisible] = useIsKeyboardVisible()
|
||||||
|
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
if (scrollable) {
|
if (scrollable) {
|
||||||
return (
|
return (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
style={styles.scrollview}
|
style={styles.scrollview}
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
keyboardDismissMode="on-drag">
|
keyboardDismissMode="none"
|
||||||
|
contentContainerStyle={[
|
||||||
|
{paddingBottom: isKeyboardVisible ? 300 : 0},
|
||||||
|
]}>
|
||||||
<View style={a.pt_md}>{children}</View>
|
<View style={a.pt_md}>{children}</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user