react-native#Easing JavaScript Examples

The following examples show how to use react-native#Easing. 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: react-native-ring-picker.js    From react-native-ring-picker with GNU General Public License v3.0 6 votes vote down vote up
calculateIconCurrentPositions(dx) {
        function extractCorrectRestDisplacementThreshold(dx) {
            if (!dx || (dx => 0 && dx <= 1)) {
                return 1;
            }

            return 10;
        }

        this.state.icons.forEach((icon) => {
            let coordinates = this.calculateIconCurrentPosition(icon);

            Animated.spring(icon.position, {
                toValue : {
                    x : coordinates.left,
                    y : coordinates.top
                },
                easing : Easing.linear,
                speed : 30,
                restSpeedThreshold : 10,
                bounciness : 0,
                restDisplacementThreshold : extractCorrectRestDisplacementThreshold(dx)
            }).start((finish) => finish.finished
                && typeof this.ALL_ICONS_FINISH_ANIMATIONS.resolvers[icon.id] === "function"
                && this.ALL_ICONS_FINISH_ANIMATIONS.resolvers[icon.id]());
        });
    }
Example #2
Source File: GameHome.js    From FlappyFace with MIT License 6 votes vote down vote up
componentDidMount() {
    Animated.timing(this.onLoad, {
      duration: 1000,
      toValue: new Animated.Value(1),
      useNativeDriver: true,
      easing: Easing.bounce,
    }).start();

    this.props.navigation.addListener('focus', () => {
      SoundPlayer.playSoundFile('point', 'wav');
      Animated.timing(this.onPlay, {
        duration: 500,
        toValue: 0,
        useNativeDriver: true,
      }).start(() => {
        Animated.timing(this.onLoad, {
          duration: 1000,
          toValue: new Animated.Value(1),
          useNativeDriver: true,
          easing: Easing.bounce,
        }).start();
      });
    });
  }
Example #3
Source File: react-native-ring-picker.js    From react-native-ring-picker with GNU General Public License v3.0 6 votes vote down vote up
animateAllIconsToMatchVerticalAxis(currentSnappedIcon) {
        Animated.spring(this.state.pan, {
            toValue : this.CURRENT_VECTOR_DIFFERENCE_LENGTH,
            easing : Easing.linear,
            speed : 12
            // useNativeDriver: true // if this is used - the last click after previous release will twist back nad forward
        }).start();
        this.setState({
            ...this.state,
            CURRENT_ICON_SHIFT : this.CURRENT_VECTOR_DIFFERENCE_LENGTH / this.STEP_LENGTH_TO_1_ANGLE,
            currentSnappedIcon : currentSnappedIcon
        }, () => this.calculateIconCurrentPositions());
    }
Example #4
Source File: rotation.js    From astrale with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Fades a set of children to the top
 * @param children {Array<React.ReactElement>}
 * @param rotate {boolean}
 * @param style {object}
 * @returns {*}
 * @constructor
 */
function Rotation({ children, rotate, style }) {
  const spinAnim = React.useRef(new Animated.Value(0)).current;

  React.useEffect(() => {
    Animated.timing(spinAnim, {
      toValue: rotate ? 1 : 0,
      easing: Easing.linear,
      duration: 250000,
      useNativeDriver: true,
    }).start();
  }, [rotate, spinAnim]);

  const spinInterpolate = spinAnim.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '10000deg'],
  });

  return (
    <Animated.View
      style={[style, { transform: [{ rotate: spinInterpolate }] }]}
    >
      {children}
    </Animated.View>
  );
}
Example #5
Source File: fade.js    From astrale with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Fades a set of children to the top
 * @param children {Array<React.ReactElement>}
 * @param fadeToTop {boolean}
 * @returns {*}
 * @constructor
 */
function Fade({ children, show }) {
  const fadeAnim = React.useRef(new Animated.Value(0)).current;

  React.useEffect(() => {
    Animated.timing(fadeAnim, {
      toValue: show ? 1 : 0,
      easing: Easing.ease,
      duration: 500,
      useNativeDriver: true,
    }).start();
  }, [fadeAnim, show]);

  return (
    <Animated.View
      style={[
        {
          flex: 1,
          paddingVertical: 10,
          opacity: fadeAnim,
        },
      ]}
    >
      {children}
    </Animated.View>
  );
}
Example #6
Source File: hook.js    From react-native-loop-game with MIT License 6 votes vote down vote up
export default function useHook(toggle) {
  const [mount, setMount] = useState(toggle);
  const [header, setHeader] = useState(false);
  const [animation] = useState(new Animated.Value(0.0));

  useEffect(() => {
    if (toggle) {
      setMount(true);
    }
    Animated.timing(animation, {
      toValue: toggle ? 1.0 : 0.0,
      duration: 400,
      ease: Easing.ease,
    }).start((e) => {
      if (e.finished && !toggle) {
        setMount(false);
      }
    });
  });
  return useMemo(() => ({
    mount,
    header,
    animation,
    setHeader,
  }));
}
Example #7
Source File: Modal.js    From actual with MIT License 6 votes vote down vote up
componentDidMount() {
    if (this.props.animate) {
      Animated.timing(this.opening, {
        toValue: 1,
        duration: 200,
        easing: Easing.bezier(0.25, 0.1, 0.25, 1.0)
      }).start();
    }
  }
Example #8
Source File: AnimatedLoading.mobile.js    From actual with MIT License 6 votes vote down vote up
animate() {
    this.rotation.setValue(-0.15);
    Animated.timing(this.rotation, {
      toValue: 1.85,
      duration: 1600,
      easing: Easing.bezier(0.17, 0.67, 0.83, 0.67),
      useNativeDriver: true
    }).start(() => this.animate());
  }
Example #9
Source File: AnimatedLoading.mobile.js    From actual with MIT License 6 votes vote down vote up
animate() {
    this.rotation.setValue(-0.15);
    Animated.timing(this.rotation, {
      toValue: 1.85,
      duration: 1600,
      easing: Easing.bezier(0.17, 0.67, 0.83, 0.67),
      useNativeDriver: true
    }).start(() => this.animate());
  }
Example #10
Source File: index.rn.jsx    From taro-form with MIT License 6 votes vote down vote up
animate() {
    this.animatedValue.setValue(1)
    Animated.timing(
      this.animatedValue,
      {
        toValue: 8,
        duration: 800,
        easing: Easing.linear,
        useNativeDriver: true
      }
    ).start(() => this.animate())
  }
Example #11
Source File: Modal.js    From actual with MIT License 5 votes vote down vote up
close() {
    Animated.timing(this.opening, {
      toValue: 0,
      duration: 200,
      easing: Easing.bezier(0.25, 0.1, 0.25, 1.0)
    }).start();
  }
Example #12
Source File: index.js    From rn-snackbar-component with MIT License 5 votes vote down vote up
easingValues = {
  entry: Easing.bezier(0.0, 0.0, 0.2, 1),
  exit: Easing.bezier(0.4, 0.0, 1, 1),
}
Example #13
Source File: Menu.js    From react-native-beauty-webview with MIT License 5 votes vote down vote up
EASING = Easing.bezier(0.4, 0, 0.2, 1)
Example #14
Source File: fade-to-top.js    From astrale with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Fades a set of children to the top
 * @param children {Array<React.ReactElement>}
 * @param fadeToTop {boolean}
 * @param initialHeight {number}
 * @param finalHeight {number}
 * @returns {*}
 * @constructor
 */
function FadeToTop({ children, fadeToTop, initialHeight, finalHeight }) {
  const fadeAnim = React.useRef(new Animated.Value(0)).current;

  React.useEffect(() => {
    Animated.timing(fadeAnim, {
      toValue: fadeToTop ? 1 : 0,
      easing: Easing.ease,
      duration: 500,
      useNativeDriver: true,
    }).start();
  }, [fadeAnim, fadeToTop]);

  return (
    <Animated.View
      style={[
        {
          flex: 1,
          opacity: fadeAnim.interpolate({
            inputRange: [0, 1],
            outputRange: [1, 0],
          }),
          height: fadeAnim.interpolate({
            inputRange: [0, 1],
            outputRange: [initialHeight, finalHeight],
          }),
        },
      ]}
    >
      {children}
    </Animated.View>
  );
}
Example #15
Source File: Icon.js    From monsuivipsy with Apache License 2.0 5 votes vote down vote up
Icon = ({
  icon,
  color,
  styleContainer,
  spin,
  badge = false,
  onPress,
  activeOpacity = 0.4,
  ...props
}) => {
  const [spinFn, setSpinFn] = useState(null);

  useEffect(() => {
    if (spin === undefined) return;

    const spinValue = new Animated.Value(spin ? 0 : 1);

    Animated.timing(spinValue, {
      toValue: spin ? 1 : 0,
      duration: 200,
      easing: Easing.linear, // Easing is an additional import from react-native
      useNativeDriver: true, // To make use of native driver for performance
    }).start();

    setSpinFn(
      spinValue.interpolate({
        inputRange: [0, 1],
        outputRange: ["0deg", "45deg"],
      })
    );
  }, [spin]);

  const Icon = mapIconToSvg(icon);

  const render = () => (
    <Animated.View
      style={[styles.iconContainer, styleContainer, spinFn && { transform: [{ rotate: spinFn }] }]}
    >
      {badge ? <View style={styles.badge}>{/* <Text style={styles.badgeText}></Text> */}</View> : null}
      <Icon width={20} height={20} color={color || "black"} {...props} />
    </Animated.View>
  );

  return onPress ? (
    <TouchableOpacity activeOpacity={activeOpacity} onPress={onPress}>
      {render()}
    </TouchableOpacity>
  ) : (
    render()
  );
}
Example #16
Source File: show-from-top.js    From astrale with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Fades a set of children to the top
 * @param children {Array<React.ReactElement>}
 * @param duration {number}
 * @returns {*}
 * @constructor
 */
function ShowFromTop({ children, duration }) {
  const fadeAnim = React.useRef(new Animated.Value(0)).current;

  Animated.timing(fadeAnim, {
    toValue: 1,
    easing: Easing.linear,
    duration,
    useNativeDriver: true,
  }).start();

  return (
    <Animated.View
      style={[
        {
          flex: 1,
          opacity: fadeAnim.interpolate({
            inputRange: [0, 1],
            outputRange: [0, 1],
          }),
          transform: [
            {
              translateY: fadeAnim.interpolate({
                inputRange: [0, 1],
                outputRange: [-25, 0],
              }),
            },
          ],
        },
      ]}
    >
      {children}
    </Animated.View>
  );
}
Example #17
Source File: ProgressBar.js    From hugin-mobile with GNU Affero General Public License v3.0 5 votes vote down vote up
update() {
        Animated.timing(this.state.progress, {
            easing: Easing.inOut(Easing.ease),
            duration: 500,
            toValue: this.props.progress,
        }).start();
    }
Example #18
Source File: LoadingModal.js    From stayaway-app with European Union Public License 1.2 5 votes vote down vote up
export default function LoadingModal (props) {
  const {
    visible,
    onClose,
    onModalWillShow,
    onModalWillHide,
    ...otherProps
  } = props;

  const { colors } = useTheme();

  const [spinAnim] = useState(new Animated.Value(0));

  const spinAnimation = Animated.loop(Animated.timing(
    spinAnim,
    {
      toValue: 1,
      duration: 3000,
      easing: Easing.linear,
      useNativeDriver: true,
    },
  ));

  const modalShow = () => {
    onModalWillShow();
    spinAnimation.start();
  };

  const modalHide = () => {
    onModalWillHide();
    spinAnimation.stop();
  };

  const spin = spinAnim.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg'],
  });

  const animationStyle = {transform: [{rotate: spin}]};

  return (
    <Modal
      backdropColor={colors.backdropColor}
      backdropOpacity={0.8}
      isVisible={visible}
      statusBarTranslucent
      animationIn='zoomIn'
      animationOut='zoomOut'
      onModalWillHide={modalHide}
      onModalWillShow={modalShow}
      {...otherProps}
    >
      <Layout style={styles.content}>
        <View style={styles.logoContainer}>
          <Animated.View style={animationStyle}>
            <Icon
              name='loading'
              width={iconSizes.size100}
              height={iconSizes.size100}
            />
          </Animated.View>
        </View>
        <View style={styles.descriptionContainer}>
          <Text textAlign='center' textColor={colors.loadingTextColor}>{i18n.translate('common.dialogs.loading.description')}</Text>
        </View>
      </Layout>
    </Modal>
  );
}
Example #19
Source File: touchable.js    From rn-checkbox-list with MIT License 5 votes vote down vote up
startRipple(event) {
    let { width, height } = this.state;
    let {
      rippleDuration,
      rippleCentered,
      rippleSize,
      onRippleAnimation,
    } = this.props;

    let w2 = 0.5 * width;
    let h2 = 0.5 * height;

    let { locationX, locationY } = rippleCentered?
      { locationX: w2, locationY: h2 }:
      event.nativeEvent;

    let offsetX = Math.abs(w2 - locationX);
    let offsetY = Math.abs(h2 - locationY);

    let R = rippleSize > 0?
      0.5 * rippleSize:
      Math.sqrt(Math.pow(w2 + offsetX, 2) + Math.pow(h2 + offsetY, 2));

    let ripple = {
      unique: this.unique++,
      progress: new Animated.Value(0),
      locationX,
      locationY,
      R,
    };

    let animation = Animated
      .timing(ripple.progress, {
        toValue: 1,
        easing: Easing.out(Easing.ease),
        duration: rippleDuration,
        useNativeDriver: true,
      });

    onRippleAnimation(animation, this.onAnimationEnd);

    this.setState(({ ripples }) => ({ ripples: ripples.concat(ripple) }));
  }
Example #20
Source File: Switch.js    From timetable with MIT License 5 votes vote down vote up
Switch = ({ isOn, onToggle }) => {
  const animatedValue = React.useRef(new Animated.Value(isOn ? 1 : 0)).current

  useEffect(() => {
    Animated.timing(animatedValue, {
      toValue: isOn ? 1 : 0,
      duration: 200,
      easing: Easing.linear,
      useNativeDriver: true
    }).start()
  }, [animatedValue, isOn])

  const moveToggle = animatedValue.interpolate({
    inputRange: [0, 1],
    outputRange: [4, 27]
  })

  const background = isOn ? '#4f5f78' : '#97b9d2'
  const toggle = isOn ? '#c4d3e0' : '#f5dd4b'
  const border = isOn ? 'white' : '#d7b04e'
  const borderWidth = isOn ? (Platform.OS === 'android' ? 0.8 : null) : 1.1
  const shadow = isOn ? 'white' : '#97b9d2'

  return (
    <TouchableWithoutFeedback onPress={onToggle}>
      <View style={[styles.switchContainer, { backgroundColor: background }]}>
        <Animated.View
          style={[
            styles.switchWheel,
            {
              transform: [{ translateX: moveToggle }],
              borderColor: border,
              borderWidth: borderWidth,
              backgroundColor: toggle,
              shadowColor: shadow
            }
          ]}
        />
      </View>
    </TouchableWithoutFeedback>
  )
}
Example #21
Source File: Modal.js    From the-eye-knows-the-garbage with MIT License 4 votes vote down vote up
RCModal = function (_React$Component) {
    _inherits(RCModal, _React$Component);

    function RCModal(props) {
        _classCallCheck(this, RCModal);

        var _this = _possibleConstructorReturn(this, (RCModal.__proto__ || Object.getPrototypeOf(RCModal)).call(this, props));

        _this.animateMask = function (visible) {
            _this.stopMaskAnim();
            _this.state.opacity.setValue(_this.getOpacity(!visible));
            _this.animMask = Animated.timing(_this.state.opacity, {
                toValue: _this.getOpacity(visible),
                duration: _this.props.animationDuration
            });
            _this.animMask.start(function () {
                _this.animMask = null;
            });
        };
        _this.stopMaskAnim = function () {
            if (_this.animMask) {
                _this.animMask.stop();
                _this.animMask = null;
            }
        };
        _this.stopDialogAnim = function () {
            if (_this.animDialog) {
                _this.animDialog.stop();
                _this.animDialog = null;
            }
        };
        _this.animateDialog = function (visible) {
            _this.stopDialogAnim();
            _this.animateMask(visible);
            var _this$props = _this.props,
                animationType = _this$props.animationType,
                animationDuration = _this$props.animationDuration;

            animationDuration = animationDuration;
            if (animationType !== 'none') {
                if (animationType === 'slide-up' || animationType === 'slide-down') {
                    _this.state.position.setValue(_this.getPosition(!visible));
                    _this.animDialog = Animated.timing(_this.state.position, {
                        toValue: _this.getPosition(visible),
                        duration: animationDuration,
                        easing: visible ? Easing.elastic(0.8) : undefined
                    });
                } else if (animationType === 'fade') {
                    _this.animDialog = Animated.parallel([Animated.timing(_this.state.opacity, {
                        toValue: _this.getOpacity(visible),
                        duration: animationDuration,
                        easing: visible ? Easing.elastic(0.8) : undefined
                    }), Animated.spring(_this.state.scale, {
                        toValue: _this.getScale(visible)
                    })]);
                }
                _this.animDialog.start(function () {
                    _this.animDialog = null;
                    if (!visible) {
                        _this.setState({
                            modalVisible: false
                        });
                    }
                    if (_this.props.onAnimationEnd) {
                        _this.props.onAnimationEnd(visible);
                    }
                });
            } else {
                if (!visible) {
                    _this.setState({
                        modalVisible: false
                    });
                }
            }
        };
        _this.close = function () {
            _this.animateDialog(false);
        };
        _this.onMaskClose = function () {
            if (_this.props.maskClosable && _this.props.onClose) {
                _this.props.onClose();
            }
        };
        _this.getPosition = function (visible) {
            if (visible) {
                return 0;
            }
            return _this.props.animationType === 'slide-down' ? -screen.height : screen.height;
        };
        _this.getScale = function (visible) {
            return visible ? 1 : 1.05;
        };
        _this.getOpacity = function (visible) {
            return visible ? 1 : 0;
        };
        var visible = props.visible;

        _this.state = {
            position: new Animated.Value(_this.getPosition(visible)),
            scale: new Animated.Value(_this.getScale(visible)),
            opacity: new Animated.Value(_this.getOpacity(visible)),
            modalVisible: visible
        };
        return _this;
    }

    _createClass(RCModal, [{
        key: 'componentWillReceiveProps',
        value: function componentWillReceiveProps(nextProps) {
            if (this.shouldComponentUpdate(nextProps, null)) {
                this.setState({
                    modalVisible: true
                });
            }
        }
    }, {
        key: 'shouldComponentUpdate',
        value: function shouldComponentUpdate(nextProps, nextState) {
            if (this.props.visible || this.props.visible !== nextProps.visible) {
                return true;
            }
            if (nextState) {
                if (nextState.modalVisible !== this.state.modalVisible) {
                    return true;
                }
            }
            return false;
        }
    }, {
        key: 'componentDidMount',
        value: function componentDidMount() {
            if (this.props.animateAppear && this.props.animationType !== 'none') {
                this.componentDidUpdate({});
            }
        }
    }, {
        key: 'componentDidUpdate',
        value: function componentDidUpdate(prevProps) {
            var props = this.props;

            if (prevProps.visible !== props.visible) {
                this.animateDialog(props.visible);
            }
        }
    }, {
        key: 'render',
        value: function render() {
            var props = this.props;

            if (!this.state.modalVisible) {
                return null;
            }
            var animationStyleMap = {
                none: {},
                'slide-up': { transform: [{ translateY: this.state.position }] },
                'slide-down': { transform: [{ translateY: this.state.position }] },
                fade: { transform: [{ scale: this.state.scale }], opacity: this.state.opacity }
            };
            return React.createElement(Modal, { visible: true, transparent: true, onRequestClose: this.props.onClose, supportedOrientations: ['portrait', 'landscape'] }, React.createElement(View, { style: [styles.wrap, props.wrapStyle] }, React.createElement(TouchableWithoutFeedback, { onPress: this.onMaskClose }, React.createElement(Animated.View, { style: [styles.absolute, { opacity: this.state.opacity }] }, React.createElement(View, { style: [styles.absolute, props.maskStyle] }))), React.createElement(Animated.View, { style: [styles.content, props.style, animationStyleMap[props.animationType]] }, this.props.children)));
        }
    }]);

    return RCModal;
}(React.Component)
Example #22
Source File: index.js    From react-native-vertical-distribution with MIT License 4 votes vote down vote up
render() {
    const fullWidth = Dimensions.get('window').width;
    const fiftyPercentWidth = Dimensions.get('window').width / 2;

    const anim = this.state.drawerWidth.interpolate({
      inputRange: [0, 1, 2],
      outputRange: [fullWidth - 60, 80, 0],
    });

    const anim2 = this.state.secondPaneWidth.interpolate({
      inputRange: [0, 0.5, 1, 2],
      outputRange: [30, 240, 310, fiftyPercentWidth],
    });

    const anim3 = this.state.thirdPaneWidth.interpolate({
      inputRange: [0, 1, 2],
      outputRange: [40, fiftyPercentWidth, 100],
    });

    const animateHeight = this.state.thumbnailHeight.interpolate({
      inputRange: [0, 1],
      outputRange: [70, 140],
    });

    const animateCircleSize = this.state.circleSize.interpolate({
      inputRange: [0, 1],
      outputRange: [80, 50],
    });

    const animateWidth = this.state.mainCategoryWidth.interpolate({
      inputRange: [0, 1],
      outputRange: [250, 180],
    });

    const overlaySize = this.overlaySize.interpolate({
      inputRange: [0, 1, 2],
      outputRange: [200, 60, 130],
    });

    const overlayOpacity = this.overlayOpacity.interpolate({
      inputRange: [0, 1],
      outputRange: [0, 10],
    });

    return (
      <SafeAreaView style={{ flex: 1 }}>
        <View
          style={{
            flexDirection: 'row',
            height: '100%',
            overflow: 'hidden',
          }}
        >
          <Animated.View
            style={[
              {
                backgroundColor: '#2E4987',
                height: overlaySize,
                width: overlaySize,
                position: 'absolute',
                zIndex: overlayOpacity,
              },
              this.moveAnimation.getLayout(),
            ]}
          />
          <Animated.View
            style={{
              width: anim,
              backgroundColor: '#F68E5E',
              shadowColor: '#000',
              shadowOpacity: 0.4,
              shadowRadius: 6,
              shadowOffset: {
                width: 10,
                height: 0,
              },
              zIndex: 2,
            }}
          >
            <View
              style={{
                backgroundColor: '#E75F5E',
                height: 60,
                justifyContent: 'center',
              }}
            >
              {!this.state.showBackButton ? (
                <View
                  style={{
                    flexDirection: 'row',
                    justifyContent: 'space-between',
                    alignItems: 'center',
                    paddingHorizontal: 20,
                  }}
                >
                  <View>{userIcon}</View>
                  <View>
                    <Text
                      style={{
                        color: '#F9BCA7',
                        fontWeight: '600',
                        fontSize: 20,
                      }}
                    >
                      CATEGORIES
                    </Text>
                  </View>
                  <View>{searchIcon}</View>
                </View>
              ) : (
                <TouchableOpacity
                  onPress={(item) => {
                    this.setState({
                      showBackButton: false,
                    });
                    Animated.parallel([
                      Animated.spring(this.state.drawerWidth, {
                        toValue: 0,
                        duration: 200,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                      Animated.spring(this.state.secondPaneWidth, {
                        toValue: 0,
                        duration: 200,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                      Animated.spring(this.state.circleSize, {
                        toValue: 0,
                        duration: 150,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                      Animated.spring(this.state.mainCategoryWidth, {
                        toValue: 0,
                        duration: 200,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                    ]).start(() => {});
                  }}
                  style={{
                    alignItems: 'center',
                  }}
                >
                  {backIcon}
                </TouchableOpacity>
              )}
            </View>
            <FlatList
              data={this.props.firstMenu}
              renderItem={(item, index) => (
                <TouchableOpacity
                  style={{
                    paddingLeft: this.state.showBackButton ? 15 : 30,
                    paddingVertical: this.state.showBackButton ? 15 : 25,
                    flexDirection: 'row',
                    backgroundColor:
                      item.index ===
                      get(this.state.selectedFirstCategory, 'index')
                        ? '#F6B972'
                        : null,
                  }}
                  onPress={() => {
                    this.setState({
                      showBackButton: true,
                      selectedFirstCategory: item,
                    });
                    Animated.parallel([
                      Animated.spring(this.state.circleSize, {
                        toValue: 1,
                        duration: 150,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                      Animated.spring(this.state.drawerWidth, {
                        toValue: 1,
                        duration: 300,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                      Animated.spring(this.state.secondPaneWidth, {
                        toValue: 1,
                        duration: 300,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                      Animated.spring(this.state.mainCategoryWidth, {
                        toValue: 0,
                        duration: 200,
                        easing: Easing.quad,
                        useNativeDriver: false,
                      }),
                    ]).start(() => {});
                    this.flatListRef.scrollToOffset({
                      animated: true,
                      offset: 0,
                    });
                  }}
                >
                  <Animated.View
                    style={{
                      backgroundColor: '#E75F5E',
                      height: animateCircleSize,
                      width: animateCircleSize,
                      borderRadius: 50,
                    }}
                  />
                  {placeholder(this.state.showBackButton)}
                </TouchableOpacity>
              )}
              keyExtractor={(item) => item.id}
            />
          </Animated.View>
          <Animated.View
            style={{
              width: anim2,
              backgroundColor: '#496FC6',
              alignItems: 'center',
              shadowColor: '#000',
              shadowOpacity: 0.4,
              shadowRadius: 6,
              shadowOffset: {
                width: 10,
                height: 0,
              },
              zIndex: 1,
            }}
          >
            <View
              style={{
                backgroundColor: '#3961AF',
                height: 60,
                justifyContent: 'center',
                width: '100%',
              }}
            >
              <View
                style={{
                  flexDirection: 'row',
                  justifyContent: 'space-evenly',
                  alignItems: 'center',
                  paddingHorizontal: 20,
                }}
              >
                <View>
                  <Text
                    style={{
                      color: '#638CE7',
                      fontWeight: '600',
                      fontSize: 20,
                    }}
                  >
                    CATEGORY
                  </Text>
                </View>
                <View>{filterIcon}</View>
              </View>
            </View>
            <FlatList
              ref={(ref) => {
                this.flatListRef = ref;
              }}
              data={this.props.secondMenu}
              renderItem={(item, index) => (
                <Animated.View
                  style={{
                    marginTop: 20,
                    paddingVertical: 20,
                  }}
                >
                  <TouchableOpacity
                    ref={(ref) => {
                      this.overlayRef = ref;
                    }}
                    onPress={(evt) => {
                      if (!this.state.cartItems.includes(item.item)) {
                        this._onmove(evt, item);
                        this.setState({
                          cartItems: [...this.state.cartItems, item.item],
                          indexToAnimate: item.index,
                        });
                      }
                      Animated.parallel([
                        Animated.spring(this.state.mainCategoryWidth, {
                          toValue: 1,
                          duration: 200,
                          easing: Easing.quad,
                          useNativeDriver: false,
                        }),
                        !this.state.isCartOpen &&
                          Animated.timing(this.state.secondPaneWidth, {
                            toValue: 0.5,
                            duration: 200,
                            easing: Easing.quad,
                            useNativeDriver: false,
                          }),
                        !this.state.isCartOpen &&
                          Animated.timing(this.state.thirdPaneWidth, {
                            toValue: 2,
                            duration: 200,
                            easing: Easing.quad,
                            useNativeDriver: false,
                          }),
                      ]).start(() => {});
                    }}
                  >
                    <Animated.View
                      style={{
                        height: animateWidth,
                        width: animateWidth,
                      }}
                    >
                      {RectPlaceholder()}
                    </Animated.View>
                  </TouchableOpacity>
                </Animated.View>
              )}
              keyExtractor={(item) => item.id}
            />
          </Animated.View>
          <Animated.View
            style={{
              width: anim3,
              backgroundColor: '#24375A',
            }}
          >
            <View
              style={{
                backgroundColor: '#182942',
                height: 60,
                justifyContent: 'center',
                width: '100%',
              }}
            >
              <View
                style={{
                  flexDirection: 'row',
                  justifyContent: 'space-evenly',
                  alignItems: 'center',
                  paddingHorizontal: 20,
                }}
              >
                {!this.state.isCartOpen ? (
                  <View>{cartIcon}</View>
                ) : (
                  <View
                    style={{
                      flexDirection: 'row',
                      justifyContent: 'space-around',
                      alignItems: 'center',
                      width: '100%',
                    }}
                  >
                    <Text
                      style={{
                        color: '#638CE7',
                        fontWeight: '600',
                        fontSize: 20,
                      }}
                    >
                      {this.state.cartItems.length} ITEM(S)
                    </Text>
                    <TouchableOpacity
                      onPress={() => {
                        this.setState({ isCartOpen: false });
                        Animated.parallel([
                          Animated.timing(this.state.drawerWidth, {
                            toValue: 1,
                            duration: 250,
                            easing: Easing.ease,
                            useNativeDriver: false,
                          }),
                          Animated.spring(this.state.secondPaneWidth, {
                            toValue: 1,
                            duration: 250,
                            easing: Easing.ease,
                            useNativeDriver: false,
                          }),
                          Animated.spring(this.state.thumbnailHeight, {
                            toValue: 0,
                            duration: 250,
                            easing: Easing.ease,
                            useNativeDriver: false,
                          }),
                          Animated.spring(this.state.mainCategoryWidth, {
                            toValue: 0,
                            duration: 200,
                            easing: Easing.quad,
                            useNativeDriver: false,
                          }),
                        ]).start(() => {});
                      }}
                    >
                      {falseIcon}
                    </TouchableOpacity>
                  </View>
                )}
              </View>
            </View>
            {this.state.cartItems.length > 0 ? (
              <FlatList
                inverted={this.state.isCartOpen ? true : false}
                ref={(ref) => {
                  this.cartFlatList = ref;
                }}
                keyExtractor={(item) => item.id}
                contentContainerStyle={{
                  flexGrow: 1,
                  justifyContent: this.state.isCartOpen
                    ? 'flex-end'
                    : 'flex-start',
                }}
                onContentSizeChange={() => {
                  this.cartFlatList.scrollToEnd({ animated: true });
                }}
                data={this.state.cartItems}
                renderItem={({ item, index }) => (
                  <TouchableOpacity
                    style={{
                      marginTop: 15,
                      padding: 15,
                    }}
                    onPress={() => {
                      this.setState({ isCartOpen: true });
                      Animated.parallel([
                        Animated.timing(this.state.drawerWidth, {
                          toValue: 2,
                          duration: 250,
                          easing: Easing.ease,
                          useNativeDriver: false,
                        }),
                        Animated.timing(this.state.secondPaneWidth, {
                          toValue: 2,
                          duration: 250,
                          easing: Easing.ease,
                          useNativeDriver: false,
                        }),
                        Animated.timing(this.state.thirdPaneWidth, {
                          toValue: 1,
                          duration: 250,
                          easing: Easing.ease,
                          useNativeDriver: false,
                        }),
                        Animated.spring(this.state.thumbnailHeight, {
                          toValue: 1,
                          duration: 250,
                          easing: Easing.ease,
                          useNativeDriver: false,
                        }),
                      ]).start(() => {});
                    }}
                  >
                    <Animated.View style={{ height: animateHeight }}>
                      {this.state.isCartOpen && (
                        <TouchableOpacity
                          style={{
                            backgroundColor: 'coral',
                            top: -10,
                            right: -10,
                            position: 'absolute',
                            borderRadius: 50,
                            zIndex: 20,
                            justifyContent: 'center',
                            alignItems: 'center',
                          }}
                          onPress={() => {
                            this.setState({
                              cartItems: this.state.cartItems.filter(
                                (data) => data.index !== index
                              ),
                            });
                          }}
                        >
                          {crossIcon}
                        </TouchableOpacity>
                      )}
                      {thumbnailPlaceholder()}
                    </Animated.View>
                  </TouchableOpacity>
                )}
              />
            ) : (
              <View
                style={{
                  width: 200,
                  position: 'absolute',
                  top: 400,
                  right: -80,
                  zIndex: 1000,
                  transform: [{ rotate: '-90deg' }],
                }}
              >
                <Text
                  style={{
                    color: '#fff',
                    fontWeight: '200',
                    fontSize: 16,
                    textAlign: 'center',
                    opacity: 0.7,
                  }}
                >
                  C A R T{'  '} I S {'  '} E M P T Y
                </Text>
              </View>
            )}
          </Animated.View>
        </View>
      </SafeAreaView>
    );
  }
Example #23
Source File: index.js    From react-native-loop-game with MIT License 4 votes vote down vote up
/**
 * I had to pass player refrence becuase when we share screenshot
 * it calls a native library to share image & I kind of put app in background state
 * react-native-audio-toolkit is configured only play music when app is on screen
 */

export default function useEngine(forceLevel, player) {
  const [level, setLevel] = useState(forceLevel);
  const { data, theme } = levels[level];
  const [grid, setGrid] = useState(data2Grid(data));
  const [success, setSuccess] = useState(false);
  const [colorAnimation] = useState(new Animated.Value(0));
  const delay = 140;
  const [prevLevel, setPrevLevel] = useState(level);

  function setRotate(x, y) {
    const newGrid = [...grid];
    const newBox = rotateBox(grid[y][x]);
    newGrid[y][x] = newBox;
    let toValue = newBox.rotate;

    if (newBox.type === 'line') {
      // eslint-disable-next-line
      toValue = newBox.animation._value + 1;
    }
    if (toValue === 0) {
      toValue = 4;
    }
    if (newBox.type === '4-point') {
      toValue = 1;
    }
    Animated.timing(newBox.animation, {
      toValue,
      duration: delay,
      easing: Easing.linear,
    }).start(() => {
      if (toValue === 4 || newBox.type === '4-point') {
        newBox.animation = new Animated.Value(0);
      }
    });

    const check = calculateSuccess(newGrid);
    setTimeout(() => setSuccess(check), delay / 2);
    setGrid(newGrid);
  }

  async function capture(ref) {
    try {
      const trace = await performance().startTrace('capture_screenshot');

      const base64 = await captureRef(ref, {
        format: 'jpg',
        quality: 1.0,
        result: 'base64',
      });
      await trace.stop();
      await share.open({
        url: `data:image/jpeg;base64,${base64}`,
        filename: `rn-loop-game-${new Date().getTime()}`,
      });
      player.play();
    } catch (e) {
      player.play();
    }
  }

  function changeLevel(no, prev) {
    setPrevLevel(prev);
    const newLevel = levels[no];
    if (newLevel) {
      // initLayout();
      setLevel(no);
      setGrid(data2Grid(newLevel.data));
    }
  }

  function animateColor(color) {
    const from = theme.light[color].rgb().string();
    let to = theme.dark[color].rgb().string();

    if (prevLevel !== level) {
      to = levels[prevLevel].theme.dark[color].rgb().string();
    }

    return colorAnimation.interpolate({
      duration: 800,
      inputRange: [0, 1],
      outputRange: [from, to],
    });
  }

  useEffect(() => {
    const check = calculateSuccess(grid);
    const timeout = setTimeout(() => setSuccess(check), delay / 2);
    return () => clearTimeout(timeout);
  });

  useEffect(() => {
    Animated.timing(colorAnimation, {
      toValue: success ? 1 : 0,
    }).start((e) => {
      if (prevLevel !== level && e.finished) {
        setPrevLevel(level);
      }
    });
  }, [success]);

  return useMemo(() => ({
    grid,
    level,
    theme,
    success,
    capture,
    setRotate,
    animateColor,
    size: Math.floor(UI.getWidth() / 8),
    controls: {
      next: () => changeLevel(level + 1, level),
      prev: () => changeLevel(level - 1, level),
      reset: () => changeLevel(level, level),
    },
  }));
}
Example #24
Source File: index.js    From designcode-app with MIT License 4 votes vote down vote up
export default function Home() {
  const [scale, setScale] = useState(new Animated.Value(1));
  const [opacity, setOpacity] = useState(new Animated.Value(1));

  const dispatch = useDispatch();
  const navigation = useNavigation();
  const action = useSelector((state) => state.app.action);
  const name = store.getState().app.name;

  const { loading, error, data } = useQuery(CardsQuery);

  function handleOpenMenu() {
    store.dispatch({
      type: "OPEN_MENU",
    });
  }

  function handleOpenLogin() {
    store.dispatch({
      type: "OPEN_LOGIN",
    });
  }

  useEffect(() => {
    if (Platform.OS === "android") StatusBar.setHidden(false);
  }, []);

  useEffect(() => {
    if (action == "openMenu") {
      Animated.timing(scale, {
        toValue: 0.9,
        duration: 300,
        easing: Easing.in(),
        useNativeDriver: false,
      }).start();

      Animated.spring(opacity, {
        toValue: 0.5,
        useNativeDriver: false,
      }).start();

      StatusBar.setBarStyle("light-content", true);
    }

    if (action == "closeMenu") {
      Animated.timing(scale, {
        toValue: 1,
        duration: 300,
        easing: Easing.in(),
        useNativeDriver: false,
      }).start();
      Animated.spring(opacity, {
        toValue: 1,
        useNativeDriver: false,
      }).start();

      StatusBar.setBarStyle("dark-content", true);
    }
  }, [action]);

  function handleAvatar() {
    if (store.getState().app.name) {
      store.dispatch({ type: "OPEN_MENU" });
    } else {
      store.dispatch({ type: "OPEN_LOGIN" });
    }
  }

  function openNotif() {
    store.dispatch({ type: "OPEN_NOTIF" });
  }

  return (
    <RootView>
      <Menu />
      <Notifications />
      <Animated.View
        style={[
          styles.animatedContainer,
          {
            transform: [{ scale: scale }],
            opacity: opacity,
          },
        ]}
      >
        <SaveAreaContainer>
          <ScrollContainer showsVerticalScrollIndicator={false}>
            <TitleBar>
              <ButtonAvatar onPress={handleAvatar}>
                <Avatar />
              </ButtonAvatar>
              <Title>Welcome back,</Title>
              <Name>{name}</Name>
              <TouchableOpacity
                onPress={openNotif}
                style={{ position: "absolute", right: 20, top: 0 }}
              >
                <NotificationButton />
              </TouchableOpacity>
            </TitleBar>
            <ScrollLogo horizontal showsHorizontalScrollIndicator={false}>
              {logos.map((item, index) => (
                <Logo key={index} image={item.image} text={item.text} />
              ))}
            </ScrollLogo>
            <Subtitle>Continue Learning</Subtitle>
            <ScrollCards horizontal showsHorizontalScrollIndicator={false}>
              <CardsContainer>
                {data &&
                  data.cardsCollection.items.map((item, index) => (
                    <ButtonCard
                      key={index}
                      activeOpacity={0.6}
                      onPress={() =>
                        navigation.navigate("Section", {
                          section: item,
                        })
                      }
                    >
                      <Card
                        title={item.title}
                        caption={item.caption}
                        subtitle={item.subtitle}
                        image={item.image}
                        logo={item.logo}
                        author={item.author}
                      />
                    </ButtonCard>
                  ))}
              </CardsContainer>
            </ScrollCards>
            <Subtitle>Popular Courses</Subtitle>
            <CoursesContainer>
              {courses.map((item, index) => (
                <Course
                  key={index}
                  title={item.title}
                  subtitle={item.subtitle}
                  image={item.image}
                  logo={item.logo}
                  caption={item.caption}
                  avatar={item.avatar}
                  author={item.author}
                />
              ))}
            </CoursesContainer>
          </ScrollContainer>
        </SaveAreaContainer>
      </Animated.View>
      <StatusBar />
      <ModalLogin />
    </RootView>
  );
}
Example #25
Source File: CountryPicker.js    From react-native-country-codes-picker with MIT License 4 votes vote down vote up
/**
 * Country picker component
 * @param {?boolean} show Hide or show component by using this props
 * @param {?boolean} disableBackdrop Hide or show component by using this props
 * @param {?boolean} enableModalAvoiding Is modal should avoid keyboard ? On android to work required to use with androidWindowSoftInputMode with value pan, by default android will avoid keyboard by itself
 * @param {?string} androidWindowSoftInputMode Hide or show component by using this props
 * @param {?string} inputPlaceholder Text to showing in input
 * @param {?string} searchMessage Text to show user when no country to show
 * @param {?string} lang Current selected lang by user
 * @param {?string} initialState Here you should define initial dial code
 * @param {?array} excludedCountries Array of countries which should be excluded from picker
 * @param {Function} pickerButtonOnPress Function to receive selected country
 * @param {Function} onBackdropPress Function to receive selected country
 * @param {?Object} style Styles
 * @param {?React.ReactNode} itemTemplate Country list template
 * @param rest
 */

export default function CountryPicker({
										  show,
										  pickerButtonOnPress,
										  inputPlaceholder,
										  searchMessage,
										  lang = 'en',
										  style,
										  enableModalAvoiding,
										  androidWindowSoftInputMode,
										  onBackdropPress,
										  disableBackdrop,
										  excludedCountries = [],
	                                      initialState,
										  itemTemplate: ItemTemplate = CountryButton,
										  ...rest
									  }) {
	const codes = countryCodes?.map(country => {
		if (excludedCountries?.find(short => country?.code === short?.toUpperCase()))
			return;

		return country;
	});
	const keyboardStatus = useKeyboardStatus();
	const animationDriver = React.useRef(new Animated.Value(0)).current;
	const animatedMargin = React.useRef(new Animated.Value(0)).current;
	const [searchValue, setSearchValue] = React.useState(initialState || '');
	const [visible, setVisible] = React.useState(show);

	React.useEffect(() => {
		if (show) {
			openModal();
		} else {
			closeModal();
		}
	}, [show]);

	React.useEffect(() => {
		if (
			enableModalAvoiding &&
			!!(
				keyboardStatus.keyboardPlatform === 'ios' ||
				(keyboardStatus.keyboardPlatform === 'android' &&
					androidWindowSoftInputMode === 'pan')
			)
		) {
			if (keyboardStatus.isOpen)
				Animated.timing(animatedMargin, {
					toValue: keyboardStatus.keyboardHeight,
					duration: 290,
					easing: Easing.ease,
					useNativeDriver: false,
				}).start();

			if (!keyboardStatus.isOpen)
				Animated.timing(animatedMargin, {
					toValue: 0,
					duration: 290,
					easing: Easing.ease,
					useNativeDriver: false,
				}).start();
		}
	}, [keyboardStatus.isOpen]);

	const resultCountries = React.useMemo(() => {
		if (!isNaN(searchValue))
			return codes.filter((country) =>
				country?.dial_code.includes(searchValue)
			);

		return codes.filter((country) =>
			country?.name[lang || 'en'].includes(searchValue)
		);
	}, [searchValue]);

	const modalPosition = animationDriver.interpolate({
		inputRange: [0, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1],
		outputRange: [height, 105, 75, 50, 30, 15, 5, 0],
		extrapolate: 'clamp',
	});

	const modalBackdropFade = animationDriver.interpolate({
		inputRange: [0, 0.5, 1],
		outputRange: [0, 0.5, 1],
		extrapolate: 'clamp'
	});

	const openModal = () => {
		setVisible(true);
		Animated.timing(animationDriver, {
			toValue: 1,
			duration: 400,
			useNativeDriver: false,
		}).start();
	};

	const closeModal = () => {
		Animated.timing(animationDriver, {
			toValue: 0,
			duration: 400,
			useNativeDriver: false,
		}).start(() => setVisible(false));
	};

	if (!visible)
		return null;

	return (
		<>
			{!disableBackdrop && (
				<Animated.View
					onStartShouldSetResponder={onBackdropPress}
					style={[
						{
							flex: 1,
							opacity: modalBackdropFade,
							backgroundColor: 'rgba(116,116,116,0.45)',
							position: 'absolute',
							width: '100%',
							height: '100%',
							justifyContent: 'flex-end'
						},
						style?.backdrop
					]}
				/>
			)}
			<Animated.View
				style={[
					styles.modal,
					style?.modal,
					{
						transform: [
							{
								translateY: modalPosition,
							},
						],
					},
				]}
			>
				<View
					style={{
						flexDirection: 'row',
						alignItems: 'center',
					}}
				>
					<TextInput
						style={[styles.searchBar, style?.textInput]}
						value={searchValue}
						onChangeText={(text) => setSearchValue(text)}
						placeholder={inputPlaceholder || 'Search your country'}
						{...rest}
					/>
				</View>
				<View style={[styles.line, style?.line]}/>
				{resultCountries.length === 0 ? (
					<View style={[styles.countryMessage, style?.countryMessageContainer]}>
						<Text
							style={[
								{
									color: '#8c8c8c',
									fontSize: 16,
								},
								style?.searchMessageText,
							]}
						>
							{searchMessage || 'Sorry we cant find your country :('}
						</Text>
					</View>
				) : (
					<FlatList
						showsVerticalScrollIndicator={false}
						data={resultCountries || codes}
						keyExtractor={(item, index) => item + index}
						initialNumToRender={10}
						maxToRenderPerBatch={10}
						style={[{
							height: 250
						}, style?.itemsList]}
						keyboardShouldPersistTaps={'handled'}
						renderItem={({item, index}) => {
							let itemName = item?.name[lang];
							let checkName = itemName.length ? itemName : item?.name['en'];

							return (
								<ItemTemplate
									key={index}
									item={item}
									style={style}
									name={checkName}
									onPress={() => {
										Keyboard.dismiss();
										typeof pickerButtonOnPress === 'function' && pickerButtonOnPress(item);
									}}
								/>
							);
						}}
						{...rest}
					/>
				)}
				<Animated.View
					style={[
						styles.modalInner,
						style?.modalInner,
						{
							height: animatedMargin,
						},
					]}
				/>
			</Animated.View>
		</>
	);
}
Example #26
Source File: Timetable.js    From timetable with MIT License 4 votes vote down vote up
Timetable = ({ route }) => {
  const { t, i18n } = useTranslation()
  const { theme } = useTheme()
  // netInfo helps to check network connection status. Timeout 15s
  const netInfo = useNetInfo({ reachabilityRequestTimeout: 15 * 1000 })

  // station ID which you get from Stations screen
  const { stationTimetableId, metadata } = route.params
  const metainfo = { station: stationTimetableId, info: metadata }

  /**
   * Arrival bus list!
   * Used to get latest info.
   * API request sample.
   * https://xxxxxxx:xxxx/xxxxxxxxxxxx/?station=${stationTimetableId}
   **/

  const endPoint =
    i18n.language == 'en'
      ? `${process.env.API_TIMETABLE_EN + stationTimetableId}`
      : `${process.env.API_TIMETABLE_GE + stationTimetableId}`

  // Local Time string object
  const [localTime, setLocalTime] = useState('')

  // Stream of data
  const fetcher = (...args) => fetch(...args).then(res => res.json())

  const { data, error } = useSWR(endPoint, fetcher, {
    refreshInterval: 1000 * 10
  })

  // Bouncing animation
  const focus = new Animated.Value(0)

  Animated.loop(
    Animated.timing(focus, {
      toValue: 10,
      duration: 4000,
      easing: Easing.bounce,
      useNativeDriver: true
    })
  ).start()

  useEffect(() => {
    // Server related warning
    if (error) {
      Alert.alert(t('timetable.error'), t('timetable.server_err'), [
        { text: t('timetable.cancel') }
      ])
    }

    const interval = setInterval(() => {
      setLocalTime(
        new Date().toLocaleTimeString('en-US', { hour12: false }, 'ka-KA')
      )
    }, 1000)

    // clean up
    return () => {
      clearInterval(interval), focus.stopAnimation()
    }
  }, [])

  /**
   * Saves station ID and metainfo to local storage!
   * Checks if ID exist in storage and displays pop up warning.
   **/

  const saveFavoriteHandler = async () => {
    try {
      const result = await AsyncStorage.getItem('TestFavorite')

      if (result == null) {
        const createArray = [metainfo]

        AsyncStorage.setItem('TestFavorite', JSON.stringify(createArray))
      } else if (result !== null) {
        const array = await JSON.parse(result)
        let onAlert = false

        array.forEach(value => {
          if (value.station == stationTimetableId) {
            onAlert = true
            Alert.alert('', t('timetable.favorite'), [
              { text: t('timetable.cancel') }
            ])
          }
        })

        if (onAlert == false) {
          array.push(metainfo)
          AsyncStorage.setItem('TestFavorite', JSON.stringify(array))
        }
      }
    } catch (err) {
      Alert.alert('', err, [{ text: t('timetable.cancel') }])
    }
  }

  /**
   * Displays Local Time!
   * Shows night time if it's between 12:00AM - 6:00AM.
   * Shows delay if timetable is empty between 7:00AM - 11:00PM,
   * also for displaying delay we check network status.
   **/

  const DisplayTime = () => {
    if (parseInt(localTime) >= 7 && parseInt(localTime) <= 22) {
      return (
        <View style={styles.localTime}>
          <Text style={{ color: theme.text }}>{localTime} (GMT+4)</Text>
          <Text style={{ color: theme.text }}>{t('timetable.localTime')}</Text>
          <Text style={{ color: theme.text }}>
            {t('timetable.localTimeDelay')}
          </Text>
        </View>
      )
    } else if (
      (parseInt(localTime) >= 0 && parseInt(localTime) <= 6) ||
      parseInt(localTime) == 23
    ) {
      return (
        <View style={styles.localTime}>
          <Text style={{ color: theme.text }}>{localTime} (GMT+4)</Text>
          <Text style={{ color: theme.text }}>{t('timetable.localTime')}</Text>
          <Text style={{ color: theme.text }}>
            {t('timetable.localTimeNight')}
          </Text>
        </View>
      )
    }
  }

  // FlatList Item
  const Item = ({ title, time, bus, nowText, minText }) => {
    // Apply animation if time is below two minutes and display 'Now' instead of time.
    // Time is number it can be between 0-100: represents minutes.

    const willBeIn = () => {
      if (time <= 2 || 0) {
        return (
          <Animated.View style={{ opacity: focus }}>
            <Text style={{ color: theme.text }}>{nowText}</Text>
          </Animated.View>
        )
      } else {
        return (
          <Text style={{ color: theme.text }}>
            {time} {minText}
          </Text>
        )
      }
    }

    return (
      <View style={[styles.listItemView, { borderColor: theme.border }]}>
        <Text style={{ color: theme.text }}>{bus}</Text>
        <Text style={[styles.title, { color: theme.text }]}>{title}</Text>
        {willBeIn()}
      </View>
    )
  }

  return (
    <View style={styles.container}>
      <Text style={[styles.info, { color: theme.text }]}>
        {t('timetable.station')} {stationTimetableId}
      </Text>

      <AntDesign
        name='staro'
        color='white'
        size={30}
        style={styles.favoriteIcon}
        onPress={saveFavoriteHandler}
      />

      <View style={styles.listHeader}>
        <Text style={{ color: theme.text }}>{t('timetable.bus')}</Text>
        <Text style={{ color: theme.text }}>{t('timetable.direction')}</Text>
        <Text style={{ color: theme.text }}>{t('timetable.time')}</Text>
      </View>

      {!data ? null : (
        <FlatList
          data={data.ArrivalTime}
          renderItem={({ item }) => (
            <Item
              title={item.DestinationStopName}
              time={item.ArrivalTime}
              bus={item.RouteNumber}
              minText={t('timetable.minText')}
              nowText={t('timetable.nowText')}
            />
          )}
          keyExtractor={item => item.RouteNumber}
        />
      )}

      {!data
        ? null
        : netInfo.isConnected && data.ArrivalTime.length === 0 && DisplayTime()}
    </View>
  )
}