Merge branch 'development' of github.com:esteemapp/esteem-mobile into bugfix/post-display

This commit is contained in:
Mustafa Buyukcelebi 2019-11-11 15:49:48 +03:00
commit 03136101d6
21 changed files with 277 additions and 286 deletions

View File

@ -16,7 +16,7 @@ export default EStyleSheet.create({
zIndex: 1, zIndex: 1,
position: 'absolute', position: 'absolute',
bottom: 0, bottom: 0,
marginHorizontal: 19, marginHorizontal: 20,
justifyContent: 'space-between', justifyContent: 'space-between',
}, },
navItem: { navItem: {

View File

@ -48,7 +48,7 @@ export default class TitleAreaView extends Component {
const { text, height } = this.state; const { text, height } = this.state;
return ( return (
<View style={globalStyles.containerHorizontal16}> <View style={[globalStyles.containerHorizontal16, { height: Math.max(35, height) }]}>
<TextInput <TextInput
style={[styles.textInput, { height: Math.max(35, height) }]} style={[styles.textInput, { height: Math.max(35, height) }]}
placeholderTextColor="#c1c5c7" placeholderTextColor="#c1c5c7"

View File

@ -1,9 +1,6 @@
import { replaceBetween } from './utils'; import { replaceBetween } from './utils';
export default async ({ getState, item, setState }) => { export default async ({ text, selection, setTextAndSelection, item }) => {
const states = getState();
let { text } = states;
const { selection } = states;
let newText; let newText;
let newSelection; let newSelection;
@ -35,6 +32,5 @@ export default async ({ getState, item, setState }) => {
newSelection = { start: selection.start + 3, end: selection.start + 3 }; newSelection = { start: selection.start + 3, end: selection.start + 3 };
} }
await setState({ text: newText, textUpdated: true }); setTextAndSelection({ text: newText, selection: newSelection });
await setState({ newSelection });
}; };

View File

@ -3,8 +3,7 @@ import { isStringWebLink, replaceBetween } from './utils';
export const writeUrlTextHere = 'https://example.com'; export const writeUrlTextHere = 'https://example.com';
export const writeTextHereString = 'Text here'; export const writeTextHereString = 'Text here';
export default async ({ getState, item, setState, isImage = null }) => { export default async ({ text, selection, setTextAndSelection, item, isImage = null }) => {
const { selection, text } = getState();
const imagePrefix = isImage ? '!' : ''; const imagePrefix = isImage ? '!' : '';
const itemText = item ? item.text : writeTextHereString; const itemText = item ? item.text : writeTextHereString;
const itemUrl = item ? item.url : writeUrlTextHere; const itemUrl = item ? item.url : writeUrlTextHere;
@ -41,7 +40,5 @@ export default async ({ getState, item, setState, isImage = null }) => {
} }
} }
await setState({ text: newText, textUpdated: true }, async () => { setTextAndSelection({ text: newText, selection: newSelection });
await setState({ newSelection });
});
}; };

View File

@ -1,7 +1,6 @@
import { replaceBetween } from './utils'; import { replaceBetween } from './utils';
export default ({ getState, item, setState }) => { export default async ({ text, selection, setTextAndSelection, item }) => {
const { text, selection } = getState();
const newText = replaceBetween( const newText = replaceBetween(
text, text,
selection, selection,
@ -14,8 +13,6 @@ export default ({ getState, item, setState }) => {
} else { } else {
newPosition = selection.end + item.wrapper.length * 2; newPosition = selection.end + item.wrapper.length * 2;
} }
const newSelection = { start: newPosition, end: newPosition };
setState({ text: newText, textUpdated: true }, () => { setTextAndSelection({ text: newText, selection: newSelection });
setState({ newSelection: { start: newPosition, end: newPosition } });
});
}; };

View File

@ -1,7 +1,6 @@
import { replaceBetween } from './utils'; import { replaceBetween } from './utils';
export default async ({ getState, item, setState }) => { export default async ({ text, selection, setTextAndSelection, item }) => {
const { text, selection } = getState();
let newText = replaceBetween( let newText = replaceBetween(
text, text,
selection, selection,
@ -42,7 +41,6 @@ export default async ({ getState, item, setState }) => {
); );
} }
await setState({ text: newText, textUpdated: true }, async () => { const newSelection = { start: newPosition, end: newPosition };
await setState({ newSelection: { start: newPosition, end: newPosition } }); setTextAndSelection({ text: newText, selection: newSelection });
});
}; };

View File

@ -1,9 +1,9 @@
import regexValidator from './webLinkValidator'; import regexValidator from './webLinkValidator';
export const replaceBetween = (text: string, selection: Object, what: string) => export const replaceBetween = (text, selection, what) =>
text.substring(0, selection.start) + what + text.substring(selection.end); text.substring(0, selection.start) + what + text.substring(selection.end);
export const isStringWebLink = (text: string): boolean => { export const isStringWebLink = text => {
const pattern = regexValidator; const pattern = regexValidator;
return pattern.test(text); return pattern.test(text);
}; };

View File

@ -1,11 +1,11 @@
import React, { Component } from 'react'; import React, { useState, useRef, useEffect } from 'react';
import { View, KeyboardAvoidingView, FlatList, Text, Platform, ScrollView } from 'react-native'; import { View, KeyboardAvoidingView, FlatList, Text, Platform, ScrollView } from 'react-native';
import ActionSheet from 'react-native-actionsheet'; import ActionSheet from 'react-native-actionsheet';
import { renderPostBody } from '@esteemapp/esteem-render-helpers'; import { renderPostBody } from '@esteemapp/esteem-render-helpers';
// Utils // Utils
import applyImageLink from './formats/applyWebLinkFormat';
import Formats from './formats/formats'; import Formats from './formats/formats';
import applyImageLink from './formats/applyWebLinkFormat';
// Components // Components
import { IconButton } from '../../iconButton'; import { IconButton } from '../../iconButton';
@ -18,73 +18,83 @@ import { ThemeContainer } from '../../../containers';
// Styles // Styles
import styles from './markdownEditorStyles'; import styles from './markdownEditorStyles';
export default class MarkdownEditorView extends Component { const MarkdownEditorView = ({
constructor(props) { draftBody,
super(props); handleIsFormValid,
this.state = { handleOpenImagePicker,
text: props.draftBody || '', intl,
selection: { start: 0, end: 0 }, isPreviewActive,
textUpdated: false, isReply,
newSelection: null, isLoading,
}; initialFields,
onChange,
handleOnTextChange,
handleIsValid,
componentID,
uploadedImage,
}) => {
const [text, setText] = useState(draftBody || '');
const [selection, setSelection] = useState({ start: 0, end: 0 });
const [editable, setEditable] = useState(null);
this.inputRef = React.createRef(); const inputRef = useRef(null);
this.galleryRef = React.createRef(); const galleryRef = useRef(null);
this.clearRef = React.createRef(); const clearRef = useRef(null);
}
// Lifecycle functions useEffect(() => {
UNSAFE_componentWillReceiveProps(nextProps) { if (!isPreviewActive) {
const { draftBody, uploadedImage, isPreviewActive } = this.props; _setTextAndSelection({ selection: { start: 0, end: 0 }, text });
if (!nextProps.isPreviewActive && isPreviewActive) {
this.setState({
selection: { start: 0, end: 0 },
});
}
if (nextProps.draftBody && draftBody !== nextProps.draftBody) {
this.setState({
text: nextProps.draftBody,
});
} }
}, [isPreviewActive]);
if ( useEffect(() => {
nextProps.uploadedImage && if (text === '' && draftBody !== '') {
nextProps.uploadedImage.url && _setTextAndSelection({ selection: { start: 0, end: 0 }, text: draftBody });
nextProps.uploadedImage !== uploadedImage }
) { }, [draftBody]);
useEffect(() => {
if (editable === null) {
// workaround for android context menu issue
setEditable(false);
setTimeout(() => {
setEditable(!isLoading);
}, 100);
} else {
setEditable(!isLoading);
}
}, [isLoading]);
useEffect(() => {
if (uploadedImage && uploadedImage.url) {
applyImageLink({ applyImageLink({
getState: this._getState, text,
setState: async (state, callback) => { selection,
await this.setState(state, callback); setTextAndSelection: _setTextAndSelection,
}, item: { url: uploadedImage.url, text: uploadedImage.hash },
item: { url: nextProps.uploadedImage.url, text: nextProps.uploadedImage.hash }, isImage: !!uploadedImage,
isImage: !!nextProps.uploadedImage,
}); });
} }
} }, [uploadedImage]);
componentDidUpdate(prevProps, prevState) { useEffect(() => {
const { text } = this.state; setText(draftBody);
const { handleIsFormValid } = this.props; }, [draftBody]);
if (prevState.text !== text) { useEffect(() => {
const nextText = text.replace(prevState.text, ''); const nextText = text.replace(text, '');
if (nextText && nextText.length > 0) { if (nextText && nextText.length > 0) {
this._changeText(text); _changeText(text);
if (handleIsFormValid) { if (handleIsFormValid) {
handleIsFormValid(text); handleIsFormValid(text);
}
} }
} }
} }, [text]);
// Component functions const _changeText = input => {
_changeText = input => { setText(input);
const { onChange, handleOnTextChange, handleIsValid, componentID } = this.props;
this.setState({ text: input });
if (onChange) { if (onChange) {
onChange(input); onChange(input);
@ -99,36 +109,31 @@ export default class MarkdownEditorView extends Component {
} }
}; };
_handleOnSelectionChange = event => { const _handleOnSelectionChange = async event => {
const { newSelection } = this.state; setSelection(event.nativeEvent.selection);
};
if (newSelection) { const _setTextAndSelection = ({ selection: _selection, text: _text }) => {
this.setState({ inputRef.current.setNativeProps({
selection: newSelection, text: _text,
newSelection: null,
});
return;
}
this.setState({
selection: event.nativeEvent.selection,
}); });
// Workaround for iOS selection update issue
setTimeout(() => {
inputRef.current.setNativeProps({
selection: _selection,
});
setSelection(_selection);
}, 200);
_changeText(_text);
}; };
_getState = () => { const _renderPreview = () => (
return this.state; <ScrollView style={styles.previewContainer}>
}; {text ? <PostBody body={renderPostBody(text)} /> : <Text>...</Text>}
</ScrollView>
);
_renderPreview = () => { const _renderMarkupButton = ({ item }) => (
const { text } = this.state;
return (
<ScrollView style={styles.previewContainer}>
{text ? <PostBody body={renderPostBody(text)} /> : <Text>...</Text>}
</ScrollView>
);
};
_renderMarkupButton = ({ item, getState, setState }) => (
<View style={styles.buttonWrapper}> <View style={styles.buttonWrapper}>
<IconButton <IconButton
size={20} size={20}
@ -136,20 +141,20 @@ export default class MarkdownEditorView extends Component {
iconStyle={styles.icon} iconStyle={styles.icon}
iconType={item.iconType} iconType={item.iconType}
name={item.icon} name={item.icon}
onPress={() => item.onPress({ getState, setState, item })} onPress={() =>
item.onPress({ text, selection, setTextAndSelection: _setTextAndSelection, item })
}
/> />
</View> </View>
); );
_renderEditorButtons = ({ getState, setState }) => ( const _renderEditorButtons = () => (
<StickyBar> <StickyBar>
<View style={styles.leftButtonsWrapper}> <View style={styles.leftButtonsWrapper}>
<FlatList <FlatList
data={Formats} data={Formats}
keyboardShouldPersistTaps="always" keyboardShouldPersistTaps="always"
renderItem={({ item, index }) => renderItem={({ item, index }) => index !== 9 && _renderMarkupButton({ item })}
index !== 9 && this._renderMarkupButton({ item, getState, setState })
}
horizontal horizontal
/> />
</View> </View>
@ -160,10 +165,12 @@ export default class MarkdownEditorView extends Component {
iconStyle={styles.icon} iconStyle={styles.icon}
iconType="FontAwesome" iconType="FontAwesome"
name="link" name="link"
onPress={() => Formats[9].onPress({ getState, setState })} onPress={() =>
Formats[9].onPress({ text, selection, setTextAndSelection: _setTextAndSelection })
}
/> />
<IconButton <IconButton
onPress={() => this.galleryRef.current.show()} onPress={() => galleryRef.current.show()}
style={styles.rightIcons} style={styles.rightIcons}
size={20} size={20}
iconStyle={styles.icon} iconStyle={styles.icon}
@ -172,7 +179,7 @@ export default class MarkdownEditorView extends Component {
/> />
<View style={styles.clearButtonWrapper}> <View style={styles.clearButtonWrapper}>
<IconButton <IconButton
onPress={() => this.clearRef.current.show()} onPress={() => clearRef.current.show()}
size={20} size={20}
iconStyle={styles.clearIcon} iconStyle={styles.clearIcon}
iconType="FontAwesome" iconType="FontAwesome"
@ -184,91 +191,81 @@ export default class MarkdownEditorView extends Component {
</StickyBar> </StickyBar>
); );
_handleClear = () => { const _handleClear = index => {
const { initialFields } = this.props; if (index === 0) {
initialFields();
initialFields(); setText('');
_setTextAndSelection({ text: '', selection: { start: 0, end: 0 } });
this.setState({ text: '' }); }
}; };
render() { return (
const { handleOpenImagePicker, intl, isPreviewActive, isReply, isLoading } = this.props; <KeyboardAvoidingView
const { text, selection } = this.state; style={styles.container}
keyboardVerticalOffset={Platform.select({ ios: 0, android: 25 })}
behavior={Platform.OS === 'ios' ? 'padding' : null}
>
{!isPreviewActive ? (
<ThemeContainer>
{({ isDarkTheme }) => (
<TextInput
multiline
autoCorrect={false}
onChangeText={_changeText}
onSelectionChange={_handleOnSelectionChange}
placeholder={intl.formatMessage({
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
})}
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
selectionColor="#357ce6"
style={styles.textWrapper}
underlineColorAndroid="transparent"
innerRef={inputRef}
editable={editable}
contextMenuHidden={false}
/>
)}
</ThemeContainer>
) : (
_renderPreview()
)}
{!isPreviewActive && _renderEditorButtons()}
<ActionSheet
ref={galleryRef}
options={[
intl.formatMessage({
id: 'editor.open_gallery',
}),
intl.formatMessage({
id: 'editor.capture_photo',
}),
intl.formatMessage({
id: 'alert.cancel',
}),
]}
cancelButtonIndex={2}
onPress={index => {
handleOpenImagePicker(index === 0 ? 'image' : index === 1 && 'camera');
}}
/>
<ActionSheet
ref={clearRef}
title={intl.formatMessage({
id: 'alert.clear_alert',
})}
options={[
intl.formatMessage({
id: 'alert.clear',
}),
intl.formatMessage({
id: 'alert.cancel',
}),
]}
cancelButtonIndex={1}
onPress={_handleClear}
/>
</KeyboardAvoidingView>
);
};
return ( export default MarkdownEditorView;
<KeyboardAvoidingView
style={styles.container}
keyboardVerticalOffset={Platform.select({ ios: 0, android: 25 })}
behavior={Platform.OS === 'ios' ? 'padding' : null}
>
{!isPreviewActive ? (
<ThemeContainer>
{({ isDarkTheme }) => (
<TextInput
multiline
onChangeText={this._changeText}
onSelectionChange={this._handleOnSelectionChange}
placeholder={intl.formatMessage({
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
})}
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
selection={selection}
selectionColor="#357ce6"
style={styles.textWrapper}
underlineColorAndroid="transparent"
value={text}
innerRef={this.inputRef}
editable={!isLoading}
/>
)}
</ThemeContainer>
) : (
this._renderPreview()
)}
{!isPreviewActive &&
this._renderEditorButtons({
getState: this._getState,
setState: (state, callback) => {
this.inputRef.current.focus();
this.setState(state, callback);
},
})}
<ActionSheet
ref={this.galleryRef}
options={[
intl.formatMessage({
id: 'editor.open_gallery',
}),
intl.formatMessage({
id: 'editor.capture_photo',
}),
intl.formatMessage({
id: 'alert.cancel',
}),
]}
cancelButtonIndex={2}
onPress={index => {
handleOpenImagePicker(index === 0 ? 'image' : index === 1 && 'camera');
}}
/>
<ActionSheet
ref={this.clearRef}
title={intl.formatMessage({
id: 'alert.clear_alert',
})}
options={[
intl.formatMessage({
id: 'alert.clear',
}),
intl.formatMessage({
id: 'alert.cancel',
}),
]}
cancelButtonIndex={1}
onPress={index => index === 0 && this._handleClear()}
/>
</KeyboardAvoidingView>
);
}
}

View File

@ -4,5 +4,6 @@ export default EStyleSheet.create({
icon: { icon: {
color: '$iconColor', color: '$iconColor',
marginRight: 2.7, marginRight: 2.7,
fontSize: 25,
}, },
}); });

View File

@ -359,12 +359,7 @@ class PostsView extends Component {
render() { render() {
const { refreshing, posts, isShowFilterBar } = this.state; const { refreshing, posts, isShowFilterBar } = this.state;
const { const { filterOptions, selectedOptionIndex, isHideImage, handleImagesHide } = this.props;
filterOptions,
selectedOptionIndex,
isHideImage,
handleImagesHide,
} = this.props;
return ( return (
<View style={styles.container}> <View style={styles.container}>

View File

@ -9,8 +9,9 @@ export default EStyleSheet.create({
}, },
upvoteIcon: { upvoteIcon: {
alignSelf: 'center', alignSelf: 'center',
fontSize: 20, fontSize: 24,
color: '$primaryBlue', color: '$primaryBlue',
marginRight: 5,
}, },
popoverSlider: { popoverSlider: {
flexDirection: 'row', flexDirection: 'row',

View File

@ -249,12 +249,14 @@ class UpvoteView extends Component {
/> />
</View> </View>
) : ( ) : (
<Icon <View hitSlop={{ top: 10, bottom: 10, left: 10, right: 5 }}>
style={[styles.upvoteIcon, isDownVoted && { color: '#ec8b88' }]} <Icon
active={!isLoggedIn} style={[styles.upvoteIcon, isDownVoted && { color: '#ec8b88' }]}
iconType={isDownVoted ? 'AntDesign' : iconType} active={!isLoggedIn}
name={isDownVoted ? 'downcircle' : iconName} iconType={isDownVoted ? 'AntDesign' : iconType}
/> name={isDownVoted ? 'downcircle' : iconName}
/>
</View>
)} )}
</Fragment> </Fragment>
</TouchableOpacity> </TouchableOpacity>

View File

@ -1,10 +1,10 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { TouchableOpacity } from 'react-native'; import { TouchableOpacity } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { NavigationActions } from 'react-navigation';
import FastImage from 'react-native-fast-image'; import FastImage from 'react-native-fast-image';
import styles from './userAvatarStyles'; import styles from './userAvatarStyles';
import NavigationService from '../../../navigation/service';
// Constants // Constants
import ROUTES from '../../../constants/routeNames'; import ROUTES from '../../../constants/routeNames';
@ -30,21 +30,18 @@ class UserAvatarView extends Component {
// Component Functions // Component Functions
_handleOnAvatarPress = username => { _handleOnAvatarPress = username => {
const { const {
dispatch,
currentUsername: { name }, currentUsername: { name },
} = this.props; } = this.props;
const routeName = name === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE; const routeName = name === username ? ROUTES.TABBAR.PROFILE : ROUTES.SCREENS.PROFILE;
const navigateAction = NavigationActions.navigate({ NavigationService.navigate({
routeName, routeName: routeName,
params: { params: {
username, username,
}, },
key: username, key: username,
action: NavigationActions.navigate({ routeName }),
}); });
dispatch(navigateAction);
}; };
render() { render() {
@ -61,7 +58,9 @@ class UserAvatarView extends Component {
let _size; let _size;
const _avatar = username const _avatar = username
? { ? {
uri: avatarUrl || (name === username ? avatar : getResizedAvatar(username, imageSize)), uri:
avatarUrl ||
(name === username && avatar ? avatar : getResizedAvatar(username, imageSize)),
} }
: DEFAULT_IMAGE; : DEFAULT_IMAGE;

View File

@ -3,7 +3,6 @@ import { Provider, connect } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react'; import { PersistGate } from 'redux-persist/integration/react';
import { IntlProvider } from 'react-intl'; import { IntlProvider } from 'react-intl';
import { useScreens } from 'react-native-screens'; import { useScreens } from 'react-native-screens';
import { setTopLevelNavigator } from './navigation/service';
import { flattenMessages } from './utils/flattenMessages'; import { flattenMessages } from './utils/flattenMessages';
import messages from './config/locales'; import messages from './config/locales';
@ -30,11 +29,7 @@ const App = connect(mapStateToProps)(_renderApp);
export default () => { export default () => {
return ( return (
<Provider store={store}> <Provider store={store}>
<App <App />
ref={navigatorRef => {
setTopLevelNavigator(navigatorRef);
}}
/>
</Provider> </Provider>
); );
}; };

View File

@ -52,7 +52,7 @@ const BaseNavigator = createBottomTabNavigator(
screen: Profile, screen: Profile,
navigationOptions: () => ({ navigationOptions: () => ({
tabBarIcon: ({ tintColor }) => ( tabBarIcon: ({ tintColor }) => (
<Icon iconType="MaterialIcons" name="credit-card" color={tintColor} size={26} /> <Icon iconType="MaterialIcons" name="person-outline" color={tintColor} size={26} />
), ),
}), }),
}, },

View File

@ -2,15 +2,21 @@ import { NavigationActions } from 'react-navigation';
let _navigator; let _navigator;
export const setTopLevelNavigator = navigatorRef => { const setTopLevelNavigator = navigatorRef => {
_navigator = navigatorRef; _navigator = navigatorRef;
}; };
export const navigate = (routeName, params) => { const navigate = navigationProps => {
_navigator.dispatch( _navigator.dispatch(
NavigationActions.navigate({ NavigationActions.navigate({
routeName, ...navigationProps,
params,
}), }),
); );
}; };
// add other navigation functions that you need and export them
export default {
navigate,
setTopLevelNavigator,
};

View File

@ -38,6 +38,7 @@ import {
import { getUser, getPost } from '../../../providers/steem/dsteem'; import { getUser, getPost } from '../../../providers/steem/dsteem';
import { switchAccount } from '../../../providers/steem/auth'; import { switchAccount } from '../../../providers/steem/auth';
import { setPushToken } from '../../../providers/esteem/esteem'; import { setPushToken } from '../../../providers/esteem/esteem';
import NavigationService from '../../../navigation/service';
// Actions // Actions
import { import {
@ -260,13 +261,11 @@ class ApplicationContainer extends Component {
if (routeName && (profile || content)) { if (routeName && (profile || content)) {
this.navigationTimeout = setTimeout(() => { this.navigationTimeout = setTimeout(() => {
clearTimeout(this.navigationTimeout); clearTimeout(this.navigationTimeout);
const navigateAction = NavigationActions.navigate({ NavigationService.navigate({
routeName, routeName,
params, params,
key: permlink || author, key: permlink || author,
action: NavigationActions.navigate({ routeName }),
}); });
dispatch(navigateAction);
}, 2000); }, 2000);
} }
}; };
@ -402,13 +401,11 @@ class ApplicationContainer extends Component {
} }
if (!some(params, isEmpty)) { if (!some(params, isEmpty)) {
const navigateAction = NavigationActions.navigate({ NavigationService.navigate({
routeName, routeName,
params, params,
key, key,
action: NavigationActions.navigate({ routeName }),
}); });
dispatch(navigateAction);
} }
} }
}, },

View File

@ -5,6 +5,7 @@ import { connect } from 'react-redux';
import { createAppContainer } from 'react-navigation'; import { createAppContainer } from 'react-navigation';
import AppNavitation from '../../../navigation/routes'; import AppNavitation from '../../../navigation/routes';
import NavigationService from '../../../navigation/service';
// Services // Services
import { toastNotification as toastNotificationAction } from '../../../redux/actions/uiAction'; import { toastNotification as toastNotificationAction } from '../../../redux/actions/uiAction';
@ -59,7 +60,11 @@ class ApplicationScreen extends Component {
)} )}
<Fragment> <Fragment>
{!isConnected && <NoInternetConnection />} {!isConnected && <NoInternetConnection />}
<Navigation /> <Navigation
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
</Fragment> </Fragment>
{isShowToastNotification && ( {isShowToastNotification && (

View File

@ -3,10 +3,10 @@ import { Alert } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';
import Config from 'react-native-config'; import Config from 'react-native-config';
import { NavigationActions } from 'react-navigation';
import get from 'lodash/get'; import get from 'lodash/get';
// Actions & Services // Actions & Services
import NavigationService from '../../../navigation/service';
import { import {
setUserDataWithPinCode, setUserDataWithPinCode,
verifyPinCode, verifyPinCode,
@ -111,12 +111,10 @@ class PinCodeContainer extends Component {
if (callback) callback(pin, oldPinCode); if (callback) callback(pin, oldPinCode);
dispatch(closePinCodeModal()); dispatch(closePinCodeModal());
if (navigateTo) { if (navigateTo) {
const navigateAction = NavigationActions.navigate({ NavigationService.navigate({
routeName: navigateTo, routeName: navigateTo,
params: navigateParams, params: navigateParams,
action: NavigationActions.navigate({ routeName: navigateTo }),
}); });
dispatch(navigateAction);
} }
resolve(); resolve();
}); });
@ -174,12 +172,10 @@ class PinCodeContainer extends Component {
if (callback) callback(pin, oldPinCode); if (callback) callback(pin, oldPinCode);
dispatch(closePinCodeModal()); dispatch(closePinCodeModal());
if (navigateTo) { if (navigateTo) {
const navigateAction = NavigationActions.navigate({ NavigationService.navigate({
routeName: navigateTo, routeName: navigateTo,
params: navigateParams, params: navigateParams,
action: NavigationActions.navigate({ routeName: navigateTo }),
}); });
dispatch(navigateAction);
} }
resolve(); resolve();
}); });
@ -215,12 +211,10 @@ class PinCodeContainer extends Component {
dispatch(closePinCodeModal()); dispatch(closePinCodeModal());
if (callback) callback(pin, oldPinCode); if (callback) callback(pin, oldPinCode);
if (navigateTo) { if (navigateTo) {
const navigateAction = NavigationActions.navigate({ NavigationService.navigate({
routeName: navigateTo, routeName: navigateTo,
params: navigateParams, params: navigateParams,
action: NavigationActions.navigate({ routeName: navigateTo }),
}); });
dispatch(navigateAction);
} }
}) })
.catch(err => { .catch(err => {

View File

@ -236,21 +236,23 @@ class SettingsContainer extends Component {
dispatch(changeNotificationSettings({ action, type: actionType })); dispatch(changeNotificationSettings({ action, type: actionType }));
setNotificationSettings({ action, type: actionType }); setNotificationSettings({ action, type: actionType });
if (actionType === 'notification') { Object.keys(notificationDetails).map(item => {
await Push.setEnabled(action); const notificationType = item.replace('Notification', '');
this._setPushToken(action ? [1, 2, 3, 4, 5, 6] : notifyTypes);
} else {
Object.keys(notificationDetails).map(item => {
const notificationType = item.replace('Notification', '');
if (notificationType === actionType.replace('notification.', '')) { if (notificationType === actionType.replace('notification.', '')) {
if (action) { if (action) {
notifyTypes.push(notifyTypesConst[notificationType]);
}
} else if (notificationDetails[item]) {
notifyTypes.push(notifyTypesConst[notificationType]); notifyTypes.push(notifyTypesConst[notificationType]);
} }
}); } else if (notificationDetails[item]) {
notifyTypes.push(notifyTypesConst[notificationType]);
}
});
notifyTypes.sort();
if (actionType === 'notification') {
await Push.setEnabled(action);
this._setPushToken(action ? notifyTypes : []);
} else {
this._setPushToken(notifyTypes); this._setPushToken(notifyTypes);
} }
}; };
@ -286,21 +288,25 @@ class SettingsContainer extends Component {
}; };
_setPushToken = async notifyTypes => { _setPushToken = async notifyTypes => {
const { isNotificationSettingsOpen, isLoggedIn, username } = this.props; const { isLoggedIn, otherAccounts = [] } = this.props;
if (isLoggedIn) { if (isLoggedIn) {
const token = await AppCenter.getInstallId(); const token = await AppCenter.getInstallId();
getExistUser().then(isExistUser => { getExistUser().then(isExistUser => {
if (isExistUser) { if (isExistUser) {
const data = { otherAccounts.forEach(item => {
username, const { isNotificationSettingsOpen } = this.props;
token,
system: Platform.OS, const data = {
allows_notify: Number(isNotificationSettingsOpen), username: item.username,
notify_types: notifyTypes, token,
}; system: Platform.OS,
setPushToken(data); allows_notify: Number(isNotificationSettingsOpen),
notify_types: notifyTypes,
};
setPushToken(data);
});
} }
}); });
} }
@ -401,6 +407,7 @@ const mapStateToProps = state => ({
username: state.account.currentAccount && state.account.currentAccount.name, username: state.account.currentAccount && state.account.currentAccount.name,
currentAccount: state.account.currentAccount, currentAccount: state.account.currentAccount,
otherAccounts: state.account.otherAccounts,
}); });
export default injectIntl(connect(mapStateToProps)(SettingsContainer)); export default injectIntl(connect(mapStateToProps)(SettingsContainer));

View File

@ -31,10 +31,10 @@ class TransferView extends Component {
super(props); super(props);
this.state = { this.state = {
from: props.currentAccountName, from: props.currentAccountName,
destination: '', destination: props.transferType === 'powerUp' ? props.currentAccountName : '',
amount: '', amount: '',
memo: '', memo: '',
isUsernameValid: false, isUsernameValid: props.transferType === 'powerUp' && props.currentAccountName ? true : false,
steemConnectTransfer: false, steemConnectTransfer: false,
isTransfering: false, isTransfering: false,
}; };
@ -217,22 +217,26 @@ class TransferView extends Component {
</TouchableOpacity> </TouchableOpacity>
)} )}
/> />
<TransferFormItem {transferType !== 'powerUp' && (
label={intl.formatMessage({ id: 'transfer.memo' })} <TransferFormItem
rightComponent={() => label={intl.formatMessage({ id: 'transfer.memo' })}
this._renderInput( rightComponent={() =>
intl.formatMessage({ id: 'transfer.memo_placeholder' }), this._renderInput({
'memo', placeholder: intl.formatMessage({ id: 'transfer.memo_placeholder' }),
'default', state: 'memo',
true, keyboardType: 'default',
) isTextArea: true,
} })
/> }
<TransferFormItem />
rightComponent={() => )}
this._renderDescription(intl.formatMessage({ id: 'transfer.memo_desc' })) {transferType !== 'powerUp' && (
} <TransferFormItem
/> rightComponent={() =>
this._renderDescription(intl.formatMessage({ id: 'transfer.memo_desc' }))
}
/>
)}
</View> </View>
<View style={styles.bottomContent}> <View style={styles.bottomContent}>
<MainButton <MainButton