+85
-71
src/screens/StarterPack/Wizard/index.tsx
+85
-71
src/screens/StarterPack/Wizard/index.tsx
···
4
4
import {useSafeAreaInsets} from 'react-native-safe-area-context'
5
5
import {Image} from 'expo-image'
6
6
import {
7
-
AppBskyActorDefs,
8
-
AppBskyGraphDefs,
7
+
type AppBskyActorDefs,
8
+
type AppBskyGraphDefs,
9
9
AtUri,
10
-
ModerationOpts,
10
+
type ModerationOpts,
11
11
} from '@atproto/api'
12
-
import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
12
+
import {type GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs'
13
13
import {msg, Plural, Trans} from '@lingui/macro'
14
14
import {useLingui} from '@lingui/react'
15
15
import {useFocusEffect, useNavigation} from '@react-navigation/native'
16
-
import {NativeStackScreenProps} from '@react-navigation/native-stack'
16
+
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
17
17
18
18
import {STARTER_PACK_MAX_SIZE} from '#/lib/constants'
19
19
import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
20
20
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
21
-
import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
21
+
import {
22
+
type CommonNavigatorParams,
23
+
type NavigationProp,
24
+
} from '#/lib/routes/types'
22
25
import {logEvent} from '#/lib/statsig/statsig'
23
26
import {sanitizeDisplayName} from '#/lib/strings/display-names'
24
27
import {sanitizeHandle} from '#/lib/strings/handles'
···
41
44
import {useSetMinimalShellMode} from '#/state/shell'
42
45
import * as Toast from '#/view/com/util/Toast'
43
46
import {UserAvatar} from '#/view/com/util/UserAvatar'
44
-
import {useWizardState, WizardStep} from '#/screens/StarterPack/Wizard/State'
47
+
import {
48
+
useWizardState,
49
+
type WizardStep,
50
+
} from '#/screens/StarterPack/Wizard/State'
45
51
import {StepDetails} from '#/screens/StarterPack/Wizard/StepDetails'
46
52
import {StepFeeds} from '#/screens/StarterPack/Wizard/StepFeeds'
47
53
import {StepProfiles} from '#/screens/StarterPack/Wizard/StepProfiles'
48
54
import {atoms as a, useTheme, web} from '#/alf'
49
-
import {Button, ButtonText} from '#/components/Button'
55
+
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
50
56
import {useDialogControl} from '#/components/Dialog'
51
57
import * as Layout from '#/components/Layout'
52
58
import {ListMaybePlaceholder} from '#/components/Lists'
53
59
import {Loader} from '#/components/Loader'
54
60
import {WizardEditListDialog} from '#/components/StarterPack/Wizard/WizardEditListDialog'
55
61
import {Text} from '#/components/Typography'
56
-
import * as bsky from '#/types/bsky'
62
+
import type * as bsky from '#/types/bsky'
57
63
import {Provider} from './State'
58
64
59
65
export function Wizard({
···
279
285
)
280
286
}
281
287
288
+
const items =
289
+
state.currentStep === 'Profiles'
290
+
? [profile, ...state.profiles]
291
+
: state.feeds
292
+
293
+
const isEditEnabled =
294
+
(state.currentStep === 'Profiles' && items.length > 1) ||
295
+
(state.currentStep === 'Feeds' && items.length > 0)
296
+
297
+
const editDialogControl = useDialogControl()
298
+
282
299
return (
283
300
<Layout.Center style={[a.flex_1]}>
284
301
<Layout.Header.Outer>
···
292
309
}
293
310
}}
294
311
/>
295
-
<Layout.Header.Content>
312
+
<Layout.Header.Content align="left">
296
313
<Layout.Header.TitleText>
297
314
{currUiStrings.header}
298
315
</Layout.Header.TitleText>
299
316
</Layout.Header.Content>
300
-
<Layout.Header.Slot />
317
+
{isEditEnabled ? (
318
+
<Button
319
+
label={_(msg`Edit`)}
320
+
color="secondary"
321
+
size="small"
322
+
onPress={editDialogControl.open}>
323
+
<ButtonText>
324
+
<Trans>Edit</Trans>
325
+
</ButtonText>
326
+
</Button>
327
+
) : (
328
+
<Layout.Header.Slot />
329
+
)}
301
330
</Layout.Header.Outer>
302
331
303
332
<Container>
···
314
343
<Footer
315
344
onNext={onNext}
316
345
nextBtnText={currUiStrings.nextBtn}
317
-
moderationOpts={moderationOpts}
318
346
profile={profile}
319
347
/>
320
348
)}
349
+
<WizardEditListDialog
350
+
control={editDialogControl}
351
+
state={state}
352
+
dispatch={dispatch}
353
+
moderationOpts={moderationOpts}
354
+
profile={profile}
355
+
/>
321
356
</Layout.Center>
322
357
)
323
358
}
···
357
392
function Footer({
358
393
onNext,
359
394
nextBtnText,
360
-
moderationOpts,
361
395
profile,
362
396
}: {
363
397
onNext: () => void
364
398
nextBtnText: string
365
-
moderationOpts: ModerationOpts
366
399
profile: AppBskyActorDefs.ProfileViewDetailed
367
400
}) {
368
-
const {_} = useLingui()
369
401
const t = useTheme()
370
-
const [state, dispatch] = useWizardState()
371
-
const editDialogControl = useDialogControl()
402
+
const [state] = useWizardState()
372
403
const {bottom: bottomInset} = useSafeAreaInsets()
373
404
374
405
const items =
···
376
407
? [profile, ...state.profiles]
377
408
: state.feeds
378
409
379
-
const isEditEnabled =
380
-
(state.currentStep === 'Profiles' && items.length > 1) ||
381
-
(state.currentStep === 'Feeds' && items.length > 0)
382
-
383
410
const minimumItems = state.currentStep === 'Profiles' ? 8 : 0
384
411
385
412
const textStyles = [a.text_md]
···
416
443
</View>
417
444
)}
418
445
419
-
<View style={[a.flex_row, a.gap_xs]}>
446
+
<View style={[a.flex_row]}>
420
447
{items.slice(0, 6).map((p, index) => (
421
-
<UserAvatar
448
+
<View
422
449
key={index}
423
-
avatar={p.avatar}
424
-
size={32}
425
-
type={state.currentStep === 'Profiles' ? 'user' : 'algo'}
426
-
/>
450
+
style={[
451
+
a.rounded_full,
452
+
{
453
+
borderWidth: 0.5,
454
+
borderColor: t.atoms.bg.backgroundColor,
455
+
},
456
+
state.currentStep === 'Profiles'
457
+
? {zIndex: 1 - index, marginLeft: index > 0 ? -8 : 0}
458
+
: {marginRight: 4},
459
+
]}>
460
+
<UserAvatar
461
+
avatar={p.avatar}
462
+
size={32}
463
+
type={state.currentStep === 'Profiles' ? 'user' : 'algo'}
464
+
/>
465
+
</View>
427
466
))}
428
467
</View>
429
468
···
523
562
524
563
<View
525
564
style={[
526
-
a.flex_row,
527
565
a.w_full,
528
-
a.justify_between,
529
566
a.align_center,
567
+
a.gap_2xl,
530
568
isNative ? a.mt_sm : a.mt_md,
531
569
]}>
532
-
{isEditEnabled ? (
533
-
<Button
534
-
label={_(msg`Edit`)}
535
-
variant="solid"
536
-
color="secondary"
537
-
size="small"
538
-
style={{width: 70}}
539
-
onPress={editDialogControl.open}>
540
-
<ButtonText>
541
-
<Trans>Edit</Trans>
542
-
</ButtonText>
543
-
</Button>
544
-
) : (
545
-
<View style={{width: 70, height: 35}} />
570
+
{state.currentStep === 'Profiles' && items.length < 8 && (
571
+
<Text style={[a.font_bold, textStyles, t.atoms.text_contrast_medium]}>
572
+
<Trans>Add {8 - items.length} more to continue</Trans>
573
+
</Text>
546
574
)}
547
-
{state.currentStep === 'Profiles' && items.length < 8 ? (
548
-
<>
549
-
<Text
550
-
style={[a.font_bold, textStyles, t.atoms.text_contrast_medium]}>
551
-
<Trans>Add {8 - items.length} more to continue</Trans>
552
-
</Text>
553
-
<View style={{width: 70}} />
554
-
</>
555
-
) : (
556
-
<Button
557
-
label={nextBtnText}
558
-
variant="solid"
559
-
color="primary"
560
-
size="small"
561
-
onPress={onNext}
562
-
disabled={!state.canNext || state.processing}>
563
-
<ButtonText>{nextBtnText}</ButtonText>
564
-
{state.processing && <Loader size="xs" style={{color: 'white'}} />}
565
-
</Button>
566
-
)}
575
+
<Button
576
+
label={nextBtnText}
577
+
style={[a.w_full, a.py_md, a.px_2xl]}
578
+
color="primary"
579
+
size="large"
580
+
onPress={onNext}
581
+
disabled={
582
+
!state.canNext ||
583
+
state.processing ||
584
+
(state.currentStep === 'Profiles' && items.length < 8)
585
+
}>
586
+
<ButtonText>{nextBtnText}</ButtonText>
587
+
{state.processing && <ButtonIcon icon={Loader} />}
588
+
</Button>
567
589
</View>
568
-
569
-
<WizardEditListDialog
570
-
control={editDialogControl}
571
-
state={state}
572
-
dispatch={dispatch}
573
-
moderationOpts={moderationOpts}
574
-
profile={profile}
575
-
/>
576
590
</View>
577
591
)
578
592
}