Merge remote-tracking branch 'origin/main' into hailey/dialogs-pt10

This commit is contained in:
Hailey
2024-10-02 11:59:58 -07:00
7 changed files with 129 additions and 73 deletions
+3
View File
@@ -15,3 +15,6 @@ android
ios ios
src/locale/locales src/locale/locales
lib/react-compiler-runtime lib/react-compiler-runtime
bskyweb/static
coverage
web-build
+1
View File
@@ -255,6 +255,7 @@ func serve(cctx *cli.Context) error {
e.GET("/support/community-guidelines", server.WebGeneric) e.GET("/support/community-guidelines", server.WebGeneric)
e.GET("/support/copyright", server.WebGeneric) e.GET("/support/copyright", server.WebGeneric)
e.GET("/intent/compose", server.WebGeneric) e.GET("/intent/compose", server.WebGeneric)
e.GET("/intent/verify-email", server.WebGeneric)
e.GET("/messages", server.WebGeneric) e.GET("/messages", server.WebGeneric)
e.GET("/messages/:conversation", server.WebGeneric) e.GET("/messages/:conversation", server.WebGeneric)
+28
View File
@@ -901,4 +901,32 @@ export const atoms = {
hidden: { hidden: {
display: 'none', display: 'none',
}, },
/*
* Transition
*/
transition_none: web({
transitionProperty: 'none',
}),
transition_all: web({
transitionProperty: 'all',
transitionTimingFunction: 'cubic-bezier(0.17, 0.73, 0.14, 1)',
transitionDuration: '100ms',
}),
transition_color: web({
transitionProperty:
'color, background-color, border-color, text-decoration-color, fill, stroke',
transitionTimingFunction: 'cubic-bezier(0.17, 0.73, 0.14, 1)',
transitionDuration: '100ms',
}),
transition_opacity: web({
transitionProperty: 'opacity',
transitionTimingFunction: 'cubic-bezier(0.17, 0.73, 0.14, 1)',
transitionDuration: '100ms',
}),
transition_transform: web({
transitionProperty: 'transform',
transitionTimingFunction: 'cubic-bezier(0.17, 0.73, 0.14, 1)',
transitionDuration: '100ms',
}),
} as const } as const
+14
View File
@@ -1,3 +1,5 @@
import {useFonts} from 'expo-font'
import {isWeb} from '#/platform/detection' import {isWeb} from '#/platform/detection'
import {Device, device} from '#/storage' import {Device, device} from '#/storage'
@@ -63,3 +65,15 @@ export function applyFonts(
*/ */
style.fontVariant = ['no-contextual'] style.fontVariant = ['no-contextual']
} }
/*
* IMPORTANT: This is unused. Expo statically extracts these fonts.
*
* All used fonts MUST be configured here. Unused fonts can be commented out.
*/
export function DO_NOT_USE() {
return useFonts({
InterVariable: require('../../assets/fonts/inter/InterVariable.ttf'),
'InterVariable-Italic': require('../../assets/fonts/inter/InterVariable-Italic.ttf'),
})
}
@@ -3,12 +3,15 @@ import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {isNative} from '#/platform/detection'
import {useAgent, useSession} from '#/state/session' import {useAgent, useSession} from '#/state/session'
import {atoms as a} from '#/alf' import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {BottomSheetButton} from '#/components/BottomSheetButton' import {BottomSheetButton} from '#/components/BottomSheetButton'
import {ButtonText} from '#/components/Button' import {ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import {DialogControlProps} from '#/components/Dialog' import {DialogControlProps} from '#/components/Dialog'
import {Divider} from '#/components/Divider'
import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as Resend} from '#/components/icons/ArrowRotateCounterClockwise'
import {useIntentDialogs} from '#/components/intents/IntentDialogs' import {useIntentDialogs} from '#/components/intents/IntentDialogs'
import {Loader} from '#/components/Loader' import {Loader} from '#/components/Loader'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
@@ -23,7 +26,9 @@ export function VerifyEmailIntentDialog() {
) )
} }
function Inner({control}: {control: DialogControlProps}) { function Inner({}: {control: DialogControlProps}) {
const t = useTheme()
const {gtMobile} = useBreakpoints()
const {_} = useLingui() const {_} = useLingui()
const {verifyEmailState: state} = useIntentDialogs() const {verifyEmailState: state} = useIntentDialogs()
const [status, setStatus] = React.useState< const [status, setStatus] = React.useState<
@@ -58,43 +63,47 @@ function Inner({control}: {control: DialogControlProps}) {
} }
return ( return (
<Dialog.ScrollableInner label={_(msg`Verify email dialog`)}> <Dialog.ScrollableInner
<Dialog.Close /> label={_(msg`Verify email dialog`)}
style={[
gtMobile ? {width: 'auto', maxWidth: 400, minWidth: 200} : a.w_full,
]}>
<View style={[a.gap_xl]}> <View style={[a.gap_xl]}>
{status === 'loading' ? ( {status === 'loading' ? (
<View style={[a.py_2xl, a.align_center, a.justify_center]}> <View style={[a.py_2xl, a.align_center, a.justify_center]}>
<Loader size="xl" /> <Loader size="xl" fill={t.atoms.text_contrast_low.color} />
</View> </View>
) : status === 'success' ? ( ) : status === 'success' ? (
<> <View style={[a.gap_sm, isNative && a.pb_xl]}>
<Text style={[a.font_bold, a.text_2xl]}> <Text style={[a.font_heavy, a.text_2xl]}>
<Trans>Email Verified</Trans> <Trans>Email Verified</Trans>
</Text> </Text>
<Text style={[a.text_md, a.leading_tight]}> <Text style={[a.text_md, a.leading_snug]}>
<Trans> <Trans>
Thanks, you have successfully verified your email address. Thanks, you have successfully verified your email address. You
can close this dialog.
</Trans> </Trans>
</Text> </Text>
</> </View>
) : status === 'failure' ? ( ) : status === 'failure' ? (
<> <View style={[a.gap_sm]}>
<Text style={[a.font_bold, a.text_2xl]}> <Text style={[a.font_heavy, a.text_2xl]}>
<Trans>Invalid Verification Code</Trans> <Trans>Invalid Verification Code</Trans>
</Text> </Text>
<Text style={[a.text_md, a.leading_tight]}> <Text style={[a.text_md, a.leading_snug]}>
<Trans> <Trans>
The verification code you have provided is invalid. Please make The verification code you have provided is invalid. Please make
sure that you have used the correct verification link or request sure that you have used the correct verification link or request
a new one. a new one.
</Trans> </Trans>
</Text> </Text>
</> </View>
) : ( ) : (
<> <View style={[a.gap_sm, isNative && a.pb_xl]}>
<Text style={[a.font_bold, a.text_2xl]}> <Text style={[a.font_heavy, a.text_2xl]}>
<Trans>Email Resent</Trans> <Trans>Email Resent</Trans>
</Text> </Text>
<Text style={[a.text_md, a.leading_tight]}> <Text style={[a.text_md, a.leading_snug]}>
<Trans> <Trans>
We have sent another verification email to{' '} We have sent another verification email to{' '}
<Text style={[a.text_md, a.font_bold]}> <Text style={[a.text_md, a.font_bold]}>
@@ -103,38 +112,29 @@ function Inner({control}: {control: DialogControlProps}) {
. .
</Trans> </Trans>
</Text> </Text>
</> </View>
)} )}
{status !== 'loading' ? (
<View style={[a.w_full, a.flex_row, a.gap_sm, {marginLeft: 'auto'}]}> {status === 'failure' && (
<>
<Divider />
<BottomSheetButton <BottomSheetButton
label={_(msg`Close`)} label={_(msg`Resend Verification Email`)}
onPress={() => control.close()} onPress={onPressResendEmail}
variant="solid" variant="solid"
color={status === 'failure' ? 'secondary' : 'primary'} color="secondary_inverted"
size="large" size="large"
style={{marginLeft: 'auto'}}> disabled={sending}>
<ButtonIcon icon={sending ? Loader : Resend} position="left" />
<ButtonText> <ButtonText>
<Trans>Close</Trans> <Trans>Resend Email</Trans>
</ButtonText> </ButtonText>
</BottomSheetButton> </BottomSheetButton>
{status === 'failure' ? ( </>
<BottomSheetButton )}
label={_(msg`Resend Verification Email`)}
onPress={onPressResendEmail}
variant="solid"
color="primary"
size="large"
disabled={sending}>
<ButtonText>
<Trans>Resend Email</Trans>
</ButtonText>
{sending ? <Loader size="sm" style={{color: 'white'}} /> : null}
</BottomSheetButton>
) : null}
</View>
) : null}
</View> </View>
<Dialog.Close />
</Dialog.ScrollableInner> </Dialog.ScrollableInner>
) )
} }
@@ -46,29 +46,31 @@ export const PlaceholderCanvas = React.forwardRef<PlaceholderCanvasRef, {}>(
return ( return (
<View style={styles.container}> <View style={styles.container}>
<LazyViewShot <React.Suspense fallback={null}>
// @ts-ignore this library doesn't have types <LazyViewShot
ref={viewshotRef} // @ts-ignore this library doesn't have types
options={{ ref={viewshotRef}
fileName: 'placeholderAvatar', options={{
format: 'jpg', fileName: 'placeholderAvatar',
quality: 0.8, format: 'jpg',
height: 150 * SIZE_MULTIPLIER, quality: 0.8,
width: 150 * SIZE_MULTIPLIER, height: 150 * SIZE_MULTIPLIER,
}}> width: 150 * SIZE_MULTIPLIER,
<View }}>
style={[ <View
styles.imageContainer, style={[
{backgroundColor: avatar.backgroundColor}, styles.imageContainer,
]} {backgroundColor: avatar.backgroundColor},
collapsable={false}> ]}
<Icon collapsable={false}>
height={85 * SIZE_MULTIPLIER} <Icon
width={85 * SIZE_MULTIPLIER} height={85 * SIZE_MULTIPLIER}
style={{color: 'white'}} width={85 * SIZE_MULTIPLIER}
/> style={{color: 'white'}}
</View> />
</LazyViewShot> </View>
</LazyViewShot>
</React.Suspense>
</View> </View>
) )
}, },
@@ -5,12 +5,12 @@ import {useLingui} from '@lingui/react'
import {PressableScale} from '#/lib/custom-animations/PressableScale' import {PressableScale} from '#/lib/custom-animations/PressableScale'
import {useHaptics} from '#/lib/haptics' import {useHaptics} from '#/lib/haptics'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {useHapticsDisabled} from '#/state/preferences' import {useHapticsDisabled} from '#/state/preferences'
import {useProfileQuery} from '#/state/queries/profile' import {useProfileQuery} from '#/state/queries/profile'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
export function PostThreadComposePrompt({ export function PostThreadComposePrompt({
@@ -21,10 +21,15 @@ export function PostThreadComposePrompt({
const {currentAccount} = useSession() const {currentAccount} = useSession()
const {data: profile} = useProfileQuery({did: currentAccount?.did}) const {data: profile} = useProfileQuery({did: currentAccount?.did})
const {_} = useLingui() const {_} = useLingui()
const {isTabletOrDesktop} = useWebMediaQueries() const {gtMobile} = useBreakpoints()
const t = useTheme() const t = useTheme()
const playHaptics = useHaptics() const playHaptics = useHaptics()
const isHapticsDisabled = useHapticsDisabled() const isHapticsDisabled = useHapticsDisabled()
const {
state: hovered,
onIn: onHoverIn,
onOut: onHoverOut,
} = useInteractionState()
const onPress = () => { const onPress = () => {
playHaptics('Light') playHaptics('Light')
@@ -42,13 +47,15 @@ export function PostThreadComposePrompt({
accessibilityLabel={_(msg`Compose reply`)} accessibilityLabel={_(msg`Compose reply`)}
accessibilityHint={_(msg`Opens composer`)} accessibilityHint={_(msg`Opens composer`)}
style={[ style={[
{paddingTop: 8, paddingBottom: isTabletOrDesktop ? 8 : 11}, gtMobile ? a.py_xs : {paddingTop: 8, paddingBottom: 11},
a.px_sm, gtMobile ? {paddingLeft: 6, paddingRight: 6} : a.px_sm,
a.border_t, a.border_t,
t.atoms.border_contrast_low, t.atoms.border_contrast_low,
t.atoms.bg, t.atoms.bg,
]} ]}
onPress={onPress}> onPress={onPress}
onHoverIn={onHoverIn}
onHoverOut={onHoverOut}>
<View <View
style={[ style={[
a.flex_row, a.flex_row,
@@ -56,10 +63,11 @@ export function PostThreadComposePrompt({
a.p_sm, a.p_sm,
a.gap_sm, a.gap_sm,
a.rounded_full, a.rounded_full,
t.atoms.bg_contrast_25, (!gtMobile || hovered) && t.atoms.bg_contrast_25,
a.transition_color,
]}> ]}>
<UserAvatar <UserAvatar
size={22} size={gtMobile ? 24 : 22}
avatar={profile?.avatar} avatar={profile?.avatar}
type={profile?.associated?.labeler ? 'labeler' : 'user'} type={profile?.associated?.labeler ? 'labeler' : 'user'}
/> />