Merge branch 'master' into bugfix/push-icon

This commit is contained in:
Feruz M 2019-01-16 10:53:34 +02:00 committed by GitHub
commit 3b8ddac072
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 446 additions and 200 deletions

View File

@ -15,7 +15,8 @@
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait"
android:configChanges="keyboard|keyboardHidden|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react';
import {
View, Text, Image, StyleSheet,
View, Image, StyleSheet,
} from 'react-native';
const styles = StyleSheet.create({
@ -35,25 +35,25 @@ export default class PulseAnimation extends Component {
},
};
mounted = true;
constructor(props) {
super(props);
this.state = {
color: this.props.color,
duration: this.props.duration,
image: this.props.image,
maxDiameter: this.props.diameter,
numPulses: this.props.numPulses,
color: props.color,
duration: props.duration,
image: props.image,
maxDiameter: props.diameter,
numPulses: props.numPulses,
pulses: [],
pulseStyle: this.props.pulseStyle,
speed: this.props.speed,
pulseStyle: props.pulseStyle,
speed: props.speed,
started: false,
style: this.props.style,
style: props.style,
};
}
mounted = true;
componentDidMount() {
const { numPulses, duration, speed } = this.state;
@ -79,15 +79,16 @@ export default class PulseAnimation extends Component {
clearInterval(this.timer);
}
createPulse = (pKey) => {
createPulse = () => {
if (this.mounted) {
const pulses = this.state.pulses;
const { pulses, maxDiameter } = this.state;
const { initialDiameter } = this.props;
const pulse = {
pulseKey: pulses.length + 1,
diameter: this.props.initialDiameter,
diameter: initialDiameter,
opacity: 0.5,
centerOffset: (this.state.maxDiameter - this.props.initialDiameter) / 2,
centerOffset: (maxDiameter - initialDiameter) / 2,
};
pulses.push(pulse);
@ -99,10 +100,10 @@ export default class PulseAnimation extends Component {
updatePulse = () => {
if (this.mounted) {
const pulses = this.state.pulses.map((p, i) => {
const maxDiameter = this.state.maxDiameter;
const { maxDiameter } = this.state;
const newDiameter = p.diameter > maxDiameter ? 0 : p.diameter + 2;
const centerOffset = (maxDiameter - newDiameter) / 2;
const opacity = Math.abs(newDiameter / this.state.maxDiameter - 1);
const opacity = Math.abs(newDiameter / maxDiameter - 1);
const pulse = {
pulseKey: i + 1,

View File

@ -22,7 +22,6 @@ const FilterBarView = ({
iconSize,
isHide,
onDropdownSelect,
pageType,
onRightIconPress,
options,
rightIconName,

View File

@ -9,14 +9,17 @@ export default EStyleSheet.create({
},
textWrapper: {
flex: 1,
flexDirection: 'column',
fontSize: 12,
marginVertical: 16,
paddingVertical: 16,
paddingHorizontal: 16,
color: '$primaryBlack',
fontFamily: '$editorFont',
textAlignVertical: 'top',
},
previewContainer: {
flex: 1,
marginHorizontal: 16,
},
inlinePadding: {
padding: 8,
},

View File

@ -1,20 +1,22 @@
import React, { Component } from 'react';
import {
View, KeyboardAvoidingView, ScrollView, FlatList, Text, Platform,
View, KeyboardAvoidingView, FlatList, Text, Platform,
} from 'react-native';
import Markdown, { getUniqueID } from 'react-native-markdown-renderer';
import ActionSheet from 'react-native-actionsheet';
// Components
import { IconButton } from '../../iconButton';
import { StickyBar } from '../../basicUIElements';
import { TextInput } from '../../textInput';
// Utils
import { markDown2Html } from '../../../utils/markdownToHtml';
import applyImageLink from './formats/applyWebLinkFormat';
import Formats from './formats/formats';
// Components
import { IconButton } from '../../iconButton';
import { PostBody } from '../../postElements';
import { StickyBar } from '../../basicUIElements';
import { TextInput } from '../../textInput';
// Styles
import styles from './markdownEditorStyles';
import markdownStyle from './markdownPreviewStyles';
export default class MarkdownEditorView extends Component {
constructor(props) {
@ -39,7 +41,11 @@ export default class MarkdownEditorView extends Component {
});
}
if (nextProps.uploadedImage && nextProps.uploadedImage.url && nextProps.uploadedImage !== uploadedImage) {
if (
nextProps.uploadedImage
&& nextProps.uploadedImage.url
&& nextProps.uploadedImage !== uploadedImage
) {
applyImageLink({
getState: this._getState,
setState: (state, callback) => {
@ -90,26 +96,10 @@ export default class MarkdownEditorView extends Component {
_renderPreview = () => {
const { text } = this.state;
const rules = {
heading1: (node, children, parent, styles) => (
<Text key={getUniqueID()} style={styles.heading1}>
{children}
</Text>
),
heading2: (node, children, parent, styles) => (
<Text key={getUniqueID()} style={styles.heading2}>
{children}
</Text>
),
};
return (
<View style={styles.textWrapper}>
<ScrollView removeClippedSubviews>
<Markdown rules={rules} style={markdownStyle}>
{text === '' ? '...' : text}
</Markdown>
</ScrollView>
<View style={styles.previewContainer}>
{text ? <PostBody body={markDown2Html(text)} /> : <Text>...</Text>}
</View>
);
};
@ -133,9 +123,7 @@ export default class MarkdownEditorView extends Component {
<FlatList
data={Formats}
keyboardShouldPersistTaps="always"
renderItem={
({ item, index }) => index !== 9
&& this._renderMarkupButton({ item, getState, setState })
renderItem={({ item, index }) => index !== 9 && this._renderMarkupButton({ item, getState, setState })
}
horizontal
/>
@ -176,7 +164,11 @@ export default class MarkdownEditorView extends Component {
const { text, selection } = this.state;
return (
<KeyboardAvoidingView style={styles.container} keyboardVerticalOffset={Platform.select({ ios: 0, android: 25 })} behavior="padding">
<KeyboardAvoidingView
style={styles.container}
keyboardVerticalOffset={Platform.select({ ios: 0, android: 25 })}
behavior="padding"
>
{!isPreviewActive ? (
<TextInput
multiline

View File

@ -5,4 +5,17 @@ export default EStyleSheet.create({
backgroundColor: '$primaryBackgroundColor',
flex: 1,
},
flatlistFooter: {
alignContent: 'center',
alignItems: 'center',
marginTop: 10,
marginBottom: 40,
borderColor: '$borderColor',
},
loading: {
alignContent: 'center',
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
});

View File

@ -1,5 +1,7 @@
import React, { PureComponent, Fragment } from 'react';
import { View, ScrollView, FlatList } from 'react-native';
import {
View, ScrollView, FlatList, ActivityIndicator, RefreshControl,
} from 'react-native';
import { injectIntl } from 'react-intl';
// Constants
@ -34,6 +36,7 @@ class NotificationView extends PureComponent {
{ key: 'follows', value: 'FOLLOWS' },
{ key: 'reblogs', value: 'REBLOGS' },
],
selectedFilter: null,
};
}
@ -45,7 +48,8 @@ class NotificationView extends PureComponent {
const { getActivities } = this.props;
const { filters } = this.state;
getActivities(filters[index].key);
this.setState({ selectedFilter: filters[index].key });
getActivities(filters[index].key, false);
};
_renderList = (data) => {
@ -60,11 +64,25 @@ class NotificationView extends PureComponent {
handleOnPressNotification={navigateToNotificationRoute}
/>
)}
initialNumToRender={data.length}
maxToRenderPerBatch={data.length}
keyExtractor={item => item.id}
/>
);
};
_renderFooterLoading = () => {
const { loading, notifications } = this.props;
if (loading && notifications.length > 0) {
return (
<View style={styles.flatlistFooter}>
<ActivityIndicator animating size="large" />
</View>
);
}
return null;
};
_getNotificationsArrays = () => {
const { notifications, intl } = this.props;
@ -113,31 +131,39 @@ class NotificationView extends PureComponent {
};
_getTimeListIndex = (timestamp) => {
if (isToday(timestamp)) {
return 0;
}
if (isToday(timestamp)) return 0;
if (isYesterday(timestamp)) {
return 1;
}
if (isYesterday(timestamp)) return 1;
if (isThisWeek(timestamp)) {
return 2;
}
if (isThisWeek(timestamp)) return 2;
if (isThisMonth(timestamp)) {
return 3;
}
if (isThisMonth(timestamp)) return 3;
return 4;
};
_getActivityIndicator = () => (
<View style={styles.loading}>
<ActivityIndicator animating size="large" />
</View>
);
render() {
const { readAllNotification } = this.props;
const { filters } = this.state;
const {
readAllNotification,
getActivities,
loading,
readAllNotificationLoading,
isDarkTheme,
} = this.props;
const { filters, selectedFilter } = this.state;
const _notifications = this._getNotificationsArrays();
if (_notifications.length === 0) {
return this._getActivityIndicator();
}
return (
<View style={styles.container}>
<FilterBar
@ -145,12 +171,36 @@ class NotificationView extends PureComponent {
options={filters.map(item => item.value)}
defaultText="ALL ACTIVITIES"
onDropdownSelect={this._handleOnDropdownSelect}
rightIconName="ios-checkmark"
rightIconName="check"
rightIconType="MaterialIcons"
onRightIconPress={readAllNotification}
/>
<ScrollView style={styles.scrollView}>
<ScrollView
style={styles.scrollView}
onScroll={(e) => {
let paddingToBottom = 1;
paddingToBottom += e.nativeEvent.layoutMeasurement.height;
if (
e.nativeEvent.contentOffset.y >= e.nativeEvent.contentSize.height - paddingToBottom
&& !loading
) {
getActivities(selectedFilter, true);
}
}}
>
<FlatList
data={_notifications}
refreshing={readAllNotificationLoading}
onRefresh={() => null}
refreshControl={(
<RefreshControl
refreshing={readAllNotificationLoading}
progressBackgroundColor="#357CE6"
tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'}
titleColor="#fff"
colors={['#fff']}
/>
)}
renderItem={({ item, index }) => (
<Fragment>
<ContainerHeader
@ -163,6 +213,7 @@ class NotificationView extends PureComponent {
</Fragment>
)}
keyExtractor={item => item.title}
ListFooterComponent={this._renderFooterLoading}
/>
</ScrollView>
</View>

View File

@ -26,10 +26,10 @@ class NotificationLineView extends PureComponent {
// Component Life Cycles
componentWillReceiveProps(nextProps) {
const { isRead } = this.props;
const { notification } = this.props;
if (isRead !== nextProps.isRead) {
this.setState({ isRead: nextProps.isRead });
if (notification.read !== nextProps.notification.read) {
this.setState({ isRead: nextProps.notification.read });
}
}

View File

@ -1,10 +1,11 @@
import React, { PureComponent, Fragment } from 'react';
import { Dimensions, Linking, Alert } from 'react-native';
import {
Dimensions, Linking, Alert,
} from 'react-native';
import { withNavigation } from 'react-navigation';
import { injectIntl } from 'react-intl';
import HTML from 'react-native-html-renderer';
// Styles
import styles from './postBodyStyles';
@ -13,6 +14,14 @@ import { default as ROUTES } from '../../../../constants/routeNames';
// Components
const WIDTH = Dimensions.get('window').width;
const CUSTOM_RENDERERS = {
// example
//center: () => <Text style={{ backgroundColor: 'blue', textAlign: 'center'}}>ugur</Text>,
};
const DEFAULT_PROPS = {
renderers: CUSTOM_RENDERERS,
debug: true,
};
class PostBody extends PureComponent {
constructor(props) {
@ -102,6 +111,7 @@ class PostBody extends PureComponent {
return (
<Fragment>
<HTML
{...DEFAULT_PROPS}
html={body}
onLinkPress={(evt, href, hrefatr) => this._handleOnLinkPress(evt, href, hrefatr)}
containerStyle={isComment ? styles.commentContainer : styles.container}

View File

@ -7,6 +7,11 @@ import { setUpvotePercent } from '../../../realm/realm';
// Services and Actions
import { setUpvotePercent as upvoteAction } from '../../../redux/actions/applicationActions';
// Utils
import parseToken from '../../../utils/parseToken';
import { isEmptyContentDate, getTimeFromNow } from '../../../utils/time';
import parseDate from '../../../utils/parseDate';
// Component
import UpvoteView from '../view/upvoteView';
@ -42,13 +47,18 @@ class UpvoteContainer extends PureComponent {
fetchPost,
isLoggedIn,
isShowPayoutValue,
upvotePercent,
pinCode,
upvotePercent,
} = this.props;
let author;
let authorPayout;
let curationPayout;
let isDecinedPayout;
let isVoted;
let payoutDate;
let pendingPayout;
let permlink;
let promotedPayout;
let totalPayout;
if (content) {
@ -57,11 +67,20 @@ class UpvoteContainer extends PureComponent {
totalPayout = content.total_payout;
isDecinedPayout = content.is_declined_payout;
({ permlink } = content);
pendingPayout = parseToken(content.pending_payout_value).toFixed(3);
promotedPayout = parseToken(content.promoted).toFixed(3);
authorPayout = parseToken(content.total_payout_value).toFixed(3);
curationPayout = parseToken(content.curator_payout_value).toFixed(3);
payoutDate = getTimeFromNow(
isEmptyContentDate(content.last_payout) ? content.cashout_time : content.last_payout,
);
}
return (
<UpvoteView
author={author}
authorPayout={authorPayout}
curationPayout={curationPayout}
currentAccount={currentAccount}
fetchPost={fetchPost}
handleSetUpvotePercent={this._setUpvotePercent}
@ -69,8 +88,11 @@ class UpvoteContainer extends PureComponent {
isLoggedIn={isLoggedIn}
isShowPayoutValue={isShowPayoutValue}
isVoted={isVoted}
payoutDate={payoutDate}
pendingPayout={pendingPayout}
permlink={permlink}
pinCode={pinCode}
promotedPayout={promotedPayout}
totalPayout={totalPayout}
upvotePercent={upvotePercent}
/>

View File

@ -4,13 +4,15 @@ export default EStyleSheet.create({
upvoteButton: {
flexDirection: 'row',
alignSelf: 'center',
alignItems: 'center',
justifyContent: 'center',
},
upvoteIcon: {
alignSelf: 'flex-start',
alignSelf: 'center',
fontSize: 20,
color: '$primaryBlue',
},
popover: {
popoverSlider: {
flexDirection: 'row',
width: '$deviceWidth - 20',
height: 48,
@ -18,6 +20,13 @@ export default EStyleSheet.create({
paddingHorizontal: 16,
backgroundColor: '$primaryBackgroundColor',
},
popoverDetails: {
flexDirection: 'row',
height: 100,
borderRadius: 20,
paddingHorizontal: 26,
backgroundColor: '$primaryBackgroundColor',
},
track: {
height: 2,
borderRadius: 1,
@ -53,6 +62,13 @@ export default EStyleSheet.create({
alignItems: 'center',
},
arrow: {
borderTopColor: '$primaryBackgroundColor',
marginLeft: 25,
},
payoutTextButton: {
alignSelf: 'center',
},
hideArrow: {
borderTopColor: 'transparent',
},
overlay: {
@ -68,4 +84,8 @@ export default EStyleSheet.create({
textDecorationLine: 'line-through',
textDecorationStyle: 'solid',
},
detailsText: {
color: '$primaryDarkGray',
fontSize: 10,
},
});

View File

@ -1,14 +1,15 @@
import React, { Component, Fragment } from 'react';
import {
View, TouchableOpacity, ActivityIndicator, Text, Alert,
View, TouchableOpacity, Text, Alert,
} from 'react-native';
import { injectIntl } from 'react-intl';
import { Popover, PopoverController } from 'react-native-modal-popover';
import Slider from 'react-native-slider';
// Constants
// Components
import { Icon } from '../../icon';
import { PulseAnimation } from '../../animations';
import { TextButton } from '../../buttons';
// STEEM
import { upvoteAmount, vote } from '../../../providers/steem/dsteem';
@ -28,6 +29,7 @@ class UpvoteView extends Component {
isVoting: false,
isVoted: props.isVoted,
amount: '0.00000',
isShowDetails: false,
};
}
@ -75,7 +77,12 @@ class UpvoteView extends Component {
_upvoteContent = async () => {
const {
author, currentAccount, fetchPost, handleSetUpvotePercent, permlink, pinCode,
author,
currentAccount,
fetchPost,
handleSetUpvotePercent,
permlink,
pinCode,
} = this.props;
const { sliderValue } = this.state;
@ -90,13 +97,7 @@ class UpvoteView extends Component {
const weight = sliderValue ? (sliderValue * 100).toFixed(0) * 100 : 0;
vote(
currentAccount,
pinCode,
author,
permlink,
weight,
)
vote(currentAccount, pinCode, author, permlink, weight)
.then(() => {
this.setState(
{
@ -119,11 +120,31 @@ class UpvoteView extends Component {
});
};
_handleOnPopoverClose = () => {
this.popoverOnClose = setTimeout(() => {
this.setState({ isShowDetails: false }, () => {
clearTimeout(this.popoverOnClose);
});
}, 300);
};
render() {
const { isDecinedPayout, isLoggedIn, isShowPayoutValue, totalPayout } = this.props;
const {
isVoting, amount, sliderValue, isVoted,
isDecinedPayout,
isLoggedIn,
isShowPayoutValue,
totalPayout,
pendingPayout,
promotedPayout,
authorPayout,
curationPayout,
payoutDate,
intl,
} = this.props;
const {
isVoting, amount, sliderValue, isVoted, isShowDetails,
} = this.state;
let iconName = 'ios-arrow-dropup';
let iconType;
@ -169,57 +190,98 @@ class UpvoteView extends Component {
name={iconName}
/>
)}
{isShowPayoutValue && (
<Text style={[styles.payoutValue, isDecinedPayout && styles.declinedPayout]}>{`$${_totalPayout}`}</Text>
)}
</Fragment>
</TouchableOpacity>
<View style={styles.payoutTextButton}>
{isShowPayoutValue && (
<TextButton
style={styles.payoutTextButton}
textStyle={[styles.payoutValue, isDecinedPayout && styles.declinedPayout]}
text={`$${_totalPayout}`}
onPress={() => {
openPopover();
this.setState({ isShowDetails: true });
}}
/>
)}
</View>
<Popover
contentStyle={styles.popover}
arrowStyle={styles.arrow}
contentStyle={isShowDetails ? styles.popoverDetails : styles.popoverSlider}
arrowStyle={isShowDetails ? styles.arrow : styles.hideArrow}
backgroundStyle={styles.overlay}
visible={popoverVisible}
onClose={closePopover}
onClose={() => {
closePopover();
this._handleOnPopoverClose();
}}
fromRect={popoverAnchorRect}
placement="top"
supportedOrientations={['portrait', 'landscape']}
>
<View style={styles.popoverWrapper}>
<TouchableOpacity
onPress={() => {
closePopover();
this._upvoteContent();
}}
style={styles.upvoteButton}
>
{isVoting ? (
<ActivityIndicator />
) : (
<Icon
size={20}
style={[styles.upvoteIcon, { color: '#007ee5' }]}
active={!isLoggedIn}
iconType={iconType}
name={iconName}
{isShowDetails ? (
<View>
<Text style={styles.detailsText}>
{`${intl.formatMessage({
id: 'payout.promoted',
})} ${promotedPayout > 0 ? '~' : ''}$${promotedPayout}`}
</Text>
<Text style={styles.detailsText}>
{`${intl.formatMessage({
id: 'payout.potential_payout',
})} ${pendingPayout > 0 ? '~' : ''}$${pendingPayout}`}
</Text>
<Text style={styles.detailsText}>
{`${intl.formatMessage({
id: 'payout.author_payout',
})} ${authorPayout > 0 ? '~' : ''}$${authorPayout}`}
</Text>
<Text style={styles.detailsText}>
{`${intl.formatMessage({
id: 'payout.curation_payout',
})} ${curationPayout > 0 ? '~' : ''}$${curationPayout}`}
</Text>
<Text style={styles.detailsText}>
{`${intl.formatMessage({
id: 'payout.payout_date',
})} ${payoutDate}`}
</Text>
</View>
) : (
<Fragment>
<TouchableOpacity
onPress={() => {
closePopover();
this._upvoteContent();
}}
style={styles.upvoteButton}
>
<Icon
size={20}
style={[styles.upvoteIcon, { color: '#007ee5' }]}
active={!isLoggedIn}
iconType={iconType}
name={iconName}
/>
</TouchableOpacity>
<Text style={styles.amount}>{_amount}</Text>
<Slider
style={styles.slider}
minimumTrackTintColor="#357ce6"
trackStyle={styles.track}
thumbStyle={styles.thumb}
thumbTintColor="#007ee5"
value={sliderValue}
onValueChange={(value) => {
this.setState({ sliderValue: value }, () => {
this._calculateEstimatedAmount();
});
}}
/>
)}
</TouchableOpacity>
<Text style={styles.amount}>{_amount}</Text>
<Slider
style={styles.slider}
minimumTrackTintColor="#357ce6"
trackStyle={styles.track}
thumbStyle={styles.thumb}
thumbTintColor="#007ee5"
value={sliderValue}
onValueChange={(value) => {
this.setState({ sliderValue: value }, () => {
this._calculateEstimatedAmount();
});
}}
/>
<Text style={styles.percent}>{_percent}</Text>
<Text style={styles.percent}>{_percent}</Text>
</Fragment>
)}
</View>
</Popover>
</Fragment>
@ -229,4 +291,4 @@ class UpvoteView extends Component {
}
}
export default UpvoteView;
export default injectIntl(UpvoteView);

View File

@ -172,5 +172,12 @@
"already_logged": "You are already logged in, please try to add another account",
"invalid_credentials": "Invalid credentials, please check and try again",
"unknow_error": "Unknown error, please contact us at support@esteem.app"
},
"payout": {
"potential_payout": "Potential Payout",
"promoted": "Promoted",
"author_payout": "Author Payout",
"curation_payout": "Curation Payout",
"payout_date": "Payout"
}
}

View File

@ -172,5 +172,12 @@
"already_logged": "Вы уже вошли, пожалуйста, попробуйте добавить другой аккаунт",
"invalid_credentials": "Некорректные данные, пожалуйста, проверьте и повторите снова",
"unknow_error": "Неизвестная ошибка, пожалуйста, напишите на support@esteem.app"
},
"payout": {
"potential_payout": "Потенциальная выплата",
"promoted": "Продвижение",
"author_payout": "Автору",
"curation_payout": "Кураторам",
"payout_date": "Выплата"
}
}

View File

@ -172,5 +172,12 @@
"already_logged": "You are already logged in, please try to add another account",
"invalid_credentials": "Invalid credentials, please check and try again",
"unknow_error": "Unknown error, please contact us at support@esteem.app"
},
"payout": {
"potential_payout": "Tahmini Ödeme",
"promoted": "Sponsor Ödemeleri",
"author_payout": "Yazar Ödemeleri",
"curation_payout": "Küratör Ödemeleri",
"payout_date": "Ödeme"
}
}

View File

@ -308,7 +308,7 @@ class EditorContainer extends Component {
options,
0,
)
.then((result) => {
.then(() => {
Alert.alert(
intl.formatMessage({
id: 'alert.success',

View File

@ -5,8 +5,6 @@ import { injectIntl } from 'react-intl';
// Utils
import { getWordsCount } from '../../../utils/editor';
// Constants
// Components
import { BasicHeader } from '../../../components/basicHeader';
import {

View File

@ -16,9 +16,20 @@ class NotificationContainer extends Component {
super(props);
this.state = {
notifications: [],
lastNotificationId: null,
notificationLoading: false,
readAllNotificationLoading: false,
};
}
componentDidMount() {
const { username } = this.props;
if (username) {
this._getAvtivities();
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.activeBottomTab === ROUTES.TABBAR.NOTIFICATION) {
if (nextProps.username) {
@ -27,12 +38,24 @@ class NotificationContainer extends Component {
}
}
_getAvtivities = (type = null) => {
_getAvtivities = (type = null, loadMore = false) => {
const { username } = this.props;
const { lastNotificationId, notifications } = this.state;
const since = loadMore ? lastNotificationId : null;
getActivities({ user: username, type }).then((res) => {
this.setState({ notifications: res });
});
this.setState({ notificationLoading: true });
getActivities({ user: username, type, since })
.then((res) => {
const lastId = [...res].pop().id;
this.setState({
notifications: loadMore ? [...notifications, ...res] : res,
lastNotificationId: lastId,
notificationLoading: false,
});
})
.catch(() => this.setState({ notificationLoading: false }));
};
_navigateToNotificationRoute = (data) => {
@ -65,10 +88,13 @@ class NotificationContainer extends Component {
_readAllNotification = () => {
const { username, dispatch } = this.props;
const { notifications } = this.state;
this.setState({ readAllNotificationLoading: true });
markActivityAsRead(username).then((result) => {
dispatch(updateUnreadActivityCount(result.unread));
const updatedNotifications = notifications.map(item => ({ ...item, read: 1 }));
this.setState({ notifications: updatedNotifications });
this.setState({ notifications: updatedNotifications, readAllNotificationLoading: false });
});
};
@ -79,24 +105,32 @@ class NotificationContainer extends Component {
};
render() {
const { notifications } = this.state;
const { isLoggedIn } = this.props;
const {
notifications, notificationLoading, readAllNotificationLoading, isDarkTheme,
} = this.state;
return (
<NotificationScreen
getActivities={this._getAvtivities}
notifications={notifications}
isDarkTheme={isDarkTheme}
navigateToNotificationRoute={this._navigateToNotificationRoute}
readAllNotification={this._readAllNotification}
handleLoginPress={this._handleOnPressLogin}
{...this.props}
notificationLoading={notificationLoading}
readAllNotificationLoading={readAllNotificationLoading}
isLoggedIn={isLoggedIn}
/>
);
}
}
const mapStateToProps = state => ({
username: state.account.currentAccount.name,
isLoggedIn: state.application.isLoggedIn,
isDarkTheme: state.application.isDarkTheme,
username: state.account.currentAccount.name,
activeBottomTab: state.ui.activeBottomTab,
});

View File

@ -29,7 +29,10 @@ class NotificationScreen extends PureComponent {
readAllNotification,
handleLoginPress,
isLoggedIn,
notificationLoading,
readAllNotificationLoading,
} = this.props;
return (
<View style={styles.container}>
<Header />
@ -51,6 +54,8 @@ class NotificationScreen extends PureComponent {
notifications={notifications}
navigateToNotificationRoute={navigateToNotificationRoute}
readAllNotification={readAllNotification}
readAllNotificationLoading={readAllNotificationLoading}
loading={notificationLoading}
/>
) : (
<NoPost

View File

@ -2,11 +2,12 @@ import Remarkable from 'remarkable';
// TODO: Refactoring need!
const md = new Remarkable({ html: true, breaks: true, linkify: true });
const imgCenterRegex = /([<center>]http(s?):)([/|.|\w|\s|-])*\.(?:jpg|gif|png|PNG|GIF|JPG)[</center>]/g;
const onlyImageLinkRegex = /([\n]http(s?):)([/|.|\w|\s|-])*\.(?:jpg|gif|png|PNG|GIF|JPG)/g;
const onlyImageDoubleLinkRegex = /(\nhttps)(.*)(?=jpg|gif|png|PNG|GIF|JPG|)/g;
//const imgCenterRegex = /([<center>]http(s?):)([/|.|\w|\s|-])*\.(?:jpg|gif|png|PNG|GIF|JPG)[</center>]/g;
//const onlyImageLinkRegex = /([\n]http(s?):)([/|.|\w|\s|-])*\.(?:jpg|gif|png|PNG|GIF|JPG)/g;
//const onlyImageDoubleLinkRegex = /(\nhttps)(.*)(?=jpg|gif|png|PNG|GIF|JPG|)/g;
//const pullRightLeftRegex = /(<div class="[^"]*?pull-[^"]*?">(.*?)(<[/]div>))/g;
//const copiedPostRegex = /\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
const postRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
const copiedPostRegex = /\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
const youTubeRegex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([^& \n<]+)(?:[^ \n<]+)?/g;
const vimeoRegex = /(https?:\/\/)?(www\.)?(?:vimeo)\.com.*(?:videos|video|channels|)\/([\d]+)/i;
const dTubeRegex = /(https?:\/\/d.tube.#!\/v\/)(\w+)\/(\w+)/g;
@ -14,14 +15,12 @@ const authorNameRegex = /(^|[^a-zA-Z0-9_!#$%&*@\/]|(^|[^a-zA-Z0-9_+~.-\/]))[@
const tagsRegex = /(^|\s|>)(#[-a-z\d]+)/gi;
const centerRegex = /(<center>)/g;
const imgRegex = /(https?:\/\/.*\.(?:tiff?|jpe?g|gif|png|svg|ico|PNG|GIF|JPG))/g;
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;
const imgTagRegex = /(<img[^>]*>)/g;
const iframeRegex = /(?:<iframe[^>]*)(?:(?:\/>)|(?:>.*?<\/iframe>))/g;
//const codeTagRegex= /(?:<code[^>]*)(?:(?:\/>)|(?:>.*?<\/code>))/g;
export const markDown2Html = (input) => {
if (!input) {
@ -69,10 +68,6 @@ export const markDown2Html = (input) => {
output = handleIframe(output);
}
// if (codeTagRegex.test(output)) {
// output = handleCodeTag(output);
// }
if (linkRegex.test(output)) {
output = handleLinks(output);
}
@ -157,33 +152,7 @@ const changeMarkdownImage = input => input.replace(markdownImageRegex, (link) =>
return link;
});
const centerStyling = input => input.replace(centerRegex, () => '<center style="text-align:center;">');
// const handleCodeTag = input => input.replace(codeTagRegex, (tag) => {
// const stringsRegex = /(?<=>)(.*)(?=<)/g;
// const match = tag.match(stringsRegex);
// if (match && match[0]) {
// return `<p class="code" >${match[0]}</p>`;
// }
// return iframeBody(match[0]);
// });
const createCenterImage = input => input.replace(imgCenterRegex, (link) => {
let _link = link;
_link = _link.split('>')[1];
_link = _link.split('<')[0];
return `><img data-href="${`https://steemitimages.com/600x0/${_link}`}" src="${`https://steemitimages.com/600x0/${_link}`}"><`;
});
const changePullRightLeft = input => input.replace(pullRightLeftRegex, (item) => {
const imageLink = item.match(linkRegex)[0];
return `<center style="text-align:center;"><img src="${`https://steemitimages.com/600x0/${imageLink}`}"/></center><br>`;
});
const centerStyling = input => input.replace(centerRegex, () => '<center style="text-align: center; align-items: center; justify-content: center;">');
const steemitUrlHandle = input => input.replace(postRegex, (link) => {
const postMatch = link.match(postRegex);
@ -194,7 +163,6 @@ const steemitUrlHandle = input => input.replace(postRegex, (link) => {
return `<a class="markdown-post-link" href="${permlink}" data_tag={${tag}} data_author="${author}">/${permlink}</a>`;
});
const createImage = input => input.replace(onlyImageLinkRegex, link => imageBody(link));
const handleImageTag = input => input.replace(imgTagRegex, (imgTag) => {
const _imgTag = imgTag.trim();
@ -207,12 +175,6 @@ const handleImageTag = input => input.replace(imgTagRegex, (imgTag) => {
return imgTag;
});
const createFromDoubleImageLink = input => input.replace(onlyImageDoubleLinkRegex, (link) => {
const _link = link.trim();
return imageBody(_link);
});
const createYoutubeIframe = input => input.replace(youTubeRegex, (link) => {
const execVideo = youTubeRegex.exec(link);
const match = link.match(youTubeRegex);
@ -237,21 +199,6 @@ const handleIframe = input => input.replace(iframeRegex, (link) => {
return link;
});
const createDtubeIframe = input => input.replace(dTubeRegex, (link) => {
const execLink = dTubeRegex.exec(link);
const dTubeMatch = link.match(dTubeRegex)[0];
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;
});
const createVimeoIframe = input => input.replace(vimeoRegex, (link) => {
const execLink = vimeoRegex.exec(link);
@ -262,3 +209,54 @@ const createVimeoIframe = input => input.replace(vimeoRegex, (link) => {
const iframeBody = link => `<iframe frameborder='0' allowfullscreen src='${link}'></iframe>`;
const imageBody = link => `<img src="${`https://steemitimages.com/600x0/${link}`}">`;
// const handleCodeTag = input => input.replace(codeTagRegex, (tag) => {
// const stringsRegex = /(?<=>)(.*)(?=<)/g;
// const match = tag.match(stringsRegex);
// if (match && match[0]) {
// return `<p class="code" >${match[0]}</p>`;
// }
// return iframeBody(match[0]);
// });
// const createCenterImage = input => input.replace(imgCenterRegex, (link) => {
// let _link = link;
// _link = _link.split('>')[1];
// _link = _link.split('<')[0];
// return `><img data-href="${`https://steemitimages.com/600x0/${_link}`}" src="${`https://steemitimages.com/600x0/${_link}`}"><`;
// });
// const changePullRightLeft = input => input.replace(pullRightLeftRegex, (item) => {
// const imageLink = item.match(linkRegex)[0];
// return `<center style="text-align:center;"><img src="${`https://steemitimages.com/600x0/${imageLink}`}"/></center><br>`;
// });
//const createImage = input => input.replace(onlyImageLinkRegex, link => imageBody(link));
// const createFromDoubleImageLink = input => input.replace(onlyImageDoubleLinkRegex, (link) => {
// const _link = link.trim();
// return imageBody(_link);
// });
// const createDtubeIframe = input => input.replace(dTubeRegex, (link) => {
// const execLink = dTubeRegex.exec(link);
// const dTubeMatch = link.match(dTubeRegex)[0];
// 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;
// });

View File

@ -1 +1,14 @@
// ^ (http: \/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$
import parseToken from './parseToken';
import { isEmptyContentDate } from './time';
export const postSumTotal = (content) => {
if (content.pending_payout_value && isEmptyContentDate(content.last_payout)) {
return content.total_payout_value
? parseToken(content.total_payout_value) + parseToken(content.pending_payout_value)
: 0;
}
return content.total_payout_value
? parseToken(content.total_payout_value) + parseToken(content.curator_payout_value)
: 0;
};

View File

@ -1,4 +1,5 @@
import moment from 'moment';
import parseToken from './parseToken';
const TODAY = moment().startOf('day');
const YESTERDAY = moment()
@ -32,3 +33,5 @@ export const isYesterday = value => moment(value).isSame(YESTERDAY, 'd');
export const isThisWeek = value => moment(value).isSameOrAfter(THIS_WEEK);
export const isThisMonth = value => moment(value).isSameOrAfter(THIS_MONTH);
export const isEmptyContentDate = value => parseInt(value.split('-')[0], 10) < 1980;