diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/composer/threadgate/ThreadgateBtn.tsx | 50 | ||||
-rw-r--r-- | src/view/com/modals/Modal.tsx | 4 | ||||
-rw-r--r-- | src/view/com/modals/Modal.web.tsx | 3 | ||||
-rw-r--r-- | src/view/com/modals/Threadgate.tsx | 208 |
4 files changed, 29 insertions, 236 deletions
diff --git a/src/view/com/composer/threadgate/ThreadgateBtn.tsx b/src/view/com/composer/threadgate/ThreadgateBtn.tsx index 2aefdfbbf..6cf2eea2c 100644 --- a/src/view/com/composer/threadgate/ThreadgateBtn.tsx +++ b/src/view/com/composer/threadgate/ThreadgateBtn.tsx @@ -5,11 +5,12 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {isNative} from '#/platform/detection' -import {useModalControls} from '#/state/modals' import {ThreadgateSetting} from '#/state/queries/threadgate' import {useAnalytics} from 'lib/analytics/analytics' import {atoms as a, useTheme} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import * as Dialog from '#/components/Dialog' +import {ThreadgateEditorDialog} from '#/components/dialogs/ThreadgateEditor' import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign' import {Earth_Stroke2_Corner0_Rounded as Earth} from '#/components/icons/Globe' import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group' @@ -26,18 +27,15 @@ export function ThreadgateBtn({ const {track} = useAnalytics() const {_} = useLingui() const t = useTheme() - const {openModal} = useModalControls() + const control = Dialog.useDialogControl() const onPress = () => { track('Composer:ThreadgateOpened') if (isNative && Keyboard.isVisible()) { Keyboard.dismiss() } - openModal({ - name: 'threadgate', - settings: threadgate, - onChange, - }) + + control.open() } const isEverybody = threadgate.length === 0 @@ -49,19 +47,29 @@ export function ThreadgateBtn({ : _(msg`Some people can reply`) return ( - <Animated.View style={[a.flex_row, a.p_sm, t.atoms.bg, style]}> - <Button - variant="solid" - color="secondary" - size="xsmall" - testID="openReplyGateButton" - onPress={onPress} - label={label}> - <ButtonIcon - icon={isEverybody ? Earth : isNobody ? CircleBanSign : Group} - /> - <ButtonText>{label}</ButtonText> - </Button> - </Animated.View> + <> + <Animated.View style={[a.flex_row, a.p_sm, t.atoms.bg, style]}> + <Button + variant="solid" + color="secondary" + size="xsmall" + testID="openReplyGateButton" + onPress={onPress} + label={label} + accessibilityHint={_( + msg`Opens a dialog to choose who can reply to this thread`, + )}> + <ButtonIcon + icon={isEverybody ? Earth : isNobody ? CircleBanSign : Group} + /> + <ButtonText>{label}</ButtonText> + </Button> + </Animated.View> + <ThreadgateEditorDialog + control={control} + threadgate={threadgate} + onChange={onChange} + /> + </> ) } diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index ecfe5806e..3455e1cdf 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -23,7 +23,6 @@ import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettin import * as LinkWarningModal from './LinkWarning' import * as ListAddUserModal from './ListAddRemoveUsers' import * as SelfLabelModal from './SelfLabel' -import * as ThreadgateModal from './Threadgate' import * as UserAddRemoveListsModal from './UserAddRemoveLists' import * as VerifyEmailModal from './VerifyEmail' @@ -76,9 +75,6 @@ export function ModalsContainer() { } else if (activeModal?.name === 'self-label') { snapPoints = SelfLabelModal.snapPoints element = <SelfLabelModal.Component {...activeModal} /> - } else if (activeModal?.name === 'threadgate') { - snapPoints = ThreadgateModal.snapPoints - element = <ThreadgateModal.Component {...activeModal} /> } else if (activeModal?.name === 'alt-text-image') { snapPoints = AltImageModal.snapPoints element = <AltImageModal.Component {...activeModal} /> diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx index 14ee99e57..c4bab6fb1 100644 --- a/src/view/com/modals/Modal.web.tsx +++ b/src/view/com/modals/Modal.web.tsx @@ -23,7 +23,6 @@ import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettin import * as LinkWarningModal from './LinkWarning' import * as ListAddUserModal from './ListAddRemoveUsers' import * as SelfLabelModal from './SelfLabel' -import * as ThreadgateModal from './Threadgate' import * as UserAddRemoveLists from './UserAddRemoveLists' import * as VerifyEmailModal from './VerifyEmail' @@ -84,8 +83,6 @@ function Modal({modal}: {modal: ModalIface}) { element = <DeleteAccountModal.Component /> } else if (modal.name === 'self-label') { element = <SelfLabelModal.Component {...modal} /> - } else if (modal.name === 'threadgate') { - element = <ThreadgateModal.Component {...modal} /> } else if (modal.name === 'change-handle') { element = <ChangeHandleModal.Component {...modal} /> } else if (modal.name === 'invite-codes') { diff --git a/src/view/com/modals/Threadgate.tsx b/src/view/com/modals/Threadgate.tsx deleted file mode 100644 index 4a9a9e2ab..000000000 --- a/src/view/com/modals/Threadgate.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import React, {useState} from 'react' -import { - Pressable, - StyleProp, - StyleSheet, - TouchableOpacity, - View, - ViewStyle, -} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import isEqual from 'lodash.isequal' - -import {useModalControls} from '#/state/modals' -import {useMyListsQuery} from '#/state/queries/my-lists' -import {ThreadgateSetting} from '#/state/queries/threadgate' -import {usePalette} from 'lib/hooks/usePalette' -import {colors, s} from 'lib/styles' -import {isWeb} from 'platform/detection' -import {ScrollView} from 'view/com/modals/util' -import {Text} from '../util/text/Text' - -export const snapPoints = ['60%'] - -export function Component({ - settings, - onChange, - onConfirm, -}: { - settings: ThreadgateSetting[] - onChange?: (settings: ThreadgateSetting[]) => void - onConfirm?: (settings: ThreadgateSetting[]) => void -}) { - const pal = usePalette('default') - const {closeModal} = useModalControls() - const [selected, setSelected] = useState(settings) - const {_} = useLingui() - const {data: lists} = useMyListsQuery('curate') - - const onPressEverybody = () => { - setSelected([]) - onChange?.([]) - } - - const onPressNobody = () => { - setSelected([{type: 'nobody'}]) - onChange?.([{type: 'nobody'}]) - } - - const onPressAudience = (setting: ThreadgateSetting) => { - // remove nobody - let newSelected = selected.filter(v => v.type !== 'nobody') - // toggle - const i = newSelected.findIndex(v => isEqual(v, setting)) - if (i === -1) { - newSelected.push(setting) - } else { - newSelected.splice(i, 1) - } - setSelected(newSelected) - onChange?.(newSelected) - } - - return ( - <View testID="threadgateModal" style={[pal.view, styles.container]}> - <View style={styles.titleSection}> - <Text type="title-lg" style={[pal.text, styles.title]}> - <Trans>Who can reply</Trans> - </Text> - </View> - - <ScrollView> - <Text style={[pal.text, styles.description]}> - <Trans>Choose "Everybody" or "Nobody"</Trans> - </Text> - <View style={{flexDirection: 'row', gap: 6, paddingHorizontal: 6}}> - <Selectable - label={_(msg`Everybody`)} - isSelected={selected.length === 0} - onPress={onPressEverybody} - style={{flex: 1}} - /> - <Selectable - label={_(msg`Nobody`)} - isSelected={!!selected.find(v => v.type === 'nobody')} - onPress={onPressNobody} - style={{flex: 1}} - /> - </View> - <Text style={[pal.text, styles.description]}> - <Trans>Or combine these options:</Trans> - </Text> - <View style={{flexDirection: 'column', gap: 4, paddingHorizontal: 6}}> - <Selectable - label={_(msg`Mentioned users`)} - isSelected={!!selected.find(v => v.type === 'mention')} - onPress={() => onPressAudience({type: 'mention'})} - /> - <Selectable - label={_(msg`Followed users`)} - isSelected={!!selected.find(v => v.type === 'following')} - onPress={() => onPressAudience({type: 'following'})} - /> - {lists?.length - ? lists.map(list => ( - <Selectable - key={list.uri} - label={_(msg`Users in "${list.name}"`)} - isSelected={ - !!selected.find( - v => v.type === 'list' && v.list === list.uri, - ) - } - onPress={() => - onPressAudience({type: 'list', list: list.uri}) - } - /> - )) - : null} - </View> - </ScrollView> - - <View style={[styles.btnContainer, pal.borderDark]}> - <TouchableOpacity - testID="confirmBtn" - onPress={() => { - closeModal() - onConfirm?.(selected) - }} - style={styles.btn} - accessibilityRole="button" - accessibilityLabel={_(msg({message: `Done`, context: 'action'}))} - accessibilityHint=""> - <Text style={[s.white, s.bold, s.f18]}> - <Trans context="action">Done</Trans> - </Text> - </TouchableOpacity> - </View> - </View> - ) -} - -function Selectable({ - label, - isSelected, - onPress, - style, -}: { - label: string - isSelected: boolean - onPress: () => void - style?: StyleProp<ViewStyle> -}) { - const pal = usePalette(isSelected ? 'inverted' : 'default') - return ( - <Pressable - onPress={onPress} - accessibilityLabel={label} - accessibilityHint="" - style={[styles.selectable, pal.border, pal.view, style]}> - <Text type="lg" style={[pal.text]}> - {label} - </Text> - {isSelected ? ( - <FontAwesomeIcon icon="check" color={pal.colors.text} size={18} /> - ) : null} - </Pressable> - ) -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - paddingBottom: isWeb ? 0 : 40, - }, - titleSection: { - paddingTop: isWeb ? 0 : 4, - }, - title: { - textAlign: 'center', - fontWeight: '600', - }, - description: { - textAlign: 'center', - paddingVertical: 16, - }, - selectable: { - flexDirection: 'row', - justifyContent: 'space-between', - paddingHorizontal: 18, - paddingVertical: 16, - borderWidth: 1, - borderRadius: 6, - }, - btn: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderRadius: 32, - padding: 14, - backgroundColor: colors.blue3, - }, - btnContainer: { - paddingTop: 20, - paddingHorizontal: 20, - }, -}) |