...
 
Commits (8)
......@@ -4,26 +4,19 @@ import React, {
import {
Text,
Image,
View,
TouchableOpacity,
Button,
StyleSheet,
Platform,
Linking,
} from 'react-native';
import {
observer,
inject
} from 'mobx-react/native'
import {
Avatar,
} from 'react-native-elements';
import FastImage from 'react-native-fast-image';
import formatDate from '../common/helpers/date';
import { CommonStyle as CS} from '../styles/Common';
import { FLAG_VIEW } from '../common/Permissions';
/**
* Blog Card
......@@ -34,7 +27,7 @@ export default class BlogCard extends PureComponent {
* Navigate to blog
*/
navToBlog = () => {
if (!this.props.navigation) return;
if (!this.props.navigation || !this.props.entity.can(FLAG_VIEW)) return;
return this.props.navigation.push('BlogView', { blog: this.props.entity });
}
......@@ -47,22 +40,20 @@ export default class BlogCard extends PureComponent {
const image = blog.getBannerSource();
return (
<TouchableOpacity onPress={this.navToBlog} style={styles.container}>
<TouchableOpacity onPress={this.navToBlog} style={CS.backgroundWhite}>
<FastImage source={image} style={styles.banner} resizeMode={FastImage.resizeMode.cover} />
<View style={styles.bodyContainer}>
<View style={styles.titleContainer}>
<View style={styles.titlecol}>
<Text style={styles.title}>{blog.title}</Text>
<View style={styles.ownerContainer}>
{ channel && <Avatar
width={24}
height={24}
rounded
source={channel.getAvatarSource()}
/> }
<Text style={styles.username}>{blog.ownerObj && blog.ownerObj.username.toUpperCase()}</Text>
<Text style={styles.createdDate}>{formatDate(blog.time_created)}</Text>
</View>
<View style={[CS.padding2x]}>
<View style={[CS.columnAlignStart, CS.fullWidth]}>
<Text style={[CS.fontL, CS.fontMedium]}>{blog.title}</Text>
<View style={[CS.marginBottom2x, CS.marginTop2x, CS.rowJustifyCenter, CS.alignCenter]}>
{ channel && <Avatar
width={24}
height={24}
rounded
source={channel.getAvatarSource()}
/> }
<Text style={[CS.fontS, CS.paddingLeft, CS.flexContainer]} numberOfLines={1}>{blog.ownerObj && blog.ownerObj.username.toUpperCase()}</Text>
<Text style={[CS.fontXS, CS.paddingLeft]}>{formatDate(blog.time_created)}</Text>
</View>
</View>
</View>
......@@ -72,73 +63,10 @@ export default class BlogCard extends PureComponent {
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#FFF',
},
bodyContainer: {
padding: 12,
paddingLeft: 12,
paddingRight: 12,
alignItems: 'stretch',
flexDirection: 'column',
width: '100%',
},
titlecol: {
flex:1
},
titleContainer: {
flexDirection: 'row',
flex:1,
},
title: {
fontWeight: '800',
fontFamily: 'Roboto',
color: '#444',
letterSpacing: 0.5,
fontSize: 16,
},
ownerContainer: {
flex:1,
flexDirection: 'row',
alignSelf: 'flex-start',
paddingTop: 4,
paddingBottom: 4,
alignItems: 'center',
justifyContent: 'center'
},
banner: {
flexDirection: 'row',
alignItems: 'stretch',
width: '100%',
height: 150,
},
headercontainer: {
flex: 1,
height: 100,
flexDirection: 'row',
},
username: {
paddingLeft: 8,
fontSize: 10,
color: '#888'
},
createdDate: {
paddingLeft: 5,
fontSize: 8,
},
countercontainer: {
paddingLeft: 130,
height: 60,
flexDirection: 'row'
},
avatar: {
height: 20,
width: 20,
borderRadius: 10
},
container: {
flex: 1,
flexDirection: 'column',
backgroundColor: '#FFF'
height: 150,
width: '100%',
}
});
......@@ -144,12 +144,10 @@ export default class BlogsViewScreen extends Component {
const blog = this.props.blogsView.blog;
const actions = (
<View style={[CS.flexContainer, CS.paddingLeft2x]}>
<View style={styles.actionsContainer}>
<RemindAction entity={blog} size={16} navigation={this.props.navigation} vertical={true}/>
<ThumbUpAction entity={blog} orientation='column' size={16} me={this.props.user.me} />
<ThumbDownAction entity={blog} orientation='column' size={16} me={this.props.user.me} />
</View>
<View style={[CS.rowJustifyStart]}>
<RemindAction entity={blog} navigation={this.props.navigation}/>
<ThumbUpAction entity={blog} />
<ThumbDownAction entity={blog} />
</View>
)
const image = blog.getBannerSource();
......@@ -166,17 +164,18 @@ export default class BlogsViewScreen extends Component {
<Text style={styles.title}>{blog.title}</Text>
{optMenu}
<View style={styles.ownerBlockContainer}>
<OwnerBlock entity={blog} navigation={this.props.navigation} rightToolbar={actions}>
<OwnerBlock entity={blog} navigation={this.props.navigation}>
<Text style={styles.timestamp}>{formatDate(blog.time_created)}</Text>
</OwnerBlock>
</View>
{actions}
<View style={styles.description}>
{blog.description ?
<BlogViewHTML html={blog.description} /> :
<CenteredLoading/>}
</View>
<View style={styles.moreInformation}>
{ blog.getLicenseText() &&
{ blog.getLicenseText() &&
<Icon color={colors.medium} size={18} name='public'/>
}
<Text style={[CS.fontXS, CS.paddingLeft, CS.colorMedium, CS.paddingRight2x]}>{blog.getLicenseText()}</Text>
......@@ -205,7 +204,7 @@ export default class BlogsViewScreen extends Component {
async showActionSheet() {
this.ActionSheet.show();
}
async handleActionSheetSelection(option) {
switch(option) {
case i18n.t('disableComments'):
......@@ -216,7 +215,7 @@ export default class BlogsViewScreen extends Component {
console.error(err);
this.showError();
}
}
}
......
......@@ -327,7 +327,7 @@ class CommentList extends React.Component<PropsType, StateType> {
const entity = this.props.entity;
if (this.state.hideInput || (!entity.allow_comments && entity.type !== "group" && entity.can(FLAG_CREATE_COMMENT))) return null;
if (this.state.hideInput || (!entity.allow_comments && entity.type !== "group") || !entity.can(FLAG_CREATE_COMMENT)) return null;
const attachment = this.props.store.attachment;
......
......@@ -567,7 +567,7 @@ export default class DiscoveryScreen extends Component {
*/
renderBlog = (row) => {
return (
<View style={styles.blogCardContainer}>
<View style={[CS.paddingBottom2x, CS.backgroundLight]}>
<ErrorBoundary containerStyle={CS.hairLineBottom}>
<BlogCard entity={row.item} navigation={this.props.navigation} />
</ErrorBoundary>
......@@ -627,9 +627,5 @@ const styles = StyleSheet.create({
},
iconActive: {
color: colors.primary,
},
blogCardContainer: {
backgroundColor: '#ececec',
paddingBottom: 8,
},
}
});
......@@ -5,17 +5,15 @@ import React, {
import { observer, inject } from 'mobx-react/native';
import {
Text,
StyleSheet,
View,
TouchableOpacity,
} from 'react-native';
import { Icon } from 'react-native-elements';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { CommonStyle } from '../../../styles/Common';
import { CommonStyle as CS } from '../../../styles/Common';
import Counter from './Counter';
import withPreventDoubleTap from '../../../common/components/PreventDoubleTap';
import { FLAG_CREATE_COMMENT } from '../../../common/Permissions';
// prevent double tap in touchable
const TouchableOpacityCustom = withPreventDoubleTap(TouchableOpacity);
......@@ -23,8 +21,9 @@ const TouchableOpacityCustom = withPreventDoubleTap(TouchableOpacity);
/**
* Comments Action Component
*/
export default
@observer
export default class CommentsAction extends Component {
class CommentsAction extends Component {
static defaultProps = {
size: 20,
......@@ -35,10 +34,14 @@ export default class CommentsAction extends Component {
render() {
const icon = this.props.entity.allow_comments ? 'chat-bubble' : 'speaker-notes-off';
const canComment = this.props.entity.allow_comments && this.props.entity.can(FLAG_CREATE_COMMENT);
const color = canComment ? (this.props.entity['comments:count'] > 0 ? CS.colorPrimary : CS.colorAction) : CS.colorLightGreyed;
return (
<TouchableOpacityCustom style={[CommonStyle.flexContainer, CommonStyle.rowJustifyCenter]} onPress={this.openComments}>
<Icon color={this.props.entity['comments:count'] > 0 ? 'rgb(70, 144, 214)' : 'rgb(96, 125, 139)'} name={icon} size={this.props.size} />
<Counter size={this.props.size * 0.75} count={this.props.entity['comments:count']} />
<TouchableOpacityCustom style={[CS.flexContainer, CS.centered, CS.rowJustifyCenter]} onPress={this.openComments}>
<Icon style={[color, CS.marginRight]} name={icon} size={this.props.size} />
<Counter size={this.props.size * 0.70} count={this.props.entity['comments:count']} />
</TouchableOpacityCustom>
);
}
......
// @flow
import React, {
PureComponent
} from 'react';
import {
Text,
StyleSheet,
View,
} from 'react-native';
import { CommonStyle } from '../../../styles/Common';
import { CommonStyle as CS } from '../../../styles/Common';
import abbrev from '../../../common/helpers/abbrev';
import type {
TextStyleProp,
} from 'react-native/Libraries/StyleSheet/StyleSheet';
import type { Node } from 'react';
type PropsType = {
size: number,
count: number,
style: TextStyleProp
};
/**
* Counters
*/
export default class Counter extends PureComponent {
export default class Counter extends PureComponent<PropsType> {
/**
* Default Props
*/
static defaultProps = {
size: 15,
style: CS.colorAction
};
/**
* Render
*/
render() {
render(): Node {
const {
orientation,
size,
count,
style,
...otherProps
} = this.props;
return (
<View style={styles.counterContainer}>
<View style={[CS.columnAlignCenter]}>
<Text
style={[ orientation != 'column' ? { paddingLeft: 4 } : { paddingLeft: 0}, styles.counter, { fontSize: Math.round(size * 0.75)}]}
style={[style, { fontSize: size}]}
{...otherProps}
>
{count > 0 ? abbrev(count,0) : ''}
......@@ -47,17 +59,4 @@ export default class Counter extends PureComponent {
</View>
)
}
}
const styles = StyleSheet.create({
counterContainer: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
counter: {
color: '#888',
fontWeight: '800',
},
});
......@@ -3,19 +3,15 @@ import React, {
} from 'react';
import {
Text,
StyleSheet,
Modal,
View,
TouchableOpacity,
} from 'react-native';
import IonIcon from 'react-native-vector-icons/Ionicons';
import { Icon } from 'react-native-elements';
import { CommonStyle } from '../../../styles/Common';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { CommonStyle as CS} from '../../../styles/Common';
import Counter from './Counter';
import withPreventDoubleTap from '../../../common/components/PreventDoubleTap';
import testID from '../../../common/helpers/testID';
import { FLAG_REMIND } from '../../../common/Permissions';
// prevent double tap in touchable
const TouchableOpacityCustom = withPreventDoubleTap(TouchableOpacity);
......@@ -29,18 +25,23 @@ export default class RemindAction extends PureComponent {
size: 20,
};
state = {
remindModalVisible: false,
}
/**
* Render
*/
render() {
const canRemind = this.props.entity.can(FLAG_REMIND);
const color = canRemind ? (this.props.entity['reminds'] > 0 ? CS.colorPrimary : CS.colorAction) : CS.colorLightGreyed;
return (
<TouchableOpacityCustom style={[CommonStyle.flexContainer, CommonStyle.rowJustifyCenter, this.props.vertical === true ? styles.verticalTouchable : null]} onPress={this.remind} {...testID('Remind activity button')}>
<Icon color={this.props.entity['reminds'] > 0 ? 'rgb(70, 144, 214)' : 'rgb(96, 125, 139)'} name='repeat' size={this.props.size} />
<Counter count={this.props.entity['reminds']} size={this.props.size * 0.75} />
<TouchableOpacityCustom
style={[CS.flexContainer, CS.centered, this.props.vertical === true ? CS.columnAlignCenter : CS.rowJustifyCenter]}
onPress={this.remind}
disabled={!canRemind}
{...testID('Remind activity button')}
>
<Icon style={[color, CS.marginRight]} name='repeat' size={this.props.size} />
<Counter count={this.props.entity['reminds']} size={this.props.size * 0.70} />
</TouchableOpacityCustom>
)
}
......@@ -54,24 +55,6 @@ export default class RemindAction extends PureComponent {
}
}
const styles = StyleSheet.create({
modal: {
flex: 1,
paddingTop: 4,
},
modalContainer: {
alignItems: 'center',
backgroundColor: '#ede3f2',
},
modalHeader: {
padding: 5
},
verticalTouchable: {
flexDirection: 'column',
alignItems: 'center',
}
});
......@@ -14,13 +14,14 @@ import {
observer,
} from 'mobx-react/native'
import { Icon } from 'react-native-elements';
import { CommonStyle } from '../../../styles/Common';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { CommonStyle as CS } from '../../../styles/Common';
import Counter from './Counter';
import withPreventDoubleTap from '../../../common/components/PreventDoubleTap';
import testID from '../../../common/helpers/testID';
import i18n from '../../../common/services/i18n.service';
import logService from '../../../common/services/log.service';
import { FLAG_VOTE } from '../../../common/Permissions';
// prevent double tap in touchable
const TouchableOpacityCustom = withPreventDoubleTap(TouchableOpacity);
......@@ -28,8 +29,9 @@ const TouchableOpacityCustom = withPreventDoubleTap(TouchableOpacity);
/**
* Thumb Up Action Component
*/
export default
@observer
export default class ThumbUpAction extends Component {
class ThumbUpAction extends Component {
/**
* Default Props
......@@ -56,14 +58,19 @@ export default class ThumbUpAction extends Component {
const count = entity[`thumbs:${this.direction}:count`];
const canVote = entity.can(FLAG_VOTE);
const color = canVote ? (this.voted ? CS.colorPrimary : CS.colorAction) : CS.colorLightGreyed;
return (
<TouchableOpacityCustom
style={[CommonStyle.flexContainer, CommonStyle.centered, this.props.orientation == 'column' ? CommonStyle.columnAlignCenter : CommonStyle.rowJustifyCenter ]}
style={[CS.flexContainer, CS.centered, this.props.orientation == 'column' ? CS.columnAlignCenter : CS.rowJustifyCenter ]}
onPress={this.toggleThumb}
disabled={!canVote}
{...testID(`Thumb ${this.direction} activity button`)}
>
<Icon color={this.voted ? 'rgb(70, 144, 214)' : 'rgb(96, 125, 139)'} name={this.iconName} size={this.props.size} />
<Counter size={this.props.size * 0.75} count={count} orientation={this.props.orientation} {...testID(`Thumb ${this.direction} count`)}/>
<Icon style={[color, CS.marginRight]} name={this.iconName} size={this.props.size} />
<Counter size={this.props.size * 0.70} count={count} orientation={this.props.orientation} {...testID(`Thumb ${this.direction} count`)}/>
</TouchableOpacityCustom>
);
}
......
export default colors = {
primary : '#4690D6',
secondary : '#FFDD63',
tertiary : '#4C9EB1',
danger : '#f53d3d',
light : '#f7f7f7',
medium : '#b0bec5',
dark : '#222222',
greyed : '#cccccc',
primary : '#4690D6',
secondary : '#FFDD63',
tertiary : '#4C9EB1',
danger : '#f53d3d',
light : '#f7f7f7',
medium : '#b0bec5',
dark : '#222222',
greyed : '#cccccc',
lightGreyed : '#d8d8d8',
darkGreyed: '#777777',
explicit : '#f44336',
darkGreyed : '#777777',
explicit : '#f44336',
action : 'rgb(96, 125, 139)',
}
......@@ -77,6 +77,9 @@ export const CommonStyle = StyleSheet.create({
colorWhite: {
color: '#FFFFFF'
},
colorAction: {
color: colors.action
},
colorBlack: {
color: '#000000'
},
......@@ -114,6 +117,9 @@ export const CommonStyle = StyleSheet.create({
backgroundWhite: {
backgroundColor: 'white'
},
backgroundAction: {
backgroundColor: colors.action,
},
backgroundLightGreyed: {
backgroundColor: colors.lightGreyed
},
......