react-native-gesture-handler#TextInput TypeScript Examples

The following examples show how to use react-native-gesture-handler#TextInput. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SettingsTab.tsx    From react-native-sdk with MIT License 6 votes vote down vote up
private renderLoggedOut() {
    console.log("renderLoggedOut")
    return (
      <View style={styles.emailContainer}>
        <TextInput
          value={this.state.email}
          style={styles.emailTextInput}
          autoCapitalize="none"
          autoCompleteType="email"
          onChangeText={(text) => this.setState({ isLoggedIn: false, email: text })}
          placeholder="[email protected]" />
        <Button
          title="Login"
          onPress={this.onLoginTapped}
        />
      </View>
    )
  }
Example #2
Source File: Login.tsx    From react-native-sdk with MIT License 6 votes vote down vote up
private renderLoggedOut() {
    console.log("renderLoggedOut")
    return (
      <View style={styles.emailContainer}>
        <TextInput testID='loginText'
          value={this.state.email}
          style={styles.emailTextInput}
          autoCapitalize="none"
          autoCompleteType="email"
          onChangeText={(text) => this.setState({ isLoggedIn: false, email: text })}
          placeholder="[email protected]" />
        <Button
          testID="loginBtn"
          title="Login"
          onPress={this.onLoginTapped}
        />
      </View>
    )
  }
Example #3
Source File: TextField.tsx    From rn-clean-architecture-template with MIT License 5 votes vote down vote up
TextField: React.FC<TextFieldProps> = (props) => {
  const {
    containerStyle,
    prefix,
    prefixIcon,
    suffix,
    suffixIcon,
    errorLabel,
    inputProps = {},
  } = props;

  const renderPrefix = () => {
    if (prefix) {
      return prefix;
    }
    if (prefixIcon) {
      return <Image source={prefixIcon} />;
    }
    return null;
  };

  const renderSuffix = () => {
    if (suffix) {
      return suffix;
    }
    if (suffixIcon) {
      return <Image source={suffixIcon} />;
    }
    return null;
  };

  return (
    <View style={[_styles.container, containerStyle]}>
      <View style={_styles.content}>
        {renderPrefix()}
        <View style={_styles.padding} />
        <TextInput {...inputProps} style={[_styles.input, inputProps.style]} />
        {renderSuffix()}
      </View>
      <TextView text={errorLabel} />
      <View style={_styles.divider} />
    </View>
  );
}
Example #4
Source File: InputContainer.tsx    From SQL-Play with GNU Affero General Public License v3.0 4 votes vote down vote up
InputContainer: FC<Props> = ({
  inputValue,
  setInputValue,
  isPremium,
  setPremiumModalOpen,
}) => {
  const historyOffset = useRef<number>(-1);
  const [autoCompleteTxt, setAutoCompleteTxt] = useState<string>('');

  const showPremiumAlert = (): void => {
    Alert.alert(
      'Go premium to unlock query history',
      'By going premium, you can unlock history with autocomplete and many more',
      [
        {text: 'Go Premium', onPress: () => setPremiumModalOpen(true)},
        {text: 'Close', style: 'cancel'},
      ],
    );
  };

  const onUpArrowPress = async (): Promise<void> => {
    /** show premium alert when user is not premium */
    if (!isPremium) {
      showPremiumAlert();
      return;
    }
    const lastCommand = await getLastUserCommand(historyOffset.current + 1);
    // console.log(historyOffset.current + 1, lastCommand);

    // only set if command is there
    if (lastCommand) {
      setInputValue(lastCommand);
      historyOffset.current++;
    }
  };
  const onDownArrowPress = async (): Promise<void> => {
    /** show premium alert when user is not premium */
    if (!isPremium) {
      showPremiumAlert();
      return;
    }

    if (historyOffset.current === 0) {
      return;
    } // do nothing if offset it 0

    const lastCommand = await getLastUserCommand(historyOffset.current - 1);
    // console.log(historyOffset.current - 1, lastCommand);
    // only set if command is there
    if (lastCommand) {
      setInputValue(lastCommand);
      historyOffset.current--;
    }
  };

  type CallbackType = (...args: string[]) => void;

  // eslint-disable-next-line react-hooks/exhaustive-deps
  const getAutoComplete = useCallback<CallbackType>(
    debounce(
      (val: string) =>
        findUserCommands(val).then(e => {
          // console.log('autocomplete', e);
          setAutoCompleteTxt(e);
        }),
      100,
    ),
    [],
  );

  useEffect(() => {
    // console.log(inputValue);
    if (!isPremium) {
      return;
    }
    if (inputValue !== '') {
      getAutoComplete(inputValue);
    } else {
      setAutoCompleteTxt('');
    }
  }, [getAutoComplete, inputValue, isPremium]);

  const clearInput = () => {
    setInputValue('');
  };

  const setAutoInput = () => {
    isPremium && setInputValue(autoCompleteTxt);
  };

  const handleSwipeLeft = ({
    nativeEvent,
  }: FlingGestureHandlerStateChangeEvent) => {
    if (nativeEvent.state === State.ACTIVE) {
      isPremium && clearInput();
    }
  };

  const handleSwipeRight = ({
    nativeEvent,
  }: FlingGestureHandlerStateChangeEvent) => {
    if (nativeEvent.oldState === State.ACTIVE) {
      setAutoInput();
    }
  };
  const styles = useDynamicValue(dynamicStyles);
  return (
    <View>
      <Text style={styles.inputHeader}>Type your SQL Query</Text>
      <View style={styles.inputContainer}>
        <GestureRecognizer
          onSwipeRight={setAutoInput}
          onSwipeLeft={() => isPremium && clearInput()}
        >
          <FlingGestureHandler
            direction={Directions.RIGHT}
            onHandlerStateChange={handleSwipeRight}
          >
            <FlingGestureHandler
              direction={Directions.LEFT}
              onHandlerStateChange={handleSwipeLeft}
            >
              <TextInput
                style={styles.input}
                autoFocus={true}
                testID={ids.queryTextInput}
                onChangeText={text => setInputValue(text)}
                multiline
                placeholderTextColor="gray"
                textAlignVertical="top"
                defaultValue={inputValue}
                keyboardType="ascii-capable"
                autoCorrect={false}
                numberOfLines={4}
                placeholder="Type your SQL query"
              />
            </FlingGestureHandler>
          </FlingGestureHandler>
        </GestureRecognizer>
        <Text
          suppressHighlighting={true}
          onLongPress={setAutoInput}
          style={styles.autoCompleteTxt}
        >
          {autoCompleteTxt}
        </Text>
      </View>
      <View style={styles.sideButtonContainer}>
        <TouchableOpacity
          accessibilityLabel="Up Button"
          accessibilityHint="gets the previous command from history"
          onPress={onUpArrowPress}
        >
          <Icon size={30} name="arrow-up-bold-box" color={sideButton} />
        </TouchableOpacity>
        <TouchableOpacity
          style={styles.downArrow}
          accessibilityLabel="Down Button"
          accessibilityHint="gets the next command from history"
          onPress={onDownArrowPress}
        >
          <Icon size={30} name="arrow-up-bold-box" color={sideButton} />
        </TouchableOpacity>
        <TouchableOpacity
          onPress={clearInput}
          accessibilityLabel="Clear command button"
          accessibilityHint="clear the command input"
        >
          <Icon size={30} name="text-box-remove" color={sideButton} />
        </TouchableOpacity>
      </View>
    </View>
  );
}
Example #5
Source File: form.tsx    From THUInfo with MIT License 4 votes vote down vote up
FormScreen = ({
	route,
	navigation,
}: {
	route: FormRouteProp;
	navigation: RootNav;
}) => {
	const url: string = route.params.url;

	const themeName = useColorScheme();
	const {colors} = themes(themeName);
	const style = styles(themeName);

	const [refreshing, setRefreshing] = useState(true);
	const [evaluationForm, setEvaluationForm] = useState<Form>();
	// TODO: 'useState' may not be the best choice.

	const fetchForm = (_url: string) => {
		setRefreshing(true);
		helper
			.getAssessmentForm(_url)
			.then((res: Form) => {
				setEvaluationForm(res);
				setRefreshing(false);
			})
			.catch(() => {
				Snackbar.show({
					text: getStr("networkRetry"),
					duration: Snackbar.LENGTH_SHORT,
				});
				setRefreshing(false);
			});
	};

	const renderEvaluation = (personList: Person[], personType: string) => {
		let evaluationList = [];
		if (personList.length !== 0) {
			personList.forEach((person, i) => {
				evaluationList.push(
					<Text style={style.personNameStyle} key={`Teacher${i}Name`}>
						{person.name}
					</Text>,
				);

				person.inputGroups.forEach((inputGroup, j) => {
					evaluationList.push(
						<View style={style.questionStyle} key={`Person${i}Question${j}`}>
							<Text style={style.questionTextStyle}>
								{inputGroup.question ?? ""}
							</Text>
							<StarRating scoreRef={inputGroup.score} />
						</View>,
					);
				});

				evaluationList.push(
					<View key={`Person${i}Suggestion`}>
						<Text style={style.textInputCaptionStyle}>
							{personType === "teacher"
								? getStr("moreSuggestionsToTeacher")
								: getStr("moreSuggestionsToAssistant")}
						</Text>
						<TextInput
							style={{
								height: 80,
								textAlign: "left",
								borderColor: "lightgrey",
								borderWidth: 1,
								borderRadius: 5,
								alignSelf: "stretch",
								textAlignVertical: "top",
								padding: 10,
								marginBottom: 20,
								color: colors.text,
								backgroundColor: colors.themeBackground,
							}}
							multiline={true}
							placeholder={getStr("inputSuggestions")}
							defaultValue={
								(personType === "teacher"
									? evaluationForm?.teachers[i]?.suggestion
									: evaluationForm?.assistants[i]?.suggestion) ?? ""
							}
							onChangeText={(text) => {
								if (evaluationForm) {
									if (personType === "teacher") {
										evaluationForm.teachers[i].suggestion = text;
									} else {
										evaluationForm.assistants[i].suggestion = text;
									}
								}
							}}
						/>
					</View>,
				);
			});
		} else {
			evaluationList.push(
				<Text style={style.captionStyle} key="stupidEvaluationWebsite">
					{getStr("noPersonToEvaluate")}
				</Text>,
			);
		}
		return <View>{evaluationList}</View>;
	};

	const post = () => {
		setRefreshing(true);
		if (evaluationForm !== undefined) {
			const invalid = evaluationForm.invalid();
			if (invalid) {
				Snackbar.show({
					text: invalid,
					duration: Snackbar.LENGTH_LONG,
				});
				setRefreshing(false);
			} else {
				helper
					.postAssessmentForm(evaluationForm)
					.then(() => {
						Snackbar.show({
							text: getStr("postSuccess"),
							duration: Snackbar.LENGTH_SHORT,
						});
						setRefreshing(false);
						navigation.pop();
					})
					.catch(() => {
						Snackbar.show({
							text: getStr("postFailure"),
							duration: Snackbar.LENGTH_SHORT,
						});
						setRefreshing(false);
					});
			}
		}
	};

	useEffect(() => fetchForm(url), [url]);

	return (
		<ScrollView
			style={style.container}
			showsVerticalScrollIndicator={false}
			refreshControl={
				<RefreshControl refreshing={refreshing} colors={[colors.accent]} />
			}>
			<View style={style.titleContainer}>
				<FontAwesome name="chevron-right" color="red" size={18} />
				<Text style={style.titleStyle}>{getStr("generalImpression")}</Text>
			</View>
			{evaluationForm && <StarRating scoreRef={evaluationForm.overall.score} />}
			<Text style={style.textInputCaptionStyle}>
				{getStr("moreSuggestionsToCourse")}
			</Text>
			<TextInput
				style={{
					height: 80,
					textAlign: "left",
					borderColor: "lightgrey",
					borderWidth: 1,
					borderRadius: 5,
					alignSelf: "stretch",
					textAlignVertical: "top",
					padding: 10,
					marginBottom: 20,
					color: colors.text,
					backgroundColor: colors.themeBackground,
				}}
				multiline={true}
				placeholder={getStr("inputSuggestions")}
				defaultValue={evaluationForm?.overall?.suggestion ?? ""}
				onChangeText={(text) => {
					if (evaluationForm) {
						evaluationForm.overall.suggestion = text;
					}
				}}
			/>
			<View style={style.titleContainer}>
				<FontAwesome name="chevron-right" color="green" size={18} />
				<Text style={style.titleStyle}>{getStr("teacherEvaluation")}</Text>
			</View>
			{evaluationForm && renderEvaluation(evaluationForm.teachers, "teacher")}
			<View style={style.titleContainer}>
				<FontAwesome name="chevron-right" color="blue" size={18} />
				<Text style={style.titleStyle}>{getStr("assistantEvaluation")}</Text>
			</View>
			{evaluationForm &&
				renderEvaluation(evaluationForm.assistants, "assistant")}
			<TouchableOpacity
				style={[
					style.buttonStyle,
					{
						backgroundColor:
							evaluationForm === undefined ? "lightgrey" : colors.primary,
					},
				]}
				onPress={post}
				disabled={evaluationForm === undefined}>
				<Text style={style.buttonTextStyle}>{getStr("post")}</Text>
			</TouchableOpacity>
		</ScrollView>
	);
}
Example #6
Source File: scheduleDetail.tsx    From THUInfo with MIT License 4 votes vote down vote up
ScheduleDetailScreen = ({route}: any) => {
	const props = route.params;
	const [delPressed, setDelPressed] = useState<boolean>(false);

	const [aliasInputText, setAliasInputText] = useState<string>("");
	const [locationInputText, setLocationInputText] = useState<string>("");

	const [newAlias, setAlias] = useState<string>(props.alias);
	const [newLocation, setLocation] = useState<string>(props.location);

	const lineLength = Dimensions.get("window").width * 0.9;

	const themeName = useColorScheme();
	const {colors} = themes(themeName);

	const horizontalLine = () => (
		<View
			style={{
				backgroundColor: "lightgray",
				height: 1,
				width: lineLength,
				margin: 5,
			}}
		/>
	);

	const delButton = (choice: Choice) => {
		if (props.type === ScheduleType.EXAM) {
			return null;
		}
		const verbText: string =
			props.type === ScheduleType.CUSTOM && choice === Choice.ALL
				? getStr("delSchedule")
				: getStr("hideSchedule");
		const buttonText: string =
			choice === Choice.ALL
				? verbText + getStr("allTime")
				: choice === Choice.REPEAT
				? verbText + getStr("repeatly")
				: verbText + getStr("once");
		return (
			<TouchableOpacity
				style={{
					borderRadius: 2,
					backgroundColor: "white",
					alignSelf: "stretch",
					justifyContent: "center",
					alignItems: "center",
					shadowColor: "gray",
					shadowOpacity: 0.8,
					shadowRadius: 2,
					shadowOffset: {height: 2, width: 2},
					margin: 5,
					padding: 12,
				}}
				onPress={() => {
					setDelPressed(true);
					store.dispatch(
						scheduleDelOrHideAction([
							props.name,
							{
								activeWeeks: [props.week],
								dayOfWeek: props.dayOfWeek,
								begin: props.begin,
								end: props.end,
							},
							choice,
						]),
					);
				}}
				disabled={delPressed}>
				<Text
					style={{
						fontWeight: "bold",
						fontSize: 18,
						color: delPressed
							? "gray"
							: choice === Choice.ALL
							? "red"
							: "black",
					}}>
					{buttonText}
				</Text>
			</TouchableOpacity>
		);
	};

	// TODO: 要允许修改计划的时间
	return (
		<View
			style={{
				paddingVertical: 30,
				paddingHorizontal: 20,
				alignItems: "center",
			}}>
			<Text
				style={{
					fontSize: 25,
					marginBottom: 20,
					lineHeight: 30,
					alignSelf: "flex-start",
					textDecorationLine: delPressed ? "line-through" : undefined,
					color: delPressed ? "gray" : colors.text,
				}}
				numberOfLines={2}>
				{(nullAlias(newAlias) ? props.name : newAlias).substr(
					props.type === ScheduleType.CUSTOM ? 6 : 0,
				)}
			</Text>
			<View
				style={{
					flexDirection: "row",
					alignItems: "center",
					marginVertical: 10,
					alignSelf: "flex-start",
				}}>
				<View
					style={{alignItems: "center", justifyContent: "center", width: 20}}>
					<FontAwesome name="map-marker" size={20} color="red" />
				</View>
				<View
					style={{
						alignItems: "flex-start",
						justifyContent: "center",
						width: getStr("mark") === "CH" ? undefined : 67,
					}}>
					<Text style={{marginHorizontal: 8, color: "gray"}}>
						{getStr("location")}
					</Text>
				</View>
				<Text
					style={{
						marginHorizontal: 5,
						color: newLocation === "" ? "gray" : colors.text,
					}}>
					{newLocation === "" ? getStr("locationUnset") : newLocation}
				</Text>
			</View>
			<View
				style={{
					flexDirection: "row",
					flexWrap: "wrap",
					alignItems: "center",
					marginVertical: 10,
					alignSelf: "flex-start",
				}}>
				<View
					style={{alignItems: "center", justifyContent: "center", width: 20}}>
					<FontAwesome name="list-alt" size={20} color="blue" />
				</View>
				<View
					style={{
						alignItems: "flex-start",
						justifyContent: "center",
						width: getStr("mark") === "CH" ? undefined : 67,
					}}>
					<Text style={{marginHorizontal: 8, color: "gray"}}>
						{getStr("timeLocation")}
					</Text>
				</View>
				<Text style={{marginLeft: 5, color: colors.text}}>
					{getStr("weekNumPrefix") + props.week + getStr("weekNumSuffix")}
				</Text>
				<Text style={{marginLeft: 5, color: colors.text}}>
					{getStr("dayOfWeek")[props.dayOfWeek]}
				</Text>
				{props.type !== ScheduleType.EXAM && (
					<>
						<Text style={{marginLeft: 5, color: colors.text}}>
							{getStr("periodNumPrefix") +
								props.begin +
								(props.begin === props.end ? "" : " ~ " + props.end) +
								getStr("periodNumSuffix")}
						</Text>
						<Text style={{marginLeft: 5, color: "gray"}}>
							{(getStr("mark") === "CH" ? "(" : "(") +
								beginTime[props.begin] +
								" ~ " +
								endTime[props.end] +
								(getStr("mark") === "CH" ? ")" : ")")}
						</Text>
					</>
				)}
				{props.type === ScheduleType.EXAM && (
					<Text style={{marginLeft: 5, color: "gray"}}>
						{(getStr("mark") === "CH" ? "(" : "(") +
							props.begin +
							" ~ " +
							props.end +
							(getStr("mark") === "CH" ? ")" : ")")}
					</Text>
				)}
			</View>
			{nullAlias(newAlias) ? null : (
				<View
					style={{
						flexDirection: "row",
						alignItems: "center",
						marginVertical: 10,
						alignSelf: "flex-start",
					}}>
					<View
						style={{alignItems: "center", justifyContent: "center", width: 20}}>
						<FontAwesome name="file-text-o" size={20} color="green" />
					</View>
					<View
						style={{
							alignItems: "flex-start",
							justifyContent: "center",
							width: getStr("mark") === "CH" ? undefined : 67,
						}}>
						<Text
							style={{marginHorizontal: 8, color: "gray"}}
							numberOfLines={2}>
							{getStr("originalName")}
						</Text>
					</View>
					<Text
						style={{
							marginHorizontal: 5,
							color: props.location === "" ? "gray" : colors.text,
						}}>
						{props.name}
					</Text>
				</View>
			)}
			{horizontalLine()}
			<Text
				style={{
					marginVertical: 10,
					alignSelf: "flex-start",
					fontSize: 18,
					color: colors.text,
				}}>
				{(nullAlias(newAlias) ? getStr("set") : getStr("delOrModify")) +
					getStr("alias")}
			</Text>
			<View
				style={{
					marginVertical: 10,
					alignSelf: "stretch",
					justifyContent: "center",
					flexDirection: "row",
				}}>
				<TextInput
					style={{
						fontSize: 15,
						flex: 5,
						backgroundColor: colors.themeBackground,
						color: colors.text,
						textAlign: "left",
						textAlignVertical: "center",
						borderColor: "lightgrey",
						borderWidth: 1,
						borderRadius: 5,
						marginHorizontal: 10,
						padding: 6,
					}}
					value={aliasInputText}
					onChangeText={setAliasInputText}
					keyboardType="default"
				/>
				<Button
					title={getStr("confirm")}
					onPress={() => {
						if (aliasInputText.length === 0) {
							Alert.alert(getStr("illegalAlias"), getStr("aliasCannotBeNull"));
							return;
						}
						const res: string =
							(props.type === ScheduleType.CUSTOM
								? props.name.substr(0, 6)
								: "") + aliasInputText;
						store.dispatch(scheduleUpdateAliasAction([props.name, res]));
						setAlias(res);
						setAliasInputText("");
					}}
				/>
				{nullAlias(newAlias) ? null : (
					<Button
						title={getStr("delAlias")}
						onPress={() => {
							store.dispatch(
								scheduleUpdateAliasAction([props.name, undefined]),
							);
							setAlias("");
							setAliasInputText("");
						}}
					/>
				)}
			</View>
			<Text
				style={{
					marginVertical: 10,
					alignSelf: "flex-start",
					fontSize: 18,
					color: colors.text,
				}}>
				{(newLocation.length ? getStr("delOrModify") : getStr("set")) +
					getStr("location") +
					(getStr("mark") === "CH" ? ":" : ":")}
			</Text>
			<View
				style={{
					marginVertical: 10,
					alignSelf: "stretch",
					justifyContent: "center",
					flexDirection: "row",
				}}>
				<TextInput
					style={{
						fontSize: 15,
						flex: 5,
						backgroundColor: colors.themeBackground,
						color: colors.text,
						textAlign: "left",
						textAlignVertical: "center",
						borderColor: "lightgrey",
						borderWidth: 1,
						borderRadius: 5,
						marginHorizontal: 10,
						padding: 6,
					}}
					value={locationInputText}
					onChangeText={setLocationInputText}
					keyboardType="default"
				/>
				<Button
					title={getStr("confirm")}
					onPress={() => {
						if (locationInputText.length === 0) {
							Alert.alert(
								getStr("illegalLocation"),
								getStr("locationCannotBeNull"),
							);
							return;
						}
						store.dispatch(
							scheduleUpdateLocationAction([props.name, locationInputText]),
						);
						setLocation(locationInputText);
						setLocationInputText("");
					}}
				/>
				{newLocation.length ? (
					<Button
						title={getStr("delLocation")}
						onPress={() => {
							Alert.alert(
								getStr("confirmDeletion"),
								getStr("confirmDeletionText"),
								[
									{
										text: getStr("confirm"),
										onPress: () => {
											store.dispatch(
												scheduleUpdateLocationAction([props.name, ""]),
											);
											setLocation("");
											setLocationInputText("");
										},
									},
									{
										text: getStr("cancel"),
									},
								],
							);
						}}
					/>
				) : null}
			</View>
			{horizontalLine()}
			{delButton(Choice.ONCE)}
			{delButton(Choice.REPEAT)}
			{delButton(Choice.ALL)}
		</View>
	);
}
Example #7
Source File: PositiveResult.tsx    From ito-app with GNU General Public License v3.0 4 votes vote down vote up
PositiveResult: React.FC<{
  navigation: PositiveResultScreenNavigationProp;
}> = ({navigation}) => {
  const {t} = useTranslation();
  const deferUploadTimeout: React.MutableRefObject<NodeJS.Timeout | null> = useRef(
    null,
  );

  const [uploadSuccess, setUploadSuccess] = useState(null);
  useEffect(() => {
    if (uploadSuccess === null) {
      return;
    }
    if (uploadSuccess) {
      console.log('TCN Upload succeeded');
      navigation.navigate('DataUpload');
    } else {
      console.warn('TCN Upload failed');
      navigation.navigate('DataUpload');
    }
  }, [navigation, uploadSuccess]);
  const doUpload = (): void => {
    if (deferUploadTimeout.current) {
      console.log('preventing more than one parallel upload timeout');
      return;
    }
    // allows uploading again when going back / visiting the screen anew
    // going back should be prevented once actual verification is implemented
    setUploadSuccess(null);
    // TODO: make timeframe for uploading TCNS configurable
    const now = Date.now() / 1000;
    const sevenDaysAgo = now - 7 * 24 * 60 * 60;
    deferUploadTimeout.current = setTimeout(() => {
      deferUploadTimeout.current = null;
      ItoBluetooth.publishBeaconUUIDs(sevenDaysAgo, now, setUploadSuccess);
    }, 3000);
    console.log('PositiveResult', {deferUploadTimeout});
    navigation.navigate('Upload', {
      deferUploadTimeout: deferUploadTimeout,
    });
  };
  return (
    <View style={[global.container]}>
      <Header
        navigationButton={{
          title: t('global.cancel'),
          fn: (): void => navigation.goBack(),
        }}
        showAlpha={true}
      />
      <Text style={design.explanation}>{t('positiveResult.instruction')}</Text>
      <View>
        <RNCamera
          captureAudio={false}
          style={styles.camera}
          androidCameraPermissionOptions={{
            title: t('positiveResult.camPermissionTitle'),
            message: t('positiveResult.camPermissionText'),
            buttonPositive: t('global.ok'),
            buttonNegative: t('global.cancel'),
          }}
          onBarCodeRead={(data: object): void => {
            console.log('onBarCodeRead:', data);
            doUpload();
          }}>
          {({
            camera: _camera,
            status,
            recordAudioPermissionStatus: _recordAudioPermissionStatus,
          }): ReactNode => {
            console.log('RNCamera status:', status);
            if (status !== 'READY') {
              return (
                <Icon name="camera" style={styles.icon} size={80}>
                  {'\n'}
                  <Text style={design.explanation}>
                    {t('positiveResult.cameraMessage')}
                  </Text>
                </Icon>
              );
            }
          }}
        </RNCamera>
      </View>
      <TextInput
        style={[design.textInput, styles.enterCode]}
        placeholder={t('positiveResult.textPlaceholderEnterCode')}
        returnKeyType="send"
        onSubmitEditing={doUpload}
      />
      <BottomMenu navigation={navigation} activate="Infected?" />
    </View>
  );
}