@react-navigation/native#useRoute TypeScript Examples

The following examples show how to use @react-navigation/native#useRoute. 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: index.tsx    From GoBarber with MIT License 6 votes vote down vote up
AppointmentCreated: React.FC = () => {
  const { reset } = useNavigation();
  const { params } = useRoute();

  const { date } = params as RouteParams;

  const formattedDate = useMemo(() => {
    return format(date, "EEEE', dia' dd 'de' MMMM 'de' yyyy 'às' HH:mm'h'", {
      locale: ptBR,
    });
  }, [date]);

  const handleOkPressed = useCallback(() => {
    reset({
      routes: [
        {
          name: 'Dashboard',
        },
      ],
      index: 0,
    });
  }, [reset]);

  return (
    <Container>
      <Icon name="check" size={80} color="#04d361" />
      <Title>Agendamento Concluído</Title>
      <Description>{formattedDate}</Description>
      <OkButton onPress={handleOkPressed}>
        <OkButtonText>Ok</OkButtonText>
      </OkButton>
    </Container>
  );
}
Example #2
Source File: index.tsx    From gobarber-mobile with MIT License 6 votes vote down vote up
AppointmentCreated: React.FC = () => {
  const { reset } = useNavigation();
  const { params } = useRoute();

  const { date } = params as RouteParams;

  const handleOkPressed = useCallback(() => {
    reset({
      routes: [{ name: 'Dashboard' }],
      index: 0,
    });
  }, [reset]);

  const formattedDate = useMemo(() => {
    return format(date, "EEEE', dia' dd 'de' MMMM 'de' yyyy 'às' HH:mm'h'", {
      locale: ptBR,
    });
  }, [date]);

  return (
    <Container>
      <Icon name="check" size={80} color="#04d461" />

      <Title>Agendamento concluído</Title>
      <Description>{formattedDate}</Description>

      <OkButton onPress={handleOkPressed}>
        <OkButtonText>Ok</OkButtonText>
      </OkButton>
    </Container>
  );
}
Example #3
Source File: index.tsx    From gobarber-project with MIT License 6 votes vote down vote up
AppointmentCreated: React.FC = () => {
  const { reset } = useNavigation();
  const { params } = useRoute();

  const { date } = params as IRouteParams;

  const handleOkPressed = useCallback(() => {
    reset({
      routes: [
        {
          name: 'Dashboard',
        },
      ],
      index: 0,
    });
  }, [reset]);

  const formattedDate = useMemo(() => {
    return format(date, "EEEE', dia' dd 'de' MMMM 'de' yyyy 'às' HH:mm'h'", {
      locale: ptBR,
    });
  }, [date]);

  return (
    <Container>
      <Icon name="check" size={80} color="#04d361" />

      <Title>Agendamento concluído</Title>
      <Description>{formattedDate}</Description>

      <OkButton onPress={handleOkPressed}>
        <OkButtonText>OK</OkButtonText>
      </OkButton>
    </Container>
  );
}
Example #4
Source File: Product.container.tsx    From react-native-woocommerce with MIT License 6 votes vote down vote up
ProductContainer = (props: ProductsState): JSX.Element => {
  const products = useSelector(selectors.products.getProducts);
  const [imagesShown, showImages] = useState(false);
  const route = useRoute();
  const handlers = {
    handleShowImages: (): void =>
      showImages((prevState) => !prevState)
  };

  return (
    <ProductComponent
      {...props}
      {...handlers}
      // @ts-ignore
      product={_getProductById(products, route.params.id)}
      imagesShown={imagesShown}
    />
  );
}
Example #5
Source File: Detail.container.tsx    From RNWCShop with GNU General Public License v3.0 6 votes vote down vote up
DetailContainer = ({ navigation }: Props): JSX.Element => {
  const initialProduct = {
    id: 1,
    name: '',
    price: 0,
    description: '',
    average_rating: '',
    images: []
  };
  const [product, setProduct] = useState<Product>(initialProduct);
  const [imagesShown, showImages] = useState(false);
  const route = useRoute<RouteProp<NavigationParams, 'Detail'>>();
  const dispatch = useDispatch();

  const handlers = {
    handleShowImages: (): void =>
      showImages((prevState: boolean) => !prevState),
    addToCart: (product: Product): Action => {
      navigation.navigate('Orders', { screen: routes.Cart });

      return dispatch(actions.addToCart(product));
    }
  };

  useEffect(() => {
    WooCommerce.get(`/products/${route.params.id}`).then(({ data }) => {
      setProduct(data);
    });
  }, [route.params.id]);

  return (
    <DetailComponent
      {...handlers}
      imagesShown={imagesShown}
      product={product}
    />
  );
}
Example #6
Source File: AuthScene.tsx    From sellflow with MIT License 6 votes vote down vote up
export default function AuthScene() {
  let {
    params: { initialRouteKey },
  } = useRoute<StackRouteProp<'Auth'>>();
  const routes: Array<TabRoute> = [
    { key: 'Login', title: 'Login', scene: LoginScene },
    { key: 'Register', title: 'Register', scene: RegisterScene },
  ];
  return (
    <TabView
      isScrollEnabled={false}
      routes={routes}
      initialRouteKey={initialRouteKey}
    />
  );
}
Example #7
Source File: debug.tsx    From bext with MIT License 6 votes vote down vote up
DebugScreen: FC = () => {
  const webView = useRef<WebView>(null);
  const { params } = useRoute<any>();
  const { script } = useDebug();

  return (
    <WebView
      ref={webView}
      originWhitelist={['*']}
      source={{
        uri: params.url,
      }}
      injectedJavaScriptBeforeContentLoaded={`${script.current};true;`}
    />
  );
}
Example #8
Source File: AlbumScreen.tsx    From SpotifyClone with MIT License 6 votes vote down vote up
AlbumScreen = () => {

  const route = useRoute();
  const albumId = route.params.id;

  const [album, setAlbum] = useState(null)

  useEffect(() => {
    const fetchAlbumDetails = async () => {
      try {
        const data = await API.graphql(graphqlOperation(getAlbum, { id: albumId }))
        setAlbum(data.data.getAlbum)
      } catch (e) {
        console.log(e);
      }
    }

    fetchAlbumDetails();
  }, [])

  if (!album) {
    return <Text>Loading...</Text>
  }

  return (
    <View>
      <FlatList
        data={album.songs.items}
        renderItem={({ item }) => <SongListItem song={item} />}
        keyExtractor={(item) => item.id}
        ListHeaderComponent={() => <AlbumHeader album={album} />}
      />
    </View>
  )
}
Example #9
Source File: Playlist.tsx    From jellyfin-audio-player with MIT License 6 votes vote down vote up
Playlist: React.FC = () => {
    const { params: { id } } = useRoute<Route>();
    const dispatch = useAppDispatch();

    // Retrieve the album data from the store
    const playlist = useTypedSelector((state) => state.music.playlists.entities[id]);
    const playlistTracks = useTypedSelector((state) => state.music.tracks.byPlaylist[id]);

    // Define a function for refreshing this entity
    const refresh = useCallback(() => dispatch(fetchTracksByPlaylist(id)), [dispatch, id]);

    // Auto-fetch the track data periodically
    useEffect(() => {
        if (!playlist?.lastRefreshed || differenceInDays(playlist?.lastRefreshed, new Date()) > ALBUM_CACHE_AMOUNT_OF_DAYS) {
            refresh();
        }
    }, [playlist?.lastRefreshed, refresh]);

    return (
        <TrackListView
            trackIds={playlistTracks || []}
            title={playlist?.Name}
            entityId={id}
            refresh={refresh}
            listNumberingStyle='index'
            playButtonText={t('play-playlist')}
            shuffleButtonText={t('shuffle-playlist')}
            downloadButtonText={t('download-playlist')} 
            deleteButtonText={t('delete-playlist')}
        />
    );
}
Example #10
Source File: ReportUnMatchButton.tsx    From vsinder with Apache License 2.0 5 votes vote down vote up
ReportUnMatchButton: React.FC<ReportUnMatchButtonProps> = ({}) => {
  const { buttonBackground } = useTheme();
  const { showActionSheetWithOptions } = useActionSheet();
  const cache = useQueryCache();
  const navigation = useNavigation();
  const [mutate] = useMutation(defaultMutationFn, {
    onSuccess: () => {
      navigation.goBack();
      cache.setQueryData<MatchesResponse>("/matches/0", (m) => {
        return {
          matches: m?.matches.filter((x) => x.userId !== params.id) || [],
        };
      });
    },
  });
  const { params } = useRoute<MatchesStackNav<"messages">["route"]>();
  return (
    <ReportDialog
      onReportMessage={(message) => {
        mutate([
          "/report",
          { message, unmatchOrReject: "unmatch", userId: params.id },
          "POST",
        ]);
      }}
    >
      {(setOpen) => (
        <TouchableOpacity
          style={{
            flex: 1,
            flexDirection: "row",
            alignItems: "center",
            justifyContent: "center",
            paddingRight: 15,
          }}
          onPress={() => {
            const options = [
              "Report user",
              "Unmatch",
              "Report a bug",
              "Cancel",
            ];
            const destructiveButtonIndex = 0;
            const cancelButtonIndex = 3;

            showActionSheetWithOptions(
              {
                options,
                cancelButtonIndex,
                destructiveButtonIndex,
              },
              (buttonIndex) => {
                if (buttonIndex === 0) {
                  setOpen(true);
                } else if (buttonIndex === 1) {
                  mutate([`/unmatch`, { userId: params.id }, "POST"]);
                } else if (buttonIndex === 2) {
                  Linking.openURL("https://github.com/benawad/vsinder/issues");
                }
              }
            );
          }}
        >
          <MaterialIcons name="bug-report" size={27} color={buttonBackground} />
        </TouchableOpacity>
      )}
    </ReportDialog>
  );
}
Example #11
Source File: index.tsx    From NLW-1.0 with MIT License 5 votes vote down vote up
Detail: React.FC = () => {
  const [data, setData] = useState<Data>({} as Data);
  const navigation = useNavigation();
  const route = useRoute();

  const routeParams = route.params as Params;

  useEffect(() => {
    async function loadPoint() {
      const response = await api.get(`/points/${routeParams.point_id}`);

      setData(response.data);
    }

    loadPoint();
  }, []);

  function handleNavigateBack() {
    navigation.goBack();
  }

  function handleComposeMail() {
    MailComposer.composeAsync({
      subject: "Interesse na coleta de resíduos",
      recipients: [data.point.email],
    });
  }

  function handleWhatsApp() {
    Linking.openURL(
      `whatsapp://send?phone=${data.point.whatsapp}&text=Tenho interesse na coleta de resíduos`
    );
  }
  if (!data.point) {
    return null;
  }

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <View style={styles.container}>
        <TouchableOpacity onPress={handleNavigateBack}>
          <Icon name="arrow-left" size={20} color="#34cb79" />
        </TouchableOpacity>

        <Image
          style={styles.pointImage}
          source={{
            uri: data.point.image_url,
          }}
        />

        <Text style={styles.pointName}>{data.point.name}</Text>
        <Text style={styles.pointItems}>
          {data.items.map((item) => item.title).join(",")}
        </Text>

        <View style={styles.address}>
          <Text style={styles.addressTitle}>Endereço</Text>
          <Text style={styles.addressContent}>
            {data.point.city}, {data.point.uf}
          </Text>
        </View>
      </View>
      <View style={styles.footer}>
        <RectButton style={styles.button} onPress={() => handleWhatsApp()}>
          <FontAwesome name="whatsapp" size={20} color="#fff" />
          <Text style={styles.buttonText}>Whatsapp</Text>
        </RectButton>
        <RectButton style={styles.button} onPress={() => handleComposeMail()}>
          <Icon name="mail" size={20} color="#fff" />
          <Text style={styles.buttonText}>E-mail</Text>
        </RectButton>
      </View>
    </SafeAreaView>
  );
}
Example #12
Source File: index.tsx    From nlw-01-omnistack with MIT License 5 votes vote down vote up
Detail = () => {
  const [data, setData] = useState<Data>({} as Data);

  const navigation = useNavigation();
  const route = useRoute();

  const routeParams = route.params as Params;

  useEffect(() => {
    api.get(`points/${routeParams.point_id}`).then(response => {
      setData(response.data);
    });
  }, []);

  function handleNavigateBack() {
    navigation.goBack();
  }

  function handleWhatsapp() {
    Linking.openURL(`whatsapp://send?phone=${data.point.whatsapp}&text=Tenho interesse sobre coleta de resíduos`);
  }

  function handleComposeMail() {
    MailComposer.composeAsync({
      subject: 'Interesse na coleta de resíduos',
      recipients: [data.point.email],
    })
  }

  if (!data.point) {
    return null;
  }

  return (
    <SafeAreaView style={{ flex: 1 }}>
      <View style={styles.container}>
        <TouchableOpacity onPress={handleNavigateBack}>
          <Icon name="arrow-left" size={20} color="#34cb79" />
        </TouchableOpacity>

        <Image style={styles.pointImage} source={{ uri: data.point.image_url }} />
      
        <Text style={styles.pointName}>{data.point.name}</Text>
        <Text style={styles.pointItems}>
          {data.items.map(item => item.title).join(', ')}
        </Text>

        <View style={styles.address}>
          <Text style={styles.addressTitle}>Endereço</Text>
          <Text style={styles.addressContent}>{data.point.city}, {data.point.uf}</Text>
        </View>
      </View>
      <View style={styles.footer}>
        <RectButton style={styles.button} onPress={handleWhatsapp}>
          <FontAwesome name="whatsapp" size={20} color="#FFF" />
          <Text style={styles.buttonText}>Whatsapp</Text>
        </RectButton>

        <RectButton style={styles.button} onPress={handleComposeMail}>
          <Icon name="mail" size={20} color="#FFF" />
          <Text style={styles.buttonText}>E-mail</Text>
        </RectButton>
      </View>
    </SafeAreaView>
  );
}
Example #13
Source File: index.tsx    From nlw-ecoleta with MIT License 5 votes vote down vote up
Detail = () => {
    const [data, setData] = useState<Data>({} as Data);
    const navigation = useNavigation();
    const route = useRoute();

    const routeParams = route.params as Params;

    useEffect(() => {
      api.get(`points/${routeParams.point_id}`).then(response => {
        setData(response.data);
      });
    }, []);

    function handleNavigateBack() {
        navigation.goBack();
    }

    function handleNavigateComposeMail() {
      MailComposer.composeAsync({
        subject: 'Interesse na coleta de resíduos',
        recipients: [data.point.email],
      })
    }

    function handleWhatsapp() {
        Linking.openURL(`whatsapp://send?phone${data.point.whatsapp}$textTEnho interesse sobre coleta de resíduos`)
    }

    if(!data.point) {
      return null;
    }

    return (
      <SafeAreaView style={{ flex: 1 }}>
        <View style={styles.container}>
            <TouchableOpacity onPress={handleNavigateBack}>
                <Icon name="arrow-left" size={20} color="#34cb79" />
            </TouchableOpacity>


            <Image style={styles.pointImage} source={{ uri: data.point.image_url }} />

            <Text style={styles.pointName}>{data.point.name}</Text>
            <Text style={styles.pointItems}>{data.items.map(item =>item.title).join(', ')}</Text>

            <View style={styles.address}>
              <Text style={styles.addressTitle}>Endereço</Text>
              <Text style={styles.addressContent}>{data.point.city}, {data.point.uf}</Text>
            </View>
        </View>
        <View style={styles.footer}>
          <RectButton style={styles.button} onPress={handleWhatsapp}>
            <FontAwesome name="whatsapp" size={20} color="#FFF" />
            <Text style={styles.buttonText}>Whatsapp</Text>
          </RectButton>

          <RectButton style={styles.button} onPress={handleNavigateComposeMail}>
            <Icon name="mail" size={20} color="#FFF" />
            <Text style={styles.buttonText}>E-mail</Text>
          </RectButton>
        </View>
        </SafeAreaView>
    );
}
Example #14
Source File: OrderHistoryScene.tsx    From sellflow with MIT License 5 votes vote down vote up
export default function OrderHistoryScene() {
  let { navigate } = useNavigation<StackNavProp<'OrderHistory'>>();
  let {
    params: { customerAccessToken },
  } = useRoute<StackRouteProp<'OrderHistory'>>();
  let first = 10;
  let {
    orderHistory,
    error,
    loading,
    refetch,
    isFetchingMore,
    hasMore,
  } = useOrderHistory(first, customerAccessToken);

  let {
    data: { countryCode },
  } = useDefaultCountry();

  if (error) {
    return (
      <ErrorPage
        onRetry={() =>
          refetch({
            customerAccessToken,
            first,
            after: orderHistory[orderHistory.length - 1].cursor || null,
            country: countryCode,
          })
        }
      />
    );
  }
  if (loading && !isFetchingMore) {
    return <ActivityIndicator style={styles.center} />;
  }

  let onEndReached = () => {
    if (!isFetchingMore && hasMore) {
      refetch({
        customerAccessToken,
        first,
        after: orderHistory[orderHistory.length - 1].cursor || null,
        country: countryCode,
      });
    }
  };

  return (
    <FlatList
      data={orderHistory}
      renderItem={({ item }) => (
        <OrderHistoryItem
          order={item}
          onPress={() => navigate('OrderDetails', { order: item })}
        />
      )}
      keyExtractor={(item) => item.orderID}
      contentContainerStyle={styles.contentContainer}
      ListEmptyComponent={() => {
        return hasMore ? null : (
          <View style={styles.center}>
            <Text>{t('No orders yet')}</Text>
          </View>
        );
      }}
      onEndReached={onEndReached}
      onEndReachedThreshold={0.25}
      ListFooterComponent={() => {
        return hasMore ? (
          <ActivityIndicator style={styles.activityIndicator} />
        ) : null;
      }}
    />
  );
}
Example #15
Source File: ReportUnMatchButton.tsx    From vsinder-app with Apache License 2.0 5 votes vote down vote up
ReportUnMatchButton: React.FC<ReportUnMatchButtonProps> = ({}) => {
  const { buttonBackground } = useTheme();
  const { showActionSheetWithOptions } = useActionSheet();
  const cache = useQueryCache();
  const navigation = useNavigation();
  const [mutate] = useMutation(defaultMutationFn, {
    onSuccess: () => {
      navigation.goBack();
      cache.setQueryData<MatchesResponse>("/matches/0", (m) => {
        return {
          matches: m?.matches.filter((x) => x.userId !== params.id) || [],
        };
      });
    },
  });
  const { params } = useRoute<MatchesStackNav<"messages">["route"]>();
  return (
    <ReportDialog
      onReportMessage={(message) => {
        mutate([
          "/report",
          { message, unmatchOrReject: "unmatch", userId: params.id },
          "POST",
        ]);
      }}
    >
      {(setOpen) => (
        <TouchableOpacity
          style={{
            flex: 1,
            flexDirection: "row",
            alignItems: "center",
            justifyContent: "center",
            paddingRight: 15,
          }}
          onPress={() => {
            const options = ["Report", "Unmatch", "Cancel"];
            const destructiveButtonIndex = 0;
            const cancelButtonIndex = 2;

            showActionSheetWithOptions(
              {
                options,
                cancelButtonIndex,
                destructiveButtonIndex,
              },
              (buttonIndex) => {
                if (buttonIndex === 0) {
                  setOpen(true);
                } else if (buttonIndex === 1) {
                  mutate([`/unmatch`, { userId: params.id }, "POST"]);
                }
              }
            );
          }}
        >
          <MaterialIcons name="bug-report" size={27} color={buttonBackground} />
        </TouchableOpacity>
      )}
    </ReportDialog>
  );
}
Example #16
Source File: TrackPopupMenu.tsx    From jellyfin-audio-player with MIT License 5 votes vote down vote up
function TrackPopupMenu() {
    // Retrieve trackId from route
    const { params: { trackId } } = useRoute<Route>();

    // Retrieve helpers
    const navigation = useNavigation();
    const dispatch = useAppDispatch();
    const playTracks = usePlayTracks();
    const getImage = useGetImage();

    // Retrieve data from store
    const track = useTypedSelector((state) => state.music.tracks.entities[trackId]);
    const isDownloaded = useTypedSelector(selectIsDownloaded(trackId));

    // Set callback to close the modal
    const closeModal = useCallback(() => {
        navigation.dispatch(StackActions.popToTop());    
    }, [navigation]);

    // Callback for adding the track to the queue as the next song
    const handlePlayNext = useCallback(() => {
        playTracks([trackId], { method: 'add-after-currently-playing', play: false });
        closeModal();
    }, [playTracks, closeModal, trackId]);

    // Callback for adding the track to the end of the queue
    const handleAddToQueue = useCallback(() => {
        playTracks([trackId], { method: 'add-to-end', play: false });
        closeModal();
    }, [playTracks, closeModal, trackId]);

    // Callback for downloading the track
    const handleDownload = useCallback(() => {
        dispatch(queueTrackForDownload(trackId));
        closeModal();
    }, [trackId, dispatch, closeModal]);

    // Callback for removing the downloaded track
    const handleDelete = useCallback(() => {
        dispatch(removeDownloadedTrack(trackId));
        closeModal();
    }, [trackId, dispatch, closeModal]);

    return (
        <Container>
            <Artwork src={getImage(track?.Id || '')} />
            <Header>{track?.Name}</Header>
            <SubHeader style={{ marginBottom: 18 }}>{track?.AlbumArtist} {track?.Album ? '— ' + track?.Album : ''}</SubHeader>
            <WrappableButtonRow>
                <WrappableButton title={t('play-next')} icon={PlayIcon} onPress={handlePlayNext} />
                <WrappableButton title={t('add-to-queue')} icon={QueueAppendIcon} onPress={handleAddToQueue} />
                {isDownloaded ? (
                    <WrappableButton title={t('delete-track')} icon={TrashIcon} onPress={handleDelete} />
                ) : (
                    <WrappableButton title={t('download-track')} icon={DownloadIcon} onPress={handleDownload} />
                )}
            </WrappableButtonRow>
        </Container>
    );
}
Example #17
Source File: Channels.tsx    From lexicon with MIT License 5 votes vote down vote up
export default function Channels() {
  const styles = useStyles();

  const { navigate, goBack } = useNavigation<RootStackNavProp<'Channels'>>();

  const {
    params: { selectedChannelId, prevScreen },
  } = useRoute<RootStackRouteProp<'Channels'>>();

  const storage = useStorage();
  const channels = storage.getItem('channels');

  const ios = Platform.OS === 'ios';

  const onPress = (id: number) => {
    if (prevScreen === 'Home') {
      navigate('Main', {
        screen: 'TabNav',
        params: {
          screen: 'Home',
          params: {
            selectedChannelId: id,
          },
        },
      });
    } else {
      navigate(prevScreen, { selectedChannelId: id });
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      {ios ? (
        <ModalHeader
          title={t('Channels')}
          left={<HeaderItem label={t('Cancel')} onPressItem={goBack} left />}
        />
      ) : (
        <CustomHeader title={t('Channels')} noShadow />
      )}
      <ScrollView>
        {prevScreen === 'Home' && (
          <ChannelItem
            isSelected={selectedChannelId === ALL_CHANNEL.id}
            channel={ALL_CHANNEL}
            onPress={() => onPress(ALL_CHANNEL.id)}
          />
        )}
        {channels?.map((channel) => {
          const { id } = channel;
          return (
            <ChannelItem
              key={id}
              isSelected={id === selectedChannelId}
              channel={channel}
              onPress={() => onPress(id)}
            />
          );
        })}
      </ScrollView>
    </SafeAreaView>
  );
}
Example #18
Source File: WebViewScene.tsx    From sellflow with MIT License 5 votes vote down vote up
export default function WebScene() {
  let {
    params: { type, webUrl },
  } = useRoute<StackRouteProp<'WebView'>>();
  let { navigate, setOptions } = useNavigation<StackNavProp<'WebView'>>();
  let { resetShoppingCart } = useResetCart();

  let title: string;

  switch (type) {
    case 'policy':
      title = t('Privacy Policy');
      break;
    case 'terms':
      title = t('Terms & Conditions');
      break;
    default:
      title = t('Payment');
  }
  useEffect(() => {
    setOptions({
      title,
    });
  });

  return webUrl ? (
    <SafeAreaView style={styles.flex}>
      <WebView
        style={styles.container}
        source={{ uri: webUrl }}
        originWhitelist={['*']}
        onShouldStartLoadWithRequest={({ url }) => {
          if (url.endsWith('thank_you')) {
            resetShoppingCart();
            navigate('OrderPlacedConfirmation', { orderNumber: '' });
            return false;
          }
          return true;
        }}
        startInLoadingState={true}
        renderLoading={() => <ActivityIndicator style={styles.center} />}
      />
    </SafeAreaView>
  ) : (
    <SafeAreaView style={styles.text}>
      <Text>{t('Please check your connection.')}</Text>
    </SafeAreaView>
  );
}
Example #19
Source File: BatteryPermission.tsx    From hamagen-react-native with MIT License 5 votes vote down vote up
BatteryPermission: FunctionComponent<Props> = ({ onEnd }) => {
  // const [userPressed,setUserPressed] = useState(false)
  const dispatch = useDispatch();
  const { strings: {
    general: { additionalInfo },
    battery: { title, description, approveButton, notApproveButton }
  }
  } = useSelector<Store, LocaleReducer>(state => state.locale);

  const { params } = useRoute();
  const [intervalDelay, setIntervalDelay] = useState<number | null>(null);

  useInterval(async () => {
    const isEnabled = await RNDisableBatteryOptimizationsAndroid.isBatteryOptimizationEnabled();
    if (!isEnabled) {
      dispatch({ type: USER_DISABLED_BATTERY, payload: true });
      await AsyncStorage.setItem(USER_AGREED_TO_BATTERY, 'true');
      onEnd();
    }
  }, intervalDelay);

  // stop interval if user moved on
  useFocusEffect(React.useCallback(() => () => setIntervalDelay(null), []));

  return (
    <>
      <View style={[{ alignItems: 'center', paddingHorizontal: IS_SMALL_SCREEN ? 20 : 40 }, IS_SMALL_SCREEN && { paddingTop: 5 }]}>
        {!IS_SMALL_SCREEN && (
          <Icon
            width={80}
            customStyles={{ marginBottom: 20 }}
            source={require('../../assets/onboarding/batteryBig.png')}
          />
        )}
        <Text style={styles.title} bold>{title}</Text>
        <Text style={styles.description}>{description}</Text>
      </View>
      <View style={{ alignItems: 'center' }}>
        <ActionButton
          text={approveButton}
          onPress={() => {
            setIntervalDelay(200);
            RNDisableBatteryOptimizationsAndroid.openBatteryModal();
          }}
          containerStyle={{ marginBottom: 20 }}
        />
        {params?.showSkip && (
        <TouchableOpacity onPress={async () => {
          onEnd();
          dispatch({ type: USER_DISABLED_BATTERY, payload: false });
          AsyncStorage.setItem(USER_AGREED_TO_BATTERY, 'false');
        }}
        >
          <Text style={{ color: MAIN_COLOR }} bold>{notApproveButton}</Text>
        </TouchableOpacity>
)}
      </View>
    </>
  );
}
Example #20
Source File: DetachedHeader.tsx    From react-native-gallery-toolkit with MIT License 5 votes vote down vote up
function useHeaderProps() {
  const route = useRoute();

  return headerPropsMap.get(route.name);
}
Example #21
Source File: index.tsx    From ecoleta with MIT License 5 votes vote down vote up
Detail = () => {
  const [data, setData] = useState<Data>({} as Data);

  const navigation = useNavigation();
  const route = useRoute();

  const routeParams = route.params as Params;

  useEffect(() => {
    api.get(`/points/${routeParams.point_id}`).then((response) => {
      setData(response.data);
    });
  }, []);

  function handleNavigateBack() {
    navigation.goBack();
  }

  function handleWhatsapp() {
    Linking.openURL(
      `whatsapp://send?phone=${data.point.whatsapp}&text=Tenho interesse em ajudar na coleta de resíduos`
    );
  }

  function handleComposeMail() {
    MailComposer.composeAsync({
      subject: 'Interesse na coleta de resíduos',
      recipients: [data.point.email],
    });
  }

  if (!data.point) {
    return null;
  }
  return (
    <SafeAreaView style={{ flex: 1 }}>
      <View style={styles.container}>
        <TouchableOpacity onPress={handleNavigateBack}>
          <Feather name="arrow-left" color="#34CB79" size={24} />
        </TouchableOpacity>

        <Image
          style={styles.pointImage}
          source={{
            uri: data.point.image_url,
          }}
        />
        <Text style={styles.pointName}>{data.point.name}</Text>
        <Text style={styles.pointItems}>
          {data.items.map((item) => item.title).join(', ')}
        </Text>

        <View style={styles.address}>
          <Text style={styles.addressTitle}>Endereço:</Text>
          <Text style={styles.addressContent}>
            {data.point.city}, {data.point.uf}
          </Text>
        </View>
      </View>

      <View style={styles.footer}>
        <RectButton style={styles.button} onPress={handleWhatsapp}>
          <FontAwesome name="whatsapp" size={20} color="#fff" />
          <Text style={styles.buttonText}>Whatsapp</Text>
        </RectButton>

        <RectButton style={styles.button} onPress={handleComposeMail}>
          <Feather name="mail" size={20} color="#fff" />
          <Text style={styles.buttonText}>E-mail</Text>
        </RectButton>
      </View>
    </SafeAreaView>
  );
}
Example #22
Source File: PostImagePreview.tsx    From lexicon with MIT License 5 votes vote down vote up
export default function PostImagePreview() {
  const styles = useStyles();
  const { colors } = useTheme();

  const { navigate, goBack } = useNavigation<
    RootStackNavProp<'PostImagePreview'>
  >();

  const {
    params: { imageUri, prevScreen },
  } = useRoute<RootStackRouteProp<'PostImagePreview'>>();

  const uploading = () => {
    navigate(prevScreen, { imageUri });
  };

  return (
    <View style={styles.container}>
      <StatusBar style={'light'} />
      <SafeAreaView style={styles.fullContainer}>
        <ImageBackground
          source={{ uri: imageUri }}
          resizeMode="contain"
          style={styles.fullContainer}
        >
          <View
            style={{ flexDirection: 'row', justifyContent: 'space-between' }}
          >
            <Icon
              name="Close"
              color={colors.pureWhite}
              onPress={goBack}
              style={styles.iconContainer}
            />
            <Icon
              name="Add"
              color={colors.pureWhite}
              onPress={uploading}
              style={styles.iconContainer}
            />
          </View>
        </ImageBackground>
      </SafeAreaView>
    </View>
  );
}
Example #23
Source File: index.tsx    From ecoleta with MIT License 5 votes vote down vote up
Detail = () => {

  const [data, setData] = useState<Data>({} as Data);

  const navigation = useNavigation();
  const route = useRoute();

  const routeParams = route.params as Params;

  useEffect(() => {
    api.get(`points/${routeParams.point_id}`).then(response => {
      setData(response.data);
    });
  }, []);

  function handleNavigateBack() {
    navigation.goBack();
  }

  function handleWhatsapp() {
    Linking.openURL(`whatsapp://send?phone=${data.point.whatsapp}&text=Tenho interesse sobre coleta de resíduos.`)
  }

  function handleComposeMail() {
    MailComposer.composeAsync({
      subject: 'Interesse na coleta de resíduos',
      recipients: [data.point.email],
    })
  }

  if (!data.point) {
    return null;
  }

  return (
    <SafeAreaView style={{ flex: 1 }} >   
      <View style={styles.container}>
        <TouchableOpacity onPress={handleNavigateBack}>
          <Icon name="arrow-left" size={20} color="#34cb79" />
        </TouchableOpacity>

        <Image style={styles.pointImage} source={{ uri: data.point.image_url }} />

        <Text style={styles.pointName}>{data.point.name}</Text>
        <Text style={styles.pointItems}>
          {data.items.map(item => item.title).join(',')}
        </Text>

        <View style={styles.address}>
          <Text style={styles.addressTitle}>Endereço</Text>
          <Text style={styles.addressContent}>{data.point.city}, {data.point.uf}</Text>
        </View>
      </View>

      <View style={styles.footer}>
        <RectButton style={styles.button} onPress={handleWhatsapp}>
          <FontAwesome name="whatsapp" size={20} color="#FFF" />
          <Text style={styles.buttonText}>WhatsApp</Text>
        </RectButton>

        <RectButton style={styles.button} onPress={handleComposeMail}>
          <Icon name="mail" size={20} color="#FFF" />
          <Text style={styles.buttonText}>E-mail</Text>
        </RectButton>
      </View>
    </SafeAreaView>
  );
}
Example #24
Source File: UserInformation.tsx    From lexicon with MIT License 4 votes vote down vote up
export default function UserInformation() {
  const styles = useStyles();

  const { navigate } = useNavigation<StackNavProp<'UserInformation'>>();

  const {
    params: { username },
  } = useRoute<StackRouteProp<'UserInformation'>>();

  const storage = useStorage();
  const channels = storage.getItem('channels');
  const currentUser = storage.getItem('user')?.username;

  const [show, setShow] = useState<boolean>();
  const [refreshing, setRefreshing] = useState(false);

  const {
    data: profileData,
    loading: profileLoading,
    error: profileError,
  } = useProfile(
    {
      variables: { username },
    },
    'HIDE_ALERT',
  );

  const name = profileData?.userProfile.user.name || '';
  const userImage = getImage(profileData?.userProfile.user.avatar || '', 'xl');
  const bio = profileData?.userProfile.user.bioRaw;
  const splittedBio = bio ? bio.split(/\r\n|\r|\n/) : [''];

  const {
    data: topicsData,
    loading: topicsLoading,
    error: topicsError,
  } = useTopicList({
    variables: { sort: TopicsSortEnum.LATEST },
    fetchPolicy: 'network-only',
  });

  const {
    data,
    loading,
    error,
    networkStatus,
    refetch,
    fetchMore,
  } = useActivity(
    { variables: { username: username, offset: 0 } },
    'HIDE_ALERT',
  );

  const activities = data?.userActivity ?? [];
  let postActivities: Array<Post> = activities.map((activity) => {
    const channel = channels?.find(
      (channel) => channel.id === activity.categoryId,
    );
    let topic;
    const listedTopics = topicsData?.topics.topicList;
    if (listedTopics?.topics) {
      topic = listedTopics.topics.find(
        (topic) => topic.id === activity.topicId,
      );
    }
    const { content, imageUrl, mentionedUsers } = anchorToMarkdown(
      activity.excerpt,
    );

    return {
      ...activity,
      id: activity.postId ?? 0,
      content,
      images: imageUrl ? [imageUrl] : undefined,
      avatar: getImage(activity.avatarTemplate),
      viewCount: 0,
      replyCount: 0,
      likeCount: 0,
      isLiked: activity.actionType === 1,
      channel: channel || DEFAULT_CHANNEL,
      tags: topic?.tags || [],
      freqPosters: [],
      mentionedUsers,
    };
  });

  const onEndReached = (distanceFromEnd: number) => {
    if (distanceFromEnd === 0) {
      return;
    }
    fetchMore({ variables: { offset: postActivities.length } });
  };

  const onRefresh = () => {
    setRefreshing(true);
    refetch();
    setRefreshing(false);
  };

  const onPressCancel = () => {
    if (!show) {
      setShow(true);
    }
    setTimeout(() => setShow(false), 50);
  };

  const onPressNewMessage = () => {
    navigate('NewMessage', {
      users: [username],
      listOfUser: [{ name, username, avatar: userImage }],
    });
  };

  if (error || topicsError || profileError) {
    let errorMessage = error
      ? errorHandler(error, true)
      : topicsError
      ? errorHandler(topicsError, true)
      : profileError
      ? errorHandler(profileError, true)
      : undefined;
    return <LoadingOrError message={errorMessage} />;
  }

  if (
    ((loading ||
      topicsLoading ||
      profileLoading ||
      (data && data.userActivity.length !== 0)) &&
      postActivities.length < 1) ||
    topicsData?.topics.topicList?.topics?.length === undefined
  ) {
    return <LoadingOrError loading />;
  }

  const Header = () => {
    return (
      <>
        <View style={styles.headerContainer}>
          <CustomHeader title="" noShadow />
          <Avatar
            src={userImage}
            size="l"
            label={username[0]}
            onPress={() => {
              setShow(true);
            }}
          />
          <View style={styles.usernameText}>
            <Text variant="semiBold" size="l">
              {username}
            </Text>
          </View>
          <Markdown
            content={
              splittedBio
                ? splittedBio.length > 3
                  ? `${splittedBio.slice(0, 3).join('\n')}...`
                  : bio
                  ? bio
                  : ''
                : ''
            }
            style={styles.bioContainer}
          />
          <View style={styles.buttonContainer}>
            {currentUser !== username && (
              <Button content={t('Message')} onPress={onPressNewMessage} />
            )}
            {
              // TODO: This LoC is meant for the next phase
              /* <View style={styles.buttonDivider} /> 
        <Button
          content={t('Badges')}
          style={styles.whiteButton}
          textColor="textNormal"
          disabled
        /> */
            }
          </View>
        </View>
        <Text variant={'semiBold'} style={styles.activityText}>
          {t('Activity')}
        </Text>
      </>
    );
  };

  let content;
  if (postActivities.length !== 0) {
    content = (
      <PostList
        ListHeaderComponent={<Header />}
        data={postActivities}
        showLabel={true}
        currentUser={username}
        onRefresh={onRefresh}
        refreshing={networkStatus === 4 || refreshing}
        scrollEventThrottle={16}
        alwaysBounceVertical={true}
        hasFooter={false}
        style={styles.fill}
        showImageRow
        onEndReachedThreshold={0.1}
        onEndReached={({ distanceFromEnd }) => onEndReached(distanceFromEnd)}
      />
    );
  } else {
    content = (
      <View style={styles.noActivity}>
        <Header />
        <Text style={styles.noActivityText}>
          {t("This user doesn't have any activity")}
        </Text>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      {content}
      {show && (
        <ShowImageModal
          show={show}
          userImage={{ uri: userImage }}
          onPressCancel={onPressCancel}
        />
      )}
    </View>
  );
}
Example #25
Source File: index.tsx    From nlw-01-omnistack with MIT License 4 votes vote down vote up
Points = () => {
  const [items, setItems] = useState<Item[]>([]);
  const [points, setPoints] = useState<Point[]>([]);
  const [selectedItems, setSelectedItems] = useState<number[]>([]);

  const [initialPosition, setInitialPosition] = useState<[number, number]>([0, 0]);

  const navigation = useNavigation();
  const route = useRoute();

  const routeParams = route.params as Params;

  useEffect(() => {
    async function loadPosition() {
      const { status } = await Location.requestPermissionsAsync();

      if (status !== 'granted') {
        Alert.alert('Oooops...', 'Precisamos de sua permissão para obter a localização');
        return;
      }

      const location = await Location.getCurrentPositionAsync();

      const { latitude, longitude } = location.coords;

      console.log(latitude, longitude);

      setInitialPosition([
        latitude,
        longitude
      ])
    }

    loadPosition();
  }, []);

  useEffect(() => {
    api.get('items').then(response => {
      setItems(response.data);
    });
  }, []);

  useEffect(() => {
    api.get('points', {
      params: {
        city: routeParams.city,
        uf: routeParams.uf,
        items: selectedItems
      }
    }).then(response => {
      setPoints(response.data);
    })
  }, [selectedItems]);

  function handleNavigateBack() {
    navigation.goBack();
  }

  function handleNavigateToDetail(id: number) {
    navigation.navigate('Detail', { point_id: id });
  }

  function handleSelectItem(id: number) {
    const alreadySelected = selectedItems.findIndex(item => item === id);

    if (alreadySelected >= 0) {
      const filteredItems = selectedItems.filter(item => item !== id);

      setSelectedItems(filteredItems);
    } else {
      setSelectedItems([ ...selectedItems, id ]);
    }
  }

  return (
    <>
      <View style={styles.container}>
        <TouchableOpacity onPress={handleNavigateBack}>
          <Icon name="arrow-left" size={20} color="#34cb79" />
        </TouchableOpacity>

        <Text style={styles.title}>Bem vindo.</Text>
        <Text style={styles.description}>Encontre no mapa um ponto de coleta.</Text>

        <View style={styles.mapContainer}>
          { initialPosition[0] !== 0 && (
            <MapView 
              style={styles.map} 
              initialRegion={{
                latitude: initialPosition[0],
                longitude: initialPosition[1],
                latitudeDelta: 0.014,
                longitudeDelta: 0.014,
              }}
            >
              {selectedItems[0] !== undefined && (points.map(point => (
                <Marker 
                  key={String(point.id)}
                  style={styles.mapMarker}
                  onPress={() => handleNavigateToDetail(point.id)}
                  coordinate={{ 
                    latitude: point.latitude,
                    longitude: point.longitude, 
                  }} 
                >
                  <View style={styles.mapMarkerContainer}>
                    <Image style={styles.mapMarkerImage} source={{ uri: point.image_url }} />
                    <Text style={styles.mapMarkerTitle}>{point.name}</Text>                
                  </View>
                </Marker>
              )))}
            </MapView>
          ) }
        </View>
      </View>
      <View style={styles.itemsContainer}>
        <ScrollView
          horizontal 
          showsHorizontalScrollIndicator={false}
          contentContainerStyle={{ paddingHorizontal: 20 }}
        >
          {items.map(item => (
            <TouchableOpacity 
              key={String(item.id)} 
              style={[
                styles.item,
                selectedItems.includes(item.id) ? styles.selectedItem : {}
              ]} 
              onPress={() => handleSelectItem(item.id)}
              activeOpacity={0.6}
            >
              <SvgUri width={42} height={42} uri={item.image_url} />
              <Text style={styles.itemTitle}>{item.title}</Text>
            </TouchableOpacity>
          ))}
        </ScrollView>
      </View>
    </>
  );
}
Example #26
Source File: index.tsx    From nlw-ecoleta with MIT License 4 votes vote down vote up
Points = () => {
  const [items, setItems] = useState<Item[]>([]);
  const [points, setPoints] = useState<Point[]>([]);
  const [selectedItems, setSelectedItems] = useState<number[]>([]);

  const  [initialPosition, setInitialPosition] = useState<[number, number]>([0, 0]);

  const navigation = useNavigation();
  const route = useRoute();

  const routeParams = route.params as Params;


    useEffect(() => {
      async function loadPosition(){
        const { status } = await Location.requestPermissionsAsync();

        if(status !== 'granted') {
          Alert.alert('Oooops...', 'Precisamos da sua permissão para obter a localização');
          return;
        }

        const location = await Location.getCurrentPositionAsync();
        const { latitude, longitude } = location.coords;

        setInitialPosition([
          latitude,
          longitude
        ])
      }

      loadPosition();
    }, []);
  
    useEffect(() => {
      api.get('items').then(response => {
          console.log(response.data);
          setItems(response.data);
      });
    }, []);

    useEffect(() => {
      api.get('points', {
        params: {
          city: routeParams.city,
          uf: routeParams.uf,
          items: selectedItems
        }
      }).then(response => {
        console.log(response.data);
        setPoints(response.data);
      })
    }, [selectedItems]);

    function handleNavigateBack() {
        navigation.goBack();
    }

    function handleNavigateToDetail(id: number) {
        navigation.navigate('Detail', { point_id: id });
    }

    function handleSelectItem(id: number) {
      const alreadySelected = selectedItems.findIndex(item => item === id);

      if (alreadySelected >= 0) {
          const filteredItems = selectedItems.filter(item => item  !== id);
          setSelectedItems(filteredItems);
      }

      else {
          setSelectedItems([ ...selectedItems, id ]);
      }
    }

    return (
        <SafeAreaView style={{ flex: 1 }}>
        <View style={styles.container}>

            <TouchableOpacity onPress={handleNavigateBack}>
                <Icon name="arrow-left" size={20} color="#34cb79" />
            </TouchableOpacity>

            <Text style={styles.title}>Bem vindo.</Text>
            <Text style={styles.description}>Encontre no mapa um ponto de coleta.</Text>

            <View style={styles.mapContainer}>
               { initialPosition[0] !== 0 && (
                  <MapView 
                  style={styles.map} 
                  initialRegion={{
                      latitude: initialPosition[0],
                      longitude: initialPosition[1],
                      latitudeDelta: 0.014,
                      longitudeDelta: 0.014,
                  }}
              >
                  {points.map(point => (
                    <Marker 
                      key={String(point.id)}
                      style={styles.mapMarker}
                      onPress={() => handleNavigateToDetail(point.id)}
                      coordinate={{  
                        latitude: point.latitude,
                        longitude: point.longitude, 
                      }}
                    >
                      <View style={styles.mapMarkerContainer}>
                        <Image style={styles.mapMarkerImage} source={{ uri: point.image_url }} /> 
                        <Text style={styles.mapMarkerTitle}>{point.name}</Text>   
                      </View>
                    </Marker>
                  ))}
              </MapView>
               ) }
            </View>
        </View>
        <View style={styles.itemsContainer}>
            <ScrollView
             horizontal 
             showsHorizontalScrollIndicator={false}
             contentContainerStyle={{ paddingHorizontal: 20 }}
             >
                {items.map(item => (
                  <TouchableOpacity 
                    key={String(item.id)} 
                    style={[
                      styles.item,
                      selectedItems.includes(item.id) ? styles.selectedItem : {} 
                    ]} 
                    onPress={() => handleSelectItem(item.id)}
                    activeOpacity={0.6}
                  >
                    <SvgUri width={42} height={42} uri={item.image_url} />
                    <Text style={styles.itemTitle}>{item.title}</Text>
                  </TouchableOpacity>
                ))}
            </ScrollView>
        </View>
    </SafeAreaView>
    );
}
Example #27
Source File: PostReply.tsx    From lexicon with MIT License 4 votes vote down vote up
export default function PostReply() {
  const { modal, setModal } = useModal();
  const styles = useStyles();
  const { colors } = useTheme();

  const navigation = useNavigation<RootStackNavProp<'PostReply'>>();
  const { navigate, goBack } = useNavigation<RootStackNavProp<'PostReply'>>();

  let {
    params: {
      title,
      topicId,
      post,
      focusedPostNumber,
      editPostId,
      oldContent = '',
      editedUser,
      hyperlinkTitle = '',
      hyperlinkUrl,
      imageUri = '',
    },
  } = useRoute<RootStackRouteProp<'PostReply'>>();

  const ios = Platform.OS === 'ios';

  const repliedPost = useMemo(() => {
    if (post) {
      return <RepliedPost hideAuthor replyTo={post} />;
    }
    return undefined;
  }, [post]);

  const storage = useStorage();
  const user = storage.getItem('user');

  const { authorizedExtensions } = useSiteSettings();
  const extensions = authorizedExtensions?.split('|');
  const normalizedExtensions = formatExtensions(extensions);

  const kasv = useKASVWorkaround();

  const [cursorPosition, setCursorPosition] = useState<CursorPosition>({
    start: 0,
    end: 0,
  });
  const [mentionLoading, setMentionLoading] = useState(false);
  const [mentionKeyword, setMentionKeyword] = useState('');

  const { control, handleSubmit, setValue, getValues, formState } = useForm<
    Form
  >({ mode: 'onChange' });

  const [imagesArray, setImagesArray] = useState<Array<Image>>([]);
  const [uri, setUri] = useState('');
  const [isValid, setValid] = useState(false);
  const [showUserList, setShowUserList] = useState(false);
  const [currentUploadToken, setCurrentUploadToken] = useState(1);

  const uploadsInProgress = imagesArray.filter((image) => !image.done).length;

  const [isKeyboardShow, setKeyboardShow] = useState(false);

  const debounced = useDebouncedCallback((value, token) => {
    if (imagesArray[token - 1]) {
      reformatMarkdownAfterUpload(value, imagesArray, token, setValue);
    }
  }, 1500);

  const postReplyRef = useRef<TextInputType>(null);

  const { upload, tempArray, completedToken } = useStatefulUpload(
    imagesArray,
    currentUploadToken,
  );

  useEffect(() => {
    const { raw } = getValues();
    if (completedToken) {
      debounced(raw, completedToken);
    }
    setImagesArray(tempArray);
  }, [getValues, tempArray, debounced, completedToken]);

  useEffect(() => setUri(imageUri), [imageUri]);

  const { mentionMembers } = useMention(
    mentionKeyword,
    showUserList,
    setMentionLoading,
  );

  useEffect(() => {
    if (!uri || !user) {
      return;
    }
    setImagesArray([...imagesArray, { link: '', done: false }]);
    setCurrentUploadToken(currentUploadToken + 1);
    const reactNativeFile = createReactNativeFile(uri);
    const { raw } = getValues();
    reformatMarkdownBeforeUpload(
      raw,
      cursorPosition.start,
      imagesArray,
      setValue,
    );
    upload({
      variables: {
        file: reactNativeFile,
        userId: user.id || 0,
        type: UploadTypeEnum.composer,
        token: currentUploadToken,
      },
    });
    setUri('');
  }, [
    currentUploadToken,
    cursorPosition.start,
    imagesArray,
    getValues,
    setValue,
    upload,
    uploadsInProgress,
    uri,
    user,
  ]);

  if (hyperlinkUrl) {
    let { newUrl, newTitle } = getHyperlink(hyperlinkUrl, hyperlinkTitle);
    hyperlinkUrl = newUrl;
    hyperlinkTitle = newTitle;
  }

  useEffect(() => {
    setModal(true);
  }, [setModal]);

  useEffect(() => {
    let postReplyObject = getValues();
    let result = insertHyperlink(
      postReplyObject.raw,
      hyperlinkTitle,
      hyperlinkUrl,
    );
    setValue('raw', result);
  }, [hyperlinkTitle, hyperlinkUrl, getValues, setValue]);

  const onNavigate = (
    screen: 'PostImagePreview' | 'HyperLink',
    params:
      | RootStackParamList['PostImagePreview']
      | RootStackParamList['HyperLink'],
  ) => {
    navigate(screen, params);
  };

  const { onInsertImage, onInsertLink } = bottomMenu(
    isKeyboardShow,
    user,
    onNavigate,
    'PostReply',
    normalizedExtensions,
    title,
    topicId,
    post,
  );

  useEffect(
    () =>
      navigation.addListener('beforeRemove', (e) => {
        if (
          (!isValid || !formState.isValid || !modal) &&
          uploadsInProgress < 1
        ) {
          return;
        }
        e.preventDefault();
        Alert.alert(
          t('Discard Post Reply?'),
          t('Are you sure you want to discard your post reply?'),
          [
            { text: t('Cancel') },
            {
              text: t('Discard'),
              onPress: () => navigation.dispatch(e.data.action),
            },
          ],
        );
      }),
    [formState.isValid, isValid, modal, navigation, uploadsInProgress],
  );

  const getData = () => {
    const { raw } = getValues();
    return {
      title,
      content: raw,
      topicId,
      post,
      createdAt: new Date().toISOString(),
    };
  };

  const onPreview = handleSubmit(() => {
    Keyboard.dismiss();
    navigate('PostPreview', {
      reply: true,
      postData: getData(),
      focusedPostNumber,
      editPostId,
      editedUser,
    });
  });

  useEffect(() => {
    const { raw: content } = getValues();
    let isValid;
    if (editPostId) {
      isValid = existingPostIsValid(
        uploadsInProgress,
        title,
        title,
        content,
        oldContent,
      );
    } else {
      isValid = newPostIsValid(title, content, uploadsInProgress);
    }
    setValid(isValid);
  }, [editPostId, getValues, oldContent, title, uploadsInProgress]);

  return (
    <SafeAreaView style={styles.container}>
      <CustomHeader
        title={editPostId ? t('Edit Post') : t('Reply')}
        rightTitle={t('Next')}
        onPressRight={onPreview}
        disabled={!isValid}
        noShadow
      />
      {ios && (
        <ModalHeader
          title={editPostId ? t('Edit Post') : t('Reply')}
          left={<HeaderItem label={t('Cancel')} onPressItem={goBack} left />}
          right={
            <HeaderItem
              label={t('Next')}
              onPressItem={onPreview}
              disabled={!isValid}
            />
          }
        />
      )}
      <KeyboardTextAreaScrollView
        {...kasv.props}
        bottomMenu={
          <View>
            <MentionList
              showUserList={showUserList}
              members={mentionMembers}
              mentionLoading={mentionLoading}
              rawText={getValues('raw')}
              textRef={postReplyRef}
              setMentionValue={setValue}
              setShowUserList={setShowUserList}
            />
            <BottomMenu
              onInsertImage={onInsertImage}
              onInsertLink={onInsertLink}
            />
          </View>
        }
      >
        <IconWithLabel
          icon="Replies"
          color={colors.textLighter}
          label={title}
          fontStyle={styles.title}
          style={styles.titleContainer}
          numberOfLines={1}
        />
        <Divider style={styles.spacingBottom} horizontalSpacing="xxl" />
        {repliedPost}
        <Controller
          name="raw"
          defaultValue={oldContent}
          rules={{ required: true }}
          control={control}
          render={({ onChange, value }) => (
            <TextArea
              value={value}
              large
              isKeyboardShow={isKeyboardShow}
              inputRef={postReplyRef}
              placeholder={t('Share your thoughts')}
              onChangeValue={(text) => {
                mentionHelper(
                  text,
                  cursorPosition,
                  setShowUserList,
                  setMentionLoading,
                  setMentionKeyword,
                );
                onChange(text);
                debounced(text, currentUploadToken);
                let isValid;
                if (editPostId) {
                  isValid = existingPostIsValid(
                    uploadsInProgress,
                    title,
                    title,
                    text,
                    oldContent,
                  );
                } else {
                  isValid = newPostIsValid(title, text, uploadsInProgress);
                }
                setValid(isValid);
              }}
              onFocus={(event) => {
                setKeyboardShow(true);
                kasv.scrollToFocusedInput(event);
              }}
              onBlur={() => {
                setKeyboardShow(false);
              }}
              onSelectedChange={(cursor) => {
                setCursorPosition(cursor);
              }}
              style={styles.markdownContainer}
              mentionToggled={showUserList}
            />
          )}
        />
      </KeyboardTextAreaScrollView>
    </SafeAreaView>
  );
}
Example #28
Source File: OrphanageData.tsx    From nlw-03-omnistack with MIT License 4 votes vote down vote up
export default function OrphanageData() {
  const route = useRoute();
  const navigation = useNavigation();

  const [open_on_weekends, setOpenOnWeekends] = useState(false);

  const params = route.params as OrphanageDataRouteParams;
  const position = params.position;

  function handleCreateOrphanage() {
    // todo
  }

  async function handleSelectImages() {
    const { status } = await ImagePicker.requestCameraRollPermissionsAsync();

    if (status !== 'granted') {
      alert('Eita! Precisamos de acesso às suas fotos...');
    }

    const result = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      quality: 1,
    });

    console.log(result);
  }

  return (
    <ScrollView style={styles.container} contentContainerStyle={{ padding: 24 }}>
      <Text style={styles.title}>Dados</Text>

      <Text style={styles.label}>Nome</Text>
      <TextInput
        style={styles.input}
      />

      <Text style={styles.label}>Sobre</Text>
      <TextInput
        style={[styles.input, { height: 110 }]}
        multiline
      />

      <Text style={styles.label}>Whatsapp</Text>
      <TextInput
        style={styles.input}
      />

      <Text style={styles.label}>Fotos</Text>
      <TouchableOpacity style={styles.imagesInput} onPress={handleSelectImages}>
        <Feather name="plus" size={24} color="#15B6D6" />
      </TouchableOpacity>

      <Text style={styles.title}>Visitação</Text>

      <Text style={styles.label}>Instruções</Text>
      <TextInput
        style={[styles.input, { height: 110 }]}
        multiline
      />

      <Text style={styles.label}>Horario de visitas</Text>
      <TextInput
        style={styles.input}
      />

      <View style={styles.switchContainer}>
        <Text style={styles.label}>Atende final de semana?</Text>
        <Switch 
          thumbColor="#fff" 
          trackColor={{ false: '#ccc', true: '#39CC83' }}
          value={open_on_weekends}
          onValueChange={setOpenOnWeekends}
        />
      </View>

      <RectButton style={styles.nextButton} onPress={handleCreateOrphanage}>
        <Text style={styles.nextButtonText}>Cadastrar</Text>
      </RectButton>
    </ScrollView>
  )
}
Example #29
Source File: AddEditAddressScene.tsx    From sellflow with MIT License 4 votes vote down vote up
export default function AddEditAddressScene() {
  let { authToken: customerAccessToken } = useAuth();
  let { navigate, setOptions } = useNavigation<
    StackNavProp<'AddEditAddress'>
  >();
  let {
    params: { address, rootScene },
  } = useRoute<StackRouteProp<'AddEditAddress'>>();

  let [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
  let [isCountryModalVisible, setIsCountryModalVisible] = useState(false);
  let [addressData, setAddressData] = useState<
    Omit<AddressItem, 'id' | 'name'>
  >(newAddress);
  let [isModalVisible, setIsModalVisible] = useState(false);
  let [errorMessage, setErrorMessage] = useState('');
  let [bottomButtonHeight, setBottomButtonHeight] = useState(0);

  let isAddressDataEmpty =
    addressData.address1 === '' ||
    addressData.city === '' ||
    addressData.country === '' ||
    addressData.firstName === '' ||
    addressData.lastName === '' ||
    addressData.phone === '' ||
    addressData.province === '' ||
    addressData.zip === '';

  let lastNameRef = useRef<TextInputType>(null);
  let address1Ref = useRef<TextInputType>(null);
  let provinceRef = useRef<TextInputType>(null);
  let cityRef = useRef<TextInputType>(null);
  let zipRef = useRef<TextInputType>(null);
  let phoneRef = useRef<TextInputType>(null);

  let {
    addNewAddress,
    loading: loadingAddNewAddress,
  } = useCustomerAddNewAddress();

  let { editAddress, loading: loadingEditAddress } = useCustomerEditAddress({
    onCompleted: () => {
      navigate(rootScene);
    },
  });

  let toggleModalVisible = () => setIsModalVisible(!isModalVisible);

  let {
    customerAddressDelete,
    loading: loadingDeleteAddress,
  } = useCustomerAddressDelete({
    onCompleted: () => {
      navigate(rootScene);
    },
  });

  useEffect(() => {
    if (address) {
      setAddressData({
        firstName: address.firstName,
        lastName: address.lastName,
        address1: address.address1,
        city: address.city,
        province: address.province,
        zip: address.zip,
        country: address.country,
        phone: address.phone,
      });
    }
  }, [address]);

  let toggleDeleteModal = () => {
    setIsDeleteModalVisible(!isDeleteModalVisible);
  };

  let toggleCountryModal = () => {
    setIsCountryModalVisible(!isCountryModalVisible);
  };

  let onPressCancel = () => {
    toggleDeleteModal();
  };

  let onPressDelete = () => {
    toggleDeleteModal();
    customerAddressDelete({
      variables: { id: address?.id ?? '', customerAccessToken },
    });
  };

  let onPressCountry = (country: string) => {
    toggleCountryModal();
    setAddressData({ ...addressData, country });
    provinceRef.current && provinceRef.current.focus();
  };

  let onPressSaveAddress = async () => {
    if (address === undefined) {
      let result = await addNewAddress({
        variables: {
          customerAccessToken,
          address: addressData,
        },
      });

      let customerUserErrors =
        result?.data?.customerAddressCreate?.customerUserErrors;

      if (customerUserErrors && customerUserErrors.length > 0) {
        setErrorMessage(customerUserErrors[0].message);
        toggleModalVisible();
      } else {
        navigate(rootScene);
      }
    } else {
      let result = await editAddress({
        variables: {
          id: address?.id ?? '',
          customerAccessToken,
          address: addressData,
        },
      });

      let customerUserErrors =
        result?.data?.customerAddressUpdate?.customerUserErrors;

      if (customerUserErrors && customerUserErrors.length > 0) {
        setErrorMessage(customerUserErrors[0].message);
        toggleModalVisible();
      } else {
        navigate(rootScene);
      }
    }
  };
  useEffect(() => {
    setOptions({
      title: address == null ? t('New Address') : t('Edit Address'),
      headerRight: () => {
        return address != null ? (
          <Text
            weight="medium"
            style={styles.headerRightText}
            onPress={toggleDeleteModal}
          >
            {t('Delete')}
          </Text>
        ) : null;
      },
    });
  });

  if (loadingDeleteAddress) {
    return <ActivityIndicator style={styles.centered} />;
  }

  return (
    <KeyboardAvoidingView keyboardVerticalOffset={bottomButtonHeight}>
      <ModalBottomSheet
        title={t('An Error Occured!')}
        isModalVisible={isModalVisible}
        toggleModal={toggleModalVisible}
      >
        <ModalBottomSheetMessage
          isError={true}
          message={errorMessage}
          onPressModalButton={toggleModalVisible}
          buttonText={t('Close')}
        />
      </ModalBottomSheet>
      <DeleteAddressModal
        deleteVisible={isDeleteModalVisible}
        toggleModal={toggleDeleteModal}
        onPressCancel={onPressCancel}
        onPressDelete={onPressDelete}
      />
      <CountryModal
        countryVisible={isCountryModalVisible}
        toggleModal={toggleCountryModal}
        onPressCountry={onPressCountry}
      />
      <ScrollView
        style={styles.scrollView}
        showsVerticalScrollIndicator={false}
      >
        <TextInput
          onSubmitEditing={() => {
            lastNameRef.current && lastNameRef.current.focus();
          }}
          returnKeyType="next"
          mode="flat"
          label={t('First Name')}
          labelStyle={textInputLabel}
          value={addressData.firstName}
          onChangeText={(firstName: string) =>
            setAddressData({ ...addressData, firstName })
          }
          containerStyle={flatTextInputContainerStyle}
          style={flatTextInputStyle}
        />
        <TextInput
          onSubmitEditing={() => {
            address1Ref.current && address1Ref.current.focus();
          }}
          ref={lastNameRef}
          returnKeyType="next"
          mode="flat"
          label={t('Last Name')}
          labelStyle={textInputLabel}
          value={addressData.lastName}
          onChangeText={(lastName: string) =>
            setAddressData({ ...addressData, lastName })
          }
          containerStyle={flatTextInputContainerStyle}
          style={flatTextInputStyle}
        />
        <TextInput
          onSubmitEditing={toggleCountryModal}
          returnKeyType="next"
          ref={address1Ref}
          mode="flat"
          label={t('Address')}
          labelStyle={textInputLabel}
          value={addressData.address1}
          onChangeText={(address1: string) =>
            setAddressData({ ...addressData, address1 })
          }
          containerStyle={flatTextInputContainerStyle}
          style={flatTextInputStyle}
          autoCapitalize="words"
        />
        <TouchableOpacity onPress={toggleCountryModal}>
          <TextInput
            mode="flat"
            label={t('Country')}
            labelStyle={textInputLabel}
            value={addressData.country}
            pointerEvents="none"
            editable={false}
            containerStyle={flatTextInputContainerStyle}
            style={flatTextInputStyle}
          />
        </TouchableOpacity>
        <TextInput
          onSubmitEditing={() => {
            cityRef.current && cityRef.current.focus();
          }}
          returnKeyType="next"
          ref={provinceRef}
          mode="flat"
          label={t('State / Province')}
          labelStyle={textInputLabel}
          value={addressData.province}
          onChangeText={(province: string) =>
            setAddressData({ ...addressData, province })
          }
          containerStyle={flatTextInputContainerStyle}
          style={flatTextInputStyle}
          autoCapitalize="words"
        />
        <TextInput
          onSubmitEditing={() => {
            zipRef.current && zipRef.current.focus();
          }}
          returnKeyType="next"
          ref={cityRef}
          mode="flat"
          label={t('City')}
          labelStyle={textInputLabel}
          value={addressData.city}
          onChangeText={(city: string) =>
            setAddressData({ ...addressData, city })
          }
          containerStyle={flatTextInputContainerStyle}
          style={flatTextInputStyle}
          autoCapitalize="words"
        />
        <TextInput
          onSubmitEditing={() => {
            phoneRef.current && phoneRef.current.focus();
          }}
          returnKeyType="next"
          ref={zipRef}
          mode="flat"
          label={t('Postal / Zip Code')}
          labelStyle={textInputLabel}
          value={addressData.zip}
          onChangeText={(zip: string) =>
            setAddressData({ ...addressData, zip })
          }
          containerStyle={flatTextInputContainerStyle}
          style={flatTextInputStyle}
        />
        <TextInput
          returnKeyType="done"
          ref={phoneRef}
          mode="flat"
          label={t('Phone Number')}
          labelStyle={textInputLabel}
          value={addressData.phone}
          onChangeText={(phone: string) =>
            setAddressData({ ...addressData, phone })
          }
          keyboardType="number-pad"
          textContentType="telephoneNumber"
          containerStyle={flatTextInputContainerStyle}
          style={flatTextInputStyle}
        />
      </ScrollView>
      <View
        onLayout={({ nativeEvent }) =>
          setBottomButtonHeight(nativeEvent.layout.height)
        }
      >
        <Button
          style={[defaultButton, styles.buttonStyle]}
          labelStyle={defaultButtonLabel}
          onPress={onPressSaveAddress}
          disabled={isAddressDataEmpty}
          loading={loadingAddNewAddress || loadingEditAddress}
        >
          <Text weight="medium" style={styles.buttonText}>
            {!loadingAddNewAddress && !loadingEditAddress && t('Save Address')}
          </Text>
        </Button>
      </View>
    </KeyboardAvoidingView>
  );
}