Skip to content

Instantly share code, notes, and snippets.

@jermainedilao
Last active May 15, 2018 15:01
Show Gist options
  • Save jermainedilao/6275ff1269c30ba0ca843afa65458940 to your computer and use it in GitHub Desktop.
Save jermainedilao/6275ff1269c30ba0ca843afa65458940 to your computer and use it in GitHub Desktop.
/**
* Bookmarks or removes bookmark from an article.
**/
export const articleBookmarkOrRemoveBookmark = (article) => {
console.log("articleBookmarkOrRemoveBookmark");
// Temporary workaround.
// Replace with bookmarking inside DB then pass the new list from DB to reducers.
article.bookmark = !article.bookmark;
return {
type: ARTICLE_BOOKMARK,
payload: article
}
};
import React, { Component } from "react";
import { FlatList, View } from "react-native";
import { connect } from "react-redux";
import { articlesFetch } from "../../actions/index";
import ArticleListItem from "./ArticleListItem";
class ArticleList extends Component {
constructor() {
super();
}
componentWillMount() {
this.props.articlesFetch();
}
componentWillReceiveProps(nextProps) {
console.log("componentWillReceiveProps");
console.log(nextProps);
}
keyExtractor = (item, index) => `${item.publishedAt}${item.title}`;
renderItem({ item }) {
console.log("renderItem");
return (
<ArticleListItem
article={item}
/>
);
}
renderView() {
let { articleList } = this.props;
console.log("renderView");
console.log(articleList);
if (articleList.length === 0) articleList = null;
return (
<FlatList
data={articleList}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
showsVerticalScrollIndicator={false}
/>
);
}
render() {
const { containerStyle } = styles;
return (
<View style={containerStyle}>
{this.renderView()}
</View>
);
}
}
const styles = {
containerStyle: {
flex: 1,
marginLeft: 10,
marginRight: 10,
}
};
const mapStateToProps = (state) => {
console.log(state);
const { articleList } = state;
return articleList;
};
export default connect(mapStateToProps, { articlesFetch })(ArticleList);
import React, { Component } from "react";
import { Image, Text, TouchableOpacity } from "react-native";
import { connect } from "react-redux";
import { CardButton, CardSection, CardView, HorizontalLineSeparator } from "../common/index";
import {
BOOKMARK_COLOR,
DEFAULT_ARTICLE_IMAGE_HEIGHT,
TEXT_COLOR_PRIMARY,
TEXT_COLOR_SECONDARY,
TEXT_SIZE_LARGE,
TEXT_SIZE_NORMAL,
TEXT_SIZE_SMALL
} from "../../styles";
import { articleBookmarkOrRemoveBookmark, articleOpen } from "../../actions";
class ArticleListItem extends Component {
constructor() {
super();
this.state = {
imageHeight: DEFAULT_ARTICLE_IMAGE_HEIGHT,
isBookmarked: false
}
}
componentWillMount() {
console.log("componentWillMount");
const { article } = this.props;
this.updateBookmarkState(article);
Image.getSize(article.urlToImage, (width, height) => {
// Adjust to original image height if less than the DEFAULT_ARTICLE_IMAGE_HEIGHT.
if (height < DEFAULT_ARTICLE_IMAGE_HEIGHT) {
this.setState({
imageHeight: height
});
}
}, (error) => {
console.log(error);
});
}
componentWillReceiveProps(nextProps) {
console.log("componentWillReceiveProps");
console.log(nextProps);
const { article } = nextProps;
this.updateBookmarkState(article);
}
updateBookmarkState = (article) => {
console.log("updateBookmarkState");
this.setState({
isBookmarked: article.bookmark
});
};
onArticlePress = () => this.props.articleOpen(this.props.article);
onBookmarkPress = () => {
console.log("onBookmarkPress");
this.props.articleBookmark(this.props.article);
};
render() {
console.log("render");
const { article } = this.props;
const {
imageStyle, titleTextStyle, descriptionTextStyle,
sourceTextStyle, horizontalLineSeparator
} = styles;
return (
<TouchableOpacity
onPress={this.onArticlePress}
activeOpacity={0.6}
>
<CardView>
<Image
style={[imageStyle, { height: this.state.imageHeight }]}
resizeMode="cover"
resizeMethod="scale"
source={{ uri: article.urlToImage }}
/>
<CardSection>
<Text style={titleTextStyle}>
{article.title}
</Text>
<Text style={descriptionTextStyle}>
{article.description}
</Text>
<Text style={sourceTextStyle}>
{`source: ${article.source.name}`}
</Text>
</CardSection>
<HorizontalLineSeparator style={horizontalLineSeparator} />
<CardButton
text={this.state.isBookmarked ? "Remove" : "Add"}
buttonIconType="material"
buttonIconName={this.state.isBookmarked ? "bookmark" : "bookmark-border"}
buttonIconColor={BOOKMARK_COLOR}
onPress={this.onBookmarkPress}
/>
</CardView>
</TouchableOpacity>
);
}
}
const styles = {
imageStyle: {
flex: 1,
width: null,
minHeight: 150
},
titleTextStyle: {
fontSize: TEXT_SIZE_LARGE,
color: TEXT_COLOR_PRIMARY,
marginTop: 4
},
descriptionTextStyle: {
fontSize: TEXT_SIZE_NORMAL,
color: TEXT_COLOR_SECONDARY,
marginTop: 8
},
sourceTextStyle: {
fontSize: TEXT_SIZE_SMALL,
fontStyle: "italic",
color: TEXT_COLOR_SECONDARY,
opacity: 0.8,
marginTop: 4,
textAlign: "right"
},
horizontalLineSeparator: {
marginLeft: 8,
marginRight: 8
}
};
const mapStateToProps = (state) => {
return {};
};
export default connect(mapStateToProps, {
articleOpen,
articleBookmark: articleBookmarkOrRemoveBookmark
})(ArticleListItem);
import React from "react";
import {
ARTICLE_BOOKMARK, ARTICLE_OPEN_URL_FAIL, ARTICLE_OPEN_URL_SUCCESS, ARTICLE_PRESS,
ARTICLES_FETCH
} from "../actions/types";
const INITIAL_STATE = {
articleList: [],
error: ""
};
export default (state = INITIAL_STATE, action) => {
console.log(state);
console.log(action.type);
console.log(action.payload);
switch (action.type) {
case ARTICLE_BOOKMARK:
let articleList = replaceArticleById(state.articleList, action.payload);
return { ...state, articleList };
default:
return state;
}
}
/**
* Replaces the article inside the list that has the same `id` with the `newArticle`.
**/
const replaceArticleById = (articleList, newArticle) => {
return articleList.map((article) => {
if (article.id === newArticle.id) {
return newArticle;
} else {
return article;
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment