[ELI5] Tweaks to hosting provider (#6935)

* minimal hosting provider

* change wording and move back up

* first time user nudge

* move tip

* reexport ticket svg

* fix ticket fr this time

* text tweak + add minHeight
This commit is contained in:
Samuel Newman
2025-01-08 19:22:04 +00:00
committed by GitHub
parent 40ab77781c
commit 7c8c78b18f
5 changed files with 122 additions and 83 deletions
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" stroke="#000" stroke-linejoin="round" d="M4 5.5a.5.5 0 0 0-.5.5v2.535a.5.5 0 0 0 .25.433A3.5 3.5 0 0 1 5.5 12a3.5 3.5 0 0 1-1.75 3.032.5.5 0 0 0-.25.433V18a.5.5 0 0 0 .5.5h16a.5.5 0 0 0 .5-.5v-2.535a.5.5 0 0 0-.25-.433A3.5 3.5 0 0 1 18.5 12a3.5 3.5 0 0 1 1.75-3.032.5.5 0 0 0 .25-.433V6a.5.5 0 0 0-.5-.5H4ZM2.5 6A1.5 1.5 0 0 1 4 4.5h16A1.5 1.5 0 0 1 21.5 6v3.17a.5.5 0 0 1-.333.472 2.501 2.501 0 0 0 0 4.716.5.5 0 0 1 .333.471V18a1.5 1.5 0 0 1-1.5 1.5H4A1.5 1.5 0 0 1 2.5 18v-3.17a.5.5 0 0 1 .333-.472 2.501 2.501 0 0 0 0-4.716.5.5 0 0 1-.333-.471V6Zm12 2a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Zm0 4a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Zm0 4a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M3 4a1 1 0 0 0-1 1v4.17a1 1 0 0 0 .667.944 2.001 2.001 0 0 1 0 3.772A1 1 0 0 0 2 14.83V19a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1v-4.17a1 1 0 0 0-.667-.944 2.001 2.001 0 0 1 0-3.772A1 1 0 0 0 22 9.17V5a1 1 0 0 0-1-1H3Zm1 4.535V6h16v2.535A4 4 0 0 0 18 12c0 1.482.805 2.773 2 3.465V18H4v-2.535A4 4 0 0 0 6 12a4 4 0 0 0-2-3.465ZM15 15a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm-1-3a1 1 0 1 1 2 0 1 1 0 0 1-2 0Zm1-5a1 1 0 1 0 0 2 1 1 0 0 0 0-2Z" clip-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 756 B

After

Width:  |  Height:  |  Size: 561 B

+83 -60
View File
@@ -6,21 +6,23 @@ import {useLingui} from '@lingui/react'
import {toNiceDomain} from '#/lib/strings/url-helpers' import {toNiceDomain} from '#/lib/strings/url-helpers'
import {isAndroid} from '#/platform/detection' import {isAndroid} from '#/platform/detection'
import {ServerInputDialog} from '#/view/com/auth/server-input' import {ServerInputDialog} from '#/view/com/auth/server-input'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, tokens, useTheme} from '#/alf'
import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe' import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {PencilLine_Stroke2_Corner0_Rounded as Pencil} from '#/components/icons/Pencil' import {useDialogControl} from '#/components/Dialog'
import {Button} from '../Button' import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe'
import {useDialogControl} from '../Dialog' import {PencilLine_Stroke2_Corner0_Rounded as PencilIcon} from '#/components/icons/Pencil'
import {Text} from '../Typography' import {Text} from '#/components/Typography'
export function HostingProvider({ export function HostingProvider({
serviceUrl, serviceUrl,
onSelectServiceUrl, onSelectServiceUrl,
onOpenDialog, onOpenDialog,
minimal,
}: { }: {
serviceUrl: string serviceUrl: string
onSelectServiceUrl: (provider: string) => void onSelectServiceUrl: (provider: string) => void
onOpenDialog?: () => void onOpenDialog?: () => void
minimal?: boolean
}) { }) {
const serverInputControl = useDialogControl() const serverInputControl = useDialogControl()
const t = useTheme() const t = useTheme()
@@ -29,9 +31,7 @@ export function HostingProvider({
const onPressSelectService = React.useCallback(() => { const onPressSelectService = React.useCallback(() => {
Keyboard.dismiss() Keyboard.dismiss()
serverInputControl.open() serverInputControl.open()
if (onOpenDialog) { onOpenDialog?.()
onOpenDialog()
}
}, [onOpenDialog, serverInputControl]) }, [onOpenDialog, serverInputControl])
return ( return (
@@ -40,57 +40,80 @@ export function HostingProvider({
control={serverInputControl} control={serverInputControl}
onSelect={onSelectServiceUrl} onSelect={onSelectServiceUrl}
/> />
<Button {minimal ? (
testID="selectServiceButton" <View style={[a.flex_row, a.align_center, a.flex_wrap]}>
label={toNiceDomain(serviceUrl)} <Text style={[a.text_sm, t.atoms.text_contrast_medium]}>
accessibilityHint={_(msg`Press to change hosting provider`)} You are creating an account on{' '}
variant="solid" </Text>
color="secondary" <Button
style={[ label={toNiceDomain(serviceUrl)}
a.w_full, accessibilityHint={_(msg`Press to change hosting provider`)}
a.flex_row, onPress={onPressSelectService}
a.align_center, variant="ghost"
a.rounded_sm, color="secondary"
a.px_md, size="tiny"
a.pr_sm, style={[a.px_xs, {marginLeft: tokens.space.xs * -1}]}>
a.gap_xs, <ButtonText style={[a.text_sm]}>
{paddingVertical: isAndroid ? 14 : 9}, {toNiceDomain(serviceUrl)}
]} </ButtonText>
onPress={onPressSelectService}> <ButtonIcon icon={PencilIcon} />
{({hovered, pressed}) => { </Button>
const interacted = hovered || pressed </View>
return ( ) : (
<> <Button
<View style={a.pr_xs}> testID="selectServiceButton"
<Globe label={toNiceDomain(serviceUrl)}
size="md" accessibilityHint={_(msg`Press to change hosting provider`)}
fill={ variant="solid"
interacted ? t.palette.contrast_800 : t.palette.contrast_500 color="secondary"
} style={[
/> a.w_full,
</View> a.flex_row,
<Text style={[a.text_md]}>{toNiceDomain(serviceUrl)}</Text> a.align_center,
<View a.rounded_sm,
style={[ a.px_md,
a.rounded_sm, a.pr_sm,
interacted a.gap_xs,
? t.atoms.bg_contrast_300 {paddingVertical: isAndroid ? 14 : 9},
: t.atoms.bg_contrast_100, ]}
{marginLeft: 'auto', padding: 6}, onPress={onPressSelectService}>
]}> {({hovered, pressed}) => {
<Pencil const interacted = hovered || pressed
size="sm" return (
style={{ <>
color: interacted <View style={a.pr_xs}>
? t.palette.contrast_800 <GlobeIcon
: t.palette.contrast_500, size="md"
}} fill={
/> interacted
</View> ? t.palette.contrast_800
</> : t.palette.contrast_500
) }
}} />
</Button> </View>
<Text style={[a.text_md]}>{toNiceDomain(serviceUrl)}</Text>
<View
style={[
a.rounded_sm,
interacted
? t.atoms.bg_contrast_300
: t.atoms.bg_contrast_100,
{marginLeft: 'auto', padding: 6},
]}>
<PencilIcon
size="sm"
style={{
color: interacted
? t.palette.contrast_800
: t.palette.contrast_500,
}}
/>
</View>
</>
)
}}
</Button>
)}
</> </>
) )
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import {createSinglePathSVG} from './TEMPLATE' import {createSinglePathSVG} from './TEMPLATE'
export const Ticket_Stroke2_Corner0_Rounded = createSinglePathSVG({ export const Ticket_Stroke2_Corner0_Rounded = createSinglePathSVG({
path: 'M4 5.5a.5.5 0 0 0-.5.5v2.535a.5.5 0 0 0 .25.433A3.498 3.498 0 0 1 5.5 12a3.498 3.498 0 0 1-1.75 3.032.5.5 0 0 0-.25.433V18a.5.5 0 0 0 .5.5h16a.5.5 0 0 0 .5-.5v-2.535a.5.5 0 0 0-.25-.433A3.498 3.498 0 0 1 18.5 12a3.5 3.5 0 0 1 1.75-3.032.5.5 0 0 0 .25-.433V6a.5.5 0 0 0-.5-.5H4ZM2.5 6A1.5 1.5 0 0 1 4 4.5h16A1.5 1.5 0 0 1 21.5 6v3.17a.5.5 0 0 1-.333.472 2.501 2.501 0 0 0 0 4.716.5.5 0 0 1 .333.471V18a1.5 1.5 0 0 1-1.5 1.5H4A1.5 1.5 0 0 1 2.5 18v-3.17a.5.5 0 0 1 .333-.472 2.501 2.501 0 0 0 0-4.716.5.5 0 0 1-.333-.471V6Zm12 2a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Zm0 4a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Zm0 4a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0Z', path: 'M3 4a1 1 0 0 0-1 1v4.17a1 1 0 0 0 .667.944 2.001 2.001 0 0 1 0 3.772A1 1 0 0 0 2 14.83V19a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1v-4.17a1 1 0 0 0-.667-.944 2.001 2.001 0 0 1 0-3.772A1 1 0 0 0 22 9.17V5a1 1 0 0 0-1-1H3Zm1 4.535V6h16v2.535A4 4 0 0 0 18 12c0 1.482.805 2.773 2 3.465V18H4v-2.535A4 4 0 0 0 6 12a4 4 0 0 0-2-3.465ZM15 15a1 1 0 1 0 0 2 1 1 0 0 0 0-2Zm-1-3a1 1 0 1 1 2 0 1 1 0 0 1-2 0Zm1-5a1 1 0 1 0 0 2 1 1 0 0 0 0-2Z',
}) })
+5 -11
View File
@@ -128,17 +128,11 @@ export function StepInfo({
<ScreenTransition> <ScreenTransition>
<View style={[a.gap_md]}> <View style={[a.gap_md]}>
<FormError error={state.error} /> <FormError error={state.error} />
<View> <HostingProvider
<TextField.LabelText> minimal
<Trans>Hosting provider</Trans> serviceUrl={state.serviceUrl}
</TextField.LabelText> onSelectServiceUrl={v => dispatch({type: 'setServiceUrl', value: v})}
<HostingProvider />
serviceUrl={state.serviceUrl}
onSelectServiceUrl={v =>
dispatch({type: 'setServiceUrl', value: v})
}
/>
</View>
{state.isLoading || isLoadingStarterPack ? ( {state.isLoading || isLoadingStarterPack ? (
<View style={[a.align_center]}> <View style={[a.align_center]}>
<Loader size="xl" /> <Loader size="xl" />
+32 -10
View File
@@ -1,11 +1,14 @@
import React from 'react' import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {useWindowDimensions} 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 {BSKY_SERVICE} from '#/lib/constants' import {BSKY_SERVICE} from '#/lib/constants'
import * as persisted from '#/state/persisted' import * as persisted from '#/state/persisted'
import {useSession} from '#/state/session'
import {atoms as a, useBreakpoints, useTheme} from '#/alf' import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog' import * as Dialog from '#/components/Dialog'
import * as TextField from '#/components/forms/TextField' import * as TextField from '#/components/forms/TextField'
@@ -23,12 +26,16 @@ export function ServerInputDialog({
}) { }) {
const {_} = useLingui() const {_} = useLingui()
const t = useTheme() const t = useTheme()
const {height} = useWindowDimensions()
const {gtMobile} = useBreakpoints() const {gtMobile} = useBreakpoints()
const [pdsAddressHistory, setPdsAddressHistory] = React.useState<string[]>( const [pdsAddressHistory, setPdsAddressHistory] = React.useState<string[]>(
persisted.get('pdsAddressHistory') || [], persisted.get('pdsAddressHistory') || [],
) )
const [fixedOption, setFixedOption] = React.useState([BSKY_SERVICE]) const [fixedOption, setFixedOption] = React.useState([BSKY_SERVICE])
const [customAddress, setCustomAddress] = React.useState('') const [customAddress, setCustomAddress] = React.useState('')
const {accounts} = useSession()
const isFirstTimeUser = accounts.length === 0
const onClose = React.useCallback(() => { const onClose = React.useCallback(() => {
let url let url
@@ -66,19 +73,18 @@ export function ServerInputDialog({
]) ])
return ( return (
<Dialog.Outer control={control} onClose={onClose}> <Dialog.Outer
control={control}
onClose={onClose}
nativeOptions={{minHeight: height / 2}}>
<Dialog.Handle /> <Dialog.Handle />
<Dialog.ScrollableInner <Dialog.ScrollableInner
accessibilityDescribedBy="dialog-description" accessibilityDescribedBy="dialog-description"
accessibilityLabelledBy="dialog-title"> accessibilityLabelledBy="dialog-title">
<View style={[a.relative, a.gap_md, a.w_full]}> <View style={[a.relative, a.gap_md, a.w_full]}>
<Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}> <Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}>
<Trans>Choose Service</Trans> <Trans>Choose your account provider</Trans>
</Text> </Text>
<P nativeID="dialog-description" style={[a.text_sm]}>
<Trans>Select the service that hosts your data.</Trans>
</P>
<ToggleButton.Group <ToggleButton.Group
label="Preferences" label="Preferences"
values={fixedOption} values={fixedOption}
@@ -98,6 +104,16 @@ export function ServerInputDialog({
</ToggleButton.Button> </ToggleButton.Button>
</ToggleButton.Group> </ToggleButton.Group>
{fixedOption[0] === BSKY_SERVICE && isFirstTimeUser && (
<Admonition type="tip">
<Trans>
Bluesky is an open network where you can choose your own
provider. If you're new here, we recommend sticking with the
default Bluesky Social option.
</Trans>
</Admonition>
)}
{fixedOption[0] === 'custom' && ( {fixedOption[0] === 'custom' && (
<View <View
style={[ style={[
@@ -148,10 +164,16 @@ export function ServerInputDialog({
a.leading_snug, a.leading_snug,
a.flex_1, a.flex_1,
]}> ]}>
<Trans> {isFirstTimeUser ? (
Bluesky is an open network where you can choose your hosting <Trans>
provider. If you're a developer, you can host your own server. If you're a developer, you can host your own server.
</Trans>{' '} </Trans>
) : (
<Trans>
Bluesky is an open network where you can choose your hosting
provider. If you're a developer, you can host your own server.
</Trans>
)}{' '}
<InlineLinkText <InlineLinkText
label={_(msg`Learn more about self hosting your PDS.`)} label={_(msg`Learn more about self hosting your PDS.`)}
to="https://atproto.com/guides/self-hosting"> to="https://atproto.com/guides/self-hosting">