diff --git a/README.md b/README.md index 3fe956e5..91af7128 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,9 @@ A simple way to stay up to date with upcoming space launches, built with [React- ## Preview -
- - - -
+

+ +

## Installation diff --git a/src/Common/ScreenTitle.js b/src/Common/ScreenTitle.js index b929ad81..ed8f7b87 100644 --- a/src/Common/ScreenTitle.js +++ b/src/Common/ScreenTitle.js @@ -1,5 +1,6 @@ import React, { Component } from "react"; import styled from "styled-components"; +import { Animated, Text, Easing } from "react-native"; const Wrapper = styled.View` padding: 0 25px; @@ -14,23 +15,49 @@ const MainText = styled.Text` margin-top: 15px; `; -const BackgroundText = styled.Text` +const BackgroundText = styled(Animated.createAnimatedComponent(Text))` position: absolute; left: 25px; right: 0; top: -20px; font-size: 100px; - color: #aaaaaa11; + color: #aaaaaa; font-weight: bold; `; export default class extends Component { + state = { + AppearAnim: new Animated.Value(0) + }; + + componentDidMount() { + Animated.timing(this.state.AppearAnim, { + toValue: 1, + duration: 500, + easing: Easing.out(Easing.quad) + }).start(); + } + render() { const { title, noBackgroundText = false, style = {} } = this.props; + const { AppearAnim } = this.state; + const left = AppearAnim.interpolate({ + inputRange: [0, 1], + outputRange: [100, 25] + }); + const opacity = AppearAnim.interpolate({ + inputRange: [0, 1], + outputRange: [0, 0.3] + }); + return ( {!noBackgroundText && ( - + {title} )} diff --git a/src/Common/Searchbar.js b/src/Common/Searchbar.js index 76b29cb9..0747c884 100644 --- a/src/Common/Searchbar.js +++ b/src/Common/Searchbar.js @@ -11,6 +11,7 @@ const Wrapper = styled.View` color: white; background: white; flex-direction: row; + align-items: center; `; const StyledInput = styled.TextInput` diff --git a/src/Common/__snapshots__/ScreenTitle.test.js.snap b/src/Common/__snapshots__/ScreenTitle.test.js.snap index 09f77bb9..51d48f05 100644 --- a/src/Common/__snapshots__/ScreenTitle.test.js.snap +++ b/src/Common/__snapshots__/ScreenTitle.test.js.snap @@ -20,18 +20,16 @@ exports[`screenTitle renders correctly 1`] = ` ellipsizeMode="clip" numberOfLines={1} style={ - Array [ - Object { - "color": "#aaaaaa11", - "fontSize": 100, - "fontWeight": "bold", - "left": 25, - "position": "absolute", - "right": 0, - "top": -20, - }, - undefined, - ] + Object { + "color": "#aaaaaa", + "fontSize": 100, + "fontWeight": "bold", + "left": 100, + "opacity": 0, + "position": "absolute", + "right": 0, + "top": -20, + } } > My screen diff --git a/src/Common/__snapshots__/Searchbar.test.js.snap b/src/Common/__snapshots__/Searchbar.test.js.snap index a48f02db..17cf009b 100644 --- a/src/Common/__snapshots__/Searchbar.test.js.snap +++ b/src/Common/__snapshots__/Searchbar.test.js.snap @@ -5,6 +5,7 @@ exports[`Searchbar renders correctly 1`] = ` style={ Array [ Object { + "alignItems": "center", "backgroundColor": "white", "borderRadius": 40, "color": "white", diff --git a/src/Components/DashboardScreen/DashboardScreen.js b/src/Components/DashboardScreen/DashboardScreen.js index 632a9dbe..418090b7 100644 --- a/src/Components/DashboardScreen/DashboardScreen.js +++ b/src/Components/DashboardScreen/DashboardScreen.js @@ -9,6 +9,7 @@ import NextLaunchCard from "../NextLaunchCard"; import ErrorCard from "../ErrorCard"; import Loader from "../../Common/Loader"; import CountdownCard from "../CountdownCard/CountdownCard"; +import { STATES } from "../../constants"; const Wrapper = styled(ScreenBackground)` flex: 1; @@ -45,9 +46,10 @@ class DashboardScreen extends Component { - {state === "loading" && this.props.launches.numberOfLaunches === 0 ? ( + {state === STATES.LOADING && + this.props.launches.numberOfLaunches === 0 ? ( - ) : state === "error" ? ( + ) : state === STATES.ERROR ? ( this.loadUpcomingLaunch()} /> ) : ( data && ( @@ -55,7 +57,7 @@ class DashboardScreen extends Component { contentContainerStyle={{ flex: 1 }} refreshControl={ this.loadUpcomingLaunch()} tintColor="#fff" /> diff --git a/src/Components/LaunchCalendarScreen/LaunchCalendarScreen.js b/src/Components/LaunchCalendarScreen/LaunchCalendarScreen.js index 8c1a26ed..d7121317 100644 --- a/src/Components/LaunchCalendarScreen/LaunchCalendarScreen.js +++ b/src/Components/LaunchCalendarScreen/LaunchCalendarScreen.js @@ -9,6 +9,7 @@ import Loader from "../../Common/Loader"; import ErrorCard from "../ErrorCard"; import Button from "../../Common/Button"; import PushableWrapper from "../../Common/PushableWrapper"; +import { STATES } from "../../constants"; const Wrapper = styled(ScreenBackground)` flex: 1; @@ -49,7 +50,7 @@ export default class extends Component { const data = this.props.launches; const showMoreEnabled = this.state.page < 5; - if (data.state === "error") { + if (data.state === STATES.ERROR) { return ( @@ -61,7 +62,7 @@ export default class extends Component { return ( - {data.state === "loading" && data.numberOfLaunches < 5 ? ( + {data.state === STATES.LOADING && data.numberOfLaunches < 5 ? ( ) : ( ( <> {showMoreEnabled && - (data.state === "loading" ? ( + (data.state === STATES.LOADING ? ( ) : ( ))} )} refreshControl={ diff --git a/src/Components/NewsScreen/NewsScreen.js b/src/Components/NewsScreen/NewsScreen.js index 0144b8c6..55f9bcd7 100644 --- a/src/Components/NewsScreen/NewsScreen.js +++ b/src/Components/NewsScreen/NewsScreen.js @@ -7,7 +7,7 @@ import { observer, inject } from "mobx-react"; import NewsCard from "../NewsCard/NewsCard"; import ErrorCard from "../ErrorCard"; import Loader from "../../Common/Loader"; -import { MONTHS_FULL } from "../../constants"; +import { MONTHS_FULL, STATES } from "../../constants"; const Wrapper = styled(ScreenBackground)` padding: 40px 0 0 0; @@ -41,7 +41,7 @@ class NewsScreen extends Component { const dateTS = new Date(); const date = `${MONTHS_FULL[dateTS.getMonth()]} ${dateTS.getDate()}`; - if (news.state === "error") { + if (news.state === STATES.ERROR) { return ( @@ -53,7 +53,7 @@ class NewsScreen extends Component { return ( - {news.state === "loading" && news.numberOfArticles <= 0 ? ( + {news.state === STATES.LOADING && news.numberOfArticles <= 0 ? ( ) : ( diff --git a/src/Components/SearchScreen/SearchScreen.js b/src/Components/SearchScreen/SearchScreen.js index 9c5555f1..78738ba9 100644 --- a/src/Components/SearchScreen/SearchScreen.js +++ b/src/Components/SearchScreen/SearchScreen.js @@ -7,6 +7,7 @@ import ScreenBackground from "../../Common/ScreenBackground"; import Searchbar from "../../Common/Searchbar"; import ResultCard from "./ResultCard"; import Loader from "../../Common/Loader"; +import { STATES } from "../../constants"; const Wrapper = styled(ScreenBackground)` flex: 1; @@ -50,9 +51,9 @@ export default class SearchScreen extends Component { searchLaunches(str)} /> - {state === "loading" && } + {state === STATES.LOADING && } {results.length >= 0 && - state === "success" && ( + state === STATES.SUCCESS && ( <> {totalResults || 0} results {results.map(data => ( diff --git a/src/Components/SettingsScreen/SettingsScreen.js b/src/Components/SettingsScreen/SettingsScreen.js index 055e7bae..62408a0c 100644 --- a/src/Components/SettingsScreen/SettingsScreen.js +++ b/src/Components/SettingsScreen/SettingsScreen.js @@ -165,7 +165,7 @@ class SettingsScreen extends Component { Version {version} )} - 2018 - Maxime Nory + 2019 - Maxime Nory diff --git a/src/Models/LaunchesModel.js b/src/Models/LaunchesModel.js index e09bc105..71303f56 100644 --- a/src/Models/LaunchesModel.js +++ b/src/Models/LaunchesModel.js @@ -2,6 +2,7 @@ import { observable, computed, action } from "mobx"; import { PushNotificationIOS, AsyncStorage, Platform } from "react-native"; import { API_URL } from "../../cfg"; import PushNotification from "react-native-push-notification"; +import { STATES } from "../constants"; storeData = async data => { try { @@ -17,7 +18,7 @@ export default class LaunchesModel { nextLaunch = []; @observable - state = "idle"; + state = STATES.IDLE; @observable notifications = { @@ -114,29 +115,29 @@ export default class LaunchesModel { @action loadNextLaunches = numberOfLaunches => { - this.state = "loading"; + this.state = STATES.LOADING; fetch(`${API_URL}next/${numberOfLaunches}`) .then(data => data.json()) .then(data => { this.launches = data.launches; - this.state = "success"; + this.state = STATES.SUCCESS; }) .catch(err => { - this.state = "error"; + this.state = STATES.ERROR; }); }; @action loadMoreLaunches = numberOfLaunches => { - this.state = "loading"; + this.state = STATES.LOADING; fetch(`${API_URL}next/${numberOfLaunches}?offset=${this.launches.length}`) .then(data => data.json()) .then(data => { this.launches = this.launches.concat(data.launches); - this.state = "success"; + this.state = STATES.SUCCESS; }) .catch(err => { - this.state = "error"; + this.state = STATES.ERROR; }); }; } diff --git a/src/Models/NewsModel.js b/src/Models/NewsModel.js index b69b7ed8..d1644a19 100644 --- a/src/Models/NewsModel.js +++ b/src/Models/NewsModel.js @@ -1,12 +1,13 @@ import { observable, computed, action } from "mobx"; import { NEWS_API_URL } from "../../cfg"; +import { STATES } from "../constants"; export default class NewsModel { @observable articles = []; @observable - state = "idle"; // @TODO: use constant instead of strings + state = STATES.IDLE; @computed get numberOfArticles() { @@ -15,15 +16,15 @@ export default class NewsModel { @action getNews = (numberOfArticles = 12) => { - this.state = "loading"; + this.state = STATES.LOADING; fetch(`${NEWS_API_URL}/articles?limit=${numberOfArticles}`) .then(data => data.json()) .then(data => { this.articles = data || []; - this.state = "success"; + this.state = STATES.SUCCESS; }) .catch(err => { - this.state = "error"; + this.state = STATES.ERROR; }); }; } diff --git a/src/Models/SearchModel.js b/src/Models/SearchModel.js index 30fad59f..00a0036d 100644 --- a/src/Models/SearchModel.js +++ b/src/Models/SearchModel.js @@ -1,26 +1,29 @@ import { observable, computed, action } from "mobx"; import { API_URL } from "../../cfg"; +import { STATES } from "../constants"; export default class SearchModel { @observable results = []; + @observable - state = "idle"; + state = STATES.IDLE; + @observable totalResults = ""; @action searchLaunches = str => { - this.state = "loading"; + this.state = STATES.LOADING; fetch(`${API_URL}/${str}`) .then(data => data.json()) .then(data => { this.results = data.launches || []; this.totalResults = data.total; - this.state = "success"; + this.state = STATES.SUCCESS; }) .catch(err => { - this.state = "error"; + this.state = STATES.ERROR; }); }; } diff --git a/src/constants.js b/src/constants.js index b1dcadbf..f732a430 100644 --- a/src/constants.js +++ b/src/constants.js @@ -43,3 +43,10 @@ export const MONTHS_FULL = [ "November", "December" ]; + +export const STATES = { + IDLE: "idle", + LOADING: "loading", + SUCCESS: "success", + ERROR: "error" +};