[IMPROVE] Migrate UIKit/MultiSelect to ActionSheet (#4255)

* Migrate UIKit/MultiSelect to ActionSheet

* Fix no options initially on CreateDiscussion  view

* Change backgroundColor and use colors from useTheme

* Define missing types

* onSearch function for the ActionSheet

* Add onClose function to the ActionSheet and use colors from useTheme

* fix theme and bottomSheet

* fix actionSheet

* fix style

Co-authored-by: GleidsonDaniel <gleidson10daniel@hotmail.com>
This commit is contained in:
Danish Ahmed Mirza 2022-07-14 01:01:58 +05:30 committed by GitHub
parent 785ae0325b
commit dd48402214
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 232 additions and 212 deletions

View File

@ -101,6 +101,11 @@ const ActionSheet = React.memo(
</>
);
const onClose = () => {
toggleVisible();
data?.onClose && data?.onClose();
};
const renderBackdrop = useCallback(
props => (
<BottomSheetBackdrop
@ -134,7 +139,7 @@ const ActionSheet = React.memo(
enablePanDownToClose
style={{ ...styles.container, ...bottomSheet }}
backgroundStyle={{ backgroundColor: colors.focusedBackground }}
onChange={index => index === -1 && toggleVisible()}
onChange={index => index === -1 && onClose()}
{...androidTablet}>
<BottomSheetContent options={data?.options} hide={hide} children={data?.children} hasCancel={data?.hasCancel} />
</BottomSheet>

View File

@ -53,7 +53,7 @@ const BottomSheetContent = React.memo(({ options, hasCancel, hide, children }: I
/>
);
}
return <BottomSheetView>{children}</BottomSheetView>;
return <BottomSheetView style={styles.contentContainer}>{children}</BottomSheetView>;
});
export default BottomSheetContent;

View File

@ -8,7 +8,7 @@ import { useTheme } from '../../theme';
export const Handle = React.memo(() => {
const { theme } = useTheme();
return (
<View style={[styles.handle, { backgroundColor: themes[theme].focusedBackground }]} testID='action-sheet-handle'>
<View style={[styles.handle]} testID='action-sheet-handle'>
<View style={[styles.handleIndicator, { backgroundColor: themes[theme].auxiliaryText }]} />
</View>
);

View File

@ -20,7 +20,8 @@ export type TActionSheetOptions = {
hasCancel?: boolean;
type?: string;
children?: React.ReactElement | null;
snaps?: string[] | number[];
snaps?: (string | number)[];
onClose?: () => void;
};
export interface IActionSheetProvider {
showActionSheet: (item: TActionSheetOptions) => void;

View File

@ -63,5 +63,15 @@ export default StyleSheet.create({
},
rightContainer: {
paddingLeft: 12
},
footerButtonsContainer: {
flexDirection: 'row',
paddingTop: 16
},
buttonSeparator: {
marginRight: 8
},
contentContainer: {
flex: 1
}
});

View File

@ -3,50 +3,50 @@ import { Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import FastImage from 'react-native-fast-image';
import { themes } from '../../../lib/constants';
import { textParser } from '../utils';
import { CustomIcon } from '../../CustomIcon';
import styles from './styles';
import { IItemData } from '.';
import { TSupportedThemes } from '../../../theme';
import { useTheme } from '../../../theme';
interface IChip {
item: IItemData;
onSelect: (item: IItemData) => void;
style?: object;
theme: TSupportedThemes;
}
interface IChips {
items: IItemData[];
onSelect: (item: IItemData) => void;
style?: object;
theme: TSupportedThemes;
}
const keyExtractor = (item: IItemData) => item.value.toString();
const Chip = ({ item, onSelect, style, theme }: IChip) => (
<Touchable
key={item.value}
onPress={() => onSelect(item)}
style={[styles.chip, { backgroundColor: themes[theme].auxiliaryBackground }, style]}
background={Touchable.Ripple(themes[theme].bannerBackground)}>
<>
{item.imageUrl ? <FastImage style={styles.chipImage} source={{ uri: item.imageUrl }} /> : null}
<Text numberOfLines={1} style={[styles.chipText, { color: themes[theme].titleText }]}>
{textParser([item.text])}
</Text>
<CustomIcon name='close' size={16} color={themes[theme].auxiliaryText} />
</>
</Touchable>
);
const Chip = ({ item, onSelect, style }: IChip) => {
const { colors } = useTheme();
return (
<Touchable
key={item.value}
onPress={() => onSelect(item)}
style={[styles.chip, { backgroundColor: colors.auxiliaryBackground }, style]}
background={Touchable.Ripple(colors.bannerBackground)}>
<>
{item.imageUrl ? <FastImage style={styles.chipImage} source={{ uri: item.imageUrl }} /> : null}
<Text numberOfLines={1} style={[styles.chipText, { color: colors.titleText }]}>
{textParser([item.text])}
</Text>
<CustomIcon name='close' size={16} color={colors.auxiliaryText} />
</>
</Touchable>
);
};
Chip.propTypes = {};
const Chips = ({ items, onSelect, style, theme }: IChips) => (
const Chips = ({ items, onSelect, style }: IChips) => (
<View style={styles.chips}>
{items.map(item => (
<Chip key={keyExtractor(item)} item={item} onSelect={onSelect} style={style} theme={theme} />
<Chip key={keyExtractor(item)} item={item} onSelect={onSelect} style={style} />
))}
</View>
);

View File

@ -3,15 +3,13 @@ import { Text, View } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import { CustomIcon } from '../../CustomIcon';
import { themes } from '../../../lib/constants';
import ActivityIndicator from '../../ActivityIndicator';
import styles from './styles';
import { TSupportedThemes } from '../../../theme';
import { useTheme } from '../../../theme';
interface IInput {
children?: JSX.Element;
onPress: () => void;
theme: TSupportedThemes;
inputStyle?: object;
disabled?: boolean | null;
placeholder?: string;
@ -19,21 +17,23 @@ interface IInput {
innerInputStyle?: object;
}
const Input = ({ children, onPress, theme, loading, inputStyle, placeholder, disabled, innerInputStyle }: IInput) => (
<Touchable
onPress={onPress}
style={[{ backgroundColor: themes[theme].backgroundColor }, inputStyle]}
background={Touchable.Ripple(themes[theme].bannerBackground)}
disabled={disabled}>
<View style={[styles.input, { borderColor: themes[theme].separatorColor }, innerInputStyle]}>
{placeholder ? <Text style={[styles.pickerText, { color: themes[theme].auxiliaryText }]}>{placeholder}</Text> : children}
{loading ? (
<ActivityIndicator style={[styles.loading, styles.icon]} />
) : (
<CustomIcon name='chevron-down' size={22} color={themes[theme].auxiliaryText} style={styles.icon} />
)}
</View>
</Touchable>
);
const Input = ({ children, onPress, loading, inputStyle, placeholder, disabled, innerInputStyle }: IInput) => {
const { colors } = useTheme();
return (
<Touchable
onPress={onPress}
style={[{ backgroundColor: colors.backgroundColor }, inputStyle]}
background={Touchable.Ripple(colors.bannerBackground)}
disabled={disabled}>
<View style={[styles.input, { borderColor: colors.separatorColor }, innerInputStyle]}>
{placeholder ? <Text style={[styles.pickerText, { color: colors.auxiliaryText }]}>{placeholder}</Text> : children}
{loading ? (
<ActivityIndicator style={styles.icon} />
) : (
<CustomIcon name='chevron-down' size={22} color={colors.auxiliaryText} style={styles.icon} />
)}
</View>
</Touchable>
);
};
export default Input;

View File

@ -1,61 +1,54 @@
import React from 'react';
import { FlatList, Text } from 'react-native';
import { Text } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import FastImage from 'react-native-fast-image';
import { FlatList } from 'react-native-gesture-handler';
import Check from '../../Check';
import * as List from '../../List';
import { textParser } from '../utils';
import { themes } from '../../../lib/constants';
import styles from './styles';
import { IItemData } from '.';
import { TSupportedThemes } from '../../../theme';
import { useTheme } from '../../../theme';
interface IItem {
item: IItemData;
selected?: string;
onSelect: Function;
theme: TSupportedThemes;
}
interface IItems {
items: IItemData[];
selected: string[];
onSelect: Function;
theme: TSupportedThemes;
}
const keyExtractor = (item: IItemData) => item.value.toString();
const keyExtractor = (item: IItemData) => item.value?.name || item.text?.text;
// RectButton doesn't work on modal (Android)
const Item = ({ item, selected, onSelect, theme }: IItem) => {
const Item = ({ item, selected, onSelect }: IItem) => {
const itemName = item.value?.name || item.text.text.toLowerCase();
const { colors } = useTheme();
return (
<Touchable
testID={`multi-select-item-${itemName}`}
key={itemName}
onPress={() => onSelect(item)}
style={[styles.item, { backgroundColor: themes[theme].backgroundColor }]}>
<Touchable testID={`multi-select-item-${itemName}`} key={itemName} onPress={() => onSelect(item)} style={[styles.item]}>
<>
{item.imageUrl ? <FastImage style={styles.itemImage} source={{ uri: item.imageUrl }} /> : null}
<Text style={{ color: themes[theme].titleText }}>{textParser([item.text])}</Text>
<Text style={{ color: colors.titleText }}>{textParser([item.text])}</Text>
{selected ? <Check /> : null}
</>
</Touchable>
);
};
const Items = ({ items, selected, onSelect, theme }: IItems) => (
const Items = ({ items, selected, onSelect }: IItems) => (
<FlatList
data={items}
style={[styles.items, { backgroundColor: themes[theme].backgroundColor }]}
contentContainerStyle={[styles.itemContent, { backgroundColor: themes[theme].backgroundColor }]}
style={[styles.items]}
contentContainerStyle={[styles.itemContent]}
keyboardShouldPersistTaps='always'
ItemSeparatorComponent={List.Separator}
keyExtractor={keyExtractor}
renderItem={({ item }) => (
<Item item={item} onSelect={onSelect} theme={theme} selected={selected.find(s => s === item.value)} />
)}
renderItem={({ item }) => <Item item={item} onSelect={onSelect} selected={selected.find(s => s === item.value)} />}
/>
);

View File

@ -0,0 +1,85 @@
import React, { useState } from 'react';
import { View } from 'react-native';
import { FormTextInput } from '../../TextInput/FormTextInput';
import { textParser } from '../utils';
import I18n from '../../../i18n';
import Items from './Items';
import styles from './styles';
import { useTheme } from '../../../theme';
import { IItemData } from '.';
import { debounce } from '../../../lib/methods/helpers/debounce';
import { isIOS } from '../../../lib/methods/helpers';
import { useActionSheet } from '../../ActionSheet';
interface IMultiSelectContentProps {
onSearch?: (keyword: string) => IItemData[] | Promise<IItemData[] | undefined>;
options?: IItemData[];
multiselect: boolean;
select: React.Dispatch<any>;
onChange: Function;
setCurrentValue: React.Dispatch<React.SetStateAction<string>>;
onHide: Function;
selectedItems: string[];
}
export const MultiSelectContent = React.memo(
({ onSearch, options, multiselect, select, onChange, setCurrentValue, onHide, selectedItems }: IMultiSelectContentProps) => {
const { colors } = useTheme();
const [selected, setSelected] = useState<string[]>(Array.isArray(selectedItems) ? selectedItems : []);
const [items, setItems] = useState<IItemData[] | undefined>(options);
const { hideActionSheet } = useActionSheet();
const onSelect = (item: IItemData) => {
const {
value,
text: { text }
} = item;
if (multiselect) {
let newSelect = [];
if (!selected.includes(value)) {
newSelect = [...selected, value];
} else {
newSelect = selected.filter((s: any) => s !== value);
}
setSelected(newSelect);
select(newSelect);
onChange({ value: newSelect });
} else {
onChange({ value });
setCurrentValue(text);
onHide();
}
};
const handleSearch = debounce(
async (text: string) => {
if (onSearch) {
const res = await onSearch(text);
setItems(res);
} else {
setItems(options?.filter((option: any) => textParser([option.text]).toLowerCase().includes(text.toLowerCase())));
}
},
onSearch ? 300 : 0
);
return (
<View style={[styles.actionSheetContainer]}>
<FormTextInput
testID='multi-select-search'
onChangeText={handleSearch}
placeholder={I18n.t('Search')}
inputStyle={{ backgroundColor: colors.focusedBackground }}
bottomSheet={isIOS}
onSubmitEditing={() => {
setTimeout(() => {
hideActionSheet();
}, 150);
}}
/>
<Items items={items || []} selected={selected} onSelect={onSelect} />
</View>
);
}
);

View File

@ -1,29 +1,15 @@
import React, { useEffect, useState } from 'react';
import {
Animated,
Easing,
KeyboardAvoidingView,
Modal,
StyleSheet,
Text,
TouchableWithoutFeedback,
View,
TextStyle
} from 'react-native';
import { Text, TextStyle } from 'react-native';
import { BlockContext } from '@rocket.chat/ui-kit';
import Button from '../../Button';
import { FormTextInput } from '../../TextInput';
import { textParser } from '../utils';
import { themes } from '../../../lib/constants';
import I18n from '../../../i18n';
import { isIOS } from '../../../lib/methods/helpers';
import { useTheme } from '../../../theme';
import { IText } from '../interfaces';
import Chips from './Chips';
import Items from './Items';
import Input from './Input';
import styles from './styles';
import { useActionSheet } from '../../ActionSheet';
import { MultiSelectContent } from './MultiSelectContent';
export interface IItemData {
value: any;
@ -38,7 +24,7 @@ interface IMultiSelect {
context?: BlockContext;
loading?: boolean;
multiselect?: boolean;
onSearch?: () => void;
onSearch?: (keyword: string) => IItemData[] | Promise<IItemData[] | undefined>;
onClose?: () => void;
inputStyle?: TextStyle;
value?: any[];
@ -46,16 +32,6 @@ interface IMultiSelect {
innerInputStyle?: object;
}
const ANIMATION_DURATION = 200;
const ANIMATION_PROPS = {
duration: ANIMATION_DURATION,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true
};
const animatedValue = new Animated.Value(0);
const behavior = isIOS ? 'padding' : null;
export const MultiSelect = React.memo(
({
options = [],
@ -71,12 +47,11 @@ export const MultiSelect = React.memo(
inputStyle,
innerInputStyle
}: IMultiSelect) => {
const { theme } = useTheme();
const [selected, select] = useState<any>(Array.isArray(values) ? values : []);
const [open, setOpen] = useState(false);
const [search, onSearchChange] = useState('');
const { colors } = useTheme();
const [selected, select] = useState<string[]>(Array.isArray(values) ? values : []);
const [currentValue, setCurrentValue] = useState('');
const [showContent, setShowContent] = useState(false);
const { showActionSheet, hideActionSheet } = useActionSheet();
useEffect(() => {
if (Array.isArray(values)) {
@ -84,10 +59,6 @@ export const MultiSelect = React.memo(
}
}, [values]);
useEffect(() => {
setOpen(showContent);
}, [showContent]);
useEffect(() => {
if (values && values.length && !multiselect) {
setCurrentValue(values[0].text);
@ -95,19 +66,26 @@ export const MultiSelect = React.memo(
}, []);
const onShow = () => {
Animated.timing(animatedValue, {
toValue: 1,
...ANIMATION_PROPS
}).start();
setShowContent(true);
showActionSheet({
children: (
<MultiSelectContent
options={options}
onSearch={onSearch}
select={select}
onChange={onChange}
setCurrentValue={setCurrentValue}
onHide={onHide}
multiselect={multiselect}
selectedItems={selected}
/>
),
onClose,
headerHeight: 275
});
};
const onHide = () => {
onClose();
Animated.timing(animatedValue, {
toValue: 0,
...ANIMATION_PROPS
}).start(() => setShowContent(false));
hideActionSheet();
};
const onSelect = (item: IItemData) => {
@ -127,45 +105,14 @@ export const MultiSelect = React.memo(
} else {
onChange({ value });
setCurrentValue(text);
onHide();
}
};
const renderContent = () => {
const items: any = onSearch
? options
: options.filter((option: any) => textParser([option.text]).toLowerCase().includes(search.toLowerCase()));
return (
<View style={[styles.modal, { backgroundColor: themes[theme].backgroundColor }]}>
<View style={[styles.content, { backgroundColor: themes[theme].backgroundColor }]}>
<FormTextInput
testID='multi-select-search'
onChangeText={onSearch || onSearchChange}
placeholder={I18n.t('Search')}
/>
<Items items={items} selected={selected} onSelect={onSelect} theme={theme} />
</View>
</View>
);
};
const translateY = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [600, 0]
});
let button = multiselect ? (
<Button title={`${selected.length} selecteds`} onPress={onShow} loading={loading} />
) : (
<Input
onPress={onShow}
theme={theme}
loading={loading}
disabled={disabled}
inputStyle={inputStyle}
innerInputStyle={innerInputStyle}>
<Text style={[styles.pickerText, { color: currentValue ? themes[theme].titleText : themes[theme].auxiliaryText }]}>
<Input onPress={onShow} loading={loading} disabled={disabled} inputStyle={inputStyle} innerInputStyle={innerInputStyle}>
<Text style={[styles.pickerText, { color: currentValue ? colors.titleText : colors.auxiliaryText }]}>
{currentValue || placeholder.text}
</Text>
</Input>
@ -173,48 +120,18 @@ export const MultiSelect = React.memo(
if (context === BlockContext.FORM) {
const items: any = options.filter((option: any) => selected.includes(option.value));
button = (
<Input
onPress={onShow}
theme={theme}
loading={loading}
disabled={disabled}
inputStyle={inputStyle}
innerInputStyle={innerInputStyle}>
<Input onPress={onShow} loading={loading} disabled={disabled} inputStyle={inputStyle} innerInputStyle={innerInputStyle}>
{items.length ? (
<Chips items={items} onSelect={(item: any) => (disabled ? {} : onSelect(item))} theme={theme} />
<Chips items={items} onSelect={(item: any) => (disabled ? {} : onSelect(item))} />
) : (
<Text style={[styles.pickerText, { color: themes[theme].auxiliaryText }]}>{placeholder.text}</Text>
<Text style={[styles.pickerText, { color: colors.auxiliaryText }]}>{placeholder.text}</Text>
)}
</Input>
);
}
return (
<>
<Modal animationType='fade' transparent visible={open} onRequestClose={onHide} onShow={onShow}>
<TouchableWithoutFeedback onPress={onHide}>
<View style={styles.container}>
<View
style={[
StyleSheet.absoluteFill,
{
opacity: themes[theme].backdropOpacity,
backgroundColor: themes[theme].backdropColor
}
]}
/>
{/* @ts-ignore*/}
<KeyboardAvoidingView style={styles.keyboardView} behavior={behavior}>
<Animated.View style={[styles.animatedContent, { transform: [{ translateY }] }]}>
{showContent ? renderContent() : null}
</Animated.View>
</KeyboardAvoidingView>
</View>
</TouchableWithoutFeedback>
</Modal>
{button}
</>
);
return <>{button}</>;
}
);

View File

@ -2,18 +2,15 @@ import { StyleSheet } from 'react-native';
import sharedStyles from '../../../views/Styles';
export default StyleSheet.create<any>({
export default StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'flex-end'
},
modal: {
height: 300,
width: '100%',
borderTopRightRadius: 16,
borderTopLeftRadius: 16,
overflow: 'hidden'
actionSheetContainer: {
padding: 16,
flex: 1
},
content: {
padding: 16

View File

@ -1,7 +1,6 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Text } from 'react-native';
import { themes } from '../../lib/constants';
import { MultiSelect } from '../../containers/UIKit/MultiSelect';
import { ISearchLocal } from '../../definitions';
import I18n from '../../i18n';
@ -9,7 +8,8 @@ import { getAvatarURL } from '../../lib/methods/helpers/getAvatarUrl';
import { ICreateDiscussionViewSelectChannel } from './interfaces';
import styles from './styles';
import { localSearch } from '../../lib/methods';
import { getRoomAvatar, getRoomTitle, debounce } from '../../lib/methods/helpers';
import { getRoomAvatar, getRoomTitle } from '../../lib/methods/helpers';
import { useTheme } from '../../theme';
const SelectChannel = ({
server,
@ -18,19 +18,28 @@ const SelectChannel = ({
onChannelSelect,
initial,
blockUnauthenticatedAccess,
serverVersion,
theme
serverVersion
}: ICreateDiscussionViewSelectChannel): React.ReactElement => {
const [channels, setChannels] = useState<ISearchLocal[]>([]);
const { colors } = useTheme();
const getChannels = debounce(async (keyword = '') => {
const getChannels = async (keyword = '') => {
try {
const res = (await localSearch({ text: keyword })) as ISearchLocal[];
const res = (await localSearch({ text: keyword, filterUsers: false })) as ISearchLocal[];
setChannels(res);
return res.map(channel => ({
value: channel,
text: { text: getRoomTitle(channel) },
imageUrl: getAvatar(channel)
}));
} catch {
// do nothing
}
}, 300);
};
useEffect(() => {
getChannels('');
}, []);
const getAvatar = (item: ISearchLocal) =>
getAvatarURL({
@ -47,7 +56,7 @@ const SelectChannel = ({
return (
<>
<Text style={[styles.label, { color: themes[theme].titleText }]}>{I18n.t('Parent_channel_or_group')}</Text>
<Text style={[styles.label, { color: colors.titleText }]}>{I18n.t('Parent_channel_or_group')}</Text>
<MultiSelect
inputStyle={styles.inputStyle}
onChange={onChannelSelect}
@ -59,7 +68,7 @@ const SelectChannel = ({
text: { text: getRoomTitle(channel) },
imageUrl: getAvatar(channel)
}))}
onClose={() => setChannels([])}
onClose={() => getChannels('')}
placeholder={{ text: `${I18n.t('Select_a_Channel')}...` }}
/>
</>

View File

@ -1,16 +1,16 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Text } from 'react-native';
import { BlockContext } from '@rocket.chat/ui-kit';
import { getAvatarURL } from '../../lib/methods/helpers/getAvatarUrl';
import I18n from '../../i18n';
import { MultiSelect } from '../../containers/UIKit/MultiSelect';
import { themes } from '../../lib/constants';
import styles from './styles';
import { ICreateDiscussionViewSelectUsers } from './interfaces';
import { SubscriptionType, IUser } from '../../definitions';
import { search } from '../../lib/methods';
import { getRoomAvatar, getRoomTitle, debounce } from '../../lib/methods/helpers';
import { getRoomAvatar, getRoomTitle } from '../../lib/methods/helpers';
import { useTheme } from '../../theme';
const SelectUsers = ({
server,
@ -19,22 +19,31 @@ const SelectUsers = ({
selected,
onUserSelect,
blockUnauthenticatedAccess,
serverVersion,
theme
serverVersion
}: ICreateDiscussionViewSelectUsers): React.ReactElement => {
const [users, setUsers] = useState<any[]>([]);
const { colors } = useTheme();
const getUsers = debounce(async (keyword = '') => {
const getUsers = async (keyword = '') => {
try {
const res = await search({ text: keyword, filterRooms: false });
const selectedUsers = users.filter((u: IUser) => selected.includes(u.name));
const filteredUsers = res.filter(r => !selectedUsers.find((u: IUser) => u.name === r.name));
const items = [...selectedUsers, ...filteredUsers];
setUsers(items);
return items.map((user: IUser) => ({
value: user.name,
text: { text: getRoomTitle(user) },
imageUrl: getAvatar(user)
}));
} catch {
// do nothing
}
}, 300);
};
useEffect(() => {
getUsers('');
}, []);
const getAvatar = (item: IUser) =>
getAvatarURL({
@ -50,7 +59,7 @@ const SelectUsers = ({
return (
<>
<Text style={[styles.label, { color: themes[theme].titleText }]}>{I18n.t('Invite_users')}</Text>
<Text style={[styles.label, { color: colors.titleText }]}>{I18n.t('Invite_users')}</Text>
<MultiSelect
inputStyle={styles.inputStyle}
onSearch={getUsers}
@ -60,7 +69,6 @@ const SelectUsers = ({
text: { text: getRoomTitle(user) },
imageUrl: getAvatar(user)
}))}
onClose={() => setUsers(users.filter((u: IUser) => selected.includes(u.name)))}
placeholder={{ text: `${I18n.t('Select_Users')}...` }}
context={BlockContext.FORM}
multiselect

View File

@ -164,7 +164,6 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreate
onChannelSelect={this.selectChannel}
blockUnauthenticatedAccess={blockUnauthenticatedAccess}
serverVersion={serverVersion}
theme={theme}
/>
<FormTextInput
label={I18n.t('Discussion_name')}
@ -182,7 +181,6 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreate
onUserSelect={this.selectUsers}
blockUnauthenticatedAccess={blockUnauthenticatedAccess}
serverVersion={serverVersion}
theme={theme}
/>
{this.isEncryptionEnabled ? (
<>

View File

@ -1,7 +1,6 @@
import { NewMessageStackParamList } from '../../stacks/types';
import { ISubscription, SubscriptionType } from '../../definitions/ISubscription';
import { IBaseScreen, IMessage, ISearchLocal, IUser } from '../../definitions';
import { TSupportedThemes } from '../../theme';
export interface IResult {
rid: string;
@ -43,7 +42,6 @@ export interface ICreateDiscussionViewSelectChannel {
onChannelSelect: Function;
blockUnauthenticatedAccess: boolean;
serverVersion: string;
theme: TSupportedThemes;
}
export interface ICreateDiscussionViewSelectUsers {
@ -54,5 +52,4 @@ export interface ICreateDiscussionViewSelectUsers {
onUserSelect: Function;
blockUnauthenticatedAccess: boolean;
serverVersion: string;
theme: TSupportedThemes;
}

View File

@ -150,9 +150,9 @@ const ForwardLivechatView = ({ navigation, route }: IBaseScreen<ChatsStackParamL
return (
<View style={[styles.container, { backgroundColor: colors.auxiliaryBackground }]}>
<Input onPress={onPressDepartment} placeholder={I18n.t('Select_a_Department')} theme={theme} />
<Input onPress={onPressDepartment} placeholder={I18n.t('Select_a_Department')} />
<OrSeparator theme={theme} />
<Input onPress={onPressUser} placeholder={I18n.t('Select_a_User')} theme={theme} />
<Input onPress={onPressUser} placeholder={I18n.t('Select_a_User')} />
</View>
);
};