diff --git a/src/components/StarterPack/Wizard/WizardAddDialog.tsx b/src/components/StarterPack/Wizard/WizardAddDialog.tsx deleted file mode 100644 index 1dec85da28..0000000000 --- a/src/components/StarterPack/Wizard/WizardAddDialog.tsx +++ /dev/null @@ -1,281 +0,0 @@ -import React, {useLayoutEffect, useRef, useState} from 'react' -import type {ListRenderItemInfo, TextInput as RNTextInput} from 'react-native' -import {View} from 'react-native' -import {AppBskyActorDefs} from '@atproto/api' -import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' -import {BottomSheetFlatListMethods} from '@discord/bottom-sheet' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import debounce from 'lodash.debounce' - -import {isWeb} from 'platform/detection' -import {useActorAutocompleteQuery} from 'state/queries/actor-autocomplete' -import { - useGetPopularFeedsQuery, - useSearchPopularFeedsMutation, -} from 'state/queries/feed' -import {useProfileFollowsQuery} from 'state/queries/profile-follows' -import {useSession} from 'state/session' -import {WizardAction, WizardState} from '#/screens/StarterPack/Wizard/State' -import {atoms as a, native, useTheme, web} from '#/alf' -import * as Dialog from '#/components/Dialog' -import {TextInput} from '#/components/dms/dialogs/TextInput' -import {useInteractionState} from '#/components/hooks/useInteractionState' -import {MagnifyingGlass2_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass2' -import {WizardFeedCard} from '#/components/StarterPack/Wizard/WizardFeedCard' -import {WizardProfileCard} from '#/components/StarterPack/Wizard/WizardProfileCard' -import {Text} from '#/components/Typography' - -interface Props { - control: Dialog.DialogControlProps - type: 'profiles' | 'feeds' - state: WizardState - dispatch: (action: WizardAction) => void -} - -function keyExtractor( - item: AppBskyActorDefs.ProfileViewBasic | GeneratorView, - index: number, -) { - return `${item.did}-${index}` -} - -export function WizardAddDialog(props: Props) { - if (props.type === 'profiles') { - return - } - return -} - -function AddProfiles(props: Props) { - const [searchText, setSearchText] = useState('') - - const {currentAccount} = useSession() - const {data: followsPages, fetchNextPage} = useProfileFollowsQuery( - currentAccount?.did, - ) - const follows = followsPages?.pages.flatMap(page => page.follows) || [] - - const {data: searchedProfiles} = useActorAutocompleteQuery( - searchText, - true, - 12, - ) - - return ( - fetchNextPage()} - searchText={searchText} - setSearchText={setSearchText} - /> - ) -} - -function AddFeeds(props: Props) { - const [searchText, setSearchText] = useState('') - - const {data: popularFeedsPages, fetchNextPage} = useGetPopularFeedsQuery() - - const popularFeeds = - popularFeedsPages?.pages.flatMap(page => page.feeds) || [] - - const { - data: searchedFeeds, - mutate: search, - reset: resetSearch, - } = useSearchPopularFeedsMutation() - - const debouncedSearch = React.useMemo( - () => debounce(q => search(q), 500), // debounce for 500ms - [search], - ) - - const onChangeText = (text: string) => { - setSearchText(text) - if (text.length > 1) { - debouncedSearch(text) - } else { - resetSearch() - } - } - - return ( - fetchNextPage()} - searchText={searchText} - setSearchText={onChangeText} - /> - ) -} - -function AddDialog({ - type, - control, - state, - dispatch, - data, - onEndReached, - searchText, - setSearchText, -}: Props & { - data?: AppBskyActorDefs.ProfileViewBasic[] | GeneratorView[] - onEndReached?: () => void - searchText: string - setSearchText: (text: string) => void -}) { - const listRef = useRef(null) - const inputRef = useRef(null) - - useLayoutEffect(() => { - if (isWeb) { - setImmediate(() => { - inputRef?.current?.focus() - }) - } - }, []) - - const renderItem = ({item}: ListRenderItemInfo) => - type === 'profiles' ? ( - - ) : ( - - ) - - return ( - - - } - stickyHeaderIndices={[0]} - style={[ - web([a.py_0, {height: '100vh', maxHeight: 600}, a.px_0]), - native({ - height: '100%', - paddingHorizontal: 0, - marginTop: 0, - paddingTop: 0, - borderTopLeftRadius: 40, - borderTopRightRadius: 40, - }), - ]} - webInnerStyle={[a.py_0, {maxWidth: 500, minWidth: 200}]} - keyboardDismissMode="on-drag" - onEndReached={onEndReached} - onEndReachedThreshold={2} - removeClippedSubviews={true} - /> - - ) -} - -function ListHeader({ - type, - searchText, - setSearchText, - inputRef, -}: { - type: 'profiles' | 'feeds' - searchText: string - setSearchText: (text: string) => void - inputRef: React.Ref -}) { - const t = useTheme() - const {_} = useLingui() - const { - state: hovered, - onIn: onMouseEnter, - onOut: onMouseLeave, - } = useInteractionState() - const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() - const interacted = hovered || focused - - return ( - - - - {type === 'profiles' ? ( - Select profiles to add - ) : ( - Select feeds to add - )} - - - - - - - - - - - - ) -} diff --git a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx new file mode 100644 index 0000000000..7d6d24b0c0 --- /dev/null +++ b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx @@ -0,0 +1,103 @@ +import React, {useLayoutEffect, useRef} from 'react' +import type {ListRenderItemInfo, TextInput as RNTextInput} from 'react-native' +import {View} from 'react-native' +import {AppBskyActorDefs} from '@atproto/api' +import {GeneratorView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' +import {BottomSheetFlatListMethods} from '@discord/bottom-sheet' +import {Trans} from '@lingui/macro' + +import {isWeb} from 'platform/detection' +import {WizardAction, WizardState} from '#/screens/StarterPack/Wizard/State' +import {atoms as a, native, useTheme, web} from '#/alf' +import * as Dialog from '#/components/Dialog' +import {WizardFeedCard} from '#/components/StarterPack/Wizard/WizardFeedCard' +import {WizardProfileCard} from '#/components/StarterPack/Wizard/WizardProfileCard' +import {Text} from '#/components/Typography' + +function keyExtractor( + item: AppBskyActorDefs.ProfileViewBasic | GeneratorView, + index: number, +) { + return `${item.did}-${index}` +} + +export function WizardEditListDialog({ + control, + state, + dispatch, +}: { + control: Dialog.DialogControlProps + state: WizardState + dispatch: (action: WizardAction) => void +}) { + const t = useTheme() + + const listRef = useRef(null) + const inputRef = useRef(null) + + useLayoutEffect(() => { + if (isWeb) { + setImmediate(() => { + inputRef?.current?.focus() + }) + } + }, []) + + const renderItem = ({item}: ListRenderItemInfo) => + state.currentStep === 'Profiles' ? ( + + ) : ( + + ) + + return ( + + + + + {state.currentStep === 'Profiles' ? ( + Edit Profiles + ) : ( + Edit Feeds + )} + + + } + stickyHeaderIndices={[0]} + style={[ + web([a.py_0, {height: '100vh', maxHeight: 600}, a.px_0]), + native({ + height: '100%', + paddingHorizontal: 0, + marginTop: 0, + paddingTop: 0, + borderTopLeftRadius: 40, + borderTopRightRadius: 40, + }), + ]} + webInnerStyle={[a.py_0, {maxWidth: 500, minWidth: 200}]} + keyboardDismissMode="on-drag" + removeClippedSubviews={true} + /> + + ) +} diff --git a/src/screens/StarterPack/Wizard/StepFeeds.tsx b/src/screens/StarterPack/Wizard/StepFeeds.tsx index fca9afe3d7..69bdf0f6ec 100644 --- a/src/screens/StarterPack/Wizard/StepFeeds.tsx +++ b/src/screens/StarterPack/Wizard/StepFeeds.tsx @@ -12,6 +12,7 @@ import {SearchInput} from 'view/com/util/forms/SearchInput' import {List} from 'view/com/util/List' import {useWizardState} from '#/screens/StarterPack/Wizard/State' import {atoms as a} from '#/alf' +import {Loader} from '#/components/Loader' import {WizardFeedCard} from '#/components/StarterPack/Wizard/WizardFeedCard' function keyExtractor(item: GeneratorView) { @@ -69,6 +70,11 @@ export function StepFeeds() { onEndReached={!query ? () => fetchNextPage() : undefined} onEndReachedThreshold={2} renderScrollComponent={props => } + ListEmptyComponent={ + + + + } /> ) diff --git a/src/screens/StarterPack/Wizard/StepProfiles.tsx b/src/screens/StarterPack/Wizard/StepProfiles.tsx index d134f8f4e8..ac8ae37ad6 100644 --- a/src/screens/StarterPack/Wizard/StepProfiles.tsx +++ b/src/screens/StarterPack/Wizard/StepProfiles.tsx @@ -10,6 +10,7 @@ import {SearchInput} from 'view/com/util/forms/SearchInput' import {List} from 'view/com/util/List' import {useWizardState} from '#/screens/StarterPack/Wizard/State' import {atoms as a} from '#/alf' +import {Loader} from '#/components/Loader' import {WizardProfileCard} from '#/components/StarterPack/Wizard/WizardProfileCard' function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic) { @@ -57,6 +58,11 @@ export function StepProfiles() { onEndReached={!query ? () => fetchNextPage() : undefined} onEndReachedThreshold={2} renderScrollComponent={props => } + ListEmptyComponent={ + + + + } /> ) diff --git a/src/screens/StarterPack/Wizard/index.tsx b/src/screens/StarterPack/Wizard/index.tsx index 254e029b5a..7d5baaeaa8 100644 --- a/src/screens/StarterPack/Wizard/index.tsx +++ b/src/screens/StarterPack/Wizard/index.tsx @@ -23,7 +23,7 @@ import {StepProfiles} from '#/screens/StarterPack/Wizard/StepProfiles' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonText} from '#/components/Button' import {useDialogControl} from '#/components/Dialog' -import {WizardAddDialog} from '#/components/StarterPack/Wizard/WizardAddDialog' +import {WizardEditListDialog} from '#/components/StarterPack/Wizard/WizardEditListDialog' import {Text} from '#/components/Typography' import {Provider} from './State' @@ -81,7 +81,6 @@ function WizardInner() { did: currentAccount?.did, staleTime: 0, }) - const addDialogControl = useDialogControl() const setMinimalShellMode = useSetMinimalShellMode() @@ -200,15 +199,6 @@ function WizardInner() { ) : (