about summary refs log tree commit diff
path: root/src/components/StarterPack/Wizard/WizardListCard.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/StarterPack/Wizard/WizardListCard.tsx')
-rw-r--r--src/components/StarterPack/Wizard/WizardListCard.tsx182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/components/StarterPack/Wizard/WizardListCard.tsx b/src/components/StarterPack/Wizard/WizardListCard.tsx
new file mode 100644
index 000000000..f1332011d
--- /dev/null
+++ b/src/components/StarterPack/Wizard/WizardListCard.tsx
@@ -0,0 +1,182 @@
+import React from 'react'
+import {Keyboard, View} from 'react-native'
+import {
+  AppBskyActorDefs,
+  AppBskyFeedDefs,
+  moderateFeedGenerator,
+  moderateProfile,
+  ModerationOpts,
+  ModerationUI,
+} from '@atproto/api'
+import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {DISCOVER_FEED_URI} from 'lib/constants'
+import {sanitizeDisplayName} from 'lib/strings/display-names'
+import {sanitizeHandle} from 'lib/strings/handles'
+import {useSession} from 'state/session'
+import {UserAvatar} from 'view/com/util/UserAvatar'
+import {WizardAction, WizardState} from '#/screens/StarterPack/Wizard/State'
+import {atoms as a, useTheme} from '#/alf'
+import * as Toggle from '#/components/forms/Toggle'
+import {Checkbox} from '#/components/forms/Toggle'
+import {Text} from '#/components/Typography'
+
+function WizardListCard({
+  type,
+  displayName,
+  subtitle,
+  onPress,
+  avatar,
+  included,
+  disabled,
+  moderationUi,
+}: {
+  type: 'user' | 'algo'
+  profile?: AppBskyActorDefs.ProfileViewBasic
+  feed?: AppBskyFeedDefs.GeneratorView
+  displayName: string
+  subtitle: string
+  onPress: () => void
+  avatar?: string
+  included?: boolean
+  disabled?: boolean
+  moderationUi: ModerationUI
+}) {
+  const t = useTheme()
+  const {_} = useLingui()
+
+  return (
+    <Toggle.Item
+      name={type === 'user' ? _(msg`Person toggle`) : _(msg`Feed toggle`)}
+      label={
+        included
+          ? _(msg`Remove ${displayName} from starter pack`)
+          : _(msg`Add ${displayName} to starter pack`)
+      }
+      value={included}
+      disabled={disabled}
+      onChange={onPress}
+      style={[
+        a.flex_row,
+        a.align_center,
+        a.px_lg,
+        a.py_md,
+        a.gap_md,
+        a.border_b,
+        t.atoms.border_contrast_low,
+      ]}>
+      <UserAvatar
+        size={45}
+        avatar={avatar}
+        moderation={moderationUi}
+        type={type}
+      />
+      <View style={[a.flex_1, a.gap_2xs]}>
+        <Text
+          style={[a.flex_1, a.font_bold, a.text_md, a.leading_tight]}
+          numberOfLines={1}>
+          {displayName}
+        </Text>
+        <Text
+          style={[a.flex_1, a.leading_tight, t.atoms.text_contrast_medium]}
+          numberOfLines={1}>
+          {subtitle}
+        </Text>
+      </View>
+      <Checkbox />
+    </Toggle.Item>
+  )
+}
+
+export function WizardProfileCard({
+  state,
+  dispatch,
+  profile,
+  moderationOpts,
+}: {
+  state: WizardState
+  dispatch: (action: WizardAction) => void
+  profile: AppBskyActorDefs.ProfileViewBasic
+  moderationOpts: ModerationOpts
+}) {
+  const {currentAccount} = useSession()
+
+  const isMe = profile.did === currentAccount?.did
+  const included = isMe || state.profiles.some(p => p.did === profile.did)
+  const disabled = isMe || (!included && state.profiles.length >= 49)
+  const moderationUi = moderateProfile(profile, moderationOpts).ui('avatar')
+  const displayName = profile.displayName
+    ? sanitizeDisplayName(profile.displayName)
+    : `@${sanitizeHandle(profile.handle)}`
+
+  const onPress = () => {
+    if (disabled) return
+
+    Keyboard.dismiss()
+    if (profile.did === currentAccount?.did) return
+
+    if (!included) {
+      dispatch({type: 'AddProfile', profile})
+    } else {
+      dispatch({type: 'RemoveProfile', profileDid: profile.did})
+    }
+  }
+
+  return (
+    <WizardListCard
+      type="user"
+      displayName={displayName}
+      subtitle={`@${sanitizeHandle(profile.handle)}`}
+      onPress={onPress}
+      avatar={profile.avatar}
+      included={included}
+      disabled={disabled}
+      moderationUi={moderationUi}
+    />
+  )
+}
+
+export function WizardFeedCard({
+  generator,
+  state,
+  dispatch,
+  moderationOpts,
+}: {
+  generator: GeneratorView
+  state: WizardState
+  dispatch: (action: WizardAction) => void
+  moderationOpts: ModerationOpts
+}) {
+  const isDiscover = generator.uri === DISCOVER_FEED_URI
+  const included = isDiscover || state.feeds.some(f => f.uri === generator.uri)
+  const disabled = isDiscover || (!included && state.feeds.length >= 3)
+  const moderationUi = moderateFeedGenerator(generator, moderationOpts).ui(
+    'avatar',
+  )
+
+  const onPress = () => {
+    if (disabled) return
+
+    Keyboard.dismiss()
+    if (included) {
+      dispatch({type: 'RemoveFeed', feedUri: generator.uri})
+    } else {
+      dispatch({type: 'AddFeed', feed: generator})
+    }
+  }
+
+  return (
+    <WizardListCard
+      type="algo"
+      displayName={sanitizeDisplayName(generator.displayName)}
+      subtitle={`Feed by @${sanitizeHandle(generator.creator.handle)}`}
+      onPress={onPress}
+      avatar={generator.avatar}
+      included={included}
+      disabled={disabled}
+      moderationUi={moderationUi}
+    />
+  )
+}