// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; import React, {ReactNode, useCallback, useState} from 'react'; import {useIntl} from 'react-intl'; import {Text, View} from 'react-native'; import CompasIcon from '@components/compass_icon'; import FormattedText from '@components/formatted_text'; import TouchableWithFeedback from '@components/touchable_with_feedback'; import {Screens, View as ViewConstants} from '@constants'; import {useTheme} from '@context/theme'; import {observeTeammateNameDisplay} from '@queries/servers/user'; import {goToScreen} from '@screens/navigation'; import {preventDoubleTap} from '@utils/tap'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import {displayUsername} from '@utils/user'; import type {WithDatabaseArgs} from '@typings/database/database'; type AutoCompleteSelectorProps = { dataSource?: string; disabled?: boolean; errorText?: ReactNode; getDynamicOptions?: (userInput?: string) => Promise; helpText?: ReactNode; label?: string; onSelected?: (selectedItem?: PostActionOption) => Promise; optional?: boolean; options?: PostActionOption[]; placeholder: string; roundedBorders?: boolean; selected?: PostActionOption; showRequiredAsterisk?: boolean; teammateNameDisplay: string; } const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { const input = { borderWidth: 1, borderColor: changeOpacity(theme.centerChannelColor, 0.1), backgroundColor: changeOpacity(theme.centerChannelBg, 0.9), paddingLeft: 10, paddingRight: 30, paddingVertical: 7, height: 40, }; return { container: { width: '100%', marginBottom: 2, marginRight: 8, marginTop: 10, }, roundedInput: { ...input, borderRadius: 5, }, input, dropdownPlaceholder: { top: 3, marginLeft: 5, color: changeOpacity(theme.centerChannelColor, 0.5), }, dropdownSelected: { top: 3, marginLeft: 5, color: theme.centerChannelColor, }, icon: { position: 'absolute', top: 13, right: 12, }, labelContainer: { flexDirection: 'row', marginTop: 15, marginBottom: 10, }, label: { fontSize: 14, color: theme.centerChannelColor, marginLeft: 15, }, optional: { color: changeOpacity(theme.centerChannelColor, 0.5), fontSize: 14, marginLeft: 5, }, helpText: { fontSize: 12, color: changeOpacity(theme.centerChannelColor, 0.5), marginHorizontal: 15, marginVertical: 10, }, errorText: { fontSize: 12, color: theme.errorTextColor, marginHorizontal: 15, marginVertical: 10, }, asterisk: { color: theme.errorTextColor, fontSize: 14, }, disabled: { opacity: 0.5, }, }; }); const AutoCompleteSelector = ({ dataSource, disabled, errorText, getDynamicOptions, helpText, label, onSelected, optional = false, options, placeholder, roundedBorders = true, selected, showRequiredAsterisk = false, teammateNameDisplay, }: AutoCompleteSelectorProps) => { const intl = useIntl(); const theme = useTheme(); const [itemText, setItemText] = useState(selected?.text); const style = getStyleSheet(theme); const title = placeholder || intl.formatMessage({id: 'mobile.action_menu.select', defaultMessage: 'Select an option'}); const goToSelectorScreen = useCallback(preventDoubleTap(() => { const screen = Screens.INTEGRATION_SELECTOR; goToScreen(screen, title, {dataSource, handleSelect, options, getDynamicOptions}); }), [dataSource, options, getDynamicOptions]); const handleSelect = useCallback((item?: any) => { if (!item) { return; } let selectedText; let selectedValue; if (dataSource === ViewConstants.DATA_SOURCE_USERS) { selectedText = displayUsername(item, undefined, teammateNameDisplay); selectedValue = item.id; } else if (dataSource === ViewConstants.DATA_SOURCE_CHANNELS) { selectedText = item.display_name; selectedValue = item.id; } else { selectedText = item.text; selectedValue = item.value; } setItemText(selectedText); if (onSelected) { onSelected({text: selectedText, value: selectedValue}); } }, []); let text = title; let selectedStyle = style.dropdownPlaceholder; if (itemText) { text = itemText; selectedStyle = style.dropdownSelected; } let inputStyle = style.input; if (roundedBorders) { inputStyle = style.roundedInput; } let optionalContent; let asterisk; if (optional) { optionalContent = ( ); } else if (showRequiredAsterisk) { asterisk = {' *'}; } let labelContent; if (label) { labelContent = ( {label} {asterisk} {optionalContent} ); } let helpTextContent; if (helpText) { helpTextContent = {helpText}; } let errorTextContent; if (errorText) { errorTextContent = {errorText}; } return ( {labelContent} {text} {helpTextContent} {errorTextContent} ); }; const withTeammateNameDisplay = withObservables([], ({database}: WithDatabaseArgs) => { return { teammateNameDisplay: observeTeammateNameDisplay(database), }; }); export default withDatabase(withTeammateNameDisplay(AutoCompleteSelector));