mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-29 00:21:41 +03:00
Merged with master
This commit is contained in:
commit
5580b17576
@ -19,7 +19,7 @@ export default EStyleSheet.create({
|
||||
saveIcon: {
|
||||
fontSize: 20,
|
||||
color: '$iconColor',
|
||||
marginLeft: 10,
|
||||
marginLeft: 15,
|
||||
},
|
||||
savedIcon: {
|
||||
color: '#a1c982',
|
||||
|
@ -9,6 +9,7 @@ export default EStyleSheet.create({
|
||||
height: 20,
|
||||
padding: 5,
|
||||
paddingHorizontal: 10,
|
||||
minWidth: 50,
|
||||
marginRight: 8,
|
||||
fontFamily: '$editorFont',
|
||||
},
|
||||
|
@ -6,6 +6,7 @@ import styles from './chipStyle';
|
||||
const Chip = props => (
|
||||
<Fragment>
|
||||
<TextInput
|
||||
allowFontScaling
|
||||
style={[styles.textInput, props.isPin && styles.isPin]}
|
||||
onChangeText={text => props.handleOnChange(text)}
|
||||
onBlur={() => props.handleOnBlur()}
|
||||
|
@ -8,6 +8,7 @@ export default EStyleSheet.create({
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
borderTopWidth: 0.1,
|
||||
shadowOpacity: 0.1,
|
||||
elevation: 10,
|
||||
},
|
||||
safeArea: {
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import { TouchableWithoutFeedback, TouchableOpacity, SafeAreaView } from 'react-native';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { TouchableOpacity, SafeAreaView } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import ViewOverflow from 'react-native-view-overflow';
|
||||
|
||||
@ -7,13 +7,14 @@ import ViewOverflow from 'react-native-view-overflow';
|
||||
import { updateActiveBottomTab } from '../../../redux/actions/uiAction';
|
||||
|
||||
// Constants
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
// Components
|
||||
|
||||
// Styles
|
||||
import styles from './bottomTabBarStyles';
|
||||
|
||||
class BottomTabBarView extends Component {
|
||||
class BottomTabBarView extends PureComponent {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
@ -37,6 +38,27 @@ class BottomTabBarView extends Component {
|
||||
}
|
||||
|
||||
// Component Functions
|
||||
_jumpTo = (route) => {
|
||||
const {
|
||||
jumpTo,
|
||||
navigation: {
|
||||
state: { index, routes },
|
||||
},
|
||||
} = this.props;
|
||||
|
||||
const _routeName = routes[index].routeName;
|
||||
|
||||
if (
|
||||
!!route
|
||||
&& !!route.params
|
||||
&& !!route.params.scrollToTop
|
||||
&& _routeName === ROUTES.TABBAR.HOME
|
||||
) {
|
||||
route.params.scrollToTop();
|
||||
}
|
||||
|
||||
jumpTo(route.key);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
@ -46,7 +68,6 @@ class BottomTabBarView extends Component {
|
||||
activeTintColor,
|
||||
inactiveTintColor,
|
||||
renderIcon,
|
||||
jumpTo,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -60,7 +81,7 @@ class BottomTabBarView extends Component {
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<TouchableOpacity onPress={() => jumpTo(route.key)}>
|
||||
<TouchableOpacity onPress={() => this._jumpTo(route)}>
|
||||
{renderIcon({
|
||||
route,
|
||||
focused: index === idx,
|
||||
|
@ -33,6 +33,18 @@ class CollapsibleCardView extends PureComponent {
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { isExpanded, moreHeight } = this.props;
|
||||
|
||||
if (!nextProps.isExpanded && isExpanded !== nextProps.isExpanded) {
|
||||
this._toggleOnPress();
|
||||
}
|
||||
|
||||
if (moreHeight !== nextProps.moreHeight) {
|
||||
this.anime.height.setValue(this._getMaxValue() + nextProps.moreHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Component Functions
|
||||
_initContentHeight = (event) => {
|
||||
if (this.anime.contentHeight > 0) return;
|
||||
@ -45,6 +57,7 @@ class CollapsibleCardView extends PureComponent {
|
||||
_getMinValue = () => 0;
|
||||
|
||||
_toggleOnPress = () => {
|
||||
const { handleOnExpanded } = this.props;
|
||||
Animated.timing(this.anime.height, {
|
||||
toValue: this.anime.expanded ? this._getMinValue() : this._getMaxValue(),
|
||||
duration: 200,
|
||||
@ -54,6 +67,8 @@ class CollapsibleCardView extends PureComponent {
|
||||
this.setState({
|
||||
expanded: this.anime.expanded,
|
||||
});
|
||||
|
||||
if (handleOnExpanded && this.anime.expanded) handleOnExpanded();
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -10,7 +10,7 @@ export default EStyleSheet.create({
|
||||
},
|
||||
hasTopBorder: {
|
||||
borderTopColor: '$borderTopColor',
|
||||
borderTopWidth: 1,
|
||||
borderTopWidth: 0.5,
|
||||
},
|
||||
title: {
|
||||
fontFamily: '$primaryFont',
|
||||
|
@ -1,21 +1,8 @@
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
textInput: {
|
||||
color: '$primaryBackgroundColor',
|
||||
fontSize: 10,
|
||||
backgroundColor: '#c1c5c7',
|
||||
borderRadius: 50,
|
||||
maxHeight: 18,
|
||||
padding: 5,
|
||||
paddingHorizontal: 10,
|
||||
marginRight: 8,
|
||||
},
|
||||
tagWrapper: {
|
||||
flexDirection: 'row',
|
||||
marginTop: 14,
|
||||
},
|
||||
firstTag: {
|
||||
backgroundColor: '$primaryBlue',
|
||||
},
|
||||
});
|
||||
|
@ -103,7 +103,7 @@ export default class TagAreaView extends Component {
|
||||
{chips.map((chip, i) => (
|
||||
<Chip
|
||||
key={i}
|
||||
refs={(input) => {
|
||||
ref={(input) => {
|
||||
this.inputs[i] = input;
|
||||
}}
|
||||
isPin={i === 0 && chips[1]}
|
||||
|
@ -6,5 +6,7 @@ export default EStyleSheet.create({
|
||||
fontWeight: 'bold',
|
||||
fontSize: 24,
|
||||
fontFamily: '$editorFont',
|
||||
textAlignVertical: 'top',
|
||||
paddingVertical: 0,
|
||||
},
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ export default class TitleAreaView extends Component {
|
||||
return (
|
||||
<View style={globalStyles.containerHorizontal16}>
|
||||
<TextInput
|
||||
style={styles.textInput}
|
||||
style={[styles.textInput, {height: Math.max(35, this.state.height)}]}
|
||||
placeholderTextColor="#c1c5c7"
|
||||
editable={!isPreviewActive}
|
||||
maxLength={250}
|
||||
@ -57,8 +57,11 @@ export default class TitleAreaView extends Component {
|
||||
id: 'editor.title',
|
||||
})}
|
||||
multiline
|
||||
autoFocus={autoFocus}
|
||||
numberOfLines={4}
|
||||
onContentSizeChange={(event) => {
|
||||
this.setState({ height: event.nativeEvent.contentSize.height })
|
||||
}}
|
||||
autoFocus={autoFocus}
|
||||
onChangeText={text => this._handleOnChange(text)}
|
||||
value={text}
|
||||
/>
|
||||
|
@ -14,7 +14,7 @@ export default EStyleSheet.create({
|
||||
alignSelf: 'center',
|
||||
},
|
||||
rightIcon: {
|
||||
color: '$primaryDarkText',
|
||||
color: '$darkIconColor',
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
|
@ -15,6 +15,7 @@ export default EStyleSheet.create({
|
||||
paddingHorizontal: 16,
|
||||
color: '$primaryBlack',
|
||||
fontFamily: '$editorFont',
|
||||
textAlignVertical: 'top',
|
||||
},
|
||||
inlinePadding: {
|
||||
padding: 8,
|
||||
|
@ -19,12 +19,13 @@ import styles from './notificationStyles';
|
||||
|
||||
class NotificationView extends PureComponent {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
// TODO: Remove filters from local state.
|
||||
filters: [
|
||||
{ key: 'activities', value: 'ALL ACTIVITIES' },
|
||||
{ key: 'votes', value: 'VOTES' },
|
||||
@ -47,31 +48,96 @@ class NotificationView extends PureComponent {
|
||||
getActivities(filters[index].key);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
notifications, intl, navigateToNotificationRoute, readAllNotification,
|
||||
} = this.props;
|
||||
const { filters } = this.state;
|
||||
const today = [];
|
||||
const yesterday = [];
|
||||
const thisWeek = [];
|
||||
const thisMonth = [];
|
||||
const olderThenMonth = [];
|
||||
_renderList = (data) => {
|
||||
const { navigateToNotificationRoute } = this.props;
|
||||
|
||||
notifications.map((item) => {
|
||||
if (isToday(item.timestamp)) {
|
||||
today.push(item);
|
||||
} else if (isYesterday(item.timestamp)) {
|
||||
yesterday.push(item);
|
||||
} else if (isThisWeek(item.timestamp)) {
|
||||
thisWeek.push(item);
|
||||
} else if (isThisMonth(item.timestamp)) {
|
||||
thisMonth.push(item);
|
||||
} else {
|
||||
olderThenMonth.push(item);
|
||||
}
|
||||
return (
|
||||
<FlatList
|
||||
data={data}
|
||||
renderItem={({ item }) => (
|
||||
<NotificationLine
|
||||
notification={item}
|
||||
handleOnPressNotification={navigateToNotificationRoute}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
_getNotificationsArrays = () => {
|
||||
const { notifications, intl } = this.props;
|
||||
|
||||
if (!notifications && notifications.length < 1) return null;
|
||||
|
||||
const notificationArray = [
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'notification.recent',
|
||||
}),
|
||||
notifications: [],
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'notification.yesterday',
|
||||
}),
|
||||
notifications: [],
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'notification.this_week',
|
||||
}),
|
||||
notifications: [],
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'notification.this_month',
|
||||
}),
|
||||
notifications: [],
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({
|
||||
id: 'notification.older_then',
|
||||
}),
|
||||
notifications: [],
|
||||
},
|
||||
];
|
||||
|
||||
notifications.forEach((item) => {
|
||||
const listIndex = this._getTimeListIndex(item.timestamp);
|
||||
|
||||
notificationArray[listIndex].notifications.push(item);
|
||||
});
|
||||
|
||||
return notificationArray;
|
||||
};
|
||||
|
||||
_getTimeListIndex = (timestamp) => {
|
||||
if (isToday(timestamp)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isYesterday(timestamp)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (isThisWeek(timestamp)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (isThisMonth(timestamp)) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 4;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { readAllNotification } = this.props;
|
||||
const { filters } = this.state;
|
||||
|
||||
const _notifications = this._getNotificationsArrays();
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<FilterBar
|
||||
@ -83,111 +149,15 @@ class NotificationView extends PureComponent {
|
||||
onRightIconPress={readAllNotification}
|
||||
/>
|
||||
<ScrollView style={styles.scrollView}>
|
||||
{today.length > 0 && (
|
||||
<Fragment>
|
||||
<ContainerHeader
|
||||
hasSeperator
|
||||
isBoldTitle
|
||||
title={intl.formatMessage({
|
||||
id: 'notification.recent',
|
||||
})}
|
||||
/>
|
||||
<FlatList
|
||||
data={today}
|
||||
renderItem={({ item }) => (
|
||||
<NotificationLine
|
||||
notification={item}
|
||||
handleOnPressNotification={navigateToNotificationRoute}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
{yesterday.length > 0 && (
|
||||
<Fragment>
|
||||
<ContainerHeader
|
||||
hasSeperator
|
||||
isBoldTitle
|
||||
title={intl.formatMessage({
|
||||
id: 'notification.yesterday',
|
||||
})}
|
||||
/>
|
||||
<FlatList
|
||||
data={yesterday}
|
||||
renderItem={({ item }) => (
|
||||
<NotificationLine
|
||||
notification={item}
|
||||
handleOnPressNotification={navigateToNotificationRoute}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
{thisWeek.length > 0 && (
|
||||
<Fragment>
|
||||
<ContainerHeader
|
||||
hasSeperator
|
||||
isBoldTitle
|
||||
title={intl.formatMessage({
|
||||
id: 'notification.this_week',
|
||||
})}
|
||||
/>
|
||||
<FlatList
|
||||
data={thisWeek}
|
||||
renderItem={({ item }) => (
|
||||
<NotificationLine
|
||||
notification={item}
|
||||
handleOnPressNotification={navigateToNotificationRoute}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
{thisMonth.length > 0 && (
|
||||
<Fragment>
|
||||
<ContainerHeader
|
||||
hasSeperator
|
||||
isBoldTitle
|
||||
title={intl.formatMessage({
|
||||
id: 'notification.this_month',
|
||||
})}
|
||||
/>
|
||||
<FlatList
|
||||
data={thisMonth}
|
||||
renderItem={({ item }) => (
|
||||
<NotificationLine
|
||||
notification={item}
|
||||
handleOnPressNotification={navigateToNotificationRoute}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
{olderThenMonth.length > 0 && (
|
||||
<Fragment>
|
||||
<ContainerHeader
|
||||
hasSeperator
|
||||
isBoldTitle
|
||||
title={intl.formatMessage({
|
||||
id: 'notification.older_then',
|
||||
})}
|
||||
/>
|
||||
<FlatList
|
||||
data={olderThenMonth}
|
||||
renderItem={({ item }) => (
|
||||
<NotificationLine
|
||||
notification={item}
|
||||
handleOnPressNotification={navigateToNotificationRoute}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.id}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
{_notifications
|
||||
&& _notifications.map(
|
||||
item => item.notifications.length > 0 && (
|
||||
<Fragment key={item.title}>
|
||||
<ContainerHeader hasSeperator={ _notifications.indexOf(item) !== 1 } isBoldTitle title={item.title} key={item.title} />
|
||||
{this._renderList(item.notifications)}
|
||||
</Fragment>
|
||||
),
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
|
@ -3,13 +3,12 @@ import {
|
||||
View, Text, Image, TouchableHighlight,
|
||||
} from 'react-native';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
// Constants
|
||||
|
||||
// Components
|
||||
import { UserAvatar } from '../../userAvatar';
|
||||
|
||||
// Styles
|
||||
// eslint-disable-next-line
|
||||
import styles from './notificationLineStyles';
|
||||
|
||||
class NotificationLineView extends PureComponent {
|
||||
@ -20,31 +19,49 @@ class NotificationLineView extends PureComponent {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.state = {
|
||||
isRead: props.notification.read,
|
||||
};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
|
||||
// Component Functions
|
||||
_handleOnNotificationPress = () => {
|
||||
const { handleOnPressNotification, notification } = this.props;
|
||||
const { isRead } = this.state;
|
||||
|
||||
if (!isRead) this.setState({ isRead: true });
|
||||
|
||||
handleOnPressNotification(notification);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
notification,
|
||||
intl: { formatMessage },
|
||||
handleOnPressNotification,
|
||||
} = this.props;
|
||||
const { isRead } = this.state;
|
||||
|
||||
let _title = formatMessage({
|
||||
id: `notification.${notification.type}`,
|
||||
});
|
||||
|
||||
if (notification.weight) {
|
||||
const _percent = `${(notification.weight / 100).toFixed(0)}% `;
|
||||
|
||||
_title = _percent + _title;
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableHighlight onPress={() => handleOnPressNotification(notification)}>
|
||||
<TouchableHighlight onPress={() => this._handleOnNotificationPress()}>
|
||||
<View
|
||||
key={Math.random()}
|
||||
style={[styles.notificationWrapper, !notification.read && styles.isNewNotification]}
|
||||
style={[styles.notificationWrapper, !isRead && styles.isNewNotification]}
|
||||
>
|
||||
<FastImage
|
||||
<UserAvatar
|
||||
username={notification.source}
|
||||
style={[styles.avatar, !notification.avatar && styles.hasNoAvatar]}
|
||||
source={{
|
||||
uri: `https://steemitimages.com/u/${notification.source}/avatar/small`,
|
||||
}}
|
||||
/>
|
||||
<View style={styles.body}>
|
||||
<View style={styles.titleWrapper}>
|
||||
@ -52,11 +69,7 @@ class NotificationLineView extends PureComponent {
|
||||
{notification.source}
|
||||
{' '}
|
||||
</Text>
|
||||
<Text style={styles.title}>
|
||||
{formatMessage({
|
||||
id: `notification.${notification.type}`,
|
||||
})}
|
||||
</Text>
|
||||
<Text style={styles.title}>{_title}</Text>
|
||||
</View>
|
||||
{notification.description && (
|
||||
<Text numberOfLines={1} style={styles.description}>
|
||||
|
@ -39,6 +39,8 @@ class PercentBarView extends PureComponent {
|
||||
_getText = (textColor, text, isTop, isRender) => {
|
||||
const { isShowText } = this.props;
|
||||
|
||||
if (!isShowText) return null;
|
||||
|
||||
if (isTop === isRender && text) {
|
||||
return (
|
||||
<View style={styles.percentTitleWrapper}>
|
||||
|
@ -23,7 +23,13 @@ class PostCardContainer extends PureComponent {
|
||||
};
|
||||
}
|
||||
|
||||
_handleOnUserPress = (username) => {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.isRefresh) {
|
||||
this._fetchPost();
|
||||
}
|
||||
}
|
||||
|
||||
_handleOnUserPress = () => {
|
||||
const { navigation, currentAccount, content } = this.props;
|
||||
if (content && currentAccount.name !== content.author) {
|
||||
navigation.navigate({
|
||||
@ -32,7 +38,7 @@ class PostCardContainer extends PureComponent {
|
||||
username: content.author,
|
||||
reputation: content.author_reputation,
|
||||
},
|
||||
key: username,
|
||||
key: content.author,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -7,11 +7,10 @@ export default EStyleSheet.create({
|
||||
marginLeft: 0,
|
||||
marginTop: 5,
|
||||
marginBottom: 10,
|
||||
borderRadius: 5,
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
shadowOpacity: 0.2,
|
||||
shadowColor: '$shadowColor',
|
||||
elevation: 3,
|
||||
elevation: 0.1,
|
||||
},
|
||||
avatar: {
|
||||
width: 30,
|
||||
|
@ -55,6 +55,7 @@ class PostsContainer extends PureComponent {
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
currentAccount: state.account.currentAccount,
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
isLoggedIn: state.application.isLoggedIn,
|
||||
isLoginDone: state.application.isLoginDone,
|
||||
isCollapsePostButtonOpen: state.ui.isCollapsePostButton,
|
||||
|
@ -28,4 +28,8 @@ export default EStyleSheet.create({
|
||||
marginBottom: 40,
|
||||
borderColor: '$borderColor',
|
||||
},
|
||||
noImage: {
|
||||
width: 193,
|
||||
height: 189,
|
||||
},
|
||||
});
|
||||
|
@ -1,5 +1,7 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { FlatList, View, ActivityIndicator } from 'react-native';
|
||||
import {
|
||||
FlatList, View, ActivityIndicator, RefreshControl,
|
||||
} from 'react-native';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
@ -32,6 +34,15 @@ class PostsView extends Component {
|
||||
};
|
||||
}
|
||||
|
||||
// Component Functions
|
||||
componentWillMount() {
|
||||
const { navigation } = this.props;
|
||||
|
||||
navigation.setParams({
|
||||
scrollToTop: this._scrollToTop,
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._loadPosts();
|
||||
}
|
||||
@ -63,14 +74,22 @@ class PostsView extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
_loadPosts = (filter = null) => {
|
||||
_scrollToTop = () => {
|
||||
if (this.flatList) this.flatList.scrollToOffset({ x: 0, y: 0, animated: true });
|
||||
};
|
||||
|
||||
_loadPosts = () => {
|
||||
const { getFor, tag, currentAccountUsername } = this.props;
|
||||
const { posts, startAuthor, startPermlink } = this.state;
|
||||
const {
|
||||
posts, startAuthor, startPermlink, refreshing, selectedFilterIndex,
|
||||
} = this.state;
|
||||
const filter = selectedFilterIndex !== 0 ? filters[selectedFilterIndex] : getFor;
|
||||
let options;
|
||||
let newPosts = [];
|
||||
|
||||
this.setState({ isLoading: true });
|
||||
|
||||
if (!filter && tag) {
|
||||
if ((!filter && tag) || filter === 'feed' || getFor === 'blog') {
|
||||
options = {
|
||||
tag,
|
||||
limit: 3,
|
||||
@ -81,25 +100,40 @@ class PostsView extends Component {
|
||||
};
|
||||
}
|
||||
|
||||
if (startAuthor && startPermlink) {
|
||||
if (startAuthor && startPermlink && !refreshing) {
|
||||
options.start_author = startAuthor;
|
||||
options.start_permlink = startPermlink;
|
||||
}
|
||||
|
||||
getPostsSummary(filter || getFor, options, currentAccountUsername)
|
||||
getPostsSummary(filter, options, currentAccountUsername)
|
||||
.then((result) => {
|
||||
if (result.length > 0) {
|
||||
let _posts = result;
|
||||
|
||||
if (_posts.length > 0) {
|
||||
if (posts.length > 0) {
|
||||
_posts.shift();
|
||||
_posts = [...posts, ..._posts];
|
||||
if (refreshing) {
|
||||
newPosts = _posts.filter(post => posts.includes(post));
|
||||
_posts = [...newPosts, ...posts];
|
||||
} else {
|
||||
_posts.shift();
|
||||
_posts = [...posts, ..._posts];
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshing && newPosts.length > 0) {
|
||||
this.setState({
|
||||
posts: _posts,
|
||||
});
|
||||
} else if (!refreshing) {
|
||||
this.setState({
|
||||
posts: _posts,
|
||||
startAuthor: result[result.length - 1] && result[result.length - 1].author,
|
||||
startPermlink: result[result.length - 1] && result[result.length - 1].permlink,
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
posts: _posts,
|
||||
startAuthor: result[result.length - 1] && result[result.length - 1].author,
|
||||
startPermlink: result[result.length - 1] && result[result.length - 1].permlink,
|
||||
refreshing: false,
|
||||
isPostsLoading: false,
|
||||
});
|
||||
@ -140,12 +174,16 @@ class PostsView extends Component {
|
||||
return null;
|
||||
};
|
||||
|
||||
_handleOnDropdownSelect = (index) => {
|
||||
this.setState({
|
||||
_handleOnDropdownSelect = async (index) => {
|
||||
await this.setState({
|
||||
isPostsLoading: true,
|
||||
selectedFilterIndex: index,
|
||||
posts: [],
|
||||
startAuthor: '',
|
||||
startPermlink: '',
|
||||
isNoPost: false,
|
||||
});
|
||||
this._loadPosts(filters[index]);
|
||||
this._loadPosts();
|
||||
};
|
||||
|
||||
_onRightIconPress = () => {
|
||||
@ -155,8 +193,10 @@ class PostsView extends Component {
|
||||
};
|
||||
|
||||
_handleOnScrollStart = () => {
|
||||
const { handleOnScrollStart } = this.props;
|
||||
const { handleOnScrollStart, handleOnScroll } = this.props;
|
||||
handleOnScrollStart();
|
||||
|
||||
if (handleOnScroll) handleOnScroll();
|
||||
};
|
||||
|
||||
_handleOnPressLogin = () => {
|
||||
@ -174,7 +214,13 @@ class PostsView extends Component {
|
||||
isNoPost,
|
||||
} = this.state;
|
||||
const {
|
||||
filterOptions, intl, isLoggedIn, getFor, isLoginDone, tag,
|
||||
filterOptions,
|
||||
intl,
|
||||
isLoggedIn,
|
||||
getFor,
|
||||
isLoginDone,
|
||||
tag,
|
||||
isDarkTheme,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -197,6 +243,7 @@ class PostsView extends Component {
|
||||
&& !isLoggedIn
|
||||
&& isLoginDone && (
|
||||
<NoPost
|
||||
imageStyle={styles.noImage}
|
||||
isButtonText
|
||||
defaultText={intl.formatMessage({
|
||||
id: 'profile.login_to_see',
|
||||
@ -206,11 +253,13 @@ class PostsView extends Component {
|
||||
)}
|
||||
</Fragment>
|
||||
|
||||
{posts && posts.length > 0 && !isPostsLoading ? (
|
||||
{posts && posts.length > 0 && !isPostsLoading && (
|
||||
<FlatList
|
||||
data={posts}
|
||||
showsVerticalScrollIndicator={false}
|
||||
renderItem={({ item }) => <PostCard content={item} isHideImage={isHideImage} />}
|
||||
renderItem={({ item }) => (
|
||||
<PostCard isRefresh={refreshing} content={item} isHideImage={isHideImage} />
|
||||
)}
|
||||
keyExtractor={(post, index) => index.toString()}
|
||||
onEndReached={() => this._loadPosts()}
|
||||
removeClippedSubviews
|
||||
@ -220,9 +269,25 @@ class PostsView extends Component {
|
||||
initialNumToRender={10}
|
||||
ListFooterComponent={this._renderFooter}
|
||||
onScrollBeginDrag={() => this._handleOnScrollStart()}
|
||||
refreshControl={(
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={this._handleOnRefreshPosts}
|
||||
progressBackgroundColor="#357CE6"
|
||||
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
|
||||
titleColor="#fff"
|
||||
colors={['#fff']}
|
||||
/>
|
||||
)}
|
||||
ref={(ref) => {
|
||||
this.flatList = ref;
|
||||
}}
|
||||
/>
|
||||
) : isNoPost ? (
|
||||
)}
|
||||
|
||||
{isNoPost ? (
|
||||
<NoPost
|
||||
imageStyle={styles.noImage}
|
||||
name={tag}
|
||||
text={intl.formatMessage({
|
||||
id: 'profile.havent_posted',
|
||||
|
@ -32,7 +32,7 @@ class ProfileSummaryView extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isShowPercentText: false,
|
||||
isShowPercentText: props.isShowPercentText,
|
||||
};
|
||||
}
|
||||
|
||||
@ -66,6 +66,7 @@ class ProfileSummaryView extends PureComponent {
|
||||
location,
|
||||
percentRC,
|
||||
percentVP,
|
||||
handleUIChange,
|
||||
} = this.props;
|
||||
const votingPowerHoursText = hoursVP && `• Full in ${hoursVP} hours`;
|
||||
const votingPowerText = `Voting power: ${percentVP}% ${votingPowerHoursText || ''}`;
|
||||
@ -84,6 +85,7 @@ class ProfileSummaryView extends PureComponent {
|
||||
const isColumn = rowLength && DEVICE_WIDTH / rowLength <= 15;
|
||||
const followButtonIcon = !isFollowing ? 'user-follow' : 'user-unfollow';
|
||||
const ignoreButtonIcon = !isMuted ? 'ban' : 'minus';
|
||||
const coverImageUrl = `http://img.esteem.app/400x0/${coverImage}`;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@ -99,13 +101,18 @@ class ProfileSummaryView extends PureComponent {
|
||||
)}
|
||||
{!!date && <TextWithIcon text={date} iconName="md-calendar" />}
|
||||
</View>
|
||||
<View />
|
||||
<Image
|
||||
style={styles.longImage}
|
||||
source={{ uri: coverImage }}
|
||||
source={{ uri: coverImageUrl }}
|
||||
defaultSource={isDarkTheme ? DARK_COVER_IMAGE : LIGHT_COVER_IMAGE}
|
||||
/>
|
||||
<TouchableOpacity onPress={() => this.setState({ isShowPercentText: !isShowPercentText })}>
|
||||
<TouchableOpacity
|
||||
onPress={() =>
|
||||
this.setState({ isShowPercentText: !isShowPercentText }, () => {
|
||||
handleUIChange(isShowPercentText ? 0 : 30);
|
||||
})
|
||||
}
|
||||
>
|
||||
<PercentBar
|
||||
isShowText={isShowPercentText}
|
||||
percent={percentVP}
|
||||
|
@ -10,11 +10,6 @@ export default EStyleSheet.create({
|
||||
height: 50,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-around',
|
||||
borderWidth: 1,
|
||||
borderTopWidth: 0,
|
||||
borderLeftWidth: 0,
|
||||
borderRightWidth: 0,
|
||||
borderColor: '$white',
|
||||
},
|
||||
tabButton: {
|
||||
flex: 1,
|
||||
|
@ -10,7 +10,7 @@
|
||||
"fill_order": "Fill Order"
|
||||
},
|
||||
"notification": {
|
||||
"vote": "voted to your post",
|
||||
"vote": "likes your post",
|
||||
"unvote": "unvoted your post",
|
||||
"reply": "replied to your post",
|
||||
"mention": "mentioned you",
|
||||
|
@ -10,8 +10,8 @@
|
||||
"fill_order": "Fill Order"
|
||||
},
|
||||
"notification": {
|
||||
"vote": "gönderini oyladı",
|
||||
"unvote": "gonderini yukarı yönde oyladı",
|
||||
"vote": "beğendi",
|
||||
"unvote": "gonderini aşaği yönde oyladı",
|
||||
"reply": "gönderine cevap verdi",
|
||||
"mention": "seni etiketledi",
|
||||
"follow": "seni takip etti",
|
||||
|
@ -37,7 +37,7 @@ export default EStyleSheet.create({
|
||||
padding: 5,
|
||||
height: 50,
|
||||
flex: 1,
|
||||
color: '#ff1954',
|
||||
color: '$primaryRed',
|
||||
paddingTop: 10,
|
||||
textAlign: 'center',
|
||||
},
|
||||
|
@ -21,7 +21,7 @@ const BaseNavigator = createBottomTabNavigator(
|
||||
<Icon
|
||||
iconType="MaterialIcons"
|
||||
style={{ padding: 15 }}
|
||||
name="menu"
|
||||
name="view-day"
|
||||
color={tintColor}
|
||||
size={26}
|
||||
/>
|
||||
|
@ -248,7 +248,9 @@ export const getPosts = async (by, query, user) => {
|
||||
try {
|
||||
let posts = await client.database.getDiscussions(by, query);
|
||||
|
||||
posts = await parsePosts(posts, user);
|
||||
if (posts) {
|
||||
posts = await parsePosts(posts, user);
|
||||
}
|
||||
return posts;
|
||||
} catch (error) {
|
||||
return error;
|
||||
@ -260,8 +262,9 @@ export const getActiveVotes = (author, permlink) => client.database.call('get_ac
|
||||
export const getPostsSummary = async (by, query, currentUserName) => {
|
||||
try {
|
||||
let posts = await client.database.getDiscussions(by, query);
|
||||
|
||||
if (posts) {
|
||||
posts = await parsePosts(posts, currentUserName);
|
||||
posts = await parsePosts(posts, currentUserName, true);
|
||||
}
|
||||
return posts;
|
||||
} catch (error) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { UPDATE_ACTIVE_BOTTOM_TAB, IS_COLLAPSE_POST_BUTTON } from '../constants/constants';
|
||||
|
||||
const initialState = {
|
||||
activeBottomTab: 'Home',
|
||||
activeBottomTab: 'HomeTabbar',
|
||||
isCollapsePostButton: false,
|
||||
};
|
||||
|
||||
|
@ -13,17 +13,17 @@ import { getFollowers, getFollowing, getFollowSearch } from '../../../providers/
|
||||
import FollowsScreen from '../screen/followsScreen';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
|
||||
class FollowsContainer extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
username: null,
|
||||
users: [],
|
||||
users: null,
|
||||
count: null,
|
||||
isFollowingPress: null,
|
||||
startWith: '',
|
||||
@ -44,7 +44,7 @@ class FollowsContainer extends Component {
|
||||
isFollowingPress,
|
||||
});
|
||||
|
||||
await this._loadFollows(username, isFollowingPress);
|
||||
this._loadFollows(username, isFollowingPress);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ class FollowsContainer extends Component {
|
||||
username, users, isFollowingPress, startWith, count,
|
||||
} = this.state;
|
||||
|
||||
if (users && count === users.length + 1) return;
|
||||
if ((users && count < 100) || (users && count === users.length + 1)) return;
|
||||
|
||||
const name = username || _username;
|
||||
const isFollowing = isFollowingPress || _isFollowingPress;
|
||||
@ -66,16 +66,16 @@ class FollowsContainer extends Component {
|
||||
if (!isFollowing) {
|
||||
await getFollowers(name, startWith).then((result) => {
|
||||
_users = result;
|
||||
_startWith = users && users[users.length - 1] && users[users.length - 1].follower;
|
||||
_startWith = result && result[result.length - 1] && result[result.length - 1].follower;
|
||||
});
|
||||
} else {
|
||||
await getFollowing(name, startWith).then((result) => {
|
||||
_users = result;
|
||||
_startWith = users && users[users.length - 1] && users[users.length - 1].following;
|
||||
_startWith = result && result[result.length - 1] && result[result.length - 1].following;
|
||||
});
|
||||
}
|
||||
|
||||
!_username && _users.shift();
|
||||
if (!_username) _users.shift();
|
||||
|
||||
this.setState({
|
||||
users: !_username ? [...users, ..._users] : _users,
|
||||
@ -99,7 +99,10 @@ class FollowsContainer extends Component {
|
||||
newData = await getFollowSearch(username, text);
|
||||
}
|
||||
|
||||
this.setState({ filterResult: newData });
|
||||
this.setState({
|
||||
filterResult: newData,
|
||||
isLoading: false,
|
||||
});
|
||||
};
|
||||
|
||||
_handleOnUserPress = (username) => {
|
||||
@ -133,7 +136,6 @@ class FollowsContainer extends Component {
|
||||
isLoading={isLoading}
|
||||
handleSearch={this._handleSearch}
|
||||
handleOnUserPress={this._handleOnUserPress}
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -21,9 +21,7 @@ class FollowsScreen extends PureComponent {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
data: props.data,
|
||||
};
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycles
|
||||
@ -78,8 +76,8 @@ class FollowsScreen extends PureComponent {
|
||||
{(filterResult && data && filterResult.length > 0) || data.length > 0 ? (
|
||||
<FlatList
|
||||
data={filterResult || data}
|
||||
keyExtractor={item => item.voter}
|
||||
onEndReached={loadMore}
|
||||
keyExtractor={(item, index) => index.toString()}
|
||||
onEndReached={() => loadMore()}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={({ item, index }) => this._renderItem(item, index)}
|
||||
ListFooterComponent={this._renderFooter}
|
||||
|
@ -16,10 +16,6 @@ class HomeContainer extends PureComponent {
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
// Component Life Cycle Functions
|
||||
|
||||
// Component Functions
|
||||
|
||||
render() {
|
||||
const { isLoggedIn, isLoginDone, currentAccount } = this.props;
|
||||
|
||||
@ -36,7 +32,6 @@ class HomeContainer extends PureComponent {
|
||||
const mapStateToProps = state => ({
|
||||
isLoggedIn: state.application.isLoggedIn,
|
||||
isLoginDone: state.application.isLoginDone,
|
||||
|
||||
currentAccount: state.account.currentAccount,
|
||||
});
|
||||
|
||||
|
@ -23,6 +23,8 @@ export default EStyleSheet.create({
|
||||
shadowColor: '$shadowColor',
|
||||
shadowOffset: { height: 4 },
|
||||
zIndex: 99,
|
||||
borderBottomColor: '$shadowColor',
|
||||
borderBottomWidth: 0.1,
|
||||
},
|
||||
tabbarItem: {
|
||||
flex: 1,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
// Utilitites
|
||||
import {
|
||||
@ -37,7 +37,7 @@ class ProfileContainer extends Component {
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
const { navigation, isLoggedIn, currentAccount } = this.props;
|
||||
const { navigation, isLoggedIn } = this.props;
|
||||
const selectedUser = navigation.state && navigation.state.params;
|
||||
|
||||
if (!isLoggedIn && !selectedUser) {
|
||||
@ -58,25 +58,35 @@ class ProfileContainer extends Component {
|
||||
}
|
||||
|
||||
this.setState({ isReverseHeader: true });
|
||||
} else {
|
||||
this._loadProfile(currentAccount.name);
|
||||
}
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { navigation, currentAccount } = this.props;
|
||||
const {
|
||||
navigation, currentAccount, activeBottomTab, isLoggedIn,
|
||||
} = this.props;
|
||||
const currentUsername = currentAccount.name
|
||||
!== nextProps.currentAccount.name
|
||||
&& nextProps.currentAccount.name;
|
||||
const isParamsChange = nextProps.navigation.state
|
||||
&& navigation.state
|
||||
&& nextProps.navigation.state.params
|
||||
&& nextProps.navigation.state.params.username
|
||||
&& nextProps.navigation.state.params.username !== navigation.state.params.username;
|
||||
|
||||
if (isLoggedIn && !nextProps.isLoggedIn) {
|
||||
navigation.navigate(ROUTES.SCREENS.LOGIN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentUsername) {
|
||||
this._loadProfile(currentUsername);
|
||||
}
|
||||
|
||||
if (activeBottomTab !== nextProps.activeBottomTab && nextProps.activeBottomTab === 'ProfileTabbar') {
|
||||
this._loadProfile(currentAccount.name);
|
||||
}
|
||||
|
||||
if (isParamsChange) {
|
||||
const selectedUser = nextProps.navigation.state && nextProps.navigation.state.params;
|
||||
|
||||
@ -299,6 +309,7 @@ const mapStateToProps = state => ({
|
||||
currentAccount: state.account.currentAccount,
|
||||
pinCode: state.account.pin,
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
activeBottomTab: state.ui.activeBottomTab,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ProfileContainer);
|
||||
export default connect(mapStateToProps)(withNavigation(ProfileContainer));
|
||||
|
@ -23,9 +23,26 @@ import styles from './profileStyles';
|
||||
class ProfileScreen extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.state = {
|
||||
isSummaryOpen: true,
|
||||
collapsibleMoreHeight: 0,
|
||||
};
|
||||
}
|
||||
|
||||
_handleOnScroll = () => {
|
||||
const { isSummaryOpen } = this.state;
|
||||
|
||||
if (isSummaryOpen) this.setState({ isSummaryOpen: false });
|
||||
};
|
||||
|
||||
_handleOnSummaryExpanded = () => {
|
||||
this.setState({ isSummaryOpen: true });
|
||||
};
|
||||
|
||||
_handleUIChange = (height) => {
|
||||
this.setState({ collapsibleMoreHeight: height });
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
about,
|
||||
@ -42,10 +59,11 @@ class ProfileScreen extends PureComponent {
|
||||
isProfileLoading,
|
||||
isReady,
|
||||
isReverseHeader,
|
||||
selectedQuickProfile,
|
||||
user,
|
||||
username,
|
||||
selectedQuickProfile,
|
||||
} = this.props;
|
||||
const { isSummaryOpen, collapsibleMoreHeight } = this.state;
|
||||
let _about;
|
||||
let coverImage;
|
||||
let location;
|
||||
@ -86,6 +104,9 @@ class ProfileScreen extends PureComponent {
|
||||
id: 'profile.details',
|
||||
})}
|
||||
expanded
|
||||
isExpanded={isSummaryOpen}
|
||||
handleOnExpanded={this._handleOnSummaryExpanded}
|
||||
moreHeight={collapsibleMoreHeight}
|
||||
// expanded={isLoggedIn}
|
||||
// locked={!isLoggedIn}
|
||||
>
|
||||
@ -110,6 +131,7 @@ class ProfileScreen extends PureComponent {
|
||||
location={location}
|
||||
percentRC={resourceCredits}
|
||||
percentVP={votingPower}
|
||||
handleUIChange={this._handleUIChange}
|
||||
/>
|
||||
</CollapsibleCard>
|
||||
)}
|
||||
@ -131,6 +153,7 @@ class ProfileScreen extends PureComponent {
|
||||
getFor="blog"
|
||||
tag={username}
|
||||
key={username}
|
||||
handleOnScroll={this._handleOnScroll}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
|
@ -24,6 +24,7 @@ export default {
|
||||
$bubblesBlue: '#5CCDFF',
|
||||
$borderTopColor: '#757575',
|
||||
$iconColor: '#788187',
|
||||
$darkIconColor: '#526d91',
|
||||
$dangerColor: '#fff',
|
||||
$warningColor: '#fff',
|
||||
$successColor: '#fff',
|
||||
|
@ -22,6 +22,7 @@ export default {
|
||||
$tagColor: '#c1c5c7',
|
||||
$bubblesBlue: '#5CCDFF',
|
||||
$iconColor: '#c1c5c7',
|
||||
$darkIconColor: '#c1c5c7',
|
||||
$borderTopColor: '#cfcfcf',
|
||||
$dangerColor: '#fff',
|
||||
$warningColor: '#fff',
|
||||
|
@ -18,6 +18,7 @@ const pullRightLeftRegex = /(<div class="[^"]*?pull-[^"]*?">(.*?)(<[/]div>))/g;
|
||||
const linkRegex = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
|
||||
const markdownImageRegex = /!\[[^\]]*\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g;
|
||||
const urlRegex = /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?/gm;
|
||||
const aTagRegex = /(<\s*a[^>]*>(.*?)<\s*[/]\s*a>)/g;
|
||||
|
||||
export const markDown2Html = (input) => {
|
||||
if (!input) {
|
||||
@ -37,8 +38,12 @@ export const markDown2Html = (input) => {
|
||||
output = createYoutubeIframe(output);
|
||||
}
|
||||
|
||||
if (dTubeRegex.test(output)) {
|
||||
output = createDtubeIframe(output);
|
||||
// if (dTubeRegex.test(output)) {
|
||||
// output = createDtubeIframe(output);
|
||||
// }
|
||||
|
||||
if (aTagRegex.test(output)) {
|
||||
output = handleATag(output);
|
||||
}
|
||||
|
||||
if (pullRightLeftRegex.test(output)) {
|
||||
@ -46,7 +51,7 @@ export const markDown2Html = (input) => {
|
||||
}
|
||||
|
||||
// if (imgRegex.test(output)) {
|
||||
// output = createImage(output);
|
||||
// output = handleImage(output);
|
||||
// }
|
||||
|
||||
if (vimeoRegex.test(output)) {
|
||||
@ -86,13 +91,13 @@ export const markDown2Html = (input) => {
|
||||
return output;
|
||||
};
|
||||
|
||||
export const replaceAuthorNames = input => input.replace(authorNameRegex, (match, preceeding1, preceeding2, user) => {
|
||||
const replaceAuthorNames = input => input.replace(authorNameRegex, (match, preceeding1, preceeding2, user) => {
|
||||
const userLower = user.toLowerCase();
|
||||
const preceedings = (preceeding1 || '') + (preceeding2 || '');
|
||||
return `${preceedings}<a class="markdown-author-link" href="${userLower}" data-author="${userLower}">@${user}</a>`;
|
||||
});
|
||||
|
||||
export const replaceTags = input => input.replace(tagsRegex, (tag) => {
|
||||
const replaceTags = input => input.replace(tagsRegex, (tag) => {
|
||||
if (/#[\d]+$/.test(tag)) return tag;
|
||||
const preceding = /^\s|>/.test(tag) ? tag[0] : '';
|
||||
tag = tag.replace('>', '');
|
||||
@ -101,7 +106,24 @@ export const replaceTags = input => input.replace(tagsRegex, (tag) => {
|
||||
return `${preceding}<a class="markdown-tag-link" href="${tagLower}" data-tag="${tagLower}">${tag.trim()}</a>`;
|
||||
});
|
||||
|
||||
export const removeOnlyPTag = input => input;
|
||||
const handleATag = input => input.replace(aTagRegex, (link) => {
|
||||
if (dTubeRegex.test(link)) {
|
||||
const dTubeMatch = link.match(dTubeRegex)[0];
|
||||
const execLink = dTubeRegex.exec(dTubeMatch);
|
||||
|
||||
if (execLink[2] && execLink[3]) {
|
||||
const embedLink = `https://emb.d.tube/#!/${execLink[2]}/${execLink[3]}`;
|
||||
|
||||
return iframeBody(embedLink);
|
||||
}
|
||||
if (dTubeMatch) {
|
||||
return iframeBody(dTubeMatch);
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
return link;
|
||||
});
|
||||
|
||||
const changeMarkdownImage = input => input.replace(markdownImageRegex, (link) => {
|
||||
const markdownMatch = link.match(markdownImageRegex);
|
||||
@ -121,7 +143,7 @@ const createCenterImage = input => input.replace(imgCenterRegex, (link) => {
|
||||
|
||||
_link = _link.split('>')[1];
|
||||
_link = _link.split('<')[0];
|
||||
return `><img data-href="${_link}" src="${_link}"><`;
|
||||
return `><img data-href="${`https://img.esteem.app/500x0/${_link}`}" src="${`https://img.esteem.app/500x0/${_link}`}"><`;
|
||||
});
|
||||
|
||||
const changePullRightLeft = input => input.replace(pullRightLeftRegex, (item) => {
|
||||
@ -144,6 +166,11 @@ const createImage = input => input.replace(
|
||||
link => `<img data-href="${`https://img.esteem.app/300x0/${link}`}" src="${`https://img.esteem.app/500x0/${link}`}">`,
|
||||
);
|
||||
|
||||
const handleImage = input => input.replace(
|
||||
imgRegex,
|
||||
link => `<img data-href="${`https://img.esteem.app/300x0/${link}`}" src="${`https://img.esteem.app/500x0/${link}`}">`,
|
||||
);
|
||||
|
||||
const createFromDoubleImageLink = input => input.replace(onlyImageDoubleLinkRegex, (link) => {
|
||||
const _link = link.trim();
|
||||
return `<img data-href="https://img.esteem.app/300x0/${_link}" src="https://img.esteem.app/500x0/${_link}">`;
|
||||
|
@ -4,50 +4,54 @@ import { getPostSummary } from './formatter';
|
||||
import { getReputation } from './reputation';
|
||||
import { getTimeFromNow } from './time';
|
||||
|
||||
export const parsePosts = (posts, currentUserName) => (!posts ? null : posts.map(post => parsePost(post, currentUserName)));
|
||||
export const parsePosts = (posts, currentUserName, isSummary) => (!posts ? null : posts.map(post => parsePost(post, currentUserName, isSummary)));
|
||||
|
||||
export const parsePost = (post, currentUserName) => {
|
||||
export const parsePost = (post, currentUserName, isSummary = false) => {
|
||||
if (!post) {
|
||||
return null;
|
||||
}
|
||||
const _post = post;
|
||||
|
||||
post.json_metadata = JSON.parse(post.json_metadata);
|
||||
post.image = postImage(post.json_metadata, post.body);
|
||||
post.pending_payout_value = parseFloat(post.pending_payout_value).toFixed(2);
|
||||
post.created = getTimeFromNow(post.created);
|
||||
post.vote_count = post.active_votes.length;
|
||||
post.author_reputation = getReputation(post.author_reputation);
|
||||
post.avatar = `https://steemitimages.com/u/${post.author}/avatar/small`;
|
||||
post.body = markDown2Html(post.body);
|
||||
post.summary = getPostSummary(post.body, 150);
|
||||
post.raw_body = post.body;
|
||||
post.active_votes.sort((a, b) => b.rshares - a.rshares);
|
||||
const totalPayout = parseFloat(post.pending_payout_value)
|
||||
+ parseFloat(post.total_payout_value)
|
||||
+ parseFloat(post.curator_payout_value);
|
||||
_post.json_metadata = JSON.parse(post.json_metadata);
|
||||
_post.image = postImage(post.json_metadata, post.body);
|
||||
_post.pending_payout_value = parseFloat(post.pending_payout_value).toFixed(2);
|
||||
_post.created = getTimeFromNow(post.created);
|
||||
_post.vote_count = post.active_votes.length;
|
||||
_post.author_reputation = getReputation(post.author_reputation);
|
||||
_post.avatar = `https://steemitimages.com/u/${post.author}/avatar/small`;
|
||||
_post.active_votes.sort((a, b) => b.rshares - a.rshares);
|
||||
|
||||
const voteRshares = post.active_votes.reduce((a, b) => a + parseFloat(b.rshares), 0);
|
||||
const ratio = totalPayout / voteRshares;
|
||||
_post.body = markDown2Html(post.body);
|
||||
_post.summary = getPostSummary(post.body, 150);
|
||||
|
||||
if (currentUserName) {
|
||||
post.is_voted = isVoted(post.active_votes, currentUserName);
|
||||
_post.is_voted = isVoted(_post.active_votes, currentUserName);
|
||||
} else {
|
||||
post.is_voted = false;
|
||||
_post.is_voted = false;
|
||||
}
|
||||
|
||||
for (const i in post.active_votes) {
|
||||
post.vote_perecent = post.active_votes[i].voter === currentUserName ? post.active_votes[i].percent : null;
|
||||
post.active_votes[i].value = (post.active_votes[i].rshares * ratio).toFixed(2);
|
||||
post.active_votes[i].reputation = getReputation(post.active_votes[i].reputation);
|
||||
post.active_votes[i].percent = post.active_votes[i].percent / 100;
|
||||
post.active_votes[i].created = getTimeFromNow(post.active_votes[i].time);
|
||||
post.active_votes[i].is_down_vote = Math.sign(post.active_votes[i].percent) < 0;
|
||||
post.active_votes[i].avatar = `https://steemitimages.com/u/${
|
||||
post.active_votes[i].voter
|
||||
}/avatar/small`;
|
||||
const totalPayout = parseFloat(_post.pending_payout_value)
|
||||
+ parseFloat(_post.total_payout_value)
|
||||
+ parseFloat(_post.curator_payout_value);
|
||||
|
||||
const voteRshares = _post.active_votes.reduce((a, b) => a + parseFloat(b.rshares), 0);
|
||||
const ratio = totalPayout / voteRshares;
|
||||
|
||||
if (_post.active_votes && _post.active_votes.length > 0) {
|
||||
for (const i in _post.active_votes) {
|
||||
_post.vote_perecent = post.active_votes[i].voter === currentUserName ? post.active_votes[i].percent : null;
|
||||
_post.active_votes[i].value = (post.active_votes[i].rshares * ratio).toFixed(2);
|
||||
_post.active_votes[i].reputation = getReputation(post.active_votes[i].reputation);
|
||||
_post.active_votes[i].percent = post.active_votes[i].percent / 100;
|
||||
_post.active_votes[i].created = getTimeFromNow(post.active_votes[i].time);
|
||||
_post.active_votes[i].is_down_vote = Math.sign(post.active_votes[i].percent) < 0;
|
||||
_post.active_votes[i].avatar = `https://steemitimages.com/u/${
|
||||
_post.active_votes[i].voter
|
||||
}/avatar/small`;
|
||||
}
|
||||
}
|
||||
|
||||
return post;
|
||||
return _post;
|
||||
};
|
||||
|
||||
const isVoted = (activeVotes, currentUserName) => activeVotes.some(v => v.voter === currentUserName && v.percent > 0);
|
||||
|
Loading…
Reference in New Issue
Block a user