mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-19 11:21:41 +03:00
Merged with development
This commit is contained in:
parent
80512a8a02
commit
d1e08e92f1
@ -277,6 +277,8 @@ PODS:
|
||||
- React-cxxreact (= 0.61.2)
|
||||
- React-jsi (= 0.61.2)
|
||||
- ReactCommon/jscallinvoker (= 0.61.2)
|
||||
- ReactNativeDarkMode (0.1.2):
|
||||
- React
|
||||
- RNGestureHandler (1.4.1):
|
||||
- React
|
||||
- RNIap (3.4.15):
|
||||
@ -341,6 +343,7 @@ DEPENDENCIES:
|
||||
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
|
||||
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- ReactNativeDarkMode (from `../node_modules/react-native-dark-mode`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNIap (from `../node_modules/react-native-iap`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
@ -351,7 +354,7 @@ DEPENDENCIES:
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
- AppCenter
|
||||
- AppCenterReactNativeShared
|
||||
- boost-for-react-native
|
||||
@ -433,6 +436,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/Libraries/Vibration"
|
||||
ReactCommon:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
ReactNativeDarkMode:
|
||||
:path: "../node_modules/react-native-dark-mode"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNIap:
|
||||
@ -492,6 +497,7 @@ SPEC CHECKSUMS:
|
||||
React-RCTText: e3ef6191cdb627855ff7fe8fa0c1e14094967fb8
|
||||
React-RCTVibration: fb54c732fd20405a76598e431aa2f8c2bf527de9
|
||||
ReactCommon: 5848032ed2f274fcb40f6b9ec24067787c42d479
|
||||
ReactNativeDarkMode: 315535c6f7a066bc4e8ba60591a63aafa16d5dca
|
||||
RNGestureHandler: 4cb47a93019c1a201df2644413a0a1569a51c8aa
|
||||
RNIap: b4c77c8bc4501203f4b743126a05da23f10f40b4
|
||||
RNImageCropPicker: bfb3ea9c8622f290532e2fe63f369e0d5a52f597
|
||||
@ -505,4 +511,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 4faf3202c73803d0ba69b4aaf79ce8642ecf11b2
|
||||
|
||||
COCOAPODS: 1.7.5
|
||||
COCOAPODS: 1.8.3
|
||||
|
Binary file not shown.
@ -49,6 +49,7 @@
|
||||
"react-native-autocomplete-input": "^4.1.0",
|
||||
"react-native-code-push": "esteemapp/react-native-code-push",
|
||||
"react-native-config": "luggit/react-native-config#master",
|
||||
"react-native-dark-mode": "^0.1.2",
|
||||
"react-native-datepicker": "^1.7.2",
|
||||
"react-native-extended-stylesheet": "^0.10.0",
|
||||
"react-native-fast-image": "^4.0.14",
|
||||
|
@ -1,34 +1,38 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { View } from 'react-native';
|
||||
import Placeholder from 'rn-placeholder';
|
||||
|
||||
import { ThemeContainer } from '../../../../containers';
|
||||
|
||||
import styles from './listItemPlaceHolderStyles';
|
||||
|
||||
const ListItemPlaceHolderView = ({ isDarkTheme }) => {
|
||||
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
||||
|
||||
const ListItemPlaceHolderView = () => {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Placeholder.Media size={30} hasRadius animate="fade" color={color} />
|
||||
<View style={styles.paragraphWrapper}>
|
||||
<Placeholder.Paragraph
|
||||
color={color}
|
||||
lineNumber={2}
|
||||
textSize={12}
|
||||
lineSpacing={8}
|
||||
width="100%"
|
||||
lastLineWidth="70%"
|
||||
firstLineWidth="50%"
|
||||
animate="fade"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<ThemeContainer>
|
||||
{({ isDarkTheme }) => (
|
||||
<View style={styles.container}>
|
||||
<Placeholder.Media
|
||||
size={30}
|
||||
hasRadius
|
||||
animate="fade"
|
||||
color={isDarkTheme ? '#2e3d51' : '#f5f5f5'}
|
||||
/>
|
||||
<View style={styles.paragraphWrapper}>
|
||||
<Placeholder.Paragraph
|
||||
color={isDarkTheme ? '#2e3d51' : '#f5f5f5'}
|
||||
lineNumber={2}
|
||||
textSize={12}
|
||||
lineSpacing={8}
|
||||
width="100%"
|
||||
lastLineWidth="70%"
|
||||
firstLineWidth="50%"
|
||||
animate="fade"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
</ThemeContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ListItemPlaceHolderView);
|
||||
export default ListItemPlaceHolderView;
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* eslint-disable radix */
|
||||
import React, { Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dimensions } from 'react-native';
|
||||
import times from 'lodash/times';
|
||||
|
||||
@ -18,9 +17,4 @@ const ListPlaceHolderView = () => {
|
||||
|
||||
return <Fragment>{listElements}</Fragment>;
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ListPlaceHolderView);
|
||||
export default ListPlaceHolderView;
|
||||
|
@ -9,6 +9,9 @@ import { updateActiveBottomTab } from '../../../redux/actions/uiAction';
|
||||
// Constants
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
// Container
|
||||
import { DarkThemeContainer } from '../../../containers';
|
||||
|
||||
// Components
|
||||
import TabBar from './tabbar';
|
||||
|
||||
@ -38,36 +41,40 @@ const BottomTabBarView = ({
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(updateActiveBottomTab(routes[index].routeName));
|
||||
}, [dispatch, routes, index]);
|
||||
}, [dispatch, index, routes]);
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.wrapper}>
|
||||
<TabBar
|
||||
selectedIndex={index}
|
||||
circleBackgroundColor="#357ce6"
|
||||
backgroundColor="#f6f6f6"
|
||||
onChange={i => _jumpTo(routes[i], index, routes, jumpTo)}
|
||||
activeTintColor={activeTintColor}
|
||||
inactiveTintColor={inactiveTintColor}
|
||||
>
|
||||
{routes.map(route => (
|
||||
<TabBar.Item
|
||||
icon={renderIcon({
|
||||
route,
|
||||
focused: false,
|
||||
tintColor: inactiveTintColor,
|
||||
})}
|
||||
selectedIcon={renderIcon({
|
||||
route,
|
||||
focused: true,
|
||||
tintColor: activeTintColor,
|
||||
})}
|
||||
key={route}
|
||||
disabled={route.routeName === ROUTES.TABBAR.POST_BUTTON}
|
||||
/>
|
||||
))}
|
||||
</TabBar>
|
||||
</SafeAreaView>
|
||||
<DarkThemeContainer>
|
||||
{({ isDarkTheme }) => (
|
||||
<SafeAreaView style={styles.wrapper}>
|
||||
<TabBar
|
||||
selectedIndex={index}
|
||||
circleBackgroundColor="#357ce6"
|
||||
backgroundColor={isDarkTheme ? '#2e3d51' : '#f6f6f6'}
|
||||
onChange={i => _jumpTo(routes[i], index, routes, jumpTo)}
|
||||
activeTintColor={activeTintColor}
|
||||
inactiveTintColor={inactiveTintColor}
|
||||
>
|
||||
{routes.map(route => (
|
||||
<TabBar.Item
|
||||
icon={renderIcon({
|
||||
route,
|
||||
focused: false,
|
||||
tintColor: inactiveTintColor,
|
||||
})}
|
||||
selectedIcon={renderIcon({
|
||||
route,
|
||||
focused: true,
|
||||
tintColor: activeTintColor,
|
||||
})}
|
||||
key={route}
|
||||
disabled={route.routeName === ROUTES.TABBAR.POST_BUTTON}
|
||||
/>
|
||||
))}
|
||||
</TabBar>
|
||||
</SafeAreaView>
|
||||
)}
|
||||
</DarkThemeContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,6 @@ export default class TabBar extends Component {
|
||||
circleRadius: new Animated.Value(91 + selectedIndex * value),
|
||||
pathD: new Animated.Value(selectedIndex * value),
|
||||
pathX: selectedIndex * value,
|
||||
showIcon: true,
|
||||
animateConstant: value,
|
||||
};
|
||||
|
||||
@ -72,15 +71,16 @@ export default class TabBar extends Component {
|
||||
_move = index => {
|
||||
const { animateConstant, pathD, circleRadius } = this.state;
|
||||
|
||||
this.setState({
|
||||
selectedIndex: index,
|
||||
showIcon: false,
|
||||
});
|
||||
this.setState({ selectedIndex: '' });
|
||||
|
||||
Animated.timing(pathD, {
|
||||
toValue: 0 + index * animateConstant,
|
||||
duration: 450,
|
||||
}).start(() => this.setState({ showIcon: true }));
|
||||
}).start(() => {
|
||||
setTimeout(() => {
|
||||
this.setState({ selectedIndex: index });
|
||||
}, 350);
|
||||
});
|
||||
Animated.timing(circleRadius, {
|
||||
toValue: 91 + index * animateConstant,
|
||||
}).start();
|
||||
@ -88,20 +88,19 @@ export default class TabBar extends Component {
|
||||
|
||||
render() {
|
||||
const { children, backgroundColor, circleBackgroundColor, style } = this.props;
|
||||
const { selectedIndex, showIcon, pathX, circleRadius } = this.state;
|
||||
const { selectedIndex, pathX, circleRadius } = this.state;
|
||||
|
||||
return (
|
||||
<View style={style}>
|
||||
<View style={styles.subContent}>
|
||||
{children.map((route, i) => {
|
||||
const element = React.cloneElement(route, {
|
||||
return React.cloneElement(route, {
|
||||
selected: selectedIndex === i,
|
||||
onPress: this._onPress,
|
||||
key: i,
|
||||
index: i,
|
||||
showIcon,
|
||||
showIcon: true,
|
||||
});
|
||||
return element;
|
||||
})}
|
||||
</View>
|
||||
|
||||
@ -148,8 +147,10 @@ const TabBarItem = ({ icon, selectedIcon, index, selected, onPress, showIcon, di
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
|
||||
return <View style={styles.navItem} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableHighlight
|
||||
underlayColor={'transparent'}
|
||||
|
@ -13,6 +13,8 @@ import { PostBody } from '../../postElements';
|
||||
import { StickyBar } from '../../basicUIElements';
|
||||
import { TextInput } from '../../textInput';
|
||||
|
||||
import { ThemeContainer } from '../../../containers';
|
||||
|
||||
// Styles
|
||||
import styles from './markdownEditorStyles';
|
||||
|
||||
@ -204,22 +206,26 @@ const MarkdownEditorView = ({
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : null}
|
||||
>
|
||||
{!isPreviewActive ? (
|
||||
<TextInput
|
||||
multiline
|
||||
onChangeText={_changeText}
|
||||
onSelectionChange={_handleOnSelectionChange}
|
||||
placeholder={intl.formatMessage({
|
||||
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
|
||||
})}
|
||||
placeholderTextColor="#c1c5c7"
|
||||
selection={_getSelection()}
|
||||
selectionColor="#357ce6"
|
||||
style={styles.textWrapper}
|
||||
underlineColorAndroid="transparent"
|
||||
value={text}
|
||||
innerRef={inputRef}
|
||||
editable={!isLoading}
|
||||
/>
|
||||
<ThemeContainer>
|
||||
{({ isDarkTheme }) => (
|
||||
<TextInput
|
||||
multiline
|
||||
onChangeText={_changeText}
|
||||
onSelectionChange={_handleOnSelectionChange}
|
||||
placeholder={intl.formatMessage({
|
||||
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
|
||||
})}
|
||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||
selection={_getSelection()}
|
||||
selectionColor="#357ce6"
|
||||
style={styles.textWrapper}
|
||||
underlineColorAndroid="transparent"
|
||||
value={text}
|
||||
innerRef={inputRef}
|
||||
editable={!isLoading}
|
||||
/>
|
||||
)}
|
||||
</ThemeContainer>
|
||||
) : (
|
||||
_renderPreview()
|
||||
)}
|
||||
|
@ -5,13 +5,14 @@ import get from 'lodash/get';
|
||||
|
||||
// Services and Actions
|
||||
import { search } from '../../../providers/esteem/esteem';
|
||||
import { lookupAccounts, getTrendingTags } from '../../../providers/steem/dsteem';
|
||||
import { lookupAccounts, getTrendingTags, getPurePost } from '../../../providers/steem/dsteem';
|
||||
|
||||
// Constants
|
||||
import { default as ROUTES } from '../../../constants/routeNames';
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
// Utilities
|
||||
import { getResizedAvatar } from '../../../utils/image';
|
||||
import postUrlParser from '../../../utils/postUrlParser';
|
||||
|
||||
// Component
|
||||
import SearchModalView from '../view/searchModalView';
|
||||
@ -41,31 +42,67 @@ class SearchModalContainer extends PureComponent {
|
||||
|
||||
_handleOnChangeSearchInput = text => {
|
||||
const { isConnected } = this.props;
|
||||
|
||||
if (text && text.length < 2) return;
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
if (!isConnected) return;
|
||||
this.timer = setTimeout(() => {
|
||||
if (text && text !== '@' && text !== '#') {
|
||||
if (text[0] === '@') {
|
||||
lookupAccounts(text.substr(1)).then(res => {
|
||||
const users = res.map(item => ({
|
||||
image: getResizedAvatar(item),
|
||||
text: item,
|
||||
...item,
|
||||
}));
|
||||
this.setState({ searchResults: { type: 'user', data: users } });
|
||||
});
|
||||
} else if (text[0] === '#') {
|
||||
getTrendingTags(text.substr(1)).then(res => {
|
||||
const tags = res.map(item => ({
|
||||
text: `#${get(item, 'name', '')}`,
|
||||
...item,
|
||||
}));
|
||||
if (text && text !== '@' && text !== '#') {
|
||||
if (text[0] === '@') {
|
||||
lookupAccounts(text.substr(1)).then(res => {
|
||||
const users = res.map(item => ({
|
||||
image: getResizedAvatar(item),
|
||||
text: item,
|
||||
...item,
|
||||
}));
|
||||
this.setState({ searchResults: { type: 'user', data: users } });
|
||||
});
|
||||
} else if (text[0] === '#') {
|
||||
getTrendingTags(text.substr(1)).then(res => {
|
||||
const tags = res.map(item => ({
|
||||
text: `#${get(item, 'name', '')}`,
|
||||
...item,
|
||||
}));
|
||||
|
||||
this.setState({ searchResults: { type: 'tag', data: tags } });
|
||||
});
|
||||
this.setState({ searchResults: { type: 'tag', data: tags } });
|
||||
});
|
||||
} else if (text.includes('https')) {
|
||||
const postUrl = postUrlParser(text.replace(/\s/g, ''));
|
||||
|
||||
if (postUrl) {
|
||||
const { author, permlink } = postUrl;
|
||||
|
||||
if (author) {
|
||||
if (permlink) {
|
||||
getPurePost(author, permlink).then(post => {
|
||||
if (post.id !== 0) {
|
||||
const result = {};
|
||||
const metadata = JSON.parse(get(post, 'json_metadata', ''));
|
||||
if (get(metadata, 'image', false) && metadata.image.length > 0) {
|
||||
result.image = metadata.image[0];
|
||||
} else {
|
||||
result.image = getResizedAvatar(author);
|
||||
}
|
||||
result.author = author;
|
||||
result.text = post.title;
|
||||
result.permlink = permlink;
|
||||
this.setState({ searchResults: { type: 'content', data: [result] } });
|
||||
} else {
|
||||
this.setState({ searchResults: { type: 'content', data: [] } });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
lookupAccounts(author).then(res => {
|
||||
const users = res.map(item => ({
|
||||
image: getResizedAvatar(item),
|
||||
text: item,
|
||||
...item,
|
||||
}));
|
||||
this.setState({ searchResults: { type: 'user', data: users } });
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
search({ q: text }).then(res => {
|
||||
res.results = res.results
|
||||
@ -79,7 +116,7 @@ class SearchModalContainer extends PureComponent {
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnPressListItem = (type, item) => {
|
||||
|
@ -1,36 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
|
||||
// Constants
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
// Component
|
||||
import VotersDisplayView from '../view/votersDisplayView';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
*@props --> props name here description here Value Type Here
|
||||
*
|
||||
*/
|
||||
|
||||
class VotersDisplayContainer extends Component {
|
||||
_handleOnUserPress = username => {
|
||||
const { navigation } = this.props;
|
||||
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.PROFILE,
|
||||
params: {
|
||||
username,
|
||||
},
|
||||
key: username,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { votes } = this.props;
|
||||
|
||||
return <VotersDisplayView handleOnUserPress={this._handleOnUserPress} votes={votes} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default withNavigation(VotersDisplayContainer);
|
@ -1,5 +1,4 @@
|
||||
import VotersDisplayView from './view/votersDisplayView';
|
||||
import VotersDisplay from './container/votersDisplayContainer';
|
||||
import VotersDisplay from './view/votersDisplayView';
|
||||
|
||||
export { VotersDisplay, VotersDisplayView };
|
||||
export { VotersDisplay };
|
||||
export default VotersDisplay;
|
||||
|
@ -2,6 +2,7 @@ import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
padding: 8,
|
||||
flexDirection: 'row',
|
||||
height: '$deviceHeight - 150',
|
||||
|
@ -1,27 +1,37 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View, FlatList, Text } from 'react-native';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import React from 'react';
|
||||
import { SafeAreaView, FlatList, Text } from 'react-native';
|
||||
import { withNavigation } from 'react-navigation';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Utils
|
||||
import { getTimeFromNow } from '../../../utils/time';
|
||||
|
||||
// Components
|
||||
import { UserListItem } from '../../basicUIElements';
|
||||
|
||||
// Constants
|
||||
import ROUTES from '../../../constants/routeNames';
|
||||
|
||||
// Styles
|
||||
import styles from './votersDisplayStyles';
|
||||
|
||||
class VotersDisplayView extends Component {
|
||||
/* Props
|
||||
* ------------------------------------------------
|
||||
* @prop { type } name - Description....
|
||||
*/
|
||||
const VotersDisplayView = ({ votes, navigation }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
// Component Functions
|
||||
_renderItem = (item, index) => {
|
||||
const { handleOnUserPress } = this.props;
|
||||
const _handleOnUserPress = username => {
|
||||
navigation.navigate({
|
||||
routeName: ROUTES.SCREENS.PROFILE,
|
||||
params: {
|
||||
username,
|
||||
},
|
||||
key: username,
|
||||
});
|
||||
};
|
||||
|
||||
const _renderItem = (item, index) => {
|
||||
const value = `$ ${item.value}`;
|
||||
const percent = `${item.percent}%`;
|
||||
|
||||
console.log(item);
|
||||
return (
|
||||
<UserListItem
|
||||
index={index}
|
||||
@ -30,35 +40,31 @@ class VotersDisplayView extends Component {
|
||||
isHasRightItem
|
||||
isRightColor={item.is_down_vote}
|
||||
rightText={value}
|
||||
handleOnPress={() => handleOnUserPress(item.voter)}
|
||||
handleOnPress={() => _handleOnUserPress(item.voter)}
|
||||
isClickable
|
||||
subRightText={percent}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { votes, intl } = this.props;
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
{votes && votes.length > 0 ? (
|
||||
<FlatList
|
||||
data={votes}
|
||||
keyExtractor={item => item.voter}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={({ item, index }) => _renderItem(item, index)}
|
||||
/>
|
||||
) : (
|
||||
<Text style={styles.text}>
|
||||
{intl.formatMessage({
|
||||
id: 'voters.no_user',
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{votes.length > 0 ? (
|
||||
<FlatList
|
||||
data={votes}
|
||||
keyExtractor={item => item.voter}
|
||||
removeClippedSubviews={false}
|
||||
renderItem={({ item, index }) => this._renderItem(item, index)}
|
||||
/>
|
||||
) : (
|
||||
<Text style={styles.text}>
|
||||
{intl.formatMessage({
|
||||
id: 'voters.no_user',
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(VotersDisplayView);
|
||||
export default withNavigation(VotersDisplayView);
|
||||
|
14
src/containers/darkThemeContainer.js
Normal file
14
src/containers/darkThemeContainer.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { React } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const DarkThemeContainer = ({ children, isDarkTheme }) =>
|
||||
children &&
|
||||
children({
|
||||
isDarkTheme,
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(DarkThemeContainer);
|
@ -1,3 +1,4 @@
|
||||
import DarkThemeContainer from './darkThemeContainer';
|
||||
import InAppPurchaseContainer from './inAppPurchaseContainer';
|
||||
import PointsContainer from './pointsContainer';
|
||||
import ProfileContainer from './profileContainer';
|
||||
@ -5,8 +6,10 @@ import ProfileEditContainer from './profileEditContainer';
|
||||
import RedeemContainer from './redeemContainer';
|
||||
import SpinGameContainer from './spinGameContainer';
|
||||
import TransferContainer from './transferContainer';
|
||||
import ThemeContainer from './themeContainer';
|
||||
|
||||
export {
|
||||
DarkThemeContainer,
|
||||
InAppPurchaseContainer,
|
||||
PointsContainer,
|
||||
ProfileContainer,
|
||||
@ -14,4 +17,5 @@ export {
|
||||
RedeemContainer,
|
||||
SpinGameContainer,
|
||||
TransferContainer,
|
||||
ThemeContainer,
|
||||
};
|
||||
|
@ -140,7 +140,6 @@ class RedeemContainer extends Component {
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
username: state.account.currentAccount.name,
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
activeBottomTab: state.ui.activeBottomTab,
|
||||
isConnected: state.application.isConnected,
|
||||
accounts: state.account.otherAccounts,
|
||||
|
18
src/containers/themeContainer.js
Normal file
18
src/containers/themeContainer.js
Normal file
@ -0,0 +1,18 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
const ThemeContainer = ({ children, isDarkTheme }) => {
|
||||
return (
|
||||
children &&
|
||||
children({
|
||||
isDarkTheme,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ThemeContainer);
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable curly */
|
||||
import { Component } from 'react';
|
||||
import { Platform, BackHandler, Alert, Linking, AppState } from 'react-native';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
@ -12,6 +13,10 @@ import { NavigationActions } from 'react-navigation';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
import { forEach, isEmpty, some } from 'lodash';
|
||||
import {
|
||||
initialMode as nativeThemeInitialMode,
|
||||
eventEmitter as nativeThemeEventEmitter,
|
||||
} from 'react-native-dark-mode';
|
||||
|
||||
// Constants
|
||||
import AUTH_TYPE from '../../../constants/authType';
|
||||
@ -96,7 +101,6 @@ class ApplicationContainer extends Component {
|
||||
|
||||
componentDidMount = () => {
|
||||
const { isIos } = this.state;
|
||||
|
||||
this._setNetworkListener();
|
||||
|
||||
if (!isIos) BackHandler.addEventListener('hardwareBackPress', this._onBackPress);
|
||||
@ -111,6 +115,14 @@ class ApplicationContainer extends Component {
|
||||
setPreviousAppState();
|
||||
|
||||
this._createPushListener();
|
||||
|
||||
if (nativeThemeEventEmitter) {
|
||||
nativeThemeEventEmitter.on('currentModeChanged', newMode => {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(isDarkTheme(newMode === 'dark'));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
@ -527,7 +539,7 @@ class ApplicationContainer extends Component {
|
||||
const settings = await getSettings();
|
||||
|
||||
if (settings) {
|
||||
if (settings.isDarkTheme !== '') dispatch(isDarkTheme(settings.isDarkTheme));
|
||||
dispatch(isDarkTheme(nativeThemeInitialMode === 'dark' || settings.isDarkTheme));
|
||||
if (settings.isPinCodeOpen !== '') dispatch(isPinCodeOpen(settings.isPinCodeOpen));
|
||||
if (settings.language !== '') dispatch(setLanguage(settings.language));
|
||||
if (settings.server !== '') dispatch(setApi(settings.server));
|
||||
|
@ -151,13 +151,12 @@ class NotificationContainer extends Component {
|
||||
|
||||
render() {
|
||||
const { isLoggedIn } = this.props;
|
||||
const { notifications, isNotificationRefreshing, isDarkTheme } = this.state;
|
||||
const { notifications, isNotificationRefreshing } = this.state;
|
||||
|
||||
return (
|
||||
<NotificationScreen
|
||||
getActivities={this._getAvtivities}
|
||||
notifications={notifications}
|
||||
isDarkTheme={isDarkTheme}
|
||||
navigateToNotificationRoute={this._navigateToNotificationRoute}
|
||||
readAllNotification={this._readAllNotification}
|
||||
handleLoginPress={this._handleOnPressLogin}
|
||||
@ -171,7 +170,6 @@ class NotificationContainer extends Component {
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isLoggedIn: state.application.isLoggedIn,
|
||||
isDarkTheme: state.application.isDarkTheme,
|
||||
isConnected: state.application.isConnected,
|
||||
|
||||
username: state.account.currentAccount.name,
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import { View, FlatList } from 'react-native';
|
||||
import { View, FlatList, SafeAreaView } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Constants
|
||||
import get from 'lodash/get';
|
||||
|
||||
// Components
|
||||
import { BasicHeader, UserListItem } from '../../../components';
|
||||
|
||||
// Container
|
||||
import AccountListContainer from '../../../containers/accountListContainer';
|
||||
|
||||
// Utils
|
||||
@ -31,13 +31,12 @@ const ReblogScreen = ({ navigation }) => {
|
||||
id: 'reblog.title',
|
||||
});
|
||||
|
||||
const activeVotes =
|
||||
navigation.state && navigation.state.params && navigation.state.params.reblogs;
|
||||
const activeVotes = get(navigation, 'state.params.reblogs');
|
||||
|
||||
return (
|
||||
<AccountListContainer data={activeVotes} navigation={navigation}>
|
||||
{({ data, filterResult, handleSearch, handleOnUserPress }) => (
|
||||
<View style={globalStyles.container}>
|
||||
<SafeAreaView style={globalStyles.container}>
|
||||
<BasicHeader
|
||||
title={`${headerTitle} (${data && data.length})`}
|
||||
isHasSearch
|
||||
@ -49,7 +48,7 @@ const ReblogScreen = ({ navigation }) => {
|
||||
removeClippedSubviews={false}
|
||||
renderItem={({ item, index }) => renderUserListItem(item, index, handleOnUserPress)}
|
||||
/>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)}
|
||||
</AccountListContainer>
|
||||
);
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
// Constants
|
||||
import get from 'lodash/get';
|
||||
|
||||
// Components
|
||||
import { BasicHeader, FilterBar, VotersDisplay } from '../../../components';
|
||||
@ -20,13 +19,12 @@ const VotersScreen = ({ navigation }) => {
|
||||
id: 'voters.voters_info',
|
||||
});
|
||||
|
||||
const activeVotes =
|
||||
navigation.state && navigation.state.params && navigation.state.params.activeVotes;
|
||||
const activeVotes = get(navigation, 'state.params.activeVotes');
|
||||
|
||||
return (
|
||||
<AccountListContainer data={activeVotes}>
|
||||
{({ data, filterResult, handleOnVotersDropdownSelect, handleSearch }) => (
|
||||
<View style={globalStyles.container}>
|
||||
<SafeAreaView style={globalStyles.container}>
|
||||
<BasicHeader
|
||||
title={`${headerTitle} (${data && data.length})`}
|
||||
isHasSearch
|
||||
@ -43,7 +41,7 @@ const VotersScreen = ({ navigation }) => {
|
||||
onDropdownSelect={handleOnVotersDropdownSelect}
|
||||
/>
|
||||
<VotersDisplay votes={filterResult || data} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
)}
|
||||
</AccountListContainer>
|
||||
);
|
||||
|
75
src/utils/postUrlParser.js
Normal file
75
src/utils/postUrlParser.js
Normal file
@ -0,0 +1,75 @@
|
||||
export default url => {
|
||||
const parseCatAuthorPermlink = u => {
|
||||
const postRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
|
||||
const postMatch = u.match(postRegex);
|
||||
if (postMatch && postMatch.length === 5) {
|
||||
return {
|
||||
author: postMatch[3].replace('@', ''),
|
||||
permlink: postMatch[4],
|
||||
};
|
||||
}
|
||||
const authorRegex = /^https?:\/\/(.*)\/(.*)\/(@[\w.\d-]+)/i;
|
||||
const authorMatch = u.match(authorRegex);
|
||||
if (authorMatch && authorMatch.length === 4) {
|
||||
return {
|
||||
author: authorMatch[3].replace('@', ''),
|
||||
permlink: null,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const parseAuthorPermlink = u => {
|
||||
const r = /^https?:\/\/(.*)\/(@[\w.\d-]+)\/(.*)/i;
|
||||
const match = u.match(r);
|
||||
if (match && match.length === 4) {
|
||||
return {
|
||||
author: match[2].replace('@', ''),
|
||||
permlink: match[3],
|
||||
};
|
||||
}
|
||||
const authorRegex = /^https?:\/\/(.*)\/(@[\w.\d-]+)/i;
|
||||
const authorMatch = u.match(authorRegex);
|
||||
if (authorMatch && authorMatch.length === 3) {
|
||||
return {
|
||||
author: authorMatch[2].replace('@', ''),
|
||||
permlink: null,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
if (
|
||||
['https://esteem.app', 'https://steemit.com', 'https://steempeak.com'].some(x =>
|
||||
url.startsWith(x),
|
||||
)
|
||||
) {
|
||||
return parseCatAuthorPermlink(url);
|
||||
}
|
||||
|
||||
if (['https://busy.org', 'https://steemhunt.com'].some(x => url.startsWith(x))) {
|
||||
return parseAuthorPermlink(url);
|
||||
}
|
||||
|
||||
// For non urls like @good-karma/esteem-london-presentation-e3105ba6637ed
|
||||
let match = url.match(/^[/]?(@[\w.\d-]+)\/(.*)/);
|
||||
if (match && match.length === 3) {
|
||||
return {
|
||||
author: match[1].replace('@', ''),
|
||||
permlink: match[2],
|
||||
};
|
||||
}
|
||||
|
||||
// For non urls with category like esteem/@good-karma/esteem-london-presentation-e3105ba6637ed
|
||||
match = url.match(/^[/]?([\w.\d-]+)\/(@[\w.\d-]+)\/(.*)/);
|
||||
if (match && match.length === 4) {
|
||||
return {
|
||||
category: match[1],
|
||||
author: match[2].replace('@', ''),
|
||||
permlink: match[3],
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
34
yarn.lock
34
yarn.lock
@ -1476,6 +1476,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
|
||||
|
||||
"@types/events@*":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
|
||||
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
|
||||
|
||||
"@types/hoist-non-react-statics@^3.3.1":
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
|
||||
@ -1519,6 +1524,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
|
||||
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
|
||||
|
||||
"@types/react-native@*":
|
||||
version "0.60.21"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.60.21.tgz#81a41cae7b232f52ab3983d854f4a0b0df79531e"
|
||||
integrity sha512-E7F+P/UG4Utu+kh8Hy544i0m4CzpHw1awNX6hVfkhlu4mXSlAn6KLZzKEkPBbHm7g1kspmZTiuP23HAKZpASPw==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*":
|
||||
version "16.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.5.tgz#079dabd918b19b32118c25fd00a786bb6d0d5e51"
|
||||
@ -3854,6 +3867,11 @@ events@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
|
||||
integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
|
||||
|
||||
events@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
|
||||
integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==
|
||||
|
||||
evp_bytestokey@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
|
||||
@ -7669,6 +7687,17 @@ react-native-config@luggit/react-native-config#master:
|
||||
version "0.11.7"
|
||||
resolved "https://codeload.github.com/luggit/react-native-config/tar.gz/89a602bf8be3808838403a97afaf915caeec76c2"
|
||||
|
||||
react-native-dark-mode@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/react-native-dark-mode/-/react-native-dark-mode-0.1.2.tgz#4afd760073d5eb02bb83fc09004733d036e9f2d8"
|
||||
integrity sha512-oCanZ5LBJvhmgNCG2uPtvKRfBZ85nBCz/2UHkizXDt3t7ep1Vp994REye/RkIW86bbpPH/Dt8QUHExw5R0ftpg==
|
||||
dependencies:
|
||||
"@types/events" "*"
|
||||
"@types/react" "*"
|
||||
"@types/react-native" "*"
|
||||
events "^3.0.0"
|
||||
toolkit.ts "^0.0.2"
|
||||
|
||||
react-native-datepicker@^1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/react-native-datepicker/-/react-native-datepicker-1.7.2.tgz#58d0822591a0ac9b32aba082650222a0ee29669d"
|
||||
@ -9325,6 +9354,11 @@ toidentifier@1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||
|
||||
toolkit.ts@^0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/toolkit.ts/-/toolkit.ts-0.0.2.tgz#91bde730e5e6ad1a22146cdaf83f4a52721cf3b2"
|
||||
integrity sha512-yJJTVbCwiD6AfFgReewJCGJuODmyZUeL1sDjnxp33t0UBxnezgQrLbz/F9++RC28CTlk5u5pVji4TbeondYEkw==
|
||||
|
||||
tough-cookie@^2.3.3, tough-cookie@^2.3.4:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||
|
Loading…
Reference in New Issue
Block a user