From 19b2c3c41fa4a2edd8b757289f96f6e072ee8617 Mon Sep 17 00:00:00 2001 From: Pablo Velez Vidal Date: Tue, 25 Oct 2022 14:06:52 +0200 Subject: [PATCH] Add the paginator --- app/screens/onboarding/form.tsx | 237 --------------------------- app/screens/onboarding/index.tsx | 44 +++-- app/screens/onboarding/paginator.tsx | 41 +++++ app/screens/onboarding/slide.tsx | 2 + 4 files changed, 76 insertions(+), 248 deletions(-) delete mode 100644 app/screens/onboarding/form.tsx create mode 100644 app/screens/onboarding/paginator.tsx diff --git a/app/screens/onboarding/form.tsx b/app/screens/onboarding/form.tsx deleted file mode 100644 index 9285a8c65..000000000 --- a/app/screens/onboarding/form.tsx +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {MutableRefObject, useCallback, useEffect, useRef} from 'react'; -import {useIntl} from 'react-intl'; -import {Keyboard, Platform, useWindowDimensions, View} from 'react-native'; -import Button from 'react-native-button'; -import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view'; - -import FloatingTextInput, {FloatingTextInputRef} from '@components/floating_text_input_label'; -import FormattedText from '@components/formatted_text'; -import Loading from '@components/loading'; -import {useIsTablet} from '@hooks/device'; -import {t} from '@i18n'; -import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles'; -import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; -import {typography} from '@utils/typography'; - -type Props = { - autoFocus?: boolean; - buttonDisabled: boolean; - connecting: boolean; - displayName?: string; - displayNameError?: string; - handleConnect: () => void; - handleDisplayNameTextChanged: (text: string) => void; - handleUrlTextChanged: (text: string) => void; - keyboardAwareRef: MutableRefObject; - theme: Theme; - url?: string; - urlError?: string; -}; - -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - formContainer: { - alignItems: 'center', - maxWidth: 600, - width: '100%', - paddingHorizontal: 20, - }, - enterServer: { - marginBottom: 24, - }, - fullWidth: { - width: '100%', - }, - error: { - marginBottom: 18, - }, - chooseText: { - alignSelf: 'flex-start', - color: changeOpacity(theme.centerChannelColor, 0.64), - marginTop: 8, - ...typography('Body', 75, 'Regular'), - }, - connectButton: { - backgroundColor: changeOpacity(theme.centerChannelColor, 0.08), - width: '100%', - marginTop: 32, - marginLeft: 20, - marginRight: 20, - padding: 15, - }, - connectingIndicator: { - marginRight: 10, - }, - loadingContainerStyle: { - marginRight: 10, - padding: 0, - top: -2, - }, -})); - -const ServerForm = ({ - autoFocus = false, - buttonDisabled, - connecting, - displayName = '', - displayNameError, - handleConnect, - handleDisplayNameTextChanged, - handleUrlTextChanged, - keyboardAwareRef, - theme, - url = '', - urlError, -}: Props) => { - const {formatMessage} = useIntl(); - const isTablet = useIsTablet(); - const dimensions = useWindowDimensions(); - const displayNameRef = useRef(null); - const urlRef = useRef(null); - const styles = getStyleSheet(theme); - - const focus = () => { - if (Platform.OS === 'ios') { - let offsetY = 160; - if (isTablet) { - const {width, height} = dimensions; - const isLandscape = width > height; - offsetY = isLandscape ? 230 : 100; - } - requestAnimationFrame(() => { - keyboardAwareRef.current?.scrollToPosition(0, offsetY); - }); - } - }; - - const onBlur = useCallback(() => { - if (Platform.OS === 'ios') { - const reset = !displayNameRef.current?.isFocused() && !urlRef.current?.isFocused(); - if (reset) { - keyboardAwareRef.current?.scrollToPosition(0, 0); - } - } - }, []); - - const onConnect = useCallback(() => { - Keyboard.dismiss(); - handleConnect(); - }, [buttonDisabled, connecting, displayName, theme, url]); - - const onFocus = useCallback(() => { - focus(); - }, [dimensions]); - - const onUrlSubmit = useCallback(() => { - displayNameRef.current?.focus(); - }, []); - - useEffect(() => { - if (Platform.OS === 'ios' && isTablet) { - if (urlRef.current?.isFocused() || displayNameRef.current?.isFocused()) { - focus(); - } else { - keyboardAwareRef.current?.scrollToPosition(0, 0); - } - } - }, [dimensions, isTablet]); - - const buttonType = buttonDisabled ? 'disabled' : 'default'; - const styleButtonText = buttonTextStyle(theme, 'lg', 'primary', buttonType); - const styleButtonBackground = buttonBackgroundStyle(theme, 'lg', 'primary', buttonType); - - let buttonID = t('mobile.components.select_server_view.connect'); - let buttonText = 'Connect'; - let buttonIcon; - - if (connecting) { - buttonID = t('mobile.components.select_server_view.connecting'); - buttonText = 'Connecting'; - buttonIcon = ( - - ); - } - - const connectButtonTestId = buttonDisabled ? 'server_form.connect.button.disabled' : 'server_form.connect.button'; - - return ( - - - - - - - - {!displayNameError && - - } - - - ); -}; - -export default ServerForm; diff --git a/app/screens/onboarding/index.tsx b/app/screens/onboarding/index.tsx index 08f8ea1c5..55a7b44ca 100644 --- a/app/screens/onboarding/index.tsx +++ b/app/screens/onboarding/index.tsx @@ -1,15 +1,16 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useCallback, useRef} from 'react'; -import {Platform, Text, View, FlatList, ScrollView, ListRenderItemInfo} from 'react-native'; -import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; +import React, {useCallback, useRef, useState} from 'react'; +import {Platform, Text, View, FlatList, Animated, ListRenderItemInfo, ViewToken} from 'react-native'; +import {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import {SafeAreaView} from 'react-native-safe-area-context'; import {generateId} from '@app/utils/general'; import Background from '@screens/background'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; +import Paginator from './paginator'; import SlideItem from './slide'; import slidesData from './slides_data'; @@ -25,6 +26,8 @@ const Onboarding = ({ }: OnboardingProps) => { const translateX = useSharedValue(0); const styles = getStyleSheet(theme); + const [currentIndex, setCurrentIndex] = useState(0); + const slidesRef = useRef(null); const transform = useAnimatedStyle(() => { const duration = Platform.OS === 'android' ? 250 : 350; @@ -33,24 +36,32 @@ const Onboarding = ({ }; }, []); - const renderSlide = useCallback(({item: t}: ListRenderItemInfo) => { + const renderSlide = useCallback(({item: i}: ListRenderItemInfo) => { return ( ); }, []); + const scrollX = useRef(new Animated.Value(0)).current; + + const viewableItemsChanged = useRef(({viewableItems}: any) => { + setCurrentIndex(viewableItems[0].index); + }).current; + + const viewConfig = useRef({viewAreaCoveragePercentThreshold: 50}).current; + return ( item.id} @@ -61,20 +72,31 @@ const Onboarding = ({ showsHorizontalScrollIndicator={true} pagingEnabled={true} bounces={false} + onScroll={Animated.event([{nativeEvent: {contentOffset: {x: scrollX}}}], { + useNativeDriver: false, + })} + onViewableItemsChanged={viewableItemsChanged} + viewabilityConfig={viewConfig} + scrollEventThrottle={32} + ref={slidesRef} /> + ); }; const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - appInfo: { - color: changeOpacity(theme.centerChannelColor, 0.56), - }, - flex: { + onBoardingContainer: { flex: 1, + alignItems: 'center', + justifyContent: 'center', }, scrollContainer: { + flex: 1, alignItems: 'center', height: '100%', justifyContent: 'center', diff --git a/app/screens/onboarding/paginator.tsx b/app/screens/onboarding/paginator.tsx new file mode 100644 index 000000000..31ca744d0 --- /dev/null +++ b/app/screens/onboarding/paginator.tsx @@ -0,0 +1,41 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {View} from 'react-native'; + +import {makeStyleSheetFromTheme} from '@utils/theme'; + +type Props = { + data: any; + theme: Theme; +}; + +const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ + dot: { + height: 10, + borderRadius: 5, + backgroundColor: theme.buttonBg, + marginHorizontal: 8, + width: 10, + }, +})); + +const Paginator = ({theme, data}: Props) => { + const styles = getStyleSheet(theme); + + return ( + + {data.map((item: any) => { + return ( + + ); + })} + + ); +}; + +export default Paginator; diff --git a/app/screens/onboarding/slide.tsx b/app/screens/onboarding/slide.tsx index 039baae95..085a2b0fe 100644 --- a/app/screens/onboarding/slide.tsx +++ b/app/screens/onboarding/slide.tsx @@ -33,6 +33,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ }, itemContainer: { flex: 1, + alignItems: 'center', + justifyContent: 'center', }, }));