about summary refs log tree commit diff
path: root/src/view
diff options
context:
space:
mode:
Diffstat (limited to 'src/view')
-rw-r--r--src/view/com/modals/InviteCodes.tsx27
-rw-r--r--src/view/screens/Settings.tsx70
-rw-r--r--src/view/shell/Drawer.tsx54
-rw-r--r--src/view/shell/desktop/RightNav.tsx72
4 files changed, 137 insertions, 86 deletions
diff --git a/src/view/com/modals/InviteCodes.tsx b/src/view/com/modals/InviteCodes.tsx
index 09cfd4de7..0cb0c56aa 100644
--- a/src/view/com/modals/InviteCodes.tsx
+++ b/src/view/com/modals/InviteCodes.tsx
@@ -26,6 +26,33 @@ export function Component({}: {}) {
     store.shell.closeModal()
   }, [store])
 
+  if (store.me.invites === null) {
+    return (
+      <View style={[styles.container, pal.view]} testID="inviteCodesModal">
+        <Text type="title-xl" style={[styles.title, pal.text]}>
+          Error
+        </Text>
+        <Text type="lg" style={[styles.description, pal.text]}>
+          An error occurred while loading invite codes.
+        </Text>
+        <View style={styles.flex1} />
+        <View
+          style={[
+            styles.btnContainer,
+            isTabletOrDesktop && styles.btnContainerDesktop,
+          ]}>
+          <Button
+            type="primary"
+            label="Done"
+            style={styles.btn}
+            labelStyle={styles.btnLabel}
+            onPress={onClose}
+          />
+        </View>
+      </View>
+    )
+  }
+
   if (store.me.invites.length === 0) {
     return (
       <View style={[styles.container, pal.view]} testID="inviteCodesModal">
diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx
index 2112ec7d1..f75222c1f 100644
--- a/src/view/screens/Settings.tsx
+++ b/src/view/screens/Settings.tsx
@@ -322,37 +322,45 @@ export const SettingsScreen = withAuthRequired(
 
           <View style={styles.spacer20} />
 
-          <Text type="xl-bold" style={[pal.text, styles.heading]}>
-            Invite a Friend
-          </Text>
-          <TouchableOpacity
-            testID="inviteFriendBtn"
-            style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
-            onPress={isSwitching ? undefined : onPressInviteCodes}
-            accessibilityRole="button"
-            accessibilityLabel="Invite"
-            accessibilityHint="Opens invite code list">
-            <View
-              style={[
-                styles.iconContainer,
-                store.me.invitesAvailable > 0 ? primaryBg : pal.btn,
-              ]}>
-              <FontAwesomeIcon
-                icon="ticket"
-                style={
-                  (store.me.invitesAvailable > 0
-                    ? primaryText
-                    : pal.text) as FontAwesomeIconStyle
-                }
-              />
-            </View>
-            <Text
-              type="lg"
-              style={store.me.invitesAvailable > 0 ? pal.link : pal.text}>
-              {formatCount(store.me.invitesAvailable)} invite{' '}
-              {pluralize(store.me.invitesAvailable, 'code')} available
-            </Text>
-          </TouchableOpacity>
+          {store.me.invitesAvailable !== null && (
+            <>
+              <Text type="xl-bold" style={[pal.text, styles.heading]}>
+                Invite a Friend
+              </Text>
+              <TouchableOpacity
+                testID="inviteFriendBtn"
+                style={[
+                  styles.linkCard,
+                  pal.view,
+                  isSwitching && styles.dimmed,
+                ]}
+                onPress={isSwitching ? undefined : onPressInviteCodes}
+                accessibilityRole="button"
+                accessibilityLabel="Invite"
+                accessibilityHint="Opens invite code list">
+                <View
+                  style={[
+                    styles.iconContainer,
+                    store.me.invitesAvailable > 0 ? primaryBg : pal.btn,
+                  ]}>
+                  <FontAwesomeIcon
+                    icon="ticket"
+                    style={
+                      (store.me.invitesAvailable > 0
+                        ? primaryText
+                        : pal.text) as FontAwesomeIconStyle
+                    }
+                  />
+                </View>
+                <Text
+                  type="lg"
+                  style={store.me.invitesAvailable > 0 ? pal.link : pal.text}>
+                  {formatCount(store.me.invitesAvailable)} invite{' '}
+                  {pluralize(store.me.invitesAvailable, 'code')} available
+                </Text>
+              </TouchableOpacity>
+            </>
+          )}
 
           <View style={styles.spacer20} />
 
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index 51a846c4a..48341170c 100644
--- a/src/view/shell/Drawer.tsx
+++ b/src/view/shell/Drawer.tsx
@@ -426,32 +426,34 @@ const InviteCodes = observer(function InviteCodesImpl({
     store.shell.openModal({name: 'invite-codes'})
   }, [store, track])
   return (
-    <TouchableOpacity
-      testID="menuItemInviteCodes"
-      style={[styles.inviteCodes, style]}
-      onPress={onPress}
-      accessibilityRole="button"
-      accessibilityLabel={
-        invitesAvailable === 1
-          ? 'Invite codes: 1 available'
-          : `Invite codes: ${invitesAvailable} available`
-      }
-      accessibilityHint="Opens list of invite codes">
-      <FontAwesomeIcon
-        icon="ticket"
-        style={[
-          styles.inviteCodesIcon,
-          store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
-        ]}
-        size={18}
-      />
-      <Text
-        type="lg-medium"
-        style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
-        {formatCount(store.me.invitesAvailable)} invite{' '}
-        {pluralize(store.me.invitesAvailable, 'code')}
-      </Text>
-    </TouchableOpacity>
+    store.me.invitesAvailable !== null && (
+      <TouchableOpacity
+        testID="menuItemInviteCodes"
+        style={[styles.inviteCodes, style]}
+        onPress={onPress}
+        accessibilityRole="button"
+        accessibilityLabel={
+          invitesAvailable === 1
+            ? 'Invite codes: 1 available'
+            : `Invite codes: ${invitesAvailable} available`
+        }
+        accessibilityHint="Opens list of invite codes">
+        <FontAwesomeIcon
+          icon="ticket"
+          style={[
+            styles.inviteCodesIcon,
+            store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
+          ]}
+          size={18}
+        />
+        <Text
+          type="lg-medium"
+          style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
+          {formatCount(store.me.invitesAvailable)} invite{' '}
+          {pluralize(store.me.invitesAvailable, 'code')}
+        </Text>
+      </TouchableOpacity>
+    )
   )
 })
 
diff --git a/src/view/shell/desktop/RightNav.tsx b/src/view/shell/desktop/RightNav.tsx
index 84d7d7854..f0e986bf4 100644
--- a/src/view/shell/desktop/RightNav.tsx
+++ b/src/view/shell/desktop/RightNav.tsx
@@ -7,6 +7,7 @@ import {DesktopSearch} from './Search'
 import {DesktopFeeds} from './Feeds'
 import {Text} from 'view/com/util/text/Text'
 import {TextLink} from 'view/com/util/Link'
+import {LoadingPlaceholder} from 'view/com/util/LoadingPlaceholder'
 import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
 import {s} from 'lib/styles'
 import {useStores} from 'state/index'
@@ -89,32 +90,41 @@ const InviteCodes = observer(function InviteCodesImpl() {
   const onPress = React.useCallback(() => {
     store.shell.openModal({name: 'invite-codes'})
   }, [store])
+
   return (
-    <TouchableOpacity
-      style={[styles.inviteCodes, pal.border]}
-      onPress={onPress}
-      accessibilityRole="button"
-      accessibilityLabel={
-        invitesAvailable === 1
-          ? 'Invite codes: 1 available'
-          : `Invite codes: ${invitesAvailable} available`
-      }
-      accessibilityHint="Opens list of invite codes">
-      <FontAwesomeIcon
-        icon="ticket"
-        style={[
-          styles.inviteCodesIcon,
-          store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
-        ]}
-        size={16}
-      />
-      <Text
-        type="md-medium"
-        style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
-        {formatCount(store.me.invitesAvailable)} invite{' '}
-        {pluralize(store.me.invitesAvailable, 'code')} available
-      </Text>
-    </TouchableOpacity>
+    <View style={[styles.separator, pal.border]}>
+      {store.me.invitesAvailable === null ? (
+        <View style={[s.p10]}>
+          <LoadingPlaceholder width={186} height={32} style={[styles.br40]} />
+        </View>
+      ) : (
+        <TouchableOpacity
+          style={[styles.inviteCodes]}
+          onPress={onPress}
+          accessibilityRole="button"
+          accessibilityLabel={
+            invitesAvailable === 1
+              ? 'Invite codes: 1 available'
+              : `Invite codes: ${invitesAvailable} available`
+          }
+          accessibilityHint="Opens list of invite codes">
+          <FontAwesomeIcon
+            icon="ticket"
+            style={[
+              styles.inviteCodesIcon,
+              store.me.invitesAvailable > 0 ? pal.link : pal.textLight,
+            ]}
+            size={16}
+          />
+          <Text
+            type="md-medium"
+            style={store.me.invitesAvailable > 0 ? pal.link : pal.textLight}>
+            {formatCount(store.me.invitesAvailable)} invite{' '}
+            {pluralize(store.me.invitesAvailable, 'code')} available
+          </Text>
+        </TouchableOpacity>
+      )}
+    </View>
   )
 })
 
@@ -131,16 +141,20 @@ const styles = StyleSheet.create({
 
   message: {
     paddingVertical: 18,
-    paddingHorizontal: 10,
+    paddingHorizontal: 12,
   },
   messageLine: {
     marginBottom: 10,
   },
 
-  inviteCodes: {
+  separator: {
     borderTopWidth: 1,
-    paddingHorizontal: 16,
-    paddingVertical: 12,
+  },
+  br40: {borderRadius: 40},
+
+  inviteCodes: {
+    paddingHorizontal: 12,
+    paddingVertical: 16,
     flexDirection: 'row',
     alignItems: 'center',
   },