about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/components/forms/HostingProvider.tsx4
-rw-r--r--src/view/com/auth/server-input/index.tsx349
2 files changed, 194 insertions, 159 deletions
diff --git a/src/components/forms/HostingProvider.tsx b/src/components/forms/HostingProvider.tsx
index 4732434b0..221a759d5 100644
--- a/src/components/forms/HostingProvider.tsx
+++ b/src/components/forms/HostingProvider.tsx
@@ -71,10 +71,10 @@ export function HostingProvider({
             a.flex_row,
             a.align_center,
             a.rounded_sm,
-            a.px_md,
+            a.pl_md,
             a.pr_sm,
             a.gap_xs,
-            {paddingVertical: isAndroid ? 14 : 9},
+            {paddingVertical: isAndroid ? 14 : 8},
           ]}
           onPress={onPressSelectService}>
           {({hovered, pressed}) => {
diff --git a/src/view/com/auth/server-input/index.tsx b/src/view/com/auth/server-input/index.tsx
index f9a5c84bf..7c0bda45b 100644
--- a/src/view/com/auth/server-input/index.tsx
+++ b/src/view/com/auth/server-input/index.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import {useCallback, useImperativeHandle, useRef, useState} from 'react'
 import {View} from 'react-native'
 import {useWindowDimensions} from 'react-native'
 import {msg, Trans} from '@lingui/macro'
@@ -24,53 +24,22 @@ export function ServerInputDialog({
   control: Dialog.DialogOuterProps['control']
   onSelect: (url: string) => void
 }) {
-  const {_} = useLingui()
-  const t = useTheme()
   const {height} = useWindowDimensions()
-  const {gtMobile} = useBreakpoints()
-  const [pdsAddressHistory, setPdsAddressHistory] = React.useState<string[]>(
-    persisted.get('pdsAddressHistory') || [],
-  )
-  const [fixedOption, setFixedOption] = React.useState([BSKY_SERVICE])
-  const [customAddress, setCustomAddress] = React.useState('')
-  const {accounts} = useSession()
+  const formRef = useRef<DialogInnerRef>(null)
 
-  const isFirstTimeUser = accounts.length === 0
-
-  const onClose = React.useCallback(() => {
-    let url
-    if (fixedOption[0] === 'custom') {
-      url = customAddress.trim().toLowerCase()
-      if (!url) {
-        return
-      }
-    } else {
-      url = fixedOption[0]
-    }
-    if (!url.startsWith('http://') && !url.startsWith('https://')) {
-      if (url === 'localhost' || url.startsWith('localhost:')) {
-        url = `http://${url}`
-      } else {
-        url = `https://${url}`
-      }
-    }
+  // persist these options between dialog open/close
+  const [fixedOption, setFixedOption] = useState(BSKY_SERVICE)
+  const [previousCustomAddress, setPreviousCustomAddress] = useState('')
 
-    if (fixedOption[0] === 'custom') {
-      if (!pdsAddressHistory.includes(url)) {
-        const newHistory = [url, ...pdsAddressHistory.slice(0, 4)]
-        setPdsAddressHistory(newHistory)
-        persisted.write('pdsAddressHistory', newHistory)
+  const onClose = useCallback(() => {
+    const result = formRef.current?.getFormState()
+    if (result) {
+      onSelect(result)
+      if (result !== BSKY_SERVICE) {
+        setPreviousCustomAddress(result)
       }
     }
-
-    onSelect(url)
-  }, [
-    fixedOption,
-    customAddress,
-    onSelect,
-    pdsAddressHistory,
-    setPdsAddressHistory,
-  ])
+  }, [onSelect])
 
   return (
     <Dialog.Outer
@@ -78,123 +47,189 @@ export function ServerInputDialog({
       onClose={onClose}
       nativeOptions={{minHeight: height / 2}}>
       <Dialog.Handle />
-      <Dialog.ScrollableInner
-        accessibilityDescribedBy="dialog-description"
-        accessibilityLabelledBy="dialog-title">
-        <View style={[a.relative, a.gap_md, a.w_full]}>
-          <Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}>
-            <Trans>Choose your account provider</Trans>
-          </Text>
-          <ToggleButton.Group
-            label="Preferences"
-            values={fixedOption}
-            onChange={setFixedOption}>
-            <ToggleButton.Button name={BSKY_SERVICE} label={_(msg`Bluesky`)}>
-              <ToggleButton.ButtonText>
-                {_(msg`Bluesky`)}
-              </ToggleButton.ButtonText>
-            </ToggleButton.Button>
-            <ToggleButton.Button
-              testID="customSelectBtn"
-              name="custom"
-              label={_(msg`Custom`)}>
-              <ToggleButton.ButtonText>
-                {_(msg`Custom`)}
-              </ToggleButton.ButtonText>
-            </ToggleButton.Button>
-          </ToggleButton.Group>
-
-          {fixedOption[0] === BSKY_SERVICE && isFirstTimeUser && (
-            <Admonition type="tip">
+      <DialogInner
+        formRef={formRef}
+        fixedOption={fixedOption}
+        setFixedOption={setFixedOption}
+        initialCustomAddress={previousCustomAddress}
+      />
+    </Dialog.Outer>
+  )
+}
+
+type DialogInnerRef = {getFormState: () => string | null}
+
+function DialogInner({
+  formRef,
+  fixedOption,
+  setFixedOption,
+  initialCustomAddress,
+}: {
+  formRef: React.Ref<DialogInnerRef>
+  fixedOption: string
+  setFixedOption: (opt: string) => void
+  initialCustomAddress: string
+}) {
+  const control = Dialog.useDialogContext()
+  const {_} = useLingui()
+  const t = useTheme()
+  const {accounts} = useSession()
+  const {gtMobile} = useBreakpoints()
+  const [customAddress, setCustomAddress] = useState(initialCustomAddress)
+  const [pdsAddressHistory, setPdsAddressHistory] = useState<string[]>(
+    persisted.get('pdsAddressHistory') || [],
+  )
+
+  useImperativeHandle(
+    formRef,
+    () => ({
+      getFormState: () => {
+        let url
+        if (fixedOption === 'custom') {
+          url = customAddress.trim().toLowerCase()
+          if (!url) {
+            return null
+          }
+        } else {
+          url = fixedOption
+        }
+        if (!url.startsWith('http://') && !url.startsWith('https://')) {
+          if (url === 'localhost' || url.startsWith('localhost:')) {
+            url = `http://${url}`
+          } else {
+            url = `https://${url}`
+          }
+        }
+
+        if (fixedOption === 'custom') {
+          if (!pdsAddressHistory.includes(url)) {
+            const newHistory = [url, ...pdsAddressHistory.slice(0, 4)]
+            setPdsAddressHistory(newHistory)
+            persisted.write('pdsAddressHistory', newHistory)
+          }
+        }
+
+        return url
+      },
+    }),
+    [customAddress, fixedOption, pdsAddressHistory],
+  )
+
+  const isFirstTimeUser = accounts.length === 0
+
+  return (
+    <Dialog.ScrollableInner
+      accessibilityDescribedBy="dialog-description"
+      accessibilityLabelledBy="dialog-title">
+      <View style={[a.relative, a.gap_md, a.w_full]}>
+        <Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}>
+          <Trans>Choose your account provider</Trans>
+        </Text>
+        <ToggleButton.Group
+          label="Preferences"
+          values={[fixedOption]}
+          onChange={values => setFixedOption(values[0])}>
+          <ToggleButton.Button name={BSKY_SERVICE} label={_(msg`Bluesky`)}>
+            <ToggleButton.ButtonText>{_(msg`Bluesky`)}</ToggleButton.ButtonText>
+          </ToggleButton.Button>
+          <ToggleButton.Button
+            testID="customSelectBtn"
+            name="custom"
+            label={_(msg`Custom`)}>
+            <ToggleButton.ButtonText>{_(msg`Custom`)}</ToggleButton.ButtonText>
+          </ToggleButton.Button>
+        </ToggleButton.Group>
+
+        {fixedOption === 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 === 'custom' && (
+          <View
+            style={[
+              a.border,
+              t.atoms.border_contrast_low,
+              a.rounded_sm,
+              a.px_md,
+              a.py_md,
+            ]}>
+            <TextField.LabelText nativeID="address-input-label">
+              <Trans>Server address</Trans>
+            </TextField.LabelText>
+            <TextField.Root>
+              <TextField.Icon icon={Globe} />
+              <Dialog.Input
+                testID="customServerTextInput"
+                value={customAddress}
+                onChangeText={setCustomAddress}
+                label="my-server.com"
+                accessibilityLabelledBy="address-input-label"
+                autoCapitalize="none"
+                keyboardType="url"
+              />
+            </TextField.Root>
+            {pdsAddressHistory.length > 0 && (
+              <View style={[a.flex_row, a.flex_wrap, a.mt_xs]}>
+                {pdsAddressHistory.map(uri => (
+                  <Button
+                    key={uri}
+                    variant="ghost"
+                    color="primary"
+                    label={uri}
+                    style={[a.px_sm, a.py_xs, a.rounded_sm, a.gap_sm]}
+                    onPress={() => setCustomAddress(uri)}>
+                    <ButtonText>{uri}</ButtonText>
+                  </Button>
+                ))}
+              </View>
+            )}
+          </View>
+        )}
+
+        <View style={[a.py_xs]}>
+          <P
+            style={[
+              t.atoms.text_contrast_medium,
+              a.text_sm,
+              a.leading_snug,
+              a.flex_1,
+            ]}>
+            {isFirstTimeUser ? (
               <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.
+                If you're a developer, you can host your own server.
               </Trans>
-            </Admonition>
-          )}
-
-          {fixedOption[0] === 'custom' && (
-            <View
-              style={[
-                a.border,
-                t.atoms.border_contrast_low,
-                a.rounded_sm,
-                a.px_md,
-                a.py_md,
-              ]}>
-              <TextField.LabelText nativeID="address-input-label">
-                <Trans>Server address</Trans>
-              </TextField.LabelText>
-              <TextField.Root>
-                <TextField.Icon icon={Globe} />
-                <Dialog.Input
-                  testID="customServerTextInput"
-                  value={customAddress}
-                  onChangeText={setCustomAddress}
-                  label="my-server.com"
-                  accessibilityLabelledBy="address-input-label"
-                  autoCapitalize="none"
-                  keyboardType="url"
-                />
-              </TextField.Root>
-              {pdsAddressHistory.length > 0 && (
-                <View style={[a.flex_row, a.flex_wrap, a.mt_xs]}>
-                  {pdsAddressHistory.map(uri => (
-                    <Button
-                      key={uri}
-                      variant="ghost"
-                      color="primary"
-                      label={uri}
-                      style={[a.px_sm, a.py_xs, a.rounded_sm, a.gap_sm]}
-                      onPress={() => setCustomAddress(uri)}>
-                      <ButtonText>{uri}</ButtonText>
-                    </Button>
-                  ))}
-                </View>
-              )}
-            </View>
-          )}
-
-          <View style={[a.py_xs]}>
-            <P
-              style={[
-                t.atoms.text_contrast_medium,
-                a.text_sm,
-                a.leading_snug,
-                a.flex_1,
-              ]}>
-              {isFirstTimeUser ? (
-                <Trans>
-                  If you're a developer, you can host your own server.
-                </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
-                label={_(msg`Learn more about self hosting your PDS.`)}
-                to="https://atproto.com/guides/self-hosting">
-                <Trans>Learn more.</Trans>
-              </InlineLinkText>
-            </P>
-          </View>
+            ) : (
+              <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
+              label={_(msg`Learn more about self hosting your PDS.`)}
+              to="https://atproto.com/guides/self-hosting">
+              <Trans>Learn more.</Trans>
+            </InlineLinkText>
+          </P>
+        </View>
 
-          <View style={gtMobile && [a.flex_row, a.justify_end]}>
-            <Button
-              testID="doneBtn"
-              variant="outline"
-              color="primary"
-              size="small"
-              onPress={() => control.close()}
-              label={_(msg`Done`)}>
-              <ButtonText>{_(msg`Done`)}</ButtonText>
-            </Button>
-          </View>
+        <View style={gtMobile && [a.flex_row, a.justify_end]}>
+          <Button
+            testID="doneBtn"
+            variant="outline"
+            color="primary"
+            size="small"
+            onPress={() => control.close()}
+            label={_(msg`Done`)}>
+            <ButtonText>{_(msg`Done`)}</ButtonText>
+          </Button>
         </View>
-      </Dialog.ScrollableInner>
-    </Dialog.Outer>
+      </View>
+    </Dialog.ScrollableInner>
   )
 }