mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-11-22 05:42:33 +03:00
initial lint --no-verify
This commit is contained in:
parent
c3bcb44762
commit
c4fca1e793
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -12,5 +12,6 @@
|
|||||||
},
|
},
|
||||||
"workbench.colorCustomizations": {
|
"workbench.colorCustomizations": {
|
||||||
"editorUnnecessaryCode.border": "#dd7aab"
|
"editorUnnecessaryCode.border": "#dd7aab"
|
||||||
}
|
},
|
||||||
|
"java.compile.nullAnalysis.mode": "automatic"
|
||||||
}
|
}
|
@ -2,80 +2,77 @@ import { TextStyle, StyleSheet, ViewStyle, ImageStyle } from 'react-native';
|
|||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
|
||||||
export default EStyleSheet.create({
|
export default EStyleSheet.create({
|
||||||
modalStyle: {
|
modalStyle: {
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
margin:0,
|
margin: 0,
|
||||||
paddingTop:32,
|
paddingTop: 32,
|
||||||
paddingBottom:8,
|
paddingBottom: 8,
|
||||||
},
|
},
|
||||||
|
|
||||||
sheetContent: {
|
sheetContent: {
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
position:'absolute',
|
position: 'absolute',
|
||||||
bottom:0,
|
bottom: 0,
|
||||||
left:0,
|
left: 0,
|
||||||
right:0,
|
right: 0,
|
||||||
zIndex:999
|
zIndex: 999,
|
||||||
},
|
},
|
||||||
|
|
||||||
container:{
|
container: {
|
||||||
marginTop:16,
|
marginTop: 16,
|
||||||
marginBottom:36,
|
marginBottom: 36,
|
||||||
paddingHorizontal:24,
|
paddingHorizontal: 24,
|
||||||
alignItems:'center',
|
alignItems: 'center',
|
||||||
justifyContent:'space-between',
|
justifyContent: 'space-between',
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
imageStyle:{
|
imageStyle: {
|
||||||
marginTop:8,
|
marginTop: 8,
|
||||||
height:150,
|
height: 150,
|
||||||
width:'100%',
|
width: '100%',
|
||||||
} as ImageStyle,
|
} as ImageStyle,
|
||||||
|
|
||||||
textContainer:{
|
textContainer: {
|
||||||
marginTop:32,
|
marginTop: 32,
|
||||||
marginBottom:44,
|
marginBottom: 44,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
title: {
|
title: {
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: '800',
|
fontWeight: '800',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
bodyText: {
|
bodyText: {
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
marginTop:4,
|
marginTop: 4,
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
btnText:{
|
btnText: {
|
||||||
color:'$pureWhite'
|
color: '$pureWhite',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
button:{
|
button: {
|
||||||
|
backgroundColor: '$primaryBlue',
|
||||||
|
minWidth: 150,
|
||||||
|
paddingVertical: 16,
|
||||||
|
marginVertical: 8,
|
||||||
|
borderRadius: 32,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
} as ViewStyle,
|
||||||
|
|
||||||
backgroundColor:'$primaryBlue',
|
actionPanel: {
|
||||||
minWidth:150,
|
width: '100%',
|
||||||
paddingVertical:16,
|
flexDirection: 'row',
|
||||||
marginVertical:8,
|
flexWrap: 'wrap',
|
||||||
borderRadius:32,
|
justifyContent: 'space-around',
|
||||||
justifyContent:'center',
|
alignItems: 'center',
|
||||||
alignItems:'center'
|
} as ViewStyle,
|
||||||
} as ViewStyle,
|
});
|
||||||
|
|
||||||
|
|
||||||
actionPanel:{
|
|
||||||
width:'100%',
|
|
||||||
flexDirection:'row',
|
|
||||||
flexWrap:'wrap',
|
|
||||||
justifyContent:'space-around',
|
|
||||||
alignItems:'center',
|
|
||||||
} as ViewStyle,
|
|
||||||
|
|
||||||
})
|
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import { ViewStyle } from "react-native"
|
import { ViewStyle } from 'react-native';
|
||||||
import EStyleSheet from "react-native-extended-stylesheet"
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
import { ImageStyle } from "react-native-fast-image"
|
import { ImageStyle } from 'react-native-fast-image';
|
||||||
|
|
||||||
export default EStyleSheet.create({
|
export default EStyleSheet.create({
|
||||||
hiveEngineWrapper: {
|
hiveEngineWrapper: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: -6,
|
top: -6,
|
||||||
right: 4,
|
right: 4,
|
||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
padding: 1,
|
padding: 1,
|
||||||
backgroundColor: '$pureWhite',
|
backgroundColor: '$pureWhite',
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
hiveEngineLogo: {
|
hiveEngineLogo: {
|
||||||
height: 14,
|
height: 14,
|
||||||
width: 14
|
width: 14,
|
||||||
} as ImageStyle,
|
} as ImageStyle,
|
||||||
logo: {
|
logo: {
|
||||||
height: 30,
|
height: 30,
|
||||||
width: 30,
|
width: 30,
|
||||||
} as ImageStyle,
|
} as ImageStyle,
|
||||||
})
|
});
|
||||||
|
@ -12,45 +12,45 @@ interface WritePostButtonProps {
|
|||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WritePostButton = forwardRef(({ placeholderId: placeholder, onPress }: WritePostButtonProps, ref) => {
|
export const WritePostButton = forwardRef(
|
||||||
const intl = useIntl();
|
({ placeholderId: placeholder, onPress }: WritePostButtonProps, ref) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
const animatedContainer = useRef<AnimatedView>();
|
const animatedContainer = useRef<AnimatedView>();
|
||||||
|
|
||||||
const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn);
|
const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn);
|
||||||
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
bounce: () => {
|
bounce: () => {
|
||||||
console.log('bouncing');
|
console.log('bouncing');
|
||||||
if (animatedContainer.current) {
|
if (animatedContainer.current) {
|
||||||
animatedContainer.current.swing(1000);
|
animatedContainer.current.swing(1000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const _onPress = () => {
|
||||||
|
if (!isLoggedIn) {
|
||||||
|
showLoginAlert({ intl });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
},
|
if (onPress) {
|
||||||
}));
|
onPress();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const _onPress = () => {
|
return (
|
||||||
if (!isLoggedIn) {
|
<AnimatedView ref={animatedContainer}>
|
||||||
showLoginAlert({ intl });
|
<TouchableOpacity onPress={_onPress}>
|
||||||
return;
|
<View style={styles.container}>
|
||||||
}
|
<UserAvatar username={currentAccount.username} />
|
||||||
if (onPress) {
|
<View style={styles.inputContainer}>
|
||||||
onPress();
|
<Text style={styles.inputPlaceholder}>{intl.formatMessage({ id: placeholder })}</Text>
|
||||||
}
|
</View>
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AnimatedView ref={animatedContainer}>
|
|
||||||
<TouchableOpacity onPress={_onPress}>
|
|
||||||
<View style={styles.container}>
|
|
||||||
<UserAvatar username={currentAccount.username} />
|
|
||||||
<View style={styles.inputContainer}>
|
|
||||||
<Text style={styles.inputPlaceholder}>
|
|
||||||
{intl.formatMessage({ id: placeholder })}
|
|
||||||
</Text>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</TouchableOpacity>
|
||||||
</TouchableOpacity>
|
</AnimatedView>
|
||||||
</AnimatedView>
|
);
|
||||||
);
|
},
|
||||||
});
|
);
|
||||||
|
@ -1 +1 @@
|
|||||||
export * from './container/writePostButton';
|
export * from './container/writePostButton';
|
||||||
|
@ -196,8 +196,8 @@ const BasicHeaderView = ({
|
|||||||
size={28}
|
size={28}
|
||||||
onPress={() => handleBrowserIconPress()}
|
onPress={() => handleBrowserIconPress()}
|
||||||
iconStyle={styles.rightIcon}
|
iconStyle={styles.rightIcon}
|
||||||
name={'open-in-browser'}
|
name="open-in-browser"
|
||||||
iconType={'MaterialIcons'}
|
iconType="MaterialIcons"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
@ -16,28 +16,22 @@ const BoostPlaceHolder = () => {
|
|||||||
const isDarkTheme = useSelector((state) => state.application.isDarkTeme);
|
const isDarkTheme = useSelector((state) => state.application.isDarkTeme);
|
||||||
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
||||||
times(parseInt(ratio), (i) => {
|
times(parseInt(ratio), (i) => {
|
||||||
listElements.push(<View style={styles.container} key={`key-${i.toString()}`}>
|
listElements.push(
|
||||||
<View style={styles.line}>
|
<View style={styles.container} key={`key-${i.toString()}`}>
|
||||||
<Placeholder.Box color={color} width={90} height={40} animate="fade" />
|
<View style={styles.line}>
|
||||||
<View style={styles.paragraphWrapper}>
|
<Placeholder.Box color={color} width={90} height={40} animate="fade" />
|
||||||
|
<View style={styles.paragraphWrapper}>
|
||||||
|
<Placeholder.Box color={color} width={140} radius={25} height={50} animate="fade" />
|
||||||
|
</View>
|
||||||
<Placeholder.Box
|
<Placeholder.Box
|
||||||
|
style={styles.rightBox}
|
||||||
color={color}
|
color={color}
|
||||||
width={140}
|
width={20}
|
||||||
radius={25}
|
height={10}
|
||||||
height={50}
|
|
||||||
animate="fade"
|
animate="fade"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Placeholder.Box
|
</View>,
|
||||||
style={styles.rightBox}
|
|
||||||
color={color}
|
|
||||||
width={20}
|
|
||||||
height={10}
|
|
||||||
animate="fade"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ const CommentPlaceHolderView = () => {
|
|||||||
height: 72,
|
height: 72,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
||||||
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
||||||
|
|
||||||
@ -33,9 +32,6 @@ const CommentPlaceHolderView = () => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CommentPlaceHolderView;
|
export default CommentPlaceHolderView;
|
||||||
|
@ -7,7 +7,7 @@ import { useSelector } from 'react-redux';
|
|||||||
import styles from './postCardPlaceHolderStyles';
|
import styles from './postCardPlaceHolderStyles';
|
||||||
// TODO: make container for place holder wrapper after alpha
|
// TODO: make container for place holder wrapper after alpha
|
||||||
const PostCardPlaceHolder = () => {
|
const PostCardPlaceHolder = () => {
|
||||||
const isDarkTheme = useSelector((state) => state.application.isDarkTheme)
|
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
||||||
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
@ -25,6 +25,5 @@ const PostCardPlaceHolder = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
export default PostCardPlaceHolder;
|
export default PostCardPlaceHolder;
|
||||||
|
@ -7,7 +7,6 @@ import { useSelector } from 'react-redux';
|
|||||||
import styles from './listItemPlaceHolderStyles';
|
import styles from './listItemPlaceHolderStyles';
|
||||||
|
|
||||||
const ListItemPlaceHolderView = () => {
|
const ListItemPlaceHolderView = () => {
|
||||||
|
|
||||||
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
||||||
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
||||||
return (
|
return (
|
||||||
@ -27,7 +26,6 @@ const ListItemPlaceHolderView = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ListItemPlaceHolderView;
|
export default ListItemPlaceHolderView;
|
||||||
|
@ -4,6 +4,7 @@ import LottieView from 'lottie-react-native';
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import styles from './postCardPlaceHolderStyles';
|
import styles from './postCardPlaceHolderStyles';
|
||||||
import getWindowDimensions from '../../../../utils/getWindowDimensions';
|
import getWindowDimensions from '../../../../utils/getWindowDimensions';
|
||||||
|
|
||||||
const PostCardPlaceHolder = () => {
|
const PostCardPlaceHolder = () => {
|
||||||
const animationStyle = {
|
const animationStyle = {
|
||||||
width: getWindowDimensions().nativeWidth - 32,
|
width: getWindowDimensions().nativeWidth - 32,
|
||||||
@ -29,6 +30,5 @@ const PostCardPlaceHolder = () => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
export default PostCardPlaceHolder;
|
export default PostCardPlaceHolder;
|
||||||
|
@ -4,8 +4,8 @@ import LottieView from 'lottie-react-native';
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import getWindowDimensions from '../../../../utils/getWindowDimensions';
|
import getWindowDimensions from '../../../../utils/getWindowDimensions';
|
||||||
const PostPlaceHolder = () => {
|
|
||||||
|
|
||||||
|
const PostPlaceHolder = () => {
|
||||||
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
||||||
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
||||||
|
|
||||||
@ -27,7 +27,6 @@ const PostPlaceHolder = () => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PostPlaceHolder;
|
export default PostPlaceHolder;
|
||||||
|
@ -29,7 +29,6 @@ const ProfileSummaryPlaceHolder = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProfileSummaryPlaceHolder;
|
export default ProfileSummaryPlaceHolder;
|
||||||
|
@ -29,7 +29,6 @@ const WalletDetailsPlaceHolder = () => {
|
|||||||
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
const isDarkTheme = useSelector((state) => state.application.isDarkTheme);
|
||||||
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
const color = isDarkTheme ? '#2e3d51' : '#f5f5f5';
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.textWrapper}>
|
<View style={styles.textWrapper}>
|
||||||
@ -37,12 +36,8 @@ const WalletDetailsPlaceHolder = () => {
|
|||||||
</View>
|
</View>
|
||||||
{listPlaceHolderView(color)}
|
{listPlaceHolderView(color)}
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default WalletDetailsPlaceHolder;
|
export default WalletDetailsPlaceHolder;
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
@ -101,6 +101,4 @@ export default EStyleSheet.create({
|
|||||||
tooltipText: {
|
tooltipText: {
|
||||||
color: '$primaryDarkText',
|
color: '$primaryDarkText',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -80,8 +80,8 @@ export default EStyleSheet.create({
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
cancelIcon:{
|
cancelIcon: {
|
||||||
marginLeft:8,
|
marginLeft: 8,
|
||||||
},
|
},
|
||||||
dropdownWrapper: {
|
dropdownWrapper: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -3,31 +3,31 @@ import { View, FlatList, Text } from 'react-native';
|
|||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { isArray, debounce } from 'lodash';
|
import { isArray, debounce } from 'lodash';
|
||||||
|
|
||||||
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||||
import { lookupAccounts } from '../../providers/hive/dhive';
|
import { lookupAccounts } from '../../providers/hive/dhive';
|
||||||
|
|
||||||
import { FormInput, MainButton, TextButton } from '..';
|
import { FormInput, MainButton, TextButton } from '..';
|
||||||
|
|
||||||
import styles from './beneficiaryModalStyles';
|
import styles from './beneficiaryModalStyles';
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
|
||||||
import IconButton from '../iconButton';
|
import IconButton from '../iconButton';
|
||||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
|
||||||
import { useAppSelector } from '../../hooks';
|
import { useAppSelector } from '../../hooks';
|
||||||
import { Beneficiary } from '../../redux/reducers/editorReducer';
|
import { Beneficiary } from '../../redux/reducers/editorReducer';
|
||||||
import { TEMP_BENEFICIARIES_ID } from '../../redux/constants/constants';
|
import { TEMP_BENEFICIARIES_ID } from '../../redux/constants/constants';
|
||||||
|
|
||||||
interface BeneficiaryModal {
|
interface BeneficiaryModal {
|
||||||
username:string,
|
username: string;
|
||||||
draftId:string,
|
draftId: string;
|
||||||
handleOnSaveBeneficiaries:()=>void
|
handleOnSaveBeneficiaries: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const beneficiariesMap = useAppSelector(state => state.editor.beneficiariesMap)
|
const beneficiariesMap = useAppSelector((state) => state.editor.beneficiariesMap);
|
||||||
|
|
||||||
const [beneficiaries, setBeneficiaries] = useState<Beneficiary[]>([
|
const [beneficiaries, setBeneficiaries] = useState<Beneficiary[]>([
|
||||||
{ account: username, weight: 10000, isValid: true},
|
{ account: username, weight: 10000, isValid: true },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const [newUsername, setNewUsername] = useState('');
|
const [newUsername, setNewUsername] = useState('');
|
||||||
@ -37,14 +37,13 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
const [newEditable, setNewEditable] = useState(false);
|
const [newEditable, setNewEditable] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
readTempBeneficiaries();
|
readTempBeneficiaries();
|
||||||
}, [draftId]);
|
}, [draftId]);
|
||||||
|
|
||||||
|
|
||||||
const readTempBeneficiaries = async () => {
|
const readTempBeneficiaries = async () => {
|
||||||
if(beneficiariesMap){
|
if (beneficiariesMap) {
|
||||||
const tempBeneficiaries = beneficiariesMap[draftId || TEMP_BENEFICIARIES_ID];
|
const tempBeneficiaries = beneficiariesMap[draftId || TEMP_BENEFICIARIES_ID];
|
||||||
|
|
||||||
if (isArray(tempBeneficiaries)) {
|
if (isArray(tempBeneficiaries)) {
|
||||||
tempBeneficiaries.forEach((item) => {
|
tempBeneficiaries.forEach((item) => {
|
||||||
item.isValid = true;
|
item.isValid = true;
|
||||||
@ -52,28 +51,24 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
setBeneficiaries(tempBeneficiaries);
|
setBeneficiaries(tempBeneficiaries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const _onSavePress = () => {
|
const _onSavePress = () => {
|
||||||
if(newEditable){
|
if (newEditable) {
|
||||||
beneficiaries.push({
|
beneficiaries.push({
|
||||||
account:newUsername,
|
account: newUsername,
|
||||||
weight:newWeight
|
weight: newWeight,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
handleOnSaveBeneficiaries(beneficiaries);
|
handleOnSaveBeneficiaries(beneficiaries);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
const _addAccount = () => {
|
const _addAccount = () => {
|
||||||
|
if (isUsernameValid && isWeightValid) {
|
||||||
if(isUsernameValid && isWeightValid){
|
|
||||||
beneficiaries.push({
|
beneficiaries.push({
|
||||||
account:newUsername,
|
account: newUsername,
|
||||||
weight:newWeight,
|
weight: newWeight,
|
||||||
})
|
});
|
||||||
setBeneficiaries([...beneficiaries]);
|
setBeneficiaries([...beneficiaries]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,43 +79,33 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
setNewEditable(true);
|
setNewEditable(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _onWeightInputChange = (value) => {
|
const _onWeightInputChange = (value) => {
|
||||||
let _value = (parseInt(value, 10) || 0) * 100;
|
const _value = (parseInt(value, 10) || 0) * 100;
|
||||||
const _diff = _value - newWeight;
|
const _diff = _value - newWeight;
|
||||||
beneficiaries[0].weight = beneficiaries[0].weight - _diff;
|
beneficiaries[0].weight = beneficiaries[0].weight - _diff;
|
||||||
setNewWeight(_value)
|
setNewWeight(_value);
|
||||||
setIsWeightValid(_value > 0 && _value <= 10000)
|
setIsWeightValid(_value > 0 && _value <= 10000);
|
||||||
setBeneficiaries([...beneficiaries]);
|
setBeneficiaries([...beneficiaries]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const _lookupAccounts = debounce((username) => {
|
const _lookupAccounts = debounce((username) => {
|
||||||
|
|
||||||
lookupAccounts(username).then((res) => {
|
lookupAccounts(username).then((res) => {
|
||||||
const isValid = res.includes(username)
|
const isValid = res.includes(username);
|
||||||
//check if username duplicates else lookup contacts, done here to avoid debounce and post call mismatch
|
// check if username duplicates else lookup contacts, done here to avoid debounce and post call mismatch
|
||||||
const notExistAlready = !beneficiaries.find((item)=>item.account === username);
|
const notExistAlready = !beneficiaries.find((item) => item.account === username);
|
||||||
setIsUsernameValid(isValid && notExistAlready)
|
setIsUsernameValid(isValid && notExistAlready);
|
||||||
});
|
});
|
||||||
}, 1000)
|
}, 1000);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _onUsernameInputChange = (value) => {
|
const _onUsernameInputChange = (value) => {
|
||||||
setNewUsername(value);
|
setNewUsername(value);
|
||||||
_lookupAccounts(value);
|
_lookupAccounts(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _isValid = () => {
|
const _isValid = () => {
|
||||||
return !newEditable || (isUsernameValid && isWeightValid);
|
return !newEditable || (isUsernameValid && isWeightValid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _renderHeader = () => (
|
const _renderHeader = () => (
|
||||||
<View style={styles.inputWrapper}>
|
<View style={styles.inputWrapper}>
|
||||||
<View style={[styles.weightInput, { alignItems: 'center' }]}>
|
<View style={[styles.weightInput, { alignItems: 'center' }]}>
|
||||||
@ -138,23 +123,20 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
|
|
||||||
|
|
||||||
const _renderInput = () => {
|
const _renderInput = () => {
|
||||||
|
|
||||||
const _onCancelPress = () => {
|
const _onCancelPress = () => {
|
||||||
if(newWeight){
|
if (newWeight) {
|
||||||
beneficiaries[0].weight = beneficiaries[0].weight + newWeight;
|
beneficiaries[0].weight = beneficiaries[0].weight + newWeight;
|
||||||
setBeneficiaries([...beneficiaries])
|
setBeneficiaries([...beneficiaries]);
|
||||||
setNewWeight(0);
|
setNewWeight(0);
|
||||||
}
|
}
|
||||||
setNewEditable(false);
|
setNewEditable(false);
|
||||||
setIsWeightValid(false);
|
setIsWeightValid(false);
|
||||||
setIsUsernameValid(false);
|
setIsUsernameValid(false);
|
||||||
setNewUsername('');
|
setNewUsername('');
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.inputWrapper}>
|
<View style={styles.inputWrapper}>
|
||||||
@ -165,8 +147,8 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
inputStyle={styles.weightFormInput}
|
inputStyle={styles.weightFormInput}
|
||||||
wrapperStyle={styles.weightFormInputWrapper}
|
wrapperStyle={styles.weightFormInputWrapper}
|
||||||
onChange={(value) => _onWeightInputChange(value)}
|
onChange={(value) => _onWeightInputChange(value)}
|
||||||
onBlur={() => {}}//_onBlur(item)}
|
onBlur={() => {}} // _onBlur(item)}
|
||||||
keyboardType='numeric'
|
keyboardType="numeric"
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@ -187,40 +169,36 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
name="close"
|
name="close"
|
||||||
iconType="MaterialCommunityIcons"
|
iconType="MaterialCommunityIcons"
|
||||||
color={EStyleSheet.value('$primaryBlack')}
|
color={EStyleSheet.value('$primaryBlack')}
|
||||||
size={24}
|
size={24}
|
||||||
iconStyle={{paddingLeft:8}}
|
iconStyle={{ paddingLeft: 8 }}
|
||||||
onPress={_onCancelPress}
|
onPress={_onCancelPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const _renderFooter = () => (
|
const _renderFooter = () => (
|
||||||
<>
|
<>
|
||||||
{newEditable && _renderInput()}
|
{newEditable && _renderInput()}
|
||||||
<View style={{marginTop: 20, marginBottom:32 }}>
|
<View style={{ marginTop: 20, marginBottom: 32 }}>
|
||||||
<TextButton
|
<TextButton
|
||||||
text={intl.formatMessage({
|
text={intl.formatMessage({
|
||||||
id: 'beneficiary_modal.addAccount',
|
id: 'beneficiary_modal.addAccount',
|
||||||
})}
|
})}
|
||||||
disabled={!isAllValid}
|
disabled={!isAllValid}
|
||||||
onPress={_addAccount}
|
onPress={_addAccount}
|
||||||
textStyle={{
|
textStyle={{
|
||||||
color:EStyleSheet.value(isAllValid?'$primaryBlue':"$iconColor"),
|
color: EStyleSheet.value(isAllValid ? '$primaryBlue' : '$iconColor'),
|
||||||
fontWeight:'bold'
|
fontWeight: 'bold',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</>
|
</>
|
||||||
|
);
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
const _renderItem = ({ item, index }) => {
|
const _renderItem = ({ item, index }) => {
|
||||||
const _isCurrentUser = item.account === username;
|
const _isCurrentUser = item.account === username;
|
||||||
@ -229,8 +207,7 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
beneficiaries[0].weight = beneficiaries[0].weight + item.weight;
|
beneficiaries[0].weight = beneficiaries[0].weight + item.weight;
|
||||||
beneficiaries.splice(index, 1);
|
beneficiaries.splice(index, 1);
|
||||||
setBeneficiaries([...beneficiaries]);
|
setBeneficiaries([...beneficiaries]);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.inputWrapper}>
|
<View style={styles.inputWrapper}>
|
||||||
@ -241,7 +218,7 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
value={`${item.weight / 100}`}
|
value={`${item.weight / 100}`}
|
||||||
inputStyle={styles.weightFormInput}
|
inputStyle={styles.weightFormInput}
|
||||||
wrapperStyle={styles.weightFormInputWrapper}
|
wrapperStyle={styles.weightFormInputWrapper}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.usernameInput}>
|
<View style={styles.usernameInput}>
|
||||||
@ -256,28 +233,25 @@ const BeneficiaryModal = ({ username, handleOnSaveBeneficiaries, draftId }) => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
{!_isCurrentUser ? (
|
{!_isCurrentUser ? (
|
||||||
<IconButton
|
<IconButton
|
||||||
name="close"
|
name="close"
|
||||||
iconType="MaterialCommunityIcons"
|
iconType="MaterialCommunityIcons"
|
||||||
size={24}
|
size={24}
|
||||||
color={EStyleSheet.value('$primaryBlack')}
|
color={EStyleSheet.value('$primaryBlack')}
|
||||||
iconStyle={{paddingLeft:8}}
|
iconStyle={{ paddingLeft: 8 }}
|
||||||
onPress={_onRemovePress}
|
onPress={_onRemovePress}
|
||||||
/>
|
/>
|
||||||
):(
|
) : (
|
||||||
<View style={{width:30}} />
|
<View style={{ width: 30 }} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const isAllValid = _isValid();
|
const isAllValid = _isValid();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
|
||||||
<KeyboardAwareScrollView style={styles.bodyWrapper}>
|
<KeyboardAwareScrollView style={styles.bodyWrapper}>
|
||||||
<FlatList
|
<FlatList
|
||||||
data={beneficiaries}
|
data={beneficiaries}
|
||||||
|
@ -78,7 +78,7 @@ const BeneficiarySelectionContent = ({
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (isArray(tempBeneficiaries) && tempBeneficiaries.length > 0) {
|
if (isArray(tempBeneficiaries) && tempBeneficiaries.length > 0) {
|
||||||
//weight correction algorithm.
|
// weight correction algorithm.
|
||||||
let othersWeight = 0;
|
let othersWeight = 0;
|
||||||
tempBeneficiaries.forEach((item, index) => {
|
tempBeneficiaries.forEach((item, index) => {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
@ -100,7 +100,7 @@ const BeneficiarySelectionContent = ({
|
|||||||
: [DEFAULT_BENEFICIARY];
|
: [DEFAULT_BENEFICIARY];
|
||||||
|
|
||||||
if (isArray(tempBeneficiaries) && tempBeneficiaries.length > 0) {
|
if (isArray(tempBeneficiaries) && tempBeneficiaries.length > 0) {
|
||||||
//weight correction algorithm.
|
// weight correction algorithm.
|
||||||
let othersWeight = 0;
|
let othersWeight = 0;
|
||||||
tempBeneficiaries.forEach((item, index) => {
|
tempBeneficiaries.forEach((item, index) => {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
@ -114,7 +114,7 @@ const BeneficiarySelectionContent = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _saveBeneficiaries = (value: Beneficiary[]) => {
|
const _saveBeneficiaries = (value: Beneficiary[]) => {
|
||||||
const filteredBeneficiaries = value.filter((item) => item.account !== username); //remove default beneficiary from array while saving
|
const filteredBeneficiaries = value.filter((item) => item.account !== username); // remove default beneficiary from array while saving
|
||||||
if (handleSaveBeneficiary) {
|
if (handleSaveBeneficiary) {
|
||||||
handleSaveBeneficiary(filteredBeneficiaries);
|
handleSaveBeneficiary(filteredBeneficiaries);
|
||||||
} else {
|
} else {
|
||||||
@ -151,7 +151,7 @@ const BeneficiarySelectionContent = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _onWeightInputChange = (value: string) => {
|
const _onWeightInputChange = (value: string) => {
|
||||||
let _value = (parseInt(value, 10) || 0) * 100;
|
const _value = (parseInt(value, 10) || 0) * 100;
|
||||||
|
|
||||||
const _diff = _value - newWeight;
|
const _diff = _value - newWeight;
|
||||||
const newAuthorWeight = beneficiaries[0].weight - _diff;
|
const newAuthorWeight = beneficiaries[0].weight - _diff;
|
||||||
@ -165,7 +165,7 @@ const BeneficiarySelectionContent = ({
|
|||||||
const _lookupAccounts = debounce((username) => {
|
const _lookupAccounts = debounce((username) => {
|
||||||
lookupAccounts(username).then((res) => {
|
lookupAccounts(username).then((res) => {
|
||||||
const isValid = res.includes(username);
|
const isValid = res.includes(username);
|
||||||
//check if username duplicates else lookup contacts, done here to avoid debounce and post call mismatch
|
// check if username duplicates else lookup contacts, done here to avoid debounce and post call mismatch
|
||||||
const notExistAlready = !beneficiaries.find((item) => item.account === username);
|
const notExistAlready = !beneficiaries.find((item) => item.account === username);
|
||||||
setIsUsernameValid(isValid && notExistAlready);
|
setIsUsernameValid(isValid && notExistAlready);
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,7 @@ import { SafeAreaView, View, TouchableOpacity, Alert } from 'react-native';
|
|||||||
// Constants
|
// Constants
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
|
import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
import ROUTES from '../../../constants/routeNames';
|
import ROUTES from '../../../constants/routeNames';
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
@ -16,7 +17,6 @@ import scalePx from '../../../utils/scalePx';
|
|||||||
import { showReplyModal, updateActiveBottomTab } from '../../../redux/actions/uiAction';
|
import { showReplyModal, updateActiveBottomTab } from '../../../redux/actions/uiAction';
|
||||||
import { useAppSelector } from '../../../hooks';
|
import { useAppSelector } from '../../../hooks';
|
||||||
import showLoginAlert from '../../../utils/showLoginAlert';
|
import showLoginAlert from '../../../utils/showLoginAlert';
|
||||||
import { useIntl } from 'react-intl';
|
|
||||||
|
|
||||||
const BottomTabBarView = ({
|
const BottomTabBarView = ({
|
||||||
state: { routes, index },
|
state: { routes, index },
|
||||||
@ -31,19 +31,15 @@ const BottomTabBarView = ({
|
|||||||
dispatch(updateActiveBottomTab(routes[index].name));
|
dispatch(updateActiveBottomTab(routes[index].name));
|
||||||
}, [index]);
|
}, [index]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _jumpTo = (route, isFocused) => {
|
const _jumpTo = (route, isFocused) => {
|
||||||
|
|
||||||
if (route.name === ROUTES.TABBAR.POST_BUTTON) {
|
if (route.name === ROUTES.TABBAR.POST_BUTTON) {
|
||||||
|
if (!isLoggedIn) {
|
||||||
if(!isLoggedIn){
|
showLoginAlert({ intl });
|
||||||
showLoginAlert({intl})
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routes[index].name === ROUTES.TABBAR.WAVES) {
|
if (routes[index].name === ROUTES.TABBAR.WAVES) {
|
||||||
dispatch(showReplyModal({mode:'wave'}));
|
dispatch(showReplyModal({ mode: 'wave' }));
|
||||||
} else {
|
} else {
|
||||||
navigation.navigate(ROUTES.SCREENS.EDITOR, { key: 'editor_post' });
|
navigation.navigate(ROUTES.SCREENS.EDITOR, { key: 'editor_post' });
|
||||||
}
|
}
|
||||||
@ -63,8 +59,6 @@ const BottomTabBarView = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _tabButtons = routes.map((route, idx) => {
|
const _tabButtons = routes.map((route, idx) => {
|
||||||
const { tabBarActiveTintColor, tabBarInactiveTintColor } = descriptors[route.key].options;
|
const { tabBarActiveTintColor, tabBarInactiveTintColor } = descriptors[route.key].options;
|
||||||
const isFocused = index == idx;
|
const isFocused = index == idx;
|
||||||
@ -88,7 +82,6 @@ const BottomTabBarView = ({
|
|||||||
_iconProps.iconType = 'MaterialCommunityIcons';
|
_iconProps.iconType = 'MaterialCommunityIcons';
|
||||||
_tabBarIcon = <Icon {..._iconProps} />;
|
_tabBarIcon = <Icon {..._iconProps} />;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -98,8 +91,6 @@ const BottomTabBarView = ({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return <SafeAreaView style={styles.wrapper}>{_tabButtons}</SafeAreaView>;
|
return <SafeAreaView style={styles.wrapper}>{_tabButtons}</SafeAreaView>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ const CommentView = ({
|
|||||||
|
|
||||||
const _handleOnContentPress = () => {
|
const _handleOnContentPress = () => {
|
||||||
openReplyThread(comment);
|
openReplyThread(comment);
|
||||||
}
|
};
|
||||||
|
|
||||||
const _handleOnReplyPress = () => {
|
const _handleOnReplyPress = () => {
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
@ -97,7 +97,6 @@ const CommentView = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const _renderComment = () => {
|
const _renderComment = () => {
|
||||||
|
|
||||||
const _hideContent = isMuted || comment.author_reputation < 25 || comment.net_rshares < 0;
|
const _hideContent = isMuted || comment.author_reputation < 25 || comment.net_rshares < 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -219,9 +218,9 @@ const CommentView = ({
|
|||||||
const customContainerStyle =
|
const customContainerStyle =
|
||||||
_depth > 1
|
_depth > 1
|
||||||
? {
|
? {
|
||||||
paddingLeft: (_depth - 2) * 44,
|
paddingLeft: (_depth - 2) * 44,
|
||||||
backgroundColor: EStyleSheet.value('$primaryLightBackground'),
|
backgroundColor: EStyleSheet.value('$primaryLightBackground'),
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -52,7 +52,7 @@ const CommentsContainer = ({
|
|||||||
incrementRepliesCount,
|
incrementRepliesCount,
|
||||||
handleOnReplyPress,
|
handleOnReplyPress,
|
||||||
handleOnCommentsLoaded,
|
handleOnCommentsLoaded,
|
||||||
postType
|
postType,
|
||||||
}) => {
|
}) => {
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
const postsCachePrimer = postQueries.usePostsCachePrimer();
|
const postsCachePrimer = postQueries.usePostsCachePrimer();
|
||||||
@ -172,7 +172,7 @@ const CommentsContainer = ({
|
|||||||
handleOnCommentsLoaded();
|
handleOnCommentsLoaded();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => { });
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -244,13 +244,11 @@ const CommentsContainer = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const _handleOnUserPress = (username) => {
|
const _handleOnUserPress = (username) => {
|
||||||
if (username) {
|
if (username) {
|
||||||
dispatch(showProfileModal(username))
|
dispatch(showProfileModal(username));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const _openReplyThread = (comment) => {
|
const _openReplyThread = (comment) => {
|
||||||
postsCachePrimer.cachePost(comment);
|
postsCachePrimer.cachePost(comment);
|
||||||
|
@ -42,7 +42,7 @@ const CommentsView = ({
|
|||||||
incrementRepliesCount,
|
incrementRepliesCount,
|
||||||
postContentView,
|
postContentView,
|
||||||
isLoading,
|
isLoading,
|
||||||
postType
|
postType,
|
||||||
}) => {
|
}) => {
|
||||||
const [selectedComment, setSelectedComment] = useState(null);
|
const [selectedComment, setSelectedComment] = useState(null);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@ -51,7 +51,6 @@ const CommentsView = ({
|
|||||||
const postInteractionRef = useRef(null);
|
const postInteractionRef = useRef(null);
|
||||||
|
|
||||||
const _openCommentMenu = (item) => {
|
const _openCommentMenu = (item) => {
|
||||||
|
|
||||||
if (handleOnOptionsPress) {
|
if (handleOnOptionsPress) {
|
||||||
handleOnOptionsPress(item);
|
handleOnOptionsPress(item);
|
||||||
} else if (commentMenu.current) {
|
} else if (commentMenu.current) {
|
||||||
@ -79,8 +78,8 @@ const CommentsView = ({
|
|||||||
|
|
||||||
const _onUpvotePress = ({ content, anchorRect, showPayoutDetails, onVotingStart }) => {
|
const _onUpvotePress = ({ content, anchorRect, showPayoutDetails, onVotingStart }) => {
|
||||||
if (upvotePopoverRef.current) {
|
if (upvotePopoverRef.current) {
|
||||||
|
const postType =
|
||||||
const postType = content.parent_author === 'ecency.waves' ? PostTypes.WAVE : PostTypes.COMMENT;
|
content.parent_author === 'ecency.waves' ? PostTypes.WAVE : PostTypes.COMMENT;
|
||||||
|
|
||||||
upvotePopoverRef.current.showPopover({
|
upvotePopoverRef.current.showPopover({
|
||||||
anchorRect,
|
anchorRect,
|
||||||
@ -147,9 +146,9 @@ const CommentsView = ({
|
|||||||
const styleOerride =
|
const styleOerride =
|
||||||
commentNumber > 1
|
commentNumber > 1
|
||||||
? {
|
? {
|
||||||
backgroundColor: EStyleSheet.value('$primaryLightBackground'),
|
backgroundColor: EStyleSheet.value('$primaryLightBackground'),
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const _renderEmptyContent = () => {
|
const _renderEmptyContent = () => {
|
||||||
@ -169,7 +168,7 @@ const CommentsView = ({
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<FlashList
|
<FlashList
|
||||||
contentContainerStyle={{ padding: 0, ...styles.list, ...styleOerride, }}
|
contentContainerStyle={{ padding: 0, ...styles.list, ...styleOerride }}
|
||||||
data={comments}
|
data={comments}
|
||||||
keyExtractor={(item) => item.author + item.permlink}
|
keyExtractor={(item) => item.author + item.permlink}
|
||||||
renderItem={_renderItem}
|
renderItem={_renderItem}
|
||||||
|
@ -5,6 +5,7 @@ import { injectIntl } from 'react-intl';
|
|||||||
// Utils
|
// Utils
|
||||||
import FastImage from 'react-native-fast-image';
|
import FastImage from 'react-native-fast-image';
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
import ESStyleSheet from 'react-native-extended-stylesheet';
|
||||||
import { getTimeFromNow } from '../../../utils/time';
|
import { getTimeFromNow } from '../../../utils/time';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
@ -16,7 +17,6 @@ import { OptionsModal } from '../../atoms';
|
|||||||
import styles from './draftListItemStyles';
|
import styles from './draftListItemStyles';
|
||||||
import { ScheduledPostStatus } from '../../../providers/ecency/ecency.types';
|
import { ScheduledPostStatus } from '../../../providers/ecency/ecency.types';
|
||||||
import { PopoverWrapper } from '../../popoverWrapper/popoverWrapperView';
|
import { PopoverWrapper } from '../../popoverWrapper/popoverWrapperView';
|
||||||
import ESStyleSheet from 'react-native-extended-stylesheet';
|
|
||||||
|
|
||||||
const DraftListItemView = ({
|
const DraftListItemView = ({
|
||||||
title,
|
title,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector, connect } from 'react-redux';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
@ -53,7 +52,6 @@ class TitleAreaView extends Component {
|
|||||||
const { isDarkTheme } = this.props;
|
const { isDarkTheme } = this.props;
|
||||||
return (
|
return (
|
||||||
<View style={[globalStyles.containerHorizontal16, { height: Math.max(maxHeight, height) }]}>
|
<View style={[globalStyles.containerHorizontal16, { height: Math.max(maxHeight, height) }]}>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
style={[styles.textInput, { height: Math.max(maxHeight, height) }]}
|
style={[styles.textInput, { height: Math.max(maxHeight, height) }]}
|
||||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||||
@ -71,19 +69,13 @@ class TitleAreaView extends Component {
|
|||||||
onChangeText={(textT) => this._handleOnChange(textT)}
|
onChangeText={(textT) => this._handleOnChange(textT)}
|
||||||
value={text}
|
value={text}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = (state) => ({
|
const mapStateToProps = (state) => ({
|
||||||
isDarkTheme: state.application.isDarkTheme,
|
isDarkTheme: state.application.isDarkTheme,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(TitleAreaView);
|
export default connect(mapStateToProps)(TitleAreaView);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import FastImage from 'react-native-fast-image';
|
|||||||
import Popover, { usePopover } from 'react-native-modal-popover';
|
import Popover, { usePopover } from 'react-native-modal-popover';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
import { TextInput } from '../../textInput';
|
import { TextInput } from '../../textInput';
|
||||||
import { Icon } from '../../icon';
|
import { Icon } from '../../icon';
|
||||||
// Utils
|
// Utils
|
||||||
@ -20,7 +21,6 @@ import { getResizedAvatar } from '../../../utils/image';
|
|||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
import styles from './formInputStyles';
|
import styles from './formInputStyles';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
interface Props extends TextInputProps {
|
interface Props extends TextInputProps {
|
||||||
type: string;
|
type: string;
|
||||||
@ -133,7 +133,7 @@ const FormInputView = ({
|
|||||||
const _renderInfoIconWithPopover = () => (
|
const _renderInfoIconWithPopover = () => (
|
||||||
<View style={styles.infoIconContainer}>
|
<View style={styles.infoIconContainer}>
|
||||||
<TouchableOpacity ref={touchableRef} onPress={_handleInfoPress}>
|
<TouchableOpacity ref={touchableRef} onPress={_handleInfoPress}>
|
||||||
<Icon iconType={'MaterialIcons'} name="info-outline" style={styles.infoIcon} />
|
<Icon iconType="MaterialIcons" name="info-outline" style={styles.infoIcon} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<Popover
|
<Popover
|
||||||
backgroundStyle={styles.overlay}
|
backgroundStyle={styles.overlay}
|
||||||
|
@ -34,7 +34,6 @@ const HeaderContainer = ({ selectedUser, isReverse, handleOnBackPress, hideUser,
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<AccountContainer>
|
<AccountContainer>
|
||||||
{({ currentAccount, isLoggedIn, isLoginDone }) => {
|
{({ currentAccount, isLoggedIn, isLoginDone }) => {
|
||||||
const _user = isReverse && selectedUser ? selectedUser : currentAccount;
|
const _user = isReverse && selectedUser ? selectedUser : currentAccount;
|
||||||
@ -58,7 +57,6 @@ const HeaderContainer = ({ selectedUser, isReverse, handleOnBackPress, hideUser,
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</AccountContainer>
|
</AccountContainer>
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { Platform, Text, TouchableOpacity, View, ActivityIndicator } from 'react
|
|||||||
import { renderPostBody } from '@ecency/render-helper';
|
import { renderPostBody } from '@ecency/render-helper';
|
||||||
import { ScrollView } from 'react-native-gesture-handler';
|
import { ScrollView } from 'react-native-gesture-handler';
|
||||||
import Clipboard from '@react-native-clipboard/clipboard';
|
import Clipboard from '@react-native-clipboard/clipboard';
|
||||||
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
import { MainButton, PostBody, TextButton } from '..';
|
import { MainButton, PostBody, TextButton } from '..';
|
||||||
import styles from './insertLinkModalStyles';
|
import styles from './insertLinkModalStyles';
|
||||||
import TextInput from '../textInput';
|
import TextInput from '../textInput';
|
||||||
@ -12,7 +13,6 @@ import { isStringWebLink } from '../markdownEditor/children/formats/utils';
|
|||||||
import applyWebLinkFormat from '../markdownEditor/children/formats/applyWebLinkFormat';
|
import applyWebLinkFormat from '../markdownEditor/children/formats/applyWebLinkFormat';
|
||||||
import getWindowDimensions from '../../utils/getWindowDimensions';
|
import getWindowDimensions from '../../utils/getWindowDimensions';
|
||||||
import Modal from '../modal';
|
import Modal from '../modal';
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
|
||||||
|
|
||||||
interface InsertLinkModalProps {
|
interface InsertLinkModalProps {
|
||||||
handleOnInsertLink: ({
|
handleOnInsertLink: ({
|
||||||
@ -78,7 +78,7 @@ export const InsertLinkModal = forwardRef(
|
|||||||
const labelText =
|
const labelText =
|
||||||
selectedUrlType === 2 ? url.split('/').pop() : selectedUrlType === 1 ? '' : label;
|
selectedUrlType === 2 ? url.split('/').pop() : selectedUrlType === 1 ? '' : label;
|
||||||
applyWebLinkFormat({
|
applyWebLinkFormat({
|
||||||
item: { text: labelText, url: url },
|
item: { text: labelText, url },
|
||||||
text: '',
|
text: '',
|
||||||
selection: { start: 0, end: 0 },
|
selection: { start: 0, end: 0 },
|
||||||
setTextAndSelection: _setFormattedTextAndSelection,
|
setTextAndSelection: _setFormattedTextAndSelection,
|
||||||
@ -98,7 +98,7 @@ export const InsertLinkModal = forwardRef(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _setFormattedTextAndSelection = ({ selection, text }) => {
|
const _setFormattedTextAndSelection = ({ selection, text }) => {
|
||||||
setPreviewBody(renderPostBody(text, true, Platform.OS === 'ios' ? false : true));
|
setPreviewBody(renderPostBody(text, true, Platform.OS !== 'ios'));
|
||||||
setFormattedText(text);
|
setFormattedText(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ export const InsertLinkModal = forwardRef(
|
|||||||
setIsUrlValid(false);
|
setIsUrlValid(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handleOnInsertLink({ snippetText: formattedText, selection: selection });
|
handleOnInsertLink({ snippetText: formattedText, selection });
|
||||||
setIsUrlValid(true);
|
setIsUrlValid(true);
|
||||||
};
|
};
|
||||||
const _renderFloatingPanel = () => {
|
const _renderFloatingPanel = () => {
|
||||||
|
@ -1,272 +1,252 @@
|
|||||||
import React, { useEffect, useState, useMemo } from 'react'
|
import React, { useEffect, useState, useMemo } from 'react';
|
||||||
import { useIntl } from 'react-intl'
|
import { useIntl } from 'react-intl';
|
||||||
import { View, Alert } from 'react-native'
|
import { View, Alert } from 'react-native';
|
||||||
import { ProfileStats, StatsData } from './profileStats'
|
import { ProfileStats, StatsData } from './profileStats';
|
||||||
import { MainButton } from '../../..'
|
import { MainButton } from '../../..';
|
||||||
import { addFavorite, checkFavorite, deleteFavorite } from '../../../../providers/ecency/ecency'
|
import { addFavorite, checkFavorite, deleteFavorite } from '../../../../providers/ecency/ecency';
|
||||||
import { followUser, getFollows, getRelationship, getUser } from '../../../../providers/hive/dhive'
|
import { followUser, getFollows, getRelationship, getUser } from '../../../../providers/hive/dhive';
|
||||||
import { getRcPower, getVotingPower } from '../../../../utils/manaBar'
|
import { getRcPower, getVotingPower } from '../../../../utils/manaBar';
|
||||||
import styles from './quickProfileStyles'
|
import styles from './quickProfileStyles';
|
||||||
import { ProfileBasic } from './profileBasic'
|
import { ProfileBasic } from './profileBasic';
|
||||||
import { parseReputation } from '../../../../utils/user'
|
import { parseReputation } from '../../../../utils/user';
|
||||||
import { default as ROUTES } from '../../../../constants/routeNames';
|
import { default as ROUTES } from '../../../../constants/routeNames';
|
||||||
import { ActionPanel } from './actionPanel'
|
import { ActionPanel } from './actionPanel';
|
||||||
import { getTimeFromNowNative } from '../../../../utils/time'
|
import { getTimeFromNowNative } from '../../../../utils/time';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../../hooks'
|
import { useAppDispatch, useAppSelector } from '../../../../hooks';
|
||||||
import { toastNotification } from '../../../../redux/actions/uiAction'
|
import { toastNotification } from '../../../../redux/actions/uiAction';
|
||||||
import bugsnapInstance from '../../../../config/bugsnag'
|
import bugsnapInstance from '../../../../config/bugsnag';
|
||||||
import RootNavigation from '../../../../navigation/rootNavigation'
|
import RootNavigation from '../../../../navigation/rootNavigation';
|
||||||
|
|
||||||
interface QuickProfileContentProps {
|
interface QuickProfileContentProps {
|
||||||
username: string,
|
username: string;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const QuickProfileContent = ({
|
export const QuickProfileContent = ({ username, onClose }: QuickProfileContentProps) => {
|
||||||
username,
|
const intl = useIntl();
|
||||||
onClose
|
const dispatch = useAppDispatch();
|
||||||
}: QuickProfileContentProps) => {
|
|
||||||
const intl = useIntl();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
||||||
const pinCode = useAppSelector((state) => state.application.pin);
|
const pinCode = useAppSelector((state) => state.application.pin);
|
||||||
const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn);
|
const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn);
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [user, setUser] = useState(null);
|
const [user, setUser] = useState(null);
|
||||||
const [follows, setFollows] = useState(null);
|
const [follows, setFollows] = useState(null);
|
||||||
const [isFollowing, setIsFollowing] = useState(false);
|
const [isFollowing, setIsFollowing] = useState(false);
|
||||||
const [isMuted, setIsMuted] = useState(false);
|
const [isMuted, setIsMuted] = useState(false);
|
||||||
const [isFavourite, setIsFavourite] = useState(false);
|
const [isFavourite, setIsFavourite] = useState(false);
|
||||||
|
|
||||||
const isOwnProfile = currentAccount && currentAccount.name === username;
|
const isOwnProfile = currentAccount && currentAccount.name === username;
|
||||||
const currentAccountName = currentAccount ? currentAccount.name : null;
|
const currentAccountName = currentAccount ? currentAccount.name : null;
|
||||||
const isProfileLoaded = (user && follows) ? true : false;
|
const isProfileLoaded = !!(user && follows);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (username) {
|
if (username) {
|
||||||
_fetchUser();
|
_fetchUser();
|
||||||
_fetchExtraUserData();
|
_fetchExtraUserData();
|
||||||
} else {
|
} else {
|
||||||
setUser(null);
|
setUser(null);
|
||||||
|
}
|
||||||
|
}, [username]);
|
||||||
|
|
||||||
|
// NETWORK CALLS
|
||||||
|
const _fetchUser = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const _user = await getUser(username, isOwnProfile);
|
||||||
|
setUser(_user);
|
||||||
|
} catch (error) {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _fetchExtraUserData = async () => {
|
||||||
|
try {
|
||||||
|
if (username) {
|
||||||
|
let _isFollowing;
|
||||||
|
let _isMuted;
|
||||||
|
let _isFavourite;
|
||||||
|
let follows;
|
||||||
|
|
||||||
|
if (!isOwnProfile) {
|
||||||
|
const res = await getRelationship(currentAccountName, username);
|
||||||
|
_isFollowing = res && res.follows;
|
||||||
|
_isMuted = res && res.ignores;
|
||||||
|
_isFavourite = await checkFavorite(username);
|
||||||
}
|
}
|
||||||
}, [username])
|
|
||||||
|
|
||||||
|
|
||||||
//NETWORK CALLS
|
|
||||||
const _fetchUser = async () => {
|
|
||||||
setIsLoading(true);
|
|
||||||
try {
|
try {
|
||||||
const _user = await getUser(username, isOwnProfile);
|
follows = await getFollows(username);
|
||||||
setUser(_user)
|
} catch (err) {
|
||||||
} catch (error) {
|
follows = null;
|
||||||
setIsLoading(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFollows(follows);
|
||||||
|
setIsFollowing(_isFollowing);
|
||||||
|
setIsMuted(_isMuted);
|
||||||
|
setIsFavourite(_isFavourite);
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to fetch complete profile data', error);
|
||||||
|
Alert.alert(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'alert.fail',
|
||||||
|
}),
|
||||||
|
error.message || error.toString(),
|
||||||
|
);
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onFollowPress = async () => {
|
||||||
|
try {
|
||||||
|
const follower = currentAccountName;
|
||||||
|
const following = username;
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
await followUser(currentAccount, pinCode, {
|
||||||
|
follower,
|
||||||
|
following,
|
||||||
|
});
|
||||||
|
|
||||||
|
setIsLoading(false);
|
||||||
|
setIsFollowing(true);
|
||||||
|
dispatch(
|
||||||
|
toastNotification(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: isFollowing ? 'alert.success_unfollow' : 'alert.success_follow',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
setIsLoading(false);
|
||||||
|
console.warn('Failed to follow user', err);
|
||||||
|
bugsnapInstance.notify(err);
|
||||||
|
Alert.alert(intl.formatMessage({ id: 'alert.fail' }), err.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onFavouritePress = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
let favoriteAction;
|
||||||
|
|
||||||
|
if (isFavourite) {
|
||||||
|
favoriteAction = deleteFavorite;
|
||||||
|
} else {
|
||||||
|
favoriteAction = addFavorite;
|
||||||
|
}
|
||||||
|
|
||||||
|
await favoriteAction(username);
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
toastNotification(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: isFavourite ? 'alert.success_unfavorite' : 'alert.success_favorite',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
setIsFavourite(!isFavourite);
|
||||||
|
setIsLoading(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to perform favorite action');
|
||||||
|
setIsLoading(false);
|
||||||
|
Alert.alert(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'alert.fail',
|
||||||
|
}),
|
||||||
|
error.message || error.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// UI CALLBACKS
|
||||||
|
|
||||||
|
const _openFullProfile = () => {
|
||||||
|
const params = {
|
||||||
|
username,
|
||||||
|
reputation: user ? user.reputation : null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RootNavigation.navigate({
|
||||||
|
name: ROUTES.SCREENS.PROFILE,
|
||||||
|
params,
|
||||||
|
key: username,
|
||||||
|
});
|
||||||
|
|
||||||
const _fetchExtraUserData = async () => {
|
if (onClose) {
|
||||||
try {
|
onClose();
|
||||||
if (username) {
|
|
||||||
let _isFollowing;
|
|
||||||
let _isMuted;
|
|
||||||
let _isFavourite;
|
|
||||||
let follows;
|
|
||||||
|
|
||||||
if (!isOwnProfile) {
|
|
||||||
const res = await getRelationship(currentAccountName, username);
|
|
||||||
_isFollowing = res && res.follows;
|
|
||||||
_isMuted = res && res.ignores;
|
|
||||||
_isFavourite = await checkFavorite(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
follows = await getFollows(username);
|
|
||||||
} catch (err) {
|
|
||||||
follows = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setFollows(follows);
|
|
||||||
setIsFollowing(_isFollowing);
|
|
||||||
setIsMuted(_isMuted)
|
|
||||||
setIsFavourite(_isFavourite)
|
|
||||||
setIsLoading(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Failed to fetch complete profile data', error);
|
|
||||||
Alert.alert(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'alert.fail',
|
|
||||||
}),
|
|
||||||
error.message || error.toString(),
|
|
||||||
);
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const _onFollowPress = async () => {
|
|
||||||
try {
|
|
||||||
const follower = currentAccountName
|
|
||||||
const following = username;
|
|
||||||
|
|
||||||
setIsLoading(true);
|
|
||||||
await followUser(currentAccount, pinCode, {
|
|
||||||
follower,
|
|
||||||
following,
|
|
||||||
})
|
|
||||||
|
|
||||||
setIsLoading(false);
|
|
||||||
setIsFollowing(true)
|
|
||||||
dispatch(
|
|
||||||
toastNotification(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: isFollowing ? 'alert.success_unfollow' : 'alert.success_follow',
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
setIsLoading(false);
|
|
||||||
console.warn("Failed to follow user", err)
|
|
||||||
bugsnapInstance.notify(err);
|
|
||||||
Alert.alert(intl.formatMessage({ id: 'alert.fail' }), err.message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const _onFavouritePress = async () => {
|
// extract prop values
|
||||||
try {
|
let _votingPower = '';
|
||||||
setIsLoading(true);
|
let _resourceCredits = '';
|
||||||
let favoriteAction;
|
let _followerCount = 0;
|
||||||
|
let _followingCount = 0;
|
||||||
|
let _postCount = 0;
|
||||||
|
let _about = '';
|
||||||
|
let _reputation = 0;
|
||||||
|
let _createdData = null;
|
||||||
|
|
||||||
if (isFavourite) {
|
if (isProfileLoaded) {
|
||||||
favoriteAction = deleteFavorite;
|
_votingPower = getVotingPower(user).toFixed(1);
|
||||||
} else {
|
_resourceCredits = getRcPower(user).toFixed(0);
|
||||||
favoriteAction = addFavorite;
|
_postCount = user.post_count || 0;
|
||||||
}
|
_about = user.about?.profile?.about || '';
|
||||||
|
_reputation = parseReputation(user.reputation);
|
||||||
|
_createdData = getTimeFromNowNative(user.created);
|
||||||
|
|
||||||
await favoriteAction(username)
|
if (follows) {
|
||||||
|
_followerCount = follows.follower_count || 0;
|
||||||
dispatch(
|
_followingCount = follows.following_count || 0;
|
||||||
toastNotification(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: isFavourite ? 'alert.success_unfavorite' : 'alert.success_favorite',
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
setIsFavourite(!isFavourite);
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (error) {
|
|
||||||
console.warn('Failed to perform favorite action');
|
|
||||||
setIsLoading(false);
|
|
||||||
Alert.alert(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'alert.fail',
|
|
||||||
}),
|
|
||||||
error.message || error.toString(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const statsData1 = [
|
||||||
|
{ label: intl.formatMessage({ id: 'profile.follower' }), value: _followerCount },
|
||||||
|
{ label: intl.formatMessage({ id: 'profile.following' }), value: _followingCount },
|
||||||
|
{ label: intl.formatMessage({ id: 'profile.post' }), value: _postCount },
|
||||||
|
] as StatsData[];
|
||||||
|
|
||||||
|
const statsData2 = [
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({ id: 'profile.resource_credits' }),
|
||||||
|
value: _resourceCredits,
|
||||||
|
suffix: '%',
|
||||||
|
},
|
||||||
|
{ label: intl.formatMessage({ id: 'profile.reputation' }), value: _reputation },
|
||||||
|
] as StatsData[];
|
||||||
|
|
||||||
//UI CALLBACKS
|
return (
|
||||||
|
<View style={styles.modalStyle}>
|
||||||
const _openFullProfile = () => {
|
<ProfileBasic
|
||||||
let params = {
|
username={username}
|
||||||
username,
|
about={_about}
|
||||||
reputation: user ? user.reputation : null
|
created={_createdData}
|
||||||
};
|
votingPower={_votingPower}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={_openFullProfile}
|
||||||
RootNavigation.navigate({
|
/>
|
||||||
name: ROUTES.SCREENS.PROFILE,
|
<ProfileStats data={statsData1} intermediate={!isProfileLoaded} />
|
||||||
params,
|
<ProfileStats horizontalMargin={16} data={statsData2} intermediate={!isProfileLoaded} />
|
||||||
key: username,
|
<MainButton
|
||||||
});
|
style={styles.button}
|
||||||
|
text={intl.formatMessage({ id: 'profile.view_full' })}
|
||||||
if (onClose) {
|
onPress={_openFullProfile}
|
||||||
onClose();
|
/>
|
||||||
}
|
{isLoggedIn && (
|
||||||
}
|
<ActionPanel
|
||||||
|
isFollowing={isFollowing}
|
||||||
//extract prop values
|
isFavourite={isFavourite}
|
||||||
let _votingPower = '';
|
isMuted={isMuted}
|
||||||
let _resourceCredits = '';
|
isLoading={isLoading}
|
||||||
let _followerCount = 0;
|
onFavouritePress={_onFavouritePress}
|
||||||
let _followingCount = 0;
|
onFollowPress={_onFollowPress}
|
||||||
let _postCount = 0;
|
/>
|
||||||
let _about = '';
|
)}
|
||||||
let _reputation = 0;
|
</View>
|
||||||
let _createdData = null;
|
);
|
||||||
|
|
||||||
if (isProfileLoaded) {
|
|
||||||
_votingPower = getVotingPower(user).toFixed(1);
|
|
||||||
_resourceCredits = getRcPower(user).toFixed(0);
|
|
||||||
_postCount = user.post_count || 0;
|
|
||||||
_about = user.about?.profile?.about || '';
|
|
||||||
_reputation = parseReputation(user.reputation);
|
|
||||||
_createdData = getTimeFromNowNative(user.created)
|
|
||||||
|
|
||||||
if (follows) {
|
|
||||||
_followerCount = follows.follower_count || 0;
|
|
||||||
_followingCount = follows.following_count || 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const statsData1 = [
|
|
||||||
{ label: intl.formatMessage({ id: 'profile.follower' }), value: _followerCount },
|
|
||||||
{ label: intl.formatMessage({ id: 'profile.following' }), value: _followingCount },
|
|
||||||
{ label: intl.formatMessage({ id: 'profile.post' }), value: _postCount },
|
|
||||||
] as StatsData[]
|
|
||||||
|
|
||||||
const statsData2 = [
|
|
||||||
{ label: intl.formatMessage({ id: 'profile.resource_credits' }), value: _resourceCredits, suffix: '%' },
|
|
||||||
{ label: intl.formatMessage({ id: 'profile.reputation' }), value: _reputation },
|
|
||||||
] as StatsData[]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles.modalStyle}>
|
|
||||||
<ProfileBasic
|
|
||||||
username={username}
|
|
||||||
about={_about}
|
|
||||||
created={_createdData}
|
|
||||||
votingPower={_votingPower}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onPress={_openFullProfile}
|
|
||||||
/>
|
|
||||||
<ProfileStats
|
|
||||||
data={statsData1}
|
|
||||||
intermediate={!isProfileLoaded}
|
|
||||||
/>
|
|
||||||
<ProfileStats
|
|
||||||
horizontalMargin={16}
|
|
||||||
data={statsData2}
|
|
||||||
intermediate={!isProfileLoaded}
|
|
||||||
/>
|
|
||||||
<MainButton
|
|
||||||
style={styles.button}
|
|
||||||
text={intl.formatMessage({ id: 'profile.view_full' })}
|
|
||||||
onPress={_openFullProfile}
|
|
||||||
/>
|
|
||||||
{isLoggedIn && (
|
|
||||||
<ActionPanel
|
|
||||||
isFollowing={isFollowing}
|
|
||||||
isFavourite={isFavourite}
|
|
||||||
isMuted={isMuted}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onFavouritePress={_onFavouritePress}
|
|
||||||
onFollowPress={_onFollowPress}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
@ -3,102 +3,98 @@ import EStyleSheet from 'react-native-extended-stylesheet';
|
|||||||
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
||||||
|
|
||||||
export default EStyleSheet.create({
|
export default EStyleSheet.create({
|
||||||
modalStyle: {
|
modalStyle: {
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
margin:0,
|
margin: 0,
|
||||||
paddingTop:32,
|
paddingTop: 32,
|
||||||
marginHorizontal:24,
|
marginHorizontal: 24,
|
||||||
paddingBottom: getBottomSpace() + 8,
|
paddingBottom: getBottomSpace() + 8,
|
||||||
},
|
},
|
||||||
|
|
||||||
sheetContent: {
|
sheetContent: {
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
},
|
},
|
||||||
|
|
||||||
container:{
|
container: {
|
||||||
alignItems:'center',
|
alignItems: 'center',
|
||||||
marginHorizontal:16
|
marginHorizontal: 16,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
image:{
|
image: {
|
||||||
width:128,
|
width: 128,
|
||||||
height:128,
|
height: 128,
|
||||||
borderRadius:64,
|
borderRadius: 64,
|
||||||
backgroundColor: '$primaryGray'
|
backgroundColor: '$primaryGray',
|
||||||
} as ImageStyle,
|
} as ImageStyle,
|
||||||
|
|
||||||
textContainer:{
|
textContainer: {
|
||||||
marginTop:32,
|
marginTop: 32,
|
||||||
marginBottom:44,
|
marginBottom: 44,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
title: {
|
title: {
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
marginTop:32,
|
marginTop: 32,
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
statValue: {
|
statValue: {
|
||||||
fontFamily:'$editorFont',
|
fontFamily: '$editorFont',
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 34,
|
fontSize: 34,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
statLabel: {
|
statLabel: {
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
|
bodyText: {
|
||||||
|
color: '$primaryBlack',
|
||||||
|
alignSelf: 'center',
|
||||||
|
textAlign: 'center',
|
||||||
|
fontSize: 18,
|
||||||
|
marginTop: 6,
|
||||||
|
} as TextStyle,
|
||||||
|
|
||||||
bodyText: {
|
btnText: {
|
||||||
color: '$primaryBlack',
|
color: '$pureWhite',
|
||||||
alignSelf: 'center',
|
} as TextStyle,
|
||||||
textAlign: 'center',
|
|
||||||
fontSize: 18,
|
|
||||||
marginTop:6,
|
|
||||||
} as TextStyle,
|
|
||||||
|
|
||||||
|
button: {
|
||||||
|
marginTop: 40,
|
||||||
|
backgroundColor: '$primaryBlue',
|
||||||
|
paddingHorizontal: 44,
|
||||||
|
paddingVertical: 16,
|
||||||
|
borderRadius: 32,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
} as ViewStyle,
|
||||||
|
|
||||||
btnText:{
|
actionPanel: {
|
||||||
color:'$pureWhite'
|
position: 'absolute',
|
||||||
} as TextStyle,
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
} as ViewStyle,
|
||||||
|
|
||||||
button:{
|
progressCircle: {
|
||||||
marginTop: 40,
|
position: 'absolute',
|
||||||
backgroundColor:'$primaryBlue',
|
top: 0,
|
||||||
paddingHorizontal:44,
|
bottom: 0,
|
||||||
paddingVertical:16,
|
left: 0,
|
||||||
borderRadius:32,
|
right: 0,
|
||||||
justifyContent:'center',
|
alignItems: 'center',
|
||||||
alignItems:'center'
|
justifyContent: 'center',
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
});
|
||||||
|
|
||||||
actionPanel:{
|
|
||||||
position: 'absolute',
|
|
||||||
right:0,
|
|
||||||
top:0,
|
|
||||||
flexDirection:'row',
|
|
||||||
alignItems:'center',
|
|
||||||
} as ViewStyle,
|
|
||||||
|
|
||||||
progressCircle:{
|
|
||||||
position:'absolute',
|
|
||||||
top:0,
|
|
||||||
bottom:0,
|
|
||||||
left:0,
|
|
||||||
right:0,
|
|
||||||
alignItems:'center',
|
|
||||||
justifyContent:'center'
|
|
||||||
} as ViewStyle
|
|
||||||
|
|
||||||
})
|
|
||||||
|
@ -1,123 +1,105 @@
|
|||||||
import React, { Fragment, useCallback, useEffect, useRef, useState } from "react";
|
import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { findNodeHandle, NativeModules, View, TouchableOpacity, Text, Alert } from "react-native";
|
import { findNodeHandle, NativeModules, View, TouchableOpacity, Text, Alert } from 'react-native';
|
||||||
import { useAppSelector } from "../../../hooks";
|
import { Rect } from 'react-native-modal-popover/lib/PopoverGeometry';
|
||||||
import { PulseAnimation } from "../../animations";
|
import { useAppSelector } from '../../../hooks';
|
||||||
|
import { PulseAnimation } from '../../animations';
|
||||||
import { isVoted as isVotedFunc, isDownVoted as isDownVotedFunc } from '../../../utils/postParser';
|
import { isVoted as isVotedFunc, isDownVoted as isDownVotedFunc } from '../../../utils/postParser';
|
||||||
import Icon from "../../icon";
|
import Icon from '../../icon';
|
||||||
import styles from './children.styles';
|
import styles from './children.styles';
|
||||||
import { FormattedCurrency } from "../../formatedElements";
|
import { FormattedCurrency } from '../../formatedElements';
|
||||||
import { Rect } from "react-native-modal-popover/lib/PopoverGeometry";
|
import { PostTypes } from '../../../constants/postTypes';
|
||||||
import { PostTypes } from "../../../constants/postTypes";
|
|
||||||
|
|
||||||
interface UpvoteButtonProps {
|
interface UpvoteButtonProps {
|
||||||
content: any,
|
content: any;
|
||||||
activeVotes: any[],
|
activeVotes: any[];
|
||||||
isShowPayoutValue?: boolean,
|
isShowPayoutValue?: boolean;
|
||||||
boldPayout?: boolean,
|
boldPayout?: boolean;
|
||||||
parentType?: PostTypes;
|
parentType?: PostTypes;
|
||||||
onUpvotePress: (anchorRect: Rect, onVotingStart: (status:number)=>void) => void,
|
onUpvotePress: (anchorRect: Rect, onVotingStart: (status: number) => void) => void;
|
||||||
onPayoutDetailsPress: (anchorRef: Rect) => void,
|
onPayoutDetailsPress: (anchorRef: Rect) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UpvoteButton = ({
|
export const UpvoteButton = ({
|
||||||
content,
|
content,
|
||||||
activeVotes,
|
activeVotes,
|
||||||
isShowPayoutValue,
|
isShowPayoutValue,
|
||||||
boldPayout,
|
boldPayout,
|
||||||
onUpvotePress,
|
onUpvotePress,
|
||||||
onPayoutDetailsPress
|
onPayoutDetailsPress,
|
||||||
}: UpvoteButtonProps) => {
|
}: UpvoteButtonProps) => {
|
||||||
|
const upvoteRef = useRef(null);
|
||||||
|
const detailsRef = useRef(null);
|
||||||
|
|
||||||
const upvoteRef = useRef(null);
|
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
||||||
const detailsRef = useRef(null);
|
|
||||||
|
|
||||||
const currentAccount = useAppSelector((state => state.account.currentAccount));
|
const [isVoted, setIsVoted] = useState<any>(null);
|
||||||
|
const [isDownVoted, setIsDownVoted] = useState<any>(null);
|
||||||
|
|
||||||
const [isVoted, setIsVoted] = useState<any>(null);
|
useEffect(() => {
|
||||||
const [isDownVoted, setIsDownVoted] = useState<any>(null);
|
_calculateVoteStatus();
|
||||||
|
}, [activeVotes]);
|
||||||
|
|
||||||
|
const _calculateVoteStatus = useCallback(async () => {
|
||||||
|
// TODO: do this heavy lifting during parsing or react-query/cache response
|
||||||
|
const _isVoted = await isVotedFunc(activeVotes, currentAccount?.name);
|
||||||
|
const _isDownVoted = await isDownVotedFunc(activeVotes, currentAccount?.name);
|
||||||
|
|
||||||
useEffect(() => {
|
setIsVoted(_isVoted && parseInt(_isVoted, 10) / 10000);
|
||||||
|
setIsDownVoted(_isDownVoted && (parseInt(_isDownVoted, 10) / 10000) * -1);
|
||||||
|
}, [activeVotes]);
|
||||||
|
|
||||||
|
const _getRectFromRef = (ref: any, callback: (anchorRect: Rect, onVotingStart?) => void) => {
|
||||||
|
const handle = findNodeHandle(ref.current);
|
||||||
|
if (handle) {
|
||||||
|
NativeModules.UIManager.measure(handle, (x0, y0, width, height, x, y) => {
|
||||||
|
const anchorRect: Rect = { x, y, width, height };
|
||||||
|
callback(anchorRect);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onPress = () => {
|
||||||
|
const _onVotingStart = (status) => {
|
||||||
|
if (status > 0) {
|
||||||
|
setIsVoted(true);
|
||||||
|
} else if (status < 0) {
|
||||||
|
setIsDownVoted(true);
|
||||||
|
} else {
|
||||||
_calculateVoteStatus();
|
_calculateVoteStatus();
|
||||||
}, [activeVotes]);
|
}
|
||||||
|
};
|
||||||
|
_getRectFromRef(upvoteRef, (rect) => {
|
||||||
|
onUpvotePress(rect, _onVotingStart);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const _onDetailsPress = () => {
|
||||||
|
_getRectFromRef(detailsRef, onPayoutDetailsPress);
|
||||||
|
};
|
||||||
|
|
||||||
const _calculateVoteStatus = useCallback(async () => {
|
const isDeclinedPayout = content?.is_declined_payout;
|
||||||
|
const totalPayout = content?.total_payout;
|
||||||
|
const maxPayout = content?.max_payout;
|
||||||
|
|
||||||
//TODO: do this heavy lifting during parsing or react-query/cache response
|
const payoutLimitHit = totalPayout >= maxPayout;
|
||||||
const _isVoted = await isVotedFunc(activeVotes, currentAccount?.name);
|
const _shownPayout = payoutLimitHit && maxPayout > 0 ? maxPayout : totalPayout;
|
||||||
const _isDownVoted = await isDownVotedFunc(activeVotes, currentAccount?.name);
|
|
||||||
|
|
||||||
|
let iconName = 'upcircleo';
|
||||||
setIsVoted(_isVoted && parseInt(_isVoted, 10) / 10000);
|
const iconType = 'AntDesign';
|
||||||
setIsDownVoted(_isDownVoted && (parseInt(_isDownVoted, 10) / 10000) * -1);
|
let downVoteIconName = 'downcircleo';
|
||||||
|
|
||||||
}, [activeVotes]);
|
|
||||||
|
|
||||||
|
if (isVoted) {
|
||||||
|
iconName = 'upcircle';
|
||||||
|
}
|
||||||
|
|
||||||
const _getRectFromRef = (ref: any, callback: (anchorRect: Rect, onVotingStart?) => void) => {
|
if (isDownVoted) {
|
||||||
const handle = findNodeHandle(ref.current);
|
downVoteIconName = 'downcircle';
|
||||||
if (handle) {
|
}
|
||||||
NativeModules.UIManager.measure(handle, (x0, y0, width, height, x, y) => {
|
|
||||||
const anchorRect: Rect = { x, y, width, height };
|
|
||||||
callback(anchorRect)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return (
|
||||||
const _onPress = () => {
|
<View style={styles.container}>
|
||||||
const _onVotingStart = (status) => {
|
<TouchableOpacity ref={upvoteRef} onPress={_onPress} style={styles.upvoteButton}>
|
||||||
if(status > 0){
|
{/* <Fragment>
|
||||||
setIsVoted(true);
|
|
||||||
} else if (status < 0) {
|
|
||||||
setIsDownVoted(true);
|
|
||||||
} else {
|
|
||||||
_calculateVoteStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_getRectFromRef(upvoteRef, (rect)=>{
|
|
||||||
onUpvotePress(rect, _onVotingStart)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const _onDetailsPress = () => {
|
|
||||||
_getRectFromRef(detailsRef, onPayoutDetailsPress)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const isDeclinedPayout = content?.is_declined_payout;
|
|
||||||
const totalPayout = content?.total_payout;
|
|
||||||
const maxPayout = content?.max_payout;
|
|
||||||
|
|
||||||
const payoutLimitHit = totalPayout >= maxPayout;
|
|
||||||
const _shownPayout = payoutLimitHit && maxPayout > 0 ? maxPayout : totalPayout;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let iconName = 'upcircleo';
|
|
||||||
const iconType = 'AntDesign';
|
|
||||||
let downVoteIconName = 'downcircleo';
|
|
||||||
|
|
||||||
if (isVoted) {
|
|
||||||
iconName = 'upcircle';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDownVoted) {
|
|
||||||
downVoteIconName = 'downcircle';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles.container}>
|
|
||||||
<TouchableOpacity
|
|
||||||
ref={upvoteRef}
|
|
||||||
onPress={_onPress}
|
|
||||||
style={styles.upvoteButton}
|
|
||||||
>
|
|
||||||
{/* <Fragment>
|
|
||||||
{isVoting ? (
|
{isVoting ? (
|
||||||
<View style={{ width: 19 }}>
|
<View style={{ width: 19 }}>
|
||||||
<PulseAnimation
|
<PulseAnimation
|
||||||
@ -130,34 +112,32 @@ export const UpvoteButton = ({
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
) : ( */}
|
) : ( */}
|
||||||
<View hitSlop={{ top: 10, bottom: 10, left: 10, right: 5 }}>
|
<View hitSlop={{ top: 10, bottom: 10, left: 10, right: 5 }}>
|
||||||
<Icon
|
<Icon
|
||||||
style={[styles.upvoteIcon, isDownVoted && { color: '#ec8b88' }]}
|
style={[styles.upvoteIcon, isDownVoted && { color: '#ec8b88' }]}
|
||||||
active={!currentAccount}
|
active={!currentAccount}
|
||||||
iconType={iconType}
|
iconType={iconType}
|
||||||
name={isDownVoted ? downVoteIconName : iconName}
|
name={isDownVoted ? downVoteIconName : iconName}
|
||||||
/>
|
/>
|
||||||
</View>
|
|
||||||
{/* )}
|
|
||||||
</Fragment> */}
|
|
||||||
</TouchableOpacity>
|
|
||||||
<View style={styles.payoutTextButton}>
|
|
||||||
{isShowPayoutValue && (
|
|
||||||
<TouchableOpacity ref={detailsRef} onPress={_onDetailsPress} >
|
|
||||||
<Text
|
|
||||||
style={[
|
|
||||||
styles.payoutValue,
|
|
||||||
isDeclinedPayout && styles.declinedPayout,
|
|
||||||
boldPayout && styles.boldText,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{<FormattedCurrency value={_shownPayout || '0.000'} />}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
|
{/* )}
|
||||||
)
|
</Fragment> */}
|
||||||
}
|
</TouchableOpacity>
|
||||||
|
<View style={styles.payoutTextButton}>
|
||||||
|
{isShowPayoutValue && (
|
||||||
|
<TouchableOpacity ref={detailsRef} onPress={_onDetailsPress}>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.payoutValue,
|
||||||
|
isDeclinedPayout && styles.declinedPayout,
|
||||||
|
boldPayout && styles.boldText,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<FormattedCurrency value={_shownPayout || '0.000'} />
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -15,12 +15,15 @@ export const CommentsSection = ({ item, index, revealReplies, ...props }) => {
|
|||||||
|
|
||||||
const _renderComment = (item, index = 0) => {
|
const _renderComment = (item, index = 0) => {
|
||||||
// animation makes sure there is 100 ms gab between each comment item
|
// animation makes sure there is 100 ms gab between each comment item
|
||||||
const _enteringAnim = index >= 0
|
const _enteringAnim =
|
||||||
? SlideInRight.duration(150).springify().delay(index * 100)
|
index >= 0
|
||||||
: undefined
|
? SlideInRight.duration(150)
|
||||||
|
.springify()
|
||||||
|
.delay(index * 100)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View key={item.author + item.permlink} entering={_enteringAnim}>
|
<Animated.View key={item.author + item.permlink} entering={_enteringAnim}>
|
||||||
<Comment
|
<Comment
|
||||||
comment={item}
|
comment={item}
|
||||||
repliesToggle={toggle}
|
repliesToggle={toggle}
|
||||||
|
@ -21,7 +21,11 @@ import { FilterBar } from '../../filterBar';
|
|||||||
import { postQueries } from '../../../providers/queries';
|
import { postQueries } from '../../../providers/queries';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../hooks';
|
import { useAppDispatch, useAppSelector } from '../../../hooks';
|
||||||
import ROUTES from '../../../constants/routeNames';
|
import ROUTES from '../../../constants/routeNames';
|
||||||
import { showActionModal, showProfileModal, toastNotification } from '../../../redux/actions/uiAction';
|
import {
|
||||||
|
showActionModal,
|
||||||
|
showProfileModal,
|
||||||
|
toastNotification,
|
||||||
|
} from '../../../redux/actions/uiAction';
|
||||||
import { writeToClipboard } from '../../../utils/clipboard';
|
import { writeToClipboard } from '../../../utils/clipboard';
|
||||||
import { deleteComment } from '../../../providers/hive/dhive';
|
import { deleteComment } from '../../../providers/hive/dhive';
|
||||||
import { updateCommentCache } from '../../../redux/actions/cacheActions';
|
import { updateCommentCache } from '../../../redux/actions/cacheActions';
|
||||||
@ -34,8 +38,6 @@ import { sortComments } from '../children/sortComments';
|
|||||||
import styles from '../children/postComments.styles';
|
import styles from '../children/postComments.styles';
|
||||||
import { PostHtmlInteractionHandler } from '../../postHtmlRenderer';
|
import { PostHtmlInteractionHandler } from '../../postHtmlRenderer';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const PostComments = forwardRef(
|
const PostComments = forwardRef(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@ -47,7 +49,7 @@ const PostComments = forwardRef(
|
|||||||
onRefresh,
|
onRefresh,
|
||||||
handleOnCommentsLoaded,
|
handleOnCommentsLoaded,
|
||||||
handleOnReplyPress,
|
handleOnReplyPress,
|
||||||
onUpvotePress
|
onUpvotePress,
|
||||||
},
|
},
|
||||||
ref,
|
ref,
|
||||||
) => {
|
) => {
|
||||||
@ -63,7 +65,7 @@ const PostComments = forwardRef(
|
|||||||
const postsCachePrimer = postQueries.usePostsCachePrimer();
|
const postsCachePrimer = postQueries.usePostsCachePrimer();
|
||||||
|
|
||||||
const writeCommentRef = useRef(null);
|
const writeCommentRef = useRef(null);
|
||||||
const postInteractionRef = useRef<typeof PostHtmlInteractionHandler|null>(null);
|
const postInteractionRef = useRef<typeof PostHtmlInteractionHandler | null>(null);
|
||||||
const commentsListRef = useRef<FlashList<any> | null>(null);
|
const commentsListRef = useRef<FlashList<any> | null>(null);
|
||||||
|
|
||||||
const [selectedFilter, setSelectedFilter] = useState('trending');
|
const [selectedFilter, setSelectedFilter] = useState('trending');
|
||||||
@ -72,7 +74,6 @@ const PostComments = forwardRef(
|
|||||||
|
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
const sortedSections = useMemo(
|
const sortedSections = useMemo(
|
||||||
() => sortComments(selectedFilter, discussionQuery.sectionedData),
|
() => sortComments(selectedFilter, discussionQuery.sectionedData),
|
||||||
[discussionQuery.sectionedData, selectedFilter],
|
[discussionQuery.sectionedData, selectedFilter],
|
||||||
@ -107,9 +108,6 @@ const PostComments = forwardRef(
|
|||||||
onRefresh();
|
onRefresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _handleOnDropdownSelect = (option, index) => {
|
const _handleOnDropdownSelect = (option, index) => {
|
||||||
setSelectedFilter(option);
|
setSelectedFilter(option);
|
||||||
setSelectedOptionIndex(index);
|
setSelectedOptionIndex(index);
|
||||||
@ -139,7 +137,6 @@ const PostComments = forwardRef(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _handleDeleteComment = (_permlink) => {
|
const _handleDeleteComment = (_permlink) => {
|
||||||
|
|
||||||
const _onConfirmDelete = async () => {
|
const _onConfirmDelete = async () => {
|
||||||
try {
|
try {
|
||||||
await deleteComment(currentAccount, pinHash, _permlink);
|
await deleteComment(currentAccount, pinHash, _permlink);
|
||||||
@ -154,23 +151,27 @@ const PostComments = forwardRef(
|
|||||||
dispatch(updateCommentCache(_commentPath, _deletedItem, { isUpdate: true }));
|
dispatch(updateCommentCache(_commentPath, _deletedItem, { isUpdate: true }));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('Failed to delete comment')
|
console.warn('Failed to delete comment');
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
dispatch(
|
||||||
|
showActionModal({
|
||||||
dispatch(showActionModal({
|
title: intl.formatMessage({ id: 'delete.confirm_delete_title' }),
|
||||||
title: intl.formatMessage({ id: 'delete.confirm_delete_title' }),
|
buttons: [
|
||||||
buttons: [{
|
{
|
||||||
text: intl.formatMessage({ id: 'alert.cancel' }),
|
text: intl.formatMessage({ id: 'alert.cancel' }),
|
||||||
onPress: () => { console.log("canceled delete comment") }
|
onPress: () => {
|
||||||
}, {
|
console.log('canceled delete comment');
|
||||||
text: intl.formatMessage({ id: 'alert.delete' }),
|
},
|
||||||
onPress: _onConfirmDelete
|
},
|
||||||
}]
|
{
|
||||||
}))
|
text: intl.formatMessage({ id: 'alert.delete' }),
|
||||||
|
onPress: _onConfirmDelete,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const _openReplyThread = (comment) => {
|
const _openReplyThread = (comment) => {
|
||||||
@ -187,7 +188,7 @@ const PostComments = forwardRef(
|
|||||||
|
|
||||||
const _handleOnUserPress = (username) => {
|
const _handleOnUserPress = (username) => {
|
||||||
dispatch(showProfileModal(username));
|
dispatch(showProfileModal(username));
|
||||||
}
|
};
|
||||||
|
|
||||||
const _handleShowOptionsMenu = (comment) => {
|
const _handleShowOptionsMenu = (comment) => {
|
||||||
const _showCopiedToast = () => {
|
const _showCopiedToast = () => {
|
||||||
@ -231,11 +232,6 @@ const PostComments = forwardRef(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _onContentSizeChange = (x: number, y: number) => {
|
const _onContentSizeChange = (x: number, y: number) => {
|
||||||
// update header height
|
// update header height
|
||||||
if (y !== headerHeight) {
|
if (y !== headerHeight) {
|
||||||
@ -243,8 +239,6 @@ const PostComments = forwardRef(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _postContentView = (
|
const _postContentView = (
|
||||||
<>
|
<>
|
||||||
{postContentView && postContentView}
|
{postContentView && postContentView}
|
||||||
@ -263,8 +257,7 @@ const PostComments = forwardRef(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const _renderEmptyContent = () => {
|
const _renderEmptyContent = () => {
|
||||||
|
if (isPostLoading) {
|
||||||
if(isPostLoading){
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,10 +296,8 @@ const PostComments = forwardRef(
|
|||||||
openReplyThread={_openReplyThread}
|
openReplyThread={_openReplyThread}
|
||||||
onUpvotePress={(args) => onUpvotePress({ ...args, postType: PostTypes.COMMENT })}
|
onUpvotePress={(args) => onUpvotePress({ ...args, postType: PostTypes.COMMENT })}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
@ -333,14 +324,10 @@ const PostComments = forwardRef(
|
|||||||
}
|
}
|
||||||
overScrollMode="never"
|
overScrollMode="never"
|
||||||
/>
|
/>
|
||||||
<PostHtmlInteractionHandler
|
<PostHtmlInteractionHandler ref={postInteractionRef} />
|
||||||
ref={postInteractionRef}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export default PostComments;
|
export default PostComments;
|
||||||
|
|
||||||
|
@ -101,7 +101,6 @@ const CommentBody = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const _handleOnUserPress = (username) => {
|
const _handleOnUserPress = (username) => {
|
||||||
if (handleOnUserPress) {
|
if (handleOnUserPress) {
|
||||||
handleOnUserPress(username);
|
handleOnUserPress(username);
|
||||||
|
@ -50,7 +50,7 @@ export const PostHtmlRenderer = memo(
|
|||||||
body = body
|
body = body
|
||||||
.replace(/<center>/g, '<div class="text-center">')
|
.replace(/<center>/g, '<div class="text-center">')
|
||||||
.replace(/<\/center>/g, '</div>')
|
.replace(/<\/center>/g, '</div>')
|
||||||
.replace(/<span(.*?)>/g, '') //TODO: later handle span with propties lie <span class="ll-key"> and remove on raw <span/>
|
.replace(/<span(.*?)>/g, '') // TODO: later handle span with propties lie <span class="ll-key"> and remove on raw <span/>
|
||||||
.replace(/<\/span>/g, '');
|
.replace(/<\/span>/g, '');
|
||||||
|
|
||||||
const _minTableColWidth = contentWidth / 3 - 12;
|
const _minTableColWidth = contentWidth / 3 - 12;
|
||||||
@ -277,7 +277,6 @@ export const PostHtmlRenderer = memo(
|
|||||||
const _paraRenderer = ({ TDefaultRenderer, ...props }: CustomRendererProps<TNode>) => {
|
const _paraRenderer = ({ TDefaultRenderer, ...props }: CustomRendererProps<TNode>) => {
|
||||||
props.style = props.tnode.parent.tagName === 'li' ? styles.pLi : styles.p;
|
props.style = props.tnode.parent.tagName === 'li' ? styles.pLi : styles.p;
|
||||||
props.onPress = !props.onPress && handleOnContentPress ? handleOnContentPress : props.onPress;
|
props.onPress = !props.onPress && handleOnContentPress ? handleOnContentPress : props.onPress;
|
||||||
|
|
||||||
|
|
||||||
return <TDefaultRenderer {...props} />;
|
return <TDefaultRenderer {...props} />;
|
||||||
};
|
};
|
||||||
@ -399,7 +398,7 @@ export const PostHtmlRenderer = memo(
|
|||||||
customHTMLElementModels={customHTMLElementModels}
|
customHTMLElementModels={customHTMLElementModels}
|
||||||
renderersProps={renderersProps}
|
renderersProps={renderersProps}
|
||||||
WebView={WebView}
|
WebView={WebView}
|
||||||
pressableHightlightColor={'transparent'}
|
pressableHightlightColor="transparent"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -87,7 +87,7 @@ export default EStyleSheet.create({
|
|||||||
color: '$primaryRed',
|
color: '$primaryRed',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
textJustify: {
|
textJustify: {
|
||||||
textAlign: Platform.select({ ios: 'justify', android: 'auto' }), //justify with selectable on android causes ends of text getting clipped,
|
textAlign: Platform.select({ ios: 'justify', android: 'auto' }), // justify with selectable on android causes ends of text getting clipped,
|
||||||
letterSpacing: 0,
|
letterSpacing: 0,
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
revealButton: {
|
revealButton: {
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import React, {
|
import React, { forwardRef, useImperativeHandle, useRef, useState, Fragment } from 'react';
|
||||||
forwardRef,
|
|
||||||
useImperativeHandle,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
Fragment,
|
|
||||||
} from 'react';
|
|
||||||
import { PermissionsAndroid, Platform, SafeAreaView, View, Text } from 'react-native';
|
import { PermissionsAndroid, Platform, SafeAreaView, View, Text } from 'react-native';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import ActionsSheet from 'react-native-actions-sheet';
|
import ActionsSheet from 'react-native-actions-sheet';
|
||||||
@ -12,29 +6,27 @@ import ImageView from 'react-native-image-viewing';
|
|||||||
|
|
||||||
// Components
|
// Components
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
import CameraRoll from '@react-native-community/cameraroll';
|
||||||
|
import RNFetchBlob from 'rn-fetch-blob';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import ROUTES from '../../constants/routeNames';
|
import ROUTES from '../../constants/routeNames';
|
||||||
import { toastNotification } from '../../redux/actions/uiAction';
|
import { toastNotification } from '../../redux/actions/uiAction';
|
||||||
import { writeToClipboard } from '../../utils/clipboard';
|
import { writeToClipboard } from '../../utils/clipboard';
|
||||||
|
|
||||||
import CameraRoll from '@react-native-community/cameraroll';
|
|
||||||
import RNFetchBlob from 'rn-fetch-blob';
|
|
||||||
import { OptionsModal } from '../atoms';
|
import { OptionsModal } from '../atoms';
|
||||||
import VideoPlayer from '../videoPlayer/videoPlayerView';
|
import VideoPlayer from '../videoPlayer/videoPlayerView';
|
||||||
|
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
import { useNavigation } from '@react-navigation/native';
|
|
||||||
import { IconButton } from '../buttons';
|
import { IconButton } from '../buttons';
|
||||||
import styles from './postHtmlRendererStyles'
|
import styles from './postHtmlRendererStyles';
|
||||||
import { PostTypes } from '../../constants/postTypes';
|
import { PostTypes } from '../../constants/postTypes';
|
||||||
|
|
||||||
interface PostHtmlInteractionHandlerProps {
|
interface PostHtmlInteractionHandlerProps {
|
||||||
postType?:PostTypes
|
postType?: PostTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PostHtmlInteractionHandler = forwardRef(({
|
export const PostHtmlInteractionHandler = forwardRef(
|
||||||
postType
|
({ postType }: PostHtmlInteractionHandlerProps, ref) => {
|
||||||
}:PostHtmlInteractionHandlerProps, ref) => {
|
|
||||||
|
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@ -52,245 +44,240 @@ export const PostHtmlInteractionHandler = forwardRef(({
|
|||||||
const [selectedImage, setSelectedImage] = useState(null);
|
const [selectedImage, setSelectedImage] = useState(null);
|
||||||
const [selectedLink, setSelectedLink] = useState(null);
|
const [selectedLink, setSelectedLink] = useState(null);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
handleImagePress: (url: string, postImgUrls: string[]) => {
|
handleImagePress: (url: string, postImgUrls: string[]) => {
|
||||||
setPostImages(postImgUrls);
|
setPostImages(postImgUrls);
|
||||||
setSelectedImage(url);
|
setSelectedImage(url);
|
||||||
if(postType === PostTypes.WAVE){
|
if (postType === PostTypes.WAVE) {
|
||||||
setIsImageModalOpen(true);
|
setIsImageModalOpen(true);
|
||||||
} else {
|
} else {
|
||||||
actionImage.current?.show();
|
actionImage.current?.show();
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
handleLinkPress: (url: string) => {
|
|
||||||
setSelectedLink(url);
|
|
||||||
actionLink.current?.show();
|
|
||||||
},
|
|
||||||
handleYoutubePress: (videoId, startTime) => {
|
|
||||||
if (videoId && youtubePlayerRef.current) {
|
|
||||||
setYoutubeVideoId(videoId);
|
|
||||||
setVideoStartTime(startTime);
|
|
||||||
youtubePlayerRef.current.setModalVisible(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleVideoPress: (embedUrl) => {
|
|
||||||
if (embedUrl && youtubePlayerRef.current) {
|
|
||||||
setVideoUrl(embedUrl);
|
|
||||||
setVideoStartTime(0);
|
|
||||||
youtubePlayerRef.current.setModalVisible(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
},
|
||||||
|
handleLinkPress: (url: string) => {
|
||||||
|
setSelectedLink(url);
|
||||||
|
actionLink.current?.show();
|
||||||
|
},
|
||||||
|
handleYoutubePress: (videoId, startTime) => {
|
||||||
|
if (videoId && youtubePlayerRef.current) {
|
||||||
|
setYoutubeVideoId(videoId);
|
||||||
|
setVideoStartTime(startTime);
|
||||||
|
youtubePlayerRef.current.setModalVisible(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleVideoPress: (embedUrl) => {
|
||||||
|
if (embedUrl && youtubePlayerRef.current) {
|
||||||
|
setVideoUrl(embedUrl);
|
||||||
|
setVideoStartTime(0);
|
||||||
|
youtubePlayerRef.current.setModalVisible(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const checkAndroidPermission = async () => {
|
const checkAndroidPermission = async () => {
|
||||||
try {
|
try {
|
||||||
const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;
|
const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;
|
||||||
await PermissionsAndroid.request(permission);
|
await PermissionsAndroid.request(permission);
|
||||||
Promise.resolve();
|
Promise.resolve();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Promise.reject(error);
|
Promise.reject(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const _downloadImage = async (uri) => {
|
const _downloadImage = async (uri) => {
|
||||||
return RNFetchBlob.config({
|
return RNFetchBlob.config({
|
||||||
fileCache: true,
|
fileCache: true,
|
||||||
appendExt: 'jpg',
|
appendExt: 'jpg',
|
||||||
})
|
})
|
||||||
.fetch('GET', uri)
|
.fetch('GET', uri)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const { status } = res.info();
|
const { status } = res.info();
|
||||||
|
|
||||||
if (status == 200) {
|
if (status == 200) {
|
||||||
return res.path();
|
return res.path();
|
||||||
} else {
|
} else {
|
||||||
Promise.reject();
|
Promise.reject();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((errorMessage) => {
|
.catch((errorMessage) => {
|
||||||
Promise.reject(errorMessage);
|
Promise.reject(errorMessage);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const _saveImage = async (uri) => {
|
const _saveImage = async (uri) => {
|
||||||
try {
|
try {
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
await checkAndroidPermission();
|
await checkAndroidPermission();
|
||||||
uri = `file://${await _downloadImage(uri)}`;
|
uri = `file://${await _downloadImage(uri)}`;
|
||||||
}
|
|
||||||
CameraRoll.saveToCameraRoll(uri)
|
|
||||||
.then(() => {
|
|
||||||
dispatch(
|
|
||||||
toastNotification(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'post.image_saved',
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
dispatch(
|
|
||||||
toastNotification(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'post.image_saved_error',
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
dispatch(
|
|
||||||
toastNotification(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'post.image_saved_error',
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
CameraRoll.saveToCameraRoll(uri)
|
||||||
|
.then(() => {
|
||||||
|
dispatch(
|
||||||
|
toastNotification(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'post.image_saved',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
dispatch(
|
||||||
|
toastNotification(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'post.image_saved_error',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(
|
||||||
|
toastNotification(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'post.image_saved_error',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const _handleImageOptionPress = (ind) => {
|
const _handleImageOptionPress = (ind) => {
|
||||||
if (ind === 1) {
|
if (ind === 1) {
|
||||||
// open gallery mode
|
// open gallery mode
|
||||||
setIsImageModalOpen(true);
|
setIsImageModalOpen(true);
|
||||||
}
|
}
|
||||||
if (ind === 0) {
|
if (ind === 0) {
|
||||||
// copy to clipboard
|
// copy to clipboard
|
||||||
writeToClipboard(selectedImage).then(() => {
|
writeToClipboard(selectedImage).then(() => {
|
||||||
dispatch(
|
dispatch(
|
||||||
toastNotification(
|
toastNotification(
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
id: 'alert.copied',
|
id: 'alert.copied',
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (ind === 2) {
|
if (ind === 2) {
|
||||||
// save to local
|
// save to local
|
||||||
_saveImage(selectedImage);
|
_saveImage(selectedImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedImage(null);
|
setSelectedImage(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const _handleLinkOptionPress = (ind) => {
|
const _handleLinkOptionPress = (ind) => {
|
||||||
if (ind === 1) {
|
if (ind === 1) {
|
||||||
// open link
|
// open link
|
||||||
if (selectedLink) {
|
if (selectedLink) {
|
||||||
navigation.navigate({
|
navigation.navigate({
|
||||||
name: ROUTES.SCREENS.WEB_BROWSER,
|
name: ROUTES.SCREENS.WEB_BROWSER,
|
||||||
params: {
|
params: {
|
||||||
url: selectedLink,
|
url: selectedLink,
|
||||||
},
|
},
|
||||||
key: selectedLink,
|
key: selectedLink,
|
||||||
} as never);
|
} as never);
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ind === 0) {
|
|
||||||
// copy to clipboard
|
|
||||||
writeToClipboard(selectedLink).then(() => {
|
|
||||||
dispatch(
|
|
||||||
toastNotification(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'alert.copied',
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (ind === 0) {
|
||||||
|
// copy to clipboard
|
||||||
|
writeToClipboard(selectedLink).then(() => {
|
||||||
|
dispatch(
|
||||||
|
toastNotification(
|
||||||
|
intl.formatMessage({
|
||||||
|
id: 'alert.copied',
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setSelectedLink(null);
|
setSelectedLink(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const _renderImageViewerHeader = (imageIndex) => {
|
const _renderImageViewerHeader = (imageIndex) => {
|
||||||
return (
|
return (
|
||||||
<SafeAreaView
|
<SafeAreaView
|
||||||
style={{
|
style={{
|
||||||
marginTop: Platform.select({ ios: 0, android: 25 }),
|
marginTop: Platform.select({ ios: 0, android: 25 }),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={styles.imageViewerHeaderContainer}>
|
<View style={styles.imageViewerHeaderContainer}>
|
||||||
<Text style={styles.imageGalleryHeaderText}>{`${imageIndex + 1}/${
|
<Text style={styles.imageGalleryHeaderText}>{`${imageIndex + 1}/${
|
||||||
postImages.length
|
postImages.length
|
||||||
}`}</Text>
|
}`}</Text>
|
||||||
<IconButton
|
<IconButton
|
||||||
name="close"
|
name="close"
|
||||||
color={EStyleSheet.value('$primaryDarkText')}
|
color={EStyleSheet.value('$primaryDarkText')}
|
||||||
buttonStyle={styles.closeIconButton}
|
buttonStyle={styles.closeIconButton}
|
||||||
size={20}
|
size={20}
|
||||||
handleOnPress={() => setIsImageModalOpen(false)}
|
handleOnPress={() => setIsImageModalOpen(false)}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<ImageView
|
<ImageView
|
||||||
images={postImages.map((url) => ({ uri: url }))}
|
images={postImages.map((url) => ({ uri: url }))}
|
||||||
imageIndex={0}
|
imageIndex={0}
|
||||||
visible={isImageModalOpen}
|
visible={isImageModalOpen}
|
||||||
animationType="slide"
|
animationType="slide"
|
||||||
swipeToCloseEnabled
|
swipeToCloseEnabled
|
||||||
onRequestClose={() => setIsImageModalOpen(false)}
|
onRequestClose={() => setIsImageModalOpen(false)}
|
||||||
HeaderComponent={(imageIndex) => _renderImageViewerHeader(imageIndex.imageIndex)}
|
HeaderComponent={(imageIndex) => _renderImageViewerHeader(imageIndex.imageIndex)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<OptionsModal
|
<OptionsModal
|
||||||
ref={actionImage}
|
ref={actionImage}
|
||||||
options={[
|
options={[
|
||||||
intl.formatMessage({ id: 'post.copy_link' }),
|
intl.formatMessage({ id: 'post.copy_link' }),
|
||||||
intl.formatMessage({ id: 'post.gallery_mode' }),
|
intl.formatMessage({ id: 'post.gallery_mode' }),
|
||||||
intl.formatMessage({ id: 'post.save_to_local' }),
|
intl.formatMessage({ id: 'post.save_to_local' }),
|
||||||
intl.formatMessage({ id: 'alert.cancel' }),
|
intl.formatMessage({ id: 'alert.cancel' }),
|
||||||
]}
|
]}
|
||||||
title={intl.formatMessage({ id: 'post.image' })}
|
title={intl.formatMessage({ id: 'post.image' })}
|
||||||
cancelButtonIndex={3}
|
cancelButtonIndex={3}
|
||||||
onPress={(index) => {
|
onPress={(index) => {
|
||||||
_handleImageOptionPress(index);
|
_handleImageOptionPress(index);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<OptionsModal
|
||||||
|
ref={actionLink}
|
||||||
|
options={[
|
||||||
|
intl.formatMessage({ id: 'post.copy_link' }),
|
||||||
|
intl.formatMessage({ id: 'alert.external_link' }),
|
||||||
|
intl.formatMessage({ id: 'alert.cancel' }),
|
||||||
|
]}
|
||||||
|
title={intl.formatMessage({ id: 'post.link' })}
|
||||||
|
cancelButtonIndex={2}
|
||||||
|
onPress={(index) => {
|
||||||
|
_handleLinkOptionPress(index);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<OptionsModal
|
<ActionsSheet
|
||||||
ref={actionLink}
|
ref={youtubePlayerRef}
|
||||||
options={[
|
gestureEnabled={true}
|
||||||
intl.formatMessage({ id: 'post.copy_link' }),
|
hideUnderlay={true}
|
||||||
intl.formatMessage({ id: 'alert.external_link' }),
|
containerStyle={{ backgroundColor: 'black' }}
|
||||||
intl.formatMessage({ id: 'alert.cancel' }),
|
indicatorColor={EStyleSheet.value('$primaryWhiteLightBackground')}
|
||||||
]}
|
onClose={() => {
|
||||||
title={intl.formatMessage({ id: 'post.link' })}
|
setYoutubeVideoId(null);
|
||||||
cancelButtonIndex={2}
|
setVideoUrl(null);
|
||||||
onPress={(index) => {
|
}}
|
||||||
_handleLinkOptionPress(index);
|
>
|
||||||
}}
|
<VideoPlayer
|
||||||
/>
|
mode={youtubeVideoId ? 'youtube' : 'uri'}
|
||||||
|
youtubeVideoId={youtubeVideoId}
|
||||||
<ActionsSheet
|
uri={videoUrl}
|
||||||
ref={youtubePlayerRef}
|
startTime={videoStartTime}
|
||||||
gestureEnabled={true}
|
/>
|
||||||
hideUnderlay={true}
|
</ActionsSheet>
|
||||||
containerStyle={{ backgroundColor: 'black' }}
|
</Fragment>
|
||||||
indicatorColor={EStyleSheet.value('$primaryWhiteLightBackground')}
|
);
|
||||||
onClose={() => {
|
},
|
||||||
setYoutubeVideoId(null);
|
);
|
||||||
setVideoUrl(null);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<VideoPlayer
|
|
||||||
mode={youtubeVideoId ? 'youtube' : 'uri'}
|
|
||||||
youtubeVideoId={youtubeVideoId}
|
|
||||||
uri={videoUrl}
|
|
||||||
startTime={videoStartTime}
|
|
||||||
/>
|
|
||||||
</ActionsSheet>
|
|
||||||
</Fragment>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
@ -15,7 +15,7 @@ export default EStyleSheet.create({
|
|||||||
marginTop: -4,
|
marginTop: -4,
|
||||||
marginBottom: 4,
|
marginBottom: 4,
|
||||||
},
|
},
|
||||||
titlePlaceholder:{
|
titlePlaceholder: {
|
||||||
marginBottom: 4,
|
marginBottom: 4,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
|
@ -110,11 +110,7 @@ const PostDisplayView = ({
|
|||||||
content,
|
content,
|
||||||
onVotingStart,
|
onVotingStart,
|
||||||
showPayoutDetails = false,
|
showPayoutDetails = false,
|
||||||
postType = isWavePost
|
postType = isWavePost ? PostTypes.WAVE : parentPost ? PostTypes.COMMENT : PostTypes.POST,
|
||||||
? PostTypes.WAVE
|
|
||||||
: parentPost
|
|
||||||
? PostTypes.COMMENT
|
|
||||||
: PostTypes.POST
|
|
||||||
}: any) => {
|
}: any) => {
|
||||||
if (upvotePopoverRef.current) {
|
if (upvotePopoverRef.current) {
|
||||||
upvotePopoverRef.current.showPopover({
|
upvotePopoverRef.current.showPopover({
|
||||||
@ -236,7 +232,7 @@ const PostDisplayView = ({
|
|||||||
// show quick reply modal
|
// show quick reply modal
|
||||||
const _showQuickReplyModal = (_post = post) => {
|
const _showQuickReplyModal = (_post = post) => {
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
dispatch(showReplyModal({mode:'comment', parentPost:_post}));
|
dispatch(showReplyModal({ mode: 'comment', parentPost: _post }));
|
||||||
} else {
|
} else {
|
||||||
console.log('Not LoggedIn');
|
console.log('Not LoggedIn');
|
||||||
}
|
}
|
||||||
@ -253,7 +249,6 @@ const PostDisplayView = ({
|
|||||||
setIsLoadedComments(true);
|
setIsLoadedComments(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const _postContentView = (
|
const _postContentView = (
|
||||||
<>
|
<>
|
||||||
{parentPost && <ParentPost post={parentPost} />}
|
{parentPost && <ParentPost post={parentPost} />}
|
||||||
@ -267,12 +262,11 @@ const PostDisplayView = ({
|
|||||||
setPostBodyHeight(event.nativeEvent.layout.height);
|
setPostBodyHeight(event.nativeEvent.layout.height);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{!!post.title && !post.depth ? (
|
||||||
{
|
<Text style={styles.title}>{post.title}</Text>
|
||||||
!!post.title && !post.depth
|
) : (
|
||||||
? <Text style={styles.title}>{post.title}</Text>
|
<View style={styles.titlePlaceholder} />
|
||||||
: <View style={styles.titlePlaceholder} />
|
)}
|
||||||
}
|
|
||||||
|
|
||||||
<PostHeaderDescription
|
<PostHeaderDescription
|
||||||
date={formatedTime}
|
date={formatedTime}
|
||||||
@ -304,7 +298,10 @@ const PostDisplayView = ({
|
|||||||
)}
|
)}
|
||||||
{formatedTime}
|
{formatedTime}
|
||||||
</Text>
|
</Text>
|
||||||
<WritePostButton placeholderId={'quick_reply.placeholder'} onPress={_showQuickReplyModal} />
|
<WritePostButton
|
||||||
|
placeholderId="quick_reply.placeholder"
|
||||||
|
onPress={_showQuickReplyModal}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
@ -7,13 +7,7 @@ import React, {
|
|||||||
Fragment,
|
Fragment,
|
||||||
useMemo,
|
useMemo,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import {
|
import { FlatListProps, FlatList, RefreshControl, ActivityIndicator, View } from 'react-native';
|
||||||
FlatListProps,
|
|
||||||
FlatList,
|
|
||||||
RefreshControl,
|
|
||||||
ActivityIndicator,
|
|
||||||
View,
|
|
||||||
} from 'react-native';
|
|
||||||
import { FlashList } from '@shopify/flash-list';
|
import { FlashList } from '@shopify/flash-list';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { TextStyle, ViewStyle } from 'react-native';
|
import { TextStyle, ViewStyle } from 'react-native';
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
import getWindowDimensions from '../../utils/getWindowDimensions';
|
import getWindowDimensions from '../../utils/getWindowDimensions';
|
||||||
|
|
||||||
const { width: SCREEN_WIDTH } = getWindowDimensions();
|
const { width: SCREEN_WIDTH } = getWindowDimensions();
|
||||||
|
|
||||||
export default EStyleSheet.create({
|
export default EStyleSheet.create({
|
||||||
|
@ -5,6 +5,7 @@ import EStyleSheet from 'react-native-extended-stylesheet';
|
|||||||
import QRCodeScanner from 'react-native-qrcode-scanner';
|
import QRCodeScanner from 'react-native-qrcode-scanner';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { check, request, PERMISSIONS, RESULTS, openSettings } from 'react-native-permissions';
|
import { check, request, PERMISSIONS, RESULTS, openSettings } from 'react-native-permissions';
|
||||||
|
import { get } from 'lodash';
|
||||||
import styles from './qrModalStyles';
|
import styles from './qrModalStyles';
|
||||||
import { useAppDispatch, useAppSelector } from '../../hooks';
|
import { useAppDispatch, useAppSelector } from '../../hooks';
|
||||||
import {
|
import {
|
||||||
@ -19,13 +20,13 @@ import getWindowDimensions from '../../utils/getWindowDimensions';
|
|||||||
import { isHiveUri, getFormattedTx } from '../../utils/hive-uri';
|
import { isHiveUri, getFormattedTx } from '../../utils/hive-uri';
|
||||||
import { handleHiveUriOperation, resolveTransaction } from '../../providers/hive/dhive';
|
import { handleHiveUriOperation, resolveTransaction } from '../../providers/hive/dhive';
|
||||||
import bugsnagInstance from '../../config/bugsnag';
|
import bugsnagInstance from '../../config/bugsnag';
|
||||||
import { get } from 'lodash';
|
|
||||||
import showLoginAlert from '../../utils/showLoginAlert';
|
import showLoginAlert from '../../utils/showLoginAlert';
|
||||||
import authType from '../../constants/authType';
|
import authType from '../../constants/authType';
|
||||||
import { delay } from '../../utils/editor';
|
import { delay } from '../../utils/editor';
|
||||||
import ROUTES from '../../../src/constants/routeNames';
|
import ROUTES from '../../constants/routeNames';
|
||||||
|
|
||||||
const hiveuri = require('hive-uri');
|
const hiveuri = require('hive-uri');
|
||||||
|
|
||||||
const screenHeight = getWindowDimensions().height;
|
const screenHeight = getWindowDimensions().height;
|
||||||
interface QRModalProps {}
|
interface QRModalProps {}
|
||||||
|
|
||||||
@ -149,7 +150,7 @@ export const QRModal = ({}: QRModalProps) => {
|
|||||||
await delay(500); // NOTE: it's required to avoid modal mis fire
|
await delay(500); // NOTE: it's required to avoid modal mis fire
|
||||||
dispatch(
|
dispatch(
|
||||||
showWebViewModal({
|
showWebViewModal({
|
||||||
uri: uri,
|
uri,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@ -157,10 +158,10 @@ export const QRModal = ({}: QRModalProps) => {
|
|||||||
|
|
||||||
const parsed = hiveuri.decode(uri);
|
const parsed = hiveuri.decode(uri);
|
||||||
const authoritiesMap = new Map();
|
const authoritiesMap = new Map();
|
||||||
authoritiesMap.set('active', currentAccount?.local?.activeKey ? true : false);
|
authoritiesMap.set('active', !!currentAccount?.local?.activeKey);
|
||||||
authoritiesMap.set('posting', currentAccount?.local?.postingKey ? true : false);
|
authoritiesMap.set('posting', !!currentAccount?.local?.postingKey);
|
||||||
authoritiesMap.set('owner', currentAccount?.local?.ownerKey ? true : false);
|
authoritiesMap.set('owner', !!currentAccount?.local?.ownerKey);
|
||||||
authoritiesMap.set('memo', currentAccount?.local?.memoKey ? true : false);
|
authoritiesMap.set('memo', !!currentAccount?.local?.memoKey);
|
||||||
|
|
||||||
getFormattedTx(parsed.tx, authoritiesMap)
|
getFormattedTx(parsed.tx, authoritiesMap)
|
||||||
.then(async (formattedTx) => {
|
.then(async (formattedTx) => {
|
||||||
@ -218,7 +219,6 @@ export const QRModal = ({}: QRModalProps) => {
|
|||||||
{ key: errObj.authorityKeyType },
|
{ key: errObj.authorityKeyType },
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,25 +9,24 @@ import React, {
|
|||||||
useMemo,
|
useMemo,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
import {
|
import { View, Text, TouchableOpacity, Keyboard, Platform, ActivityIndicator } from 'react-native';
|
||||||
View,
|
|
||||||
Text,
|
|
||||||
TouchableOpacity,
|
|
||||||
Keyboard,
|
|
||||||
Platform,
|
|
||||||
ActivityIndicator,
|
|
||||||
} from 'react-native';
|
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { get, debounce } from 'lodash';
|
import { get, debounce } from 'lodash';
|
||||||
import { postBodySummary } from '@ecency/render-helper';
|
import { postBodySummary } from '@ecency/render-helper';
|
||||||
|
import FastImage from 'react-native-fast-image';
|
||||||
import styles from './quickReplyModalStyles';
|
import styles from './quickReplyModalStyles';
|
||||||
import { Icon, IconButton, MainButton, TextButton, TextInput, UploadsGalleryModal, UserAvatar } from '..';
|
|
||||||
import { delay } from '../../utils/editor';
|
|
||||||
import {
|
import {
|
||||||
deleteDraftCacheEntry,
|
Icon,
|
||||||
updateDraftCache,
|
IconButton,
|
||||||
} from '../../redux/actions/cacheActions';
|
MainButton,
|
||||||
|
TextButton,
|
||||||
|
TextInput,
|
||||||
|
UploadsGalleryModal,
|
||||||
|
UserAvatar,
|
||||||
|
} from '..';
|
||||||
|
import { delay } from '../../utils/editor';
|
||||||
|
import { deleteDraftCacheEntry, updateDraftCache } from '../../redux/actions/cacheActions';
|
||||||
import { default as ROUTES } from '../../constants/routeNames';
|
import { default as ROUTES } from '../../constants/routeNames';
|
||||||
import RootNavigation from '../../navigation/rootNavigation';
|
import RootNavigation from '../../navigation/rootNavigation';
|
||||||
import { Draft } from '../../redux/reducers/cacheReducer';
|
import { Draft } from '../../redux/reducers/cacheReducer';
|
||||||
@ -35,11 +34,13 @@ import { RootState } from '../../redux/store/store';
|
|||||||
|
|
||||||
import { postQueries } from '../../providers/queries';
|
import { postQueries } from '../../providers/queries';
|
||||||
import { usePostSubmitter } from './usePostSubmitter';
|
import { usePostSubmitter } from './usePostSubmitter';
|
||||||
import { MediaInsertData, MediaInsertStatus } from '../uploadsGalleryModal/container/uploadsGalleryModal';
|
import {
|
||||||
import FastImage from 'react-native-fast-image';
|
MediaInsertData,
|
||||||
|
MediaInsertStatus,
|
||||||
|
} from '../uploadsGalleryModal/container/uploadsGalleryModal';
|
||||||
|
|
||||||
export interface QuickReplyModalContentProps {
|
export interface QuickReplyModalContentProps {
|
||||||
mode: 'comment' | 'wave' | 'post',
|
mode: 'comment' | 'wave' | 'post';
|
||||||
selectedPost?: any;
|
selectedPost?: any;
|
||||||
handleCloseRef?: any;
|
handleCloseRef?: any;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@ -48,17 +49,12 @@ export interface QuickReplyModalContentProps {
|
|||||||
const MAX_BODY_LENGTH = 250;
|
const MAX_BODY_LENGTH = 250;
|
||||||
|
|
||||||
export const QuickReplyModalContent = forwardRef(
|
export const QuickReplyModalContent = forwardRef(
|
||||||
({
|
({ mode, selectedPost, onClose }: QuickReplyModalContentProps, ref) => {
|
||||||
mode,
|
|
||||||
selectedPost,
|
|
||||||
onClose
|
|
||||||
}: QuickReplyModalContentProps, ref) => {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const uploadsGalleryModalRef = useRef(null);
|
const uploadsGalleryModalRef = useRef(null);
|
||||||
|
|
||||||
|
|
||||||
const postsCachePrimer = postQueries.usePostsCachePrimer();
|
const postsCachePrimer = postQueries.usePostsCachePrimer();
|
||||||
|
|
||||||
const postSubmitter = usePostSubmitter();
|
const postSubmitter = usePostSubmitter();
|
||||||
@ -76,19 +72,20 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
const parentAuthor = selectedPost ? selectedPost.author : '';
|
const parentAuthor = selectedPost ? selectedPost.author : '';
|
||||||
const parentPermlink = selectedPost ? selectedPost.permlink : '';
|
const parentPermlink = selectedPost ? selectedPost.permlink : '';
|
||||||
|
|
||||||
|
const headerText =
|
||||||
|
mode === 'wave'
|
||||||
|
? intl.formatMessage({ id: 'quick_reply.summary_wave' }, { host: 'ecency.waves' }) // TODO: update based on selected host
|
||||||
|
: selectedPost && (selectedPost.summary || postBodySummary(selectedPost, 150, Platform.OS));
|
||||||
|
|
||||||
const headerText = mode === 'wave'
|
const draftId =
|
||||||
? intl.formatMessage({ id: 'quick_reply.summary_wave' }, { host: 'ecency.waves' }) //TODO: update based on selected host
|
mode === 'wave'
|
||||||
: selectedPost && (selectedPost.summary || postBodySummary(selectedPost, 150, Platform.OS));
|
? `${currentAccount.name}/ecency.waves` // TODO: update author based on selected host
|
||||||
|
: `${currentAccount.name}/${parentAuthor}/${parentPermlink}`; // different draftId for each user acount
|
||||||
const draftId = mode === 'wave'
|
|
||||||
? `${currentAccount.name}/ecency.waves` //TODO: update author based on selected host
|
|
||||||
: `${currentAccount.name}/${parentAuthor}/${parentPermlink}`; // different draftId for each user acount
|
|
||||||
|
|
||||||
|
|
||||||
const bodyLengthExceeded = useMemo(
|
const bodyLengthExceeded = useMemo(
|
||||||
() => commentValue.length > MAX_BODY_LENGTH && mode === 'wave',
|
() => commentValue.length > MAX_BODY_LENGTH && mode === 'wave',
|
||||||
[commentValue, mode]);
|
[commentValue, mode],
|
||||||
|
);
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
handleSheetClose() {
|
handleSheetClose() {
|
||||||
@ -112,7 +109,6 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCommentValue(_value);
|
setCommentValue(_value);
|
||||||
|
|
||||||
}, [selectedPost]);
|
}, [selectedPost]);
|
||||||
|
|
||||||
// add quick comment value into cache
|
// add quick comment value into cache
|
||||||
@ -146,29 +142,24 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// handle submit reply
|
// handle submit reply
|
||||||
const _submitPost = async () => {
|
const _submitPost = async () => {
|
||||||
|
|
||||||
let _isSuccess = false;
|
let _isSuccess = false;
|
||||||
let _body = mediaUrls.length > 0 ? commentValue + `\n\n ![Wave Media](${mediaUrls[0]})` : commentValue;
|
const _body =
|
||||||
|
mediaUrls.length > 0 ? `${commentValue}\n\n ![Wave Media](${mediaUrls[0]})` : commentValue;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'comment':
|
case 'comment':
|
||||||
_isSuccess = await postSubmitter.submitReply(_body, selectedPost);
|
_isSuccess = await postSubmitter.submitReply(_body, selectedPost);
|
||||||
break;;
|
break;
|
||||||
case 'wave':
|
case 'wave':
|
||||||
_isSuccess = await postSubmitter.submitWave(_body);
|
_isSuccess = await postSubmitter.submitWave(_body);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("mode needs implementing")
|
throw new Error('mode needs implementing');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (_isSuccess) {
|
if (_isSuccess) {
|
||||||
|
|
||||||
// delete quick comment draft cache if it exist
|
// delete quick comment draft cache if it exist
|
||||||
if (draftsCollection && draftsCollection[draftId]) {
|
if (draftsCollection && draftsCollection[draftId]) {
|
||||||
dispatch(deleteDraftCacheEntry(draftId));
|
dispatch(deleteDraftCacheEntry(draftId));
|
||||||
@ -178,13 +169,10 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
} else {
|
} else {
|
||||||
_addQuickCommentIntoCache(); // add comment value into cache if there is error while posting comment
|
_addQuickCommentIntoCache(); // add comment value into cache if there is error while posting comment
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _handleMediaInsert = (data: MediaInsertData[]) => {
|
const _handleMediaInsert = (data: MediaInsertData[]) => {
|
||||||
const _insertUrls: string[] = []
|
const _insertUrls: string[] = [];
|
||||||
|
|
||||||
const _item = data[0];
|
const _item = data[0];
|
||||||
|
|
||||||
@ -192,7 +180,7 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
switch (_item.status) {
|
switch (_item.status) {
|
||||||
case MediaInsertStatus.READY:
|
case MediaInsertStatus.READY:
|
||||||
if (_item.url) {
|
if (_item.url) {
|
||||||
_insertUrls.push(_item.url)
|
_insertUrls.push(_item.url);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MediaInsertStatus.FAILED:
|
case MediaInsertStatus.FAILED:
|
||||||
@ -201,14 +189,10 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setMediaModalVisible(false);
|
setMediaModalVisible(false);
|
||||||
uploadsGalleryModalRef.current?.toggleModal(false);
|
uploadsGalleryModalRef.current?.toggleModal(false);
|
||||||
setMediaUrls(_insertUrls);
|
setMediaUrls(_insertUrls);
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _handleExpandBtn = async () => {
|
const _handleExpandBtn = async () => {
|
||||||
if (selectedPost) {
|
if (selectedPost) {
|
||||||
@ -228,10 +212,10 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
|
|
||||||
const _handleMediaBtn = () => {
|
const _handleMediaBtn = () => {
|
||||||
if (uploadsGalleryModalRef.current) {
|
if (uploadsGalleryModalRef.current) {
|
||||||
uploadsGalleryModalRef.current.toggleModal(!mediaModalVisible)
|
uploadsGalleryModalRef.current.toggleModal(!mediaModalVisible);
|
||||||
setMediaModalVisible(!mediaModalVisible)
|
setMediaModalVisible(!mediaModalVisible);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const _deboucedCacheUpdate = useCallback(debounce(_addQuickCommentIntoCache, 500), []);
|
const _deboucedCacheUpdate = useCallback(debounce(_addQuickCommentIntoCache, 500), []);
|
||||||
|
|
||||||
@ -240,9 +224,6 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
_deboucedCacheUpdate(value);
|
_deboucedCacheUpdate(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// VIEW_RENDERERS
|
// VIEW_RENDERERS
|
||||||
|
|
||||||
const _renderSummary = () => (
|
const _renderSummary = () => (
|
||||||
@ -253,8 +234,6 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _renderAvatar = () => (
|
const _renderAvatar = () => (
|
||||||
<View style={styles.avatarAndNameContainer}>
|
<View style={styles.avatarAndNameContainer}>
|
||||||
<UserAvatar noAction username={currentAccount.username} />
|
<UserAvatar noAction username={currentAccount.username} />
|
||||||
@ -264,14 +243,12 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const _renderMediaPanel = () => {
|
const _renderMediaPanel = () => {
|
||||||
const _onPress = () => {
|
const _onPress = () => {
|
||||||
setMediaUrls([])
|
setMediaUrls([]);
|
||||||
}
|
};
|
||||||
|
|
||||||
const _minusIcon = (
|
const _minusIcon = !isUploading && (
|
||||||
!isUploading &&
|
|
||||||
<View style={styles.minusContainer}>
|
<View style={styles.minusContainer}>
|
||||||
<Icon
|
<Icon
|
||||||
color={EStyleSheet.value('$pureWhite')}
|
color={EStyleSheet.value('$pureWhite')}
|
||||||
@ -280,52 +257,46 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
size={16}
|
size={16}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
|
|
||||||
|
const _mediaThumb = !mediaModalVisible && mediaUrls.length > 0 && (
|
||||||
|
<TouchableOpacity onPress={_onPress} disabled={isUploading}>
|
||||||
|
<FastImage source={{ uri: mediaUrls[0] }} style={styles.mediaItem} />
|
||||||
|
{_minusIcon}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
|
||||||
const _mediaThumb = (
|
const _uploadingPlaceholder = isUploading && (
|
||||||
!mediaModalVisible && mediaUrls.length > 0 && (
|
<View style={styles.mediaItem}>
|
||||||
<TouchableOpacity onPress={_onPress} disabled={isUploading}>
|
|
||||||
<FastImage
|
|
||||||
source={{ uri: mediaUrls[0] }}
|
|
||||||
style={styles.mediaItem}
|
|
||||||
/>
|
|
||||||
{_minusIcon}
|
|
||||||
</TouchableOpacity>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
const _uploadingPlaceholder = (
|
|
||||||
isUploading && <View style={styles.mediaItem}>
|
|
||||||
<ActivityIndicator />
|
<ActivityIndicator />
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
|
|
||||||
return <Fragment>
|
return (
|
||||||
{_mediaThumb}
|
<Fragment>
|
||||||
{_uploadingPlaceholder}
|
{_mediaThumb}
|
||||||
|
{_uploadingPlaceholder}
|
||||||
<UploadsGalleryModal
|
|
||||||
ref={uploadsGalleryModalRef}
|
|
||||||
isPreviewActive={false}
|
|
||||||
username={currentAccount.username}
|
|
||||||
allowMultiple={false}
|
|
||||||
hideToolbarExtension={() => {
|
|
||||||
setMediaModalVisible(false);
|
|
||||||
}}
|
|
||||||
handleMediaInsert={_handleMediaInsert}
|
|
||||||
setIsUploading={setIsUploading}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
<UploadsGalleryModal
|
||||||
|
ref={uploadsGalleryModalRef}
|
||||||
|
isPreviewActive={false}
|
||||||
|
username={currentAccount.username}
|
||||||
|
allowMultiple={false}
|
||||||
|
hideToolbarExtension={() => {
|
||||||
|
setMediaModalVisible(false);
|
||||||
|
}}
|
||||||
|
handleMediaInsert={_handleMediaInsert}
|
||||||
|
setIsUploading={setIsUploading}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const _renderExpandBtn = () => {
|
const _renderExpandBtn = () => {
|
||||||
|
|
||||||
const _lengthTextStyle = {
|
const _lengthTextStyle = {
|
||||||
...styles.toolbarSpacer,
|
...styles.toolbarSpacer,
|
||||||
color: EStyleSheet.value(bodyLengthExceeded ? '$primaryRed' : '$iconColor')
|
color: EStyleSheet.value(bodyLengthExceeded ? '$primaryRed' : '$iconColor'),
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.toolbarContainer}>
|
<View style={styles.toolbarContainer}>
|
||||||
@ -346,16 +317,11 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
color={EStyleSheet.value('$primaryBlack')}
|
color={EStyleSheet.value('$primaryBlack')}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Text style={_lengthTextStyle}>
|
<Text style={_lengthTextStyle}>{`${commentValue.length}/${MAX_BODY_LENGTH}`}</Text>
|
||||||
{`${commentValue.length}/${MAX_BODY_LENGTH}`}
|
|
||||||
</Text>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _renderReplyBtn = () => {
|
const _renderReplyBtn = () => {
|
||||||
const _titleId = mode !== 'comment' ? 'quick_reply.publish' : 'quick_reply.reply';
|
const _titleId = mode !== 'comment' ? 'quick_reply.publish' : 'quick_reply.reply';
|
||||||
@ -378,13 +344,11 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
isLoading={postSubmitter.isSending}
|
isLoading={postSubmitter.isSending}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const _placeholderId =
|
||||||
|
mode === 'comment' ? 'quick_reply.placeholder' : 'quick_reply.placeholder_wave';
|
||||||
const _placeholderId = mode === 'comment' ? 'quick_reply.placeholder' : 'quick_reply.placeholder_wave'
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.modalContainer}>
|
<View style={styles.modalContainer}>
|
||||||
@ -409,14 +373,11 @@ export const QuickReplyModalContent = forwardRef(
|
|||||||
|
|
||||||
{_renderMediaPanel()}
|
{_renderMediaPanel()}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<View style={styles.footer}>
|
<View style={styles.footer}>
|
||||||
{_renderExpandBtn()}
|
{_renderExpandBtn()}
|
||||||
{_renderReplyBtn()}
|
{_renderReplyBtn()}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -108,8 +108,8 @@ export default EStyleSheet.create({
|
|||||||
width: 96,
|
width: 96,
|
||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
backgroundColor: '$primaryLightBackground',
|
backgroundColor: '$primaryLightBackground',
|
||||||
justifyContent:'center',
|
justifyContent: 'center',
|
||||||
alignItems:'center'
|
alignItems: 'center',
|
||||||
} as ImageStyle,
|
} as ImageStyle,
|
||||||
minusContainer: {
|
minusContainer: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@ -119,12 +119,11 @@ export default EStyleSheet.create({
|
|||||||
borderRadius: 16,
|
borderRadius: 16,
|
||||||
padding: 2,
|
padding: 2,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
toolbarContainer:{
|
toolbarContainer: {
|
||||||
flexDirection:'row',
|
flexDirection: 'row',
|
||||||
alignItems:'center'
|
alignItems: 'center',
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
toolbarSpacer:{
|
toolbarSpacer: {
|
||||||
marginLeft:8
|
marginLeft: 8,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ const QuickReplyModal = () => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const replyModalVisible = useAppSelector((state) => state.ui.replyModalVisible);
|
const replyModalVisible = useAppSelector((state) => state.ui.replyModalVisible);
|
||||||
const replyModalData:PostEditorModalData = useAppSelector((state) => state.ui.replyModalData);
|
const replyModalData: PostEditorModalData = useAppSelector((state) => state.ui.replyModalData);
|
||||||
const modalContentRef = useRef(null);
|
const modalContentRef = useRef(null);
|
||||||
|
|
||||||
const _onClose = () => {
|
const _onClose = () => {
|
||||||
|
@ -1,172 +1,155 @@
|
|||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from 'react-redux';
|
||||||
import { useAppSelector } from "../../hooks";
|
import { Alert } from 'react-native';
|
||||||
import { postComment } from "../../providers/hive/dhive";
|
import { useIntl } from 'react-intl';
|
||||||
import { extractMetadata, generateUniquePermlink, makeJsonMetadata } from "../../utils/editor";
|
import { useState } from 'react';
|
||||||
import { Alert } from "react-native";
|
import { useAppSelector } from '../../hooks';
|
||||||
import { updateCommentCache } from "../../redux/actions/cacheActions";
|
import { postComment } from '../../providers/hive/dhive';
|
||||||
import { toastNotification } from "../../redux/actions/uiAction";
|
import { extractMetadata, generateUniquePermlink, makeJsonMetadata } from '../../utils/editor';
|
||||||
import { useIntl } from "react-intl";
|
import { updateCommentCache } from '../../redux/actions/cacheActions';
|
||||||
import { useState } from "react";
|
import { toastNotification } from '../../redux/actions/uiAction';
|
||||||
import { useUserActivityMutation, wavesQueries } from "../../providers/queries";
|
import { useUserActivityMutation, wavesQueries } from '../../providers/queries';
|
||||||
import { PointActivityIds } from "../../providers/ecency/ecency.types";
|
import { PointActivityIds } from '../../providers/ecency/ecency.types';
|
||||||
import { usePublishWaveMutation } from "../../providers/queries/postQueries/wavesQueries";
|
import { usePublishWaveMutation } from '../../providers/queries/postQueries/wavesQueries';
|
||||||
import { PostTypes } from "../../constants/postTypes";
|
import { PostTypes } from '../../constants/postTypes';
|
||||||
|
|
||||||
|
|
||||||
export const usePostSubmitter = () => {
|
export const usePostSubmitter = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const pusblishWaveMutation = usePublishWaveMutation();
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
const pusblishWaveMutation = usePublishWaveMutation();
|
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
||||||
|
const pinCode = useAppSelector((state) => state.application.pin);
|
||||||
|
const userActivityMutation = useUserActivityMutation();
|
||||||
|
const [isSending, setIsSending] = useState(false);
|
||||||
|
|
||||||
|
// handle submit reply
|
||||||
|
const _submitReply = async (
|
||||||
|
commentBody: string,
|
||||||
|
parentPost: any,
|
||||||
|
postType: PostTypes = PostTypes.COMMENT,
|
||||||
|
) => {
|
||||||
|
if (!commentBody) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isSending) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
if (currentAccount) {
|
||||||
const pinCode = useAppSelector(state => state.application.pin);
|
setIsSending(true);
|
||||||
const userActivityMutation = useUserActivityMutation();
|
|
||||||
const [isSending, setIsSending] = useState(false);
|
|
||||||
|
|
||||||
|
const _prefix =
|
||||||
|
postType === PostTypes.WAVE ? postType : `re-${parentPost.author.replace(/\./g, '')}`;
|
||||||
|
const permlink = generateUniquePermlink(_prefix);
|
||||||
|
|
||||||
// handle submit reply
|
const author = currentAccount.name;
|
||||||
const _submitReply = async (commentBody: string, parentPost: any, postType: PostTypes = PostTypes.COMMENT) => {
|
const parentAuthor = parentPost.author;
|
||||||
if (!commentBody) {
|
const parentPermlink = parentPost.permlink;
|
||||||
return false;
|
const parentTags = parentPost.json_metadata.tags;
|
||||||
}
|
const category = parentPost.category || '';
|
||||||
if (isSending) {
|
const url = `/${category}/@${parentAuthor}/${parentPermlink}#@${author}/${permlink}`;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentAccount) {
|
// adding jsonmeta with image ratios here....
|
||||||
setIsSending(true);
|
const meta = await extractMetadata({
|
||||||
|
body: commentBody,
|
||||||
|
fetchRatios: true,
|
||||||
|
postType,
|
||||||
|
});
|
||||||
|
const jsonMetadata = makeJsonMetadata(meta, parentTags || ['ecency']);
|
||||||
|
|
||||||
const _prefix = postType === PostTypes.WAVE
|
console.log(
|
||||||
? postType
|
currentAccount,
|
||||||
: `re-${parentPost.author.replace(/\./g, '')}`
|
pinCode,
|
||||||
const permlink = generateUniquePermlink(_prefix);
|
parentAuthor,
|
||||||
|
parentPermlink,
|
||||||
|
permlink,
|
||||||
|
commentBody,
|
||||||
|
jsonMetadata,
|
||||||
|
);
|
||||||
|
|
||||||
const author = currentAccount.name;
|
try {
|
||||||
const parentAuthor = parentPost.author;
|
const response = await postComment(
|
||||||
const parentPermlink = parentPost.permlink;
|
currentAccount,
|
||||||
const parentTags = parentPost.json_metadata.tags;
|
pinCode,
|
||||||
const category = parentPost.category || '';
|
parentAuthor,
|
||||||
const url = `/${category}/@${parentAuthor}/${parentPermlink}#@${author}/${permlink}`;
|
parentPermlink,
|
||||||
|
permlink,
|
||||||
|
commentBody,
|
||||||
|
jsonMetadata,
|
||||||
|
);
|
||||||
|
|
||||||
//adding jsonmeta with image ratios here....
|
userActivityMutation.mutate({
|
||||||
const meta = await extractMetadata({
|
pointsTy: PointActivityIds.COMMENT,
|
||||||
body: commentBody,
|
transactionId: response.id,
|
||||||
fetchRatios: true,
|
});
|
||||||
postType
|
setIsSending(false);
|
||||||
})
|
|
||||||
const jsonMetadata = makeJsonMetadata(meta, parentTags || ['ecency'])
|
|
||||||
|
|
||||||
console.log(
|
dispatch(
|
||||||
currentAccount,
|
toastNotification(
|
||||||
pinCode,
|
intl.formatMessage({
|
||||||
parentAuthor,
|
id: 'alert.success',
|
||||||
parentPermlink,
|
}),
|
||||||
permlink,
|
),
|
||||||
commentBody,
|
);
|
||||||
jsonMetadata
|
|
||||||
);
|
|
||||||
|
|
||||||
|
// add comment cache entry
|
||||||
|
const _cacheCommentData = {
|
||||||
|
author,
|
||||||
|
permlink,
|
||||||
|
url,
|
||||||
|
parent_author: parentAuthor,
|
||||||
|
parent_permlink: parentPermlink,
|
||||||
|
markdownBody: commentBody,
|
||||||
|
json_metadata: jsonMetadata,
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
dispatch(
|
||||||
const response = await postComment(
|
updateCommentCache(`${author}/${permlink}`, _cacheCommentData, {
|
||||||
currentAccount,
|
parentTags: parentTags || ['ecency'],
|
||||||
pinCode,
|
}),
|
||||||
parentAuthor,
|
);
|
||||||
parentPermlink,
|
|
||||||
permlink,
|
|
||||||
commentBody,
|
|
||||||
jsonMetadata
|
|
||||||
)
|
|
||||||
|
|
||||||
userActivityMutation.mutate({
|
return _cacheCommentData;
|
||||||
pointsTy: PointActivityIds.COMMENT,
|
} catch (error) {
|
||||||
transactionId: response.id,
|
console.log(error);
|
||||||
});
|
Alert.alert(
|
||||||
setIsSending(false);
|
intl.formatMessage({
|
||||||
|
id: 'alert.something_wrong',
|
||||||
dispatch(
|
}),
|
||||||
toastNotification(
|
error.message || JSON.stringify(error),
|
||||||
intl.formatMessage({
|
);
|
||||||
id: 'alert.success',
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// add comment cache entry
|
|
||||||
const _cacheCommentData = {
|
|
||||||
author,
|
|
||||||
permlink,
|
|
||||||
url,
|
|
||||||
parent_author: parentAuthor,
|
|
||||||
parent_permlink: parentPermlink,
|
|
||||||
markdownBody: commentBody,
|
|
||||||
json_metadata: jsonMetadata
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
updateCommentCache(
|
|
||||||
`${author}/${permlink}`,
|
|
||||||
_cacheCommentData,
|
|
||||||
{
|
|
||||||
parentTags: parentTags || ['ecency'],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return _cacheCommentData;
|
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
Alert.alert(
|
|
||||||
intl.formatMessage({
|
|
||||||
id: 'alert.something_wrong',
|
|
||||||
}),
|
|
||||||
error.message || JSON.stringify(error),
|
|
||||||
);
|
|
||||||
|
|
||||||
setIsSending(false);
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
setIsSending(false);
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//feteced lates wafves container and post wave to that container
|
|
||||||
const _submitWave = async (body: string) => {
|
|
||||||
|
|
||||||
try {
|
|
||||||
const _wavesHost = 'ecency.waves' //TODO: make waves host selection dynamic
|
|
||||||
const latestWavesPost = await wavesQueries.fetchLatestWavesContainer(_wavesHost);
|
|
||||||
|
|
||||||
const _cacheCommentData = await _submitReply(body, latestWavesPost, PostTypes.WAVE)
|
|
||||||
|
|
||||||
if (_cacheCommentData) {
|
|
||||||
pusblishWaveMutation.mutate(_cacheCommentData)
|
|
||||||
}
|
|
||||||
|
|
||||||
return _cacheCommentData
|
|
||||||
} catch (err) {
|
|
||||||
Alert.alert("Fail", err.message)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// feteced lates wafves container and post wave to that container
|
||||||
|
const _submitWave = async (body: string) => {
|
||||||
|
try {
|
||||||
|
const _wavesHost = 'ecency.waves'; // TODO: make waves host selection dynamic
|
||||||
|
const latestWavesPost = await wavesQueries.fetchLatestWavesContainer(_wavesHost);
|
||||||
|
|
||||||
return {
|
const _cacheCommentData = await _submitReply(body, latestWavesPost, PostTypes.WAVE);
|
||||||
submitReply: _submitReply,
|
|
||||||
submitWave: _submitWave,
|
if (_cacheCommentData) {
|
||||||
isSending
|
pusblishWaveMutation.mutate(_cacheCommentData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cacheCommentData;
|
||||||
|
} catch (err) {
|
||||||
|
Alert.alert('Fail', err.message);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
return {
|
||||||
|
submitReply: _submitReply,
|
||||||
|
submitWave: _submitWave,
|
||||||
|
isSending,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -2,12 +2,12 @@ import React, { useEffect } from 'react';
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
import { useDrawerStatus } from '@react-navigation/drawer';
|
||||||
import { logout, toggleAccountsBottomSheet } from '../../../redux/actions/uiAction';
|
import { logout, toggleAccountsBottomSheet } from '../../../redux/actions/uiAction';
|
||||||
import { setInitPosts, setFeedPosts } from '../../../redux/actions/postsAction';
|
import { setInitPosts, setFeedPosts } from '../../../redux/actions/postsAction';
|
||||||
|
|
||||||
// Component
|
// Component
|
||||||
import SideMenuView from '../view/sideMenuView';
|
import SideMenuView from '../view/sideMenuView';
|
||||||
import { useDrawerStatus } from '@react-navigation/drawer';
|
|
||||||
import { updateCurrentAccount } from '../../../redux/actions/accountAction';
|
import { updateCurrentAccount } from '../../../redux/actions/accountAction';
|
||||||
import { getUser } from '../../../providers/hive/dhive';
|
import { getUser } from '../../../providers/hive/dhive';
|
||||||
import bugsnapInstance from '../../../config/bugsnag';
|
import bugsnapInstance from '../../../config/bugsnag';
|
||||||
@ -16,40 +16,33 @@ const SideMenuContainer = ({ navigation }) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const drawerStatus = useDrawerStatus();
|
const drawerStatus = useDrawerStatus();
|
||||||
|
|
||||||
|
|
||||||
const isLoggedIn = useSelector((state) => state.application.isLoggedIn);
|
const isLoggedIn = useSelector((state) => state.application.isLoggedIn);
|
||||||
const currentAccount = useSelector((state) => state.account.currentAccount);
|
const currentAccount = useSelector((state) => state.account.currentAccount);
|
||||||
const isVisibleAccountsBottomSheet = useSelector(
|
const isVisibleAccountsBottomSheet = useSelector(
|
||||||
(state) => state.ui.isVisibleAccountsBottomSheet,
|
(state) => state.ui.isVisibleAccountsBottomSheet,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
useEffect(()=>{
|
if (drawerStatus === 'open') {
|
||||||
if(drawerStatus === 'open'){
|
// update profile on drawer open
|
||||||
//update profile on drawer open
|
|
||||||
_updateUserData();
|
_updateUserData();
|
||||||
}
|
}
|
||||||
|
}, [drawerStatus]);
|
||||||
}, [drawerStatus])
|
|
||||||
|
|
||||||
|
// fetches and update user data
|
||||||
//fetches and update user data
|
|
||||||
const _updateUserData = async () => {
|
const _updateUserData = async () => {
|
||||||
try{
|
try {
|
||||||
if(currentAccount?.username){
|
if (currentAccount?.username) {
|
||||||
let accountData = await getUser(currentAccount.username);
|
const accountData = await getUser(currentAccount.username);
|
||||||
if(accountData){
|
if (accountData) {
|
||||||
dispatch(updateCurrentAccount({...currentAccount, ...accountData}))
|
dispatch(updateCurrentAccount({ ...currentAccount, ...accountData }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
} catch(err){
|
console.warn('failed to update user data');
|
||||||
console.warn("failed to update user data")
|
|
||||||
bugsnapInstance.notify(err);
|
bugsnapInstance.notify(err);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const _navigateToRoute = (route = null) => {
|
const _navigateToRoute = (route = null) => {
|
||||||
if (route) {
|
if (route) {
|
||||||
|
@ -2,63 +2,61 @@ import { TextStyle, StyleSheet, ViewStyle } from 'react-native';
|
|||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
|
||||||
export default EStyleSheet.create({
|
export default EStyleSheet.create({
|
||||||
modalStyle: {
|
modalStyle: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
margin:0,
|
margin: 0,
|
||||||
paddingTop:32,
|
paddingTop: 32,
|
||||||
paddingBottom:8
|
paddingBottom: 8,
|
||||||
},
|
},
|
||||||
container:{
|
container: {
|
||||||
flexGrow:1,
|
flexGrow: 1,
|
||||||
marginTop:24,
|
marginTop: 24,
|
||||||
paddingHorizontal:24,
|
paddingHorizontal: 24,
|
||||||
},
|
},
|
||||||
inputContainer:{
|
inputContainer: {
|
||||||
flex:1
|
flex: 1,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
titleInput:{
|
titleInput: {
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
textAlignVertical: 'top',
|
textAlignVertical: 'top',
|
||||||
paddingVertical: 0,
|
paddingVertical: 0,
|
||||||
backgroundColor:'$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
borderBottomWidth:StyleSheet.hairlineWidth,
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
borderBottomColor:'$primaryDarkGray'
|
borderBottomColor: '$primaryDarkGray',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
bodyWrapper: {
|
bodyWrapper: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
paddingTop: 16,
|
paddingTop: 16,
|
||||||
paddingBottom: 0, // On android side, textinput has default padding
|
paddingBottom: 0, // On android side, textinput has default padding
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
textAlignVertical: 'top',
|
textAlignVertical: 'top',
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
},
|
},
|
||||||
btnText:{
|
btnText: {
|
||||||
color:'$pureWhite'
|
color: '$pureWhite',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
saveButton:{
|
saveButton: {
|
||||||
|
backgroundColor: '$primaryBlue',
|
||||||
backgroundColor:'$primaryBlue',
|
width: 150,
|
||||||
width:150,
|
paddingVertical: 16,
|
||||||
paddingVertical:16,
|
borderRadius: 32,
|
||||||
borderRadius:32,
|
justifyContent: 'center',
|
||||||
justifyContent:'center',
|
alignItems: 'center',
|
||||||
alignItems:'center'
|
} as ViewStyle,
|
||||||
} as ViewStyle,
|
closeButton: {
|
||||||
closeButton:{
|
marginRight: 16,
|
||||||
marginRight:16,
|
paddingVertical: 8,
|
||||||
paddingVertical:8,
|
borderRadius: 16,
|
||||||
borderRadius:16,
|
justifyContent: 'center',
|
||||||
justifyContent:'center',
|
alignItems: 'center',
|
||||||
alignItems:'center'
|
} as ViewStyle,
|
||||||
} as ViewStyle,
|
actionPanel: {
|
||||||
actionPanel:{
|
flexDirection: 'row',
|
||||||
flexDirection:'row',
|
justifyContent: 'flex-end',
|
||||||
justifyContent:'flex-end',
|
alignItems: 'center',
|
||||||
alignItems:'center',
|
marginBottom: 16,
|
||||||
marginBottom:16
|
} as ViewStyle,
|
||||||
} as ViewStyle,
|
});
|
||||||
|
|
||||||
})
|
|
||||||
|
@ -9,44 +9,43 @@ export default EStyleSheet.create({
|
|||||||
},
|
},
|
||||||
bodyWrapper: {
|
bodyWrapper: {
|
||||||
flex: 3,
|
flex: 3,
|
||||||
paddingHorizontal:16
|
paddingHorizontal: 16,
|
||||||
},
|
},
|
||||||
floatingContainer:{
|
floatingContainer: {
|
||||||
position:'absolute',
|
position: 'absolute',
|
||||||
bottom:0,
|
bottom: 0,
|
||||||
right:20,
|
right: 20,
|
||||||
justifyContent:'flex-end',
|
justifyContent: 'flex-end',
|
||||||
zIndex:10
|
zIndex: 10,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
itemWrapper: {
|
itemWrapper: {
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
paddingVertical:8,
|
paddingVertical: 8,
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
},
|
},
|
||||||
itemHeader:{
|
itemHeader: {
|
||||||
flexDirection:'row',
|
flexDirection: 'row',
|
||||||
alignItems:'center',
|
alignItems: 'center',
|
||||||
height:35
|
height: 35,
|
||||||
},
|
},
|
||||||
itemWrapperGray: {
|
itemWrapperGray: {
|
||||||
backgroundColor: '$primaryLightBackground',
|
backgroundColor: '$primaryLightBackground',
|
||||||
},
|
},
|
||||||
itemIcon:{
|
itemIcon: {
|
||||||
color:'$primaryDarkGray',
|
color: '$primaryDarkGray',
|
||||||
},
|
},
|
||||||
itemIconWrapper:{
|
itemIconWrapper: {
|
||||||
marginLeft:8,
|
marginLeft: 8,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
flex:1,
|
flex: 1,
|
||||||
fontSize:16,
|
fontSize: 16,
|
||||||
color:'$primaryBlack'
|
color: '$primaryBlack',
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
paddingBottom:8,
|
paddingBottom: 8,
|
||||||
color:'$primaryBlack'
|
color: '$primaryBlack',
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -4,7 +4,6 @@ import { TabbedPostsProps } from '../services/tabbedPostsModels';
|
|||||||
import { StackedTabBar, TabItem } from '../view/stackedTabBar';
|
import { StackedTabBar, TabItem } from '../view/stackedTabBar';
|
||||||
import TabContent from '../view/tabContent';
|
import TabContent from '../view/tabContent';
|
||||||
|
|
||||||
|
|
||||||
export const TabbedPosts = ({
|
export const TabbedPosts = ({
|
||||||
filterOptions,
|
filterOptions,
|
||||||
filterOptionsValue,
|
filterOptionsValue,
|
||||||
@ -20,45 +19,48 @@ export const TabbedPosts = ({
|
|||||||
onTabChange,
|
onTabChange,
|
||||||
...props
|
...props
|
||||||
}: TabbedPostsProps) => {
|
}: TabbedPostsProps) => {
|
||||||
|
// initialize state
|
||||||
|
const [initialTabIndex] = useState(
|
||||||
|
selectedOptionIndex == 0 && stackedTabs ? filterOptions.length : selectedOptionIndex,
|
||||||
|
);
|
||||||
|
|
||||||
//initialize state
|
const mainFilters = filterOptions.map(
|
||||||
const [initialTabIndex] = useState(selectedOptionIndex == 0 && stackedTabs ? filterOptions.length : selectedOptionIndex)
|
(label, index) =>
|
||||||
|
({
|
||||||
const mainFilters = filterOptions.map((label, index) => ({
|
filterKey: filterOptionsValue[index],
|
||||||
filterKey: filterOptionsValue[index],
|
label,
|
||||||
label
|
} as TabItem),
|
||||||
} as TabItem));
|
);
|
||||||
|
|
||||||
const subFilters = feedSubfilterOptions
|
const subFilters = feedSubfilterOptions
|
||||||
? feedSubfilterOptions.map((label, index) => ({
|
? feedSubfilterOptions.map(
|
||||||
filterKey: feedSubfilterOptionsValue[index],
|
(label, index) =>
|
||||||
label
|
({
|
||||||
} as TabItem))
|
filterKey: feedSubfilterOptionsValue[index],
|
||||||
|
label,
|
||||||
|
} as TabItem),
|
||||||
|
)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const combinedFilters = [...mainFilters, ...subFilters]
|
const combinedFilters = [...mainFilters, ...subFilters];
|
||||||
|
|
||||||
const [selectedFilter, setSelectedFilter] = useState(combinedFilters[initialTabIndex].filterKey)
|
const [selectedFilter, setSelectedFilter] = useState(combinedFilters[initialTabIndex].filterKey);
|
||||||
const [filterScrollRequest, createFilterScrollRequest] = useState<string | null>(null)
|
const [filterScrollRequest, createFilterScrollRequest] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// components actions
|
||||||
|
|
||||||
//components actions
|
|
||||||
const _onFilterSelect = (filter: string) => {
|
const _onFilterSelect = (filter: string) => {
|
||||||
if (filter === selectedFilter) {
|
if (filter === selectedFilter) {
|
||||||
createFilterScrollRequest(selectedFilter)
|
createFilterScrollRequest(selectedFilter);
|
||||||
} else {
|
} else {
|
||||||
setSelectedFilter(filter)
|
setSelectedFilter(filter);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const _onScrollRequestProcessed = () => {
|
const _onScrollRequestProcessed = () => {
|
||||||
createFilterScrollRequest(null);
|
createFilterScrollRequest(null);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// initialize first set of pages
|
||||||
|
|
||||||
//initialize first set of pages
|
|
||||||
const pages = combinedFilters.map((filter, index) => {
|
const pages = combinedFilters.map((filter, index) => {
|
||||||
if (tabContentOverrides && tabContentOverrides.has(index)) {
|
if (tabContentOverrides && tabContentOverrides.has(index)) {
|
||||||
return tabContentOverrides.get(index);
|
return tabContentOverrides.get(index);
|
||||||
@ -76,11 +78,10 @@ export const TabbedPosts = ({
|
|||||||
onScrollRequestProcessed={_onScrollRequestProcessed}
|
onScrollRequestProcessed={_onScrollRequestProcessed}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// render tab bar
|
||||||
//render tab bar
|
|
||||||
const _renderTabBar = (props) => {
|
const _renderTabBar = (props) => {
|
||||||
return (
|
return (
|
||||||
<StackedTabBar
|
<StackedTabBar
|
||||||
@ -92,9 +93,8 @@ export const TabbedPosts = ({
|
|||||||
toggleHideImagesFlag={imagesToggleEnabled}
|
toggleHideImagesFlag={imagesToggleEnabled}
|
||||||
pageType={pageType}
|
pageType={pageType}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollableTabView
|
<ScrollableTabView
|
||||||
@ -107,5 +107,4 @@ export const TabbedPosts = ({
|
|||||||
{pages}
|
{pages}
|
||||||
</ScrollableTabView>
|
</ScrollableTabView>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
}
|
|
||||||
|
@ -184,12 +184,11 @@ export const loadPosts = async ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchPromotedEntries = async (username: string, nsfwFilter:string) => {
|
export const fetchPromotedEntries = async (username: string, nsfwFilter: string) => {
|
||||||
try {
|
try {
|
||||||
const posts = await getPromotedEntries(username);
|
const posts = await getPromotedEntries(username);
|
||||||
|
|
||||||
return Array.isArray(posts) ? filterNsfwPost(posts, nsfwFilter) : [];
|
return Array.isArray(posts) ? filterNsfwPost(posts, nsfwFilter) : [];
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('Failed to get promoted posts, ', err);
|
console.warn('Failed to get promoted posts, ', err);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { AppState, NativeEventSubscription, NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
import {
|
||||||
|
AppState,
|
||||||
|
NativeEventSubscription,
|
||||||
|
NativeScrollEvent,
|
||||||
|
NativeSyntheticEvent,
|
||||||
|
} from 'react-native';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import BackgroundTimer from 'react-native-background-timer';
|
import BackgroundTimer from 'react-native-background-timer';
|
||||||
import PostsList from '../../postsList';
|
import PostsList from '../../postsList';
|
||||||
@ -41,7 +46,7 @@ const TabContent = ({
|
|||||||
}: TabContentProps) => {
|
}: TabContentProps) => {
|
||||||
let _isMounted = true;
|
let _isMounted = true;
|
||||||
|
|
||||||
//redux properties
|
// redux properties
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const isLoggedIn = useSelector((state) => state.application.isLoggedIn);
|
const isLoggedIn = useSelector((state) => state.application.isLoggedIn);
|
||||||
const nsfw = useSelector((state) => state.application.nsfw);
|
const nsfw = useSelector((state) => state.application.nsfw);
|
||||||
@ -49,11 +54,10 @@ const TabContent = ({
|
|||||||
const currentAccount = useSelector((state) => state.account.currentAccount);
|
const currentAccount = useSelector((state) => state.account.currentAccount);
|
||||||
const initPosts = useSelector((state) => state.posts.initPosts);
|
const initPosts = useSelector((state) => state.posts.initPosts);
|
||||||
|
|
||||||
|
const { username } = currentAccount;
|
||||||
const username = currentAccount.username;
|
|
||||||
const userPinned = currentAccount.about?.profile?.pinned;
|
const userPinned = currentAccount.about?.profile?.pinned;
|
||||||
|
|
||||||
//state
|
// state
|
||||||
const [posts, setPosts] = useState([]);
|
const [posts, setPosts] = useState([]);
|
||||||
const [promotedPosts, setPromotedPosts] = useState([]);
|
const [promotedPosts, setPromotedPosts] = useState([]);
|
||||||
const [sessionUser, setSessionUser] = useState(username);
|
const [sessionUser, setSessionUser] = useState(username);
|
||||||
@ -62,21 +66,20 @@ const TabContent = ({
|
|||||||
const [enableScrollTop, setEnableScrollTop] = useState(false);
|
const [enableScrollTop, setEnableScrollTop] = useState(false);
|
||||||
const [curPinned, setCurPinned] = useState(pinnedPermlink);
|
const [curPinned, setCurPinned] = useState(pinnedPermlink);
|
||||||
|
|
||||||
//refs
|
// refs
|
||||||
let postsListRef = useRef<PostsListRef>();
|
const postsListRef = useRef<PostsListRef>();
|
||||||
const appState = useRef(AppState.currentState);
|
const appState = useRef(AppState.currentState);
|
||||||
const appStateSubRef = useRef<NativeEventSubscription|null>()
|
const appStateSubRef = useRef<NativeEventSubscription | null>();
|
||||||
const postsRef = useRef(posts);
|
const postsRef = useRef(posts);
|
||||||
const sessionUserRef = useRef(sessionUser);
|
const sessionUserRef = useRef(sessionUser);
|
||||||
const postFetchTimerRef = useRef<any>(null);
|
const postFetchTimerRef = useRef<any>(null);
|
||||||
|
|
||||||
//init state refs;
|
// init state refs;
|
||||||
postsRef.current = posts;
|
postsRef.current = posts;
|
||||||
sessionUserRef.current = sessionUser;
|
sessionUserRef.current = sessionUser;
|
||||||
|
|
||||||
//side effects
|
// side effects
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (isFeedScreen) {
|
if (isFeedScreen) {
|
||||||
appStateSubRef.current = AppState.addEventListener('change', _handleAppStateChange);
|
appStateSubRef.current = AppState.addEventListener('change', _handleAppStateChange);
|
||||||
}
|
}
|
||||||
@ -88,7 +91,7 @@ const TabContent = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isConnected && (username !== sessionUser || forceLoadPosts)) {
|
if (isConnected && (username !== sessionUser || forceLoadPosts)) {
|
||||||
_initContent(false, username);
|
_initContent(false, username);
|
||||||
}
|
}
|
||||||
}, [username, forceLoadPosts]);
|
}, [username, forceLoadPosts]);
|
||||||
|
|
||||||
@ -113,7 +116,7 @@ const TabContent = ({
|
|||||||
const _cleanup = () => {
|
const _cleanup = () => {
|
||||||
_isMounted = false;
|
_isMounted = false;
|
||||||
if (postFetchTimerRef.current) {
|
if (postFetchTimerRef.current) {
|
||||||
BackgroundTimer.clearTimeout(postFetchTimerRef.current)
|
BackgroundTimer.clearTimeout(postFetchTimerRef.current);
|
||||||
postFetchTimerRef.current = null;
|
postFetchTimerRef.current = null;
|
||||||
}
|
}
|
||||||
if (isFeedScreen && appStateSubRef.current) {
|
if (isFeedScreen && appStateSubRef.current) {
|
||||||
@ -121,7 +124,7 @@ const TabContent = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//actions
|
// actions
|
||||||
const _handleAppStateChange = (nextAppState) => {
|
const _handleAppStateChange = (nextAppState) => {
|
||||||
if (
|
if (
|
||||||
appState.current.match(/inactive|background/) &&
|
appState.current.match(/inactive|background/) &&
|
||||||
@ -166,7 +169,7 @@ const TabContent = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//fetch posts from server
|
// fetch posts from server
|
||||||
const _loadPosts = async ({
|
const _loadPosts = async ({
|
||||||
shouldReset = false,
|
shouldReset = false,
|
||||||
isLatestPostsCheck = false,
|
isLatestPostsCheck = false,
|
||||||
@ -225,7 +228,7 @@ const TabContent = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//schedules post fetch
|
// schedules post fetch
|
||||||
const _scheduleLatestPostsCheck = (firstPost: any) => {
|
const _scheduleLatestPostsCheck = (firstPost: any) => {
|
||||||
if (firstPost) {
|
if (firstPost) {
|
||||||
if (postFetchTimerRef.current) {
|
if (postFetchTimerRef.current) {
|
||||||
@ -241,13 +244,12 @@ const TabContent = ({
|
|||||||
isLatestPostsCheck,
|
isLatestPostsCheck,
|
||||||
});
|
});
|
||||||
}, timeLeft);
|
}, timeLeft);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//processes response from loadPost
|
// processes response from loadPost
|
||||||
const _postProcessLoadResult = ({ updatedPosts, latestPosts }: any) => {
|
const _postProcessLoadResult = ({ updatedPosts, latestPosts }: any) => {
|
||||||
//process new posts avatart
|
// process new posts avatart
|
||||||
if (latestPosts && Array.isArray(latestPosts)) {
|
if (latestPosts && Array.isArray(latestPosts)) {
|
||||||
if (latestPosts.length > 0) {
|
if (latestPosts.length > 0) {
|
||||||
setLatestPosts(latestPosts);
|
setLatestPosts(latestPosts);
|
||||||
@ -256,14 +258,14 @@ const TabContent = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//process returned data
|
// process returned data
|
||||||
if (Array.isArray(updatedPosts)) {
|
if (Array.isArray(updatedPosts)) {
|
||||||
if (updatedPosts.length) {
|
if (updatedPosts.length) {
|
||||||
//match new and old first post
|
// match new and old first post
|
||||||
const firstPostChanged =
|
const firstPostChanged =
|
||||||
posts.length == 0 || posts[0].permlink !== updatedPosts[0].permlink;
|
posts.length == 0 || posts[0].permlink !== updatedPosts[0].permlink;
|
||||||
if (isFeedScreen && firstPostChanged) {
|
if (isFeedScreen && firstPostChanged) {
|
||||||
//schedule refetch of new posts by checking time of current post
|
// schedule refetch of new posts by checking time of current post
|
||||||
_scheduleLatestPostsCheck(updatedPosts[0]);
|
_scheduleLatestPostsCheck(updatedPosts[0]);
|
||||||
|
|
||||||
if (isInitialTab) {
|
if (isInitialTab) {
|
||||||
@ -271,14 +273,14 @@ const TabContent = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isFeedScreen && isInitialTab) {
|
} else if (isFeedScreen && isInitialTab) {
|
||||||
//clear posts cache if no first tab posts available, precautionary measure for accoutn change
|
// clear posts cache if no first tab posts available, precautionary measure for accoutn change
|
||||||
dispatch(setInitPosts([]));
|
dispatch(setInitPosts([]));
|
||||||
}
|
}
|
||||||
setPosts(updatedPosts);
|
setPosts(updatedPosts);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//view related routines
|
// view related routines
|
||||||
const _onPostsPopupPress = () => {
|
const _onPostsPopupPress = () => {
|
||||||
_scrollToTop();
|
_scrollToTop();
|
||||||
_getPromotedPosts();
|
_getPromotedPosts();
|
||||||
@ -303,7 +305,7 @@ const TabContent = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//view rendereres
|
// view rendereres
|
||||||
const _renderEmptyContent = () => {
|
const _renderEmptyContent = () => {
|
||||||
return <TabEmptyView filterKey={filterKey} isNoPost={tabMeta.isNoPost} />;
|
return <TabEmptyView filterKey={filterKey} isNoPost={tabMeta.isNoPost} />;
|
||||||
};
|
};
|
||||||
@ -317,8 +319,8 @@ const TabContent = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const _onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
const _onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
let currentOffset = event.nativeEvent.contentOffset.y;
|
const currentOffset = event.nativeEvent.contentOffset.y;
|
||||||
let scrollUp = currentOffset < scrollOffset;
|
const scrollUp = currentOffset < scrollOffset;
|
||||||
scrollOffset = currentOffset;
|
scrollOffset = currentOffset;
|
||||||
|
|
||||||
if (scrollUp && !blockPopup && currentOffset > SCROLL_POPUP_THRESHOLD) {
|
if (scrollUp && !blockPopup && currentOffset > SCROLL_POPUP_THRESHOLD) {
|
||||||
@ -329,9 +331,9 @@ const TabContent = ({
|
|||||||
// show quick reply modal
|
// show quick reply modal
|
||||||
const _showQuickReplyModal = (post: any) => {
|
const _showQuickReplyModal = (post: any) => {
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
dispatch(showReplyModal({mode:'comment', parentPost:post}));
|
dispatch(showReplyModal({ mode: 'comment', parentPost: post }));
|
||||||
} else {
|
} else {
|
||||||
//TODO: show proper alert message
|
// TODO: show proper alert message
|
||||||
console.log('Not LoggedIn');
|
console.log('Not LoggedIn');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { View, Text } from 'react-native';
|
import { View, Text } from 'react-native';
|
||||||
import IconButton from '../iconButton';
|
|
||||||
import Clipboard from '@react-native-clipboard/clipboard';
|
import Clipboard from '@react-native-clipboard/clipboard';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import IconButton from '../iconButton';
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
import styles from './textBoxWithCopyStyles';
|
import styles from './textBoxWithCopyStyles';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
import { toastNotification } from '../../redux/actions/uiAction';
|
import { toastNotification } from '../../redux/actions/uiAction';
|
||||||
|
|
||||||
interface TextBoxWithCopyProps {
|
interface TextBoxWithCopyProps {
|
||||||
@ -23,7 +23,7 @@ const TextBoxWithCopy = ({ label, value, renderSecondButton }: TextBoxWithCopyPr
|
|||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.labelContainer}>
|
<View style={styles.labelContainer}>
|
||||||
<Text style={styles.inputLabel}>{label}</Text>
|
<Text style={styles.inputLabel}>{label}</Text>
|
||||||
{renderSecondButton ? renderSecondButton : null}
|
{renderSecondButton || null}
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.copyInputContainer}>
|
<View style={styles.copyInputContainer}>
|
||||||
<View style={styles.textValueContainer}>
|
<View style={styles.textValueContainer}>
|
||||||
@ -33,7 +33,7 @@ const TextBoxWithCopy = ({ label, value, renderSecondButton }: TextBoxWithCopyPr
|
|||||||
</View>
|
</View>
|
||||||
<IconButton
|
<IconButton
|
||||||
size={20}
|
size={20}
|
||||||
color={'white'}
|
color="white"
|
||||||
style={styles.copyIconStyle}
|
style={styles.copyIconStyle}
|
||||||
name="content-copy"
|
name="content-copy"
|
||||||
iconType="MaterialIcons"
|
iconType="MaterialIcons"
|
||||||
|
@ -15,7 +15,7 @@ const TransactionView = ({ item, index, cancelling, onCancelPress, onRepeatPress
|
|||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [collapsed, setCollapsed] = useState(true);
|
const [collapsed, setCollapsed] = useState(true);
|
||||||
|
|
||||||
const title = !!intl.messages[`wallet.${item.textKey}`]
|
const title = intl.messages[`wallet.${item.textKey}`]
|
||||||
? intl.formatMessage({
|
? intl.formatMessage({
|
||||||
id: `wallet.${item.textKey}`,
|
id: `wallet.${item.textKey}`,
|
||||||
})
|
})
|
||||||
|
@ -94,7 +94,6 @@ const TransferAccountSelector = ({
|
|||||||
}
|
}
|
||||||
const isValid = res.includes(username);
|
const isValid = res.includes(username);
|
||||||
|
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
getRecurrentTransferOfUser(username);
|
getRecurrentTransferOfUser(username);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ const TransferAmountInputSection = ({
|
|||||||
|
|
||||||
const _onDelete = () => {
|
const _onDelete = () => {
|
||||||
onNext(true);
|
onNext(true);
|
||||||
}
|
};
|
||||||
|
|
||||||
const _renderDescription = (text) => <Text style={styles.description}>{text}</Text>;
|
const _renderDescription = (text) => <Text style={styles.description}>{text}</Text>;
|
||||||
const _renderCenterDescription = (text, extraStyles = {}) => (
|
const _renderCenterDescription = (text, extraStyles = {}) => (
|
||||||
|
@ -51,7 +51,7 @@ import { CacheStatus } from '../../../redux/reducers/cacheReducer';
|
|||||||
import showLoginAlert from '../../../utils/showLoginAlert';
|
import showLoginAlert from '../../../utils/showLoginAlert';
|
||||||
import { delay } from '../../../utils/editor';
|
import { delay } from '../../../utils/editor';
|
||||||
|
|
||||||
interface Props { }
|
interface Props {}
|
||||||
interface PopoverOptions {
|
interface PopoverOptions {
|
||||||
anchorRect: Rect;
|
anchorRect: Rect;
|
||||||
content: any;
|
content: any;
|
||||||
@ -66,7 +66,7 @@ interface PopoverOptions {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
const UpvotePopover = forwardRef(({}: Props, ref) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
@ -94,7 +94,6 @@ const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
|||||||
const [sliderValue, setSliderValue] = useState(1);
|
const [sliderValue, setSliderValue] = useState(1);
|
||||||
const [amount, setAmount] = useState('0.00000');
|
const [amount, setAmount] = useState('0.00000');
|
||||||
|
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
showPopover: ({
|
showPopover: ({
|
||||||
anchorRect: _anchorRect,
|
anchorRect: _anchorRect,
|
||||||
@ -141,19 +140,22 @@ const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
let _upvotePercent = 1;
|
let _upvotePercent = 1;
|
||||||
switch(postType){
|
switch (postType) {
|
||||||
case PostTypes.POST: _upvotePercent = postUpvotePercent; break;
|
case PostTypes.POST:
|
||||||
case PostTypes.COMMENT: _upvotePercent = commentUpvotePercent; break;
|
_upvotePercent = postUpvotePercent;
|
||||||
case PostTypes.WAVE: _upvotePercent = waveUpvotePercent; break;
|
break;
|
||||||
|
case PostTypes.COMMENT:
|
||||||
|
_upvotePercent = commentUpvotePercent;
|
||||||
|
break;
|
||||||
|
case PostTypes.WAVE:
|
||||||
|
_upvotePercent = waveUpvotePercent;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
setSliderValue(_upvotePercent)
|
setSliderValue(_upvotePercent);
|
||||||
_calculateEstimatedAmount(_upvotePercent)
|
_calculateEstimatedAmount(_upvotePercent);
|
||||||
|
|
||||||
}, [content, postType]);
|
}, [content, postType]);
|
||||||
|
|
||||||
|
|
||||||
// Component Functions
|
// Component Functions
|
||||||
const _calculateEstimatedAmount = async (value: number = sliderValue) => {
|
const _calculateEstimatedAmount = async (value: number = sliderValue) => {
|
||||||
if (currentAccount && Object.entries(currentAccount).length !== 0) {
|
if (currentAccount && Object.entries(currentAccount).length !== 0) {
|
||||||
@ -204,7 +206,13 @@ const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setIsVoted(!!sliderValue);
|
setIsVoted(!!sliderValue);
|
||||||
_updateVoteCache(_author, _permlink, amount, false, !!sliderValue ? CacheStatus.PUBLISHED : CacheStatus.DELETED);
|
_updateVoteCache(
|
||||||
|
_author,
|
||||||
|
_permlink,
|
||||||
|
amount,
|
||||||
|
false,
|
||||||
|
sliderValue ? CacheStatus.PUBLISHED : CacheStatus.DELETED,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
_updateVoteCache(_author, _permlink, amount, false, CacheStatus.FAILED);
|
_updateVoteCache(_author, _permlink, amount, false, CacheStatus.FAILED);
|
||||||
@ -267,7 +275,13 @@ const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
|||||||
transactionId: response.id,
|
transactionId: response.id,
|
||||||
});
|
});
|
||||||
setIsVoted(!!sliderValue);
|
setIsVoted(!!sliderValue);
|
||||||
_updateVoteCache(_author, _permlink, amount, true, !!sliderValue ? CacheStatus.PUBLISHED : CacheStatus.DELETED);
|
_updateVoteCache(
|
||||||
|
_author,
|
||||||
|
_permlink,
|
||||||
|
amount,
|
||||||
|
true,
|
||||||
|
sliderValue ? CacheStatus.PUBLISHED : CacheStatus.DELETED,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
@ -286,17 +300,21 @@ const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
|||||||
|
|
||||||
const _setUpvotePercent = (value) => {
|
const _setUpvotePercent = (value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
|
let _dispatchAction: any = null;
|
||||||
let _dispatchAction:any = null
|
switch (postType) {
|
||||||
switch(postType){
|
case PostTypes.POST:
|
||||||
case PostTypes.POST: _dispatchAction = setPostUpvotePercent; break;
|
_dispatchAction = setPostUpvotePercent;
|
||||||
case PostTypes.COMMENT: _dispatchAction = setCommentUpvotePercent; break;
|
break;
|
||||||
case PostTypes.WAVE: _dispatchAction = setWaveUpvotePercent; break;
|
case PostTypes.COMMENT:
|
||||||
|
_dispatchAction = setCommentUpvotePercent;
|
||||||
|
break;
|
||||||
|
case PostTypes.WAVE:
|
||||||
|
_dispatchAction = setWaveUpvotePercent;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(_dispatchAction){
|
if (_dispatchAction) {
|
||||||
dispatch(_dispatchAction(value))
|
dispatch(_dispatchAction(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -311,7 +329,7 @@ const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
|||||||
|
|
||||||
const percent = Math.floor(sliderValue * 10000 * (isDownvote ? -1 : 1));
|
const percent = Math.floor(sliderValue * 10000 * (isDownvote ? -1 : 1));
|
||||||
const rshares = calculateEstimatedRShares(currentAccount, percent) * (isDownvote ? -1 : 1);
|
const rshares = calculateEstimatedRShares(currentAccount, percent) * (isDownvote ? -1 : 1);
|
||||||
|
|
||||||
// update redux
|
// update redux
|
||||||
const postPath = `${author || ''}/${permlink || ''}`;
|
const postPath = `${author || ''}/${permlink || ''}`;
|
||||||
const curTime = new Date().getTime();
|
const curTime = new Date().getTime();
|
||||||
@ -348,7 +366,7 @@ const UpvotePopover = forwardRef(({ }: Props, ref) => {
|
|||||||
|
|
||||||
const sliderColor = isDownVoted ? '#ec8b88' : '#357ce6';
|
const sliderColor = isDownVoted ? '#ec8b88' : '#357ce6';
|
||||||
|
|
||||||
const _minSliderVal = isVoted || isDownVoted ? 0 : 0.01
|
const _minSliderVal = isVoted || isDownVoted ? 0 : 0.01;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SafeAreaView, FlatList } from 'react-native';
|
import { SafeAreaView, FlatList } from 'react-native';
|
||||||
|
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { useNavigation } from '@react-navigation/native';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
import { getTimeFromNow } from '../../../utils/time';
|
import { getTimeFromNow } from '../../../utils/time';
|
||||||
|
@ -112,7 +112,6 @@ const WalletView = ({ setEstimatedWalletValue, selectedUser, handleOnScroll }) =
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</WalletContainer>
|
</WalletContainer>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
import WebView from 'react-native-webview';
|
||||||
import { useAppDispatch, useAppSelector } from '../../hooks';
|
import { useAppDispatch, useAppSelector } from '../../hooks';
|
||||||
import { hideWebViewModal } from '../../redux/actions/uiAction';
|
import { hideWebViewModal } from '../../redux/actions/uiAction';
|
||||||
import WebView from 'react-native-webview';
|
|
||||||
import { hsOptions } from '../../constants/hsOptions';
|
import { hsOptions } from '../../constants/hsOptions';
|
||||||
import { Modal } from '..';
|
import { Modal } from '..';
|
||||||
import styles from './webViewModalStyles';
|
import styles from './webViewModalStyles';
|
||||||
|
@ -24,18 +24,17 @@ const DEFAULT_ASSETS = [
|
|||||||
symbol: 'HBD',
|
symbol: 'HBD',
|
||||||
notCrypto: false,
|
notCrypto: false,
|
||||||
isEngine: false,
|
isEngine: false,
|
||||||
}
|
},
|
||||||
] as CoinBase[];
|
] as CoinBase[];
|
||||||
|
|
||||||
|
|
||||||
export enum ASSET_IDS {
|
export enum ASSET_IDS {
|
||||||
ECENCY= 'ecency',
|
ECENCY = 'ecency',
|
||||||
HIVE = 'hive',
|
HIVE = 'hive',
|
||||||
HBD = 'hive_dollar',
|
HBD = 'hive_dollar',
|
||||||
HP = 'hive_power',
|
HP = 'hive_power',
|
||||||
SPK = 'SPK',
|
SPK = 'SPK',
|
||||||
LARYNX = 'LARYNX',
|
LARYNX = 'LARYNX',
|
||||||
LARYNX_POWER = 'LP'
|
LARYNX_POWER = 'LP',
|
||||||
};
|
}
|
||||||
|
|
||||||
export default DEFAULT_ASSETS;
|
export default DEFAULT_ASSETS;
|
||||||
|
@ -15,12 +15,12 @@ export const VALUE = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const SERVER_LIST = [
|
export const SERVER_LIST = [
|
||||||
"https://rpc.ecency.com",
|
'https://rpc.ecency.com',
|
||||||
"https://api.hive.blog",
|
'https://api.hive.blog',
|
||||||
"https://api.deathwing.me",
|
'https://api.deathwing.me',
|
||||||
"https://api.pharesim.me",
|
'https://api.pharesim.me',
|
||||||
"https://anyx.io",
|
'https://anyx.io',
|
||||||
"https://rpc.ausbit.dev",
|
'https://rpc.ausbit.dev',
|
||||||
"https://api.openhive.network",
|
'https://api.openhive.network',
|
||||||
"https://api.hivekings.com"
|
'https://api.hivekings.com',
|
||||||
];
|
];
|
||||||
|
@ -19,7 +19,7 @@ export default {
|
|||||||
icon: 'trophy-outline',
|
icon: 'trophy-outline',
|
||||||
textKey: 'community_reward',
|
textKey: 'community_reward',
|
||||||
iconType: 'MaterialCommunityIcons',
|
iconType: 'MaterialCommunityIcons',
|
||||||
point: 0.1
|
point: 0.1,
|
||||||
},
|
},
|
||||||
160: {
|
160: {
|
||||||
icon: 'target',
|
icon: 'target',
|
||||||
@ -93,7 +93,7 @@ export default {
|
|||||||
iconType: 'MaterialCommunityIcons',
|
iconType: 'MaterialCommunityIcons',
|
||||||
point: 10,
|
point: 10,
|
||||||
},
|
},
|
||||||
'default': {
|
default: {
|
||||||
icon: 'local-activity',
|
icon: 'local-activity',
|
||||||
textKey: 'points_activity',
|
textKey: 'points_activity',
|
||||||
iconType: 'MaterialIcons',
|
iconType: 'MaterialIcons',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export enum PostTypes {
|
export enum PostTypes {
|
||||||
POST = 'post',
|
POST = 'post',
|
||||||
COMMENT = 'comment',
|
COMMENT = 'comment',
|
||||||
WAVE = 'wave'
|
WAVE = 'wave',
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ const ROUTES = {
|
|||||||
WELCOME: `Welcome${SCREEN_SUFFIX}`,
|
WELCOME: `Welcome${SCREEN_SUFFIX}`,
|
||||||
BACKUP_KEYS: `BackupKeys${SCREEN_SUFFIX}`,
|
BACKUP_KEYS: `BackupKeys${SCREEN_SUFFIX}`,
|
||||||
TRADE: `Trade${SCREEN_SUFFIX}`,
|
TRADE: `Trade${SCREEN_SUFFIX}`,
|
||||||
|
|
||||||
},
|
},
|
||||||
MODALS: {
|
MODALS: {
|
||||||
ASSETS_SELECT: `AssetsSelect${MODAL_SUFFIX}`,
|
ASSETS_SELECT: `AssetsSelect${MODAL_SUFFIX}`,
|
||||||
|
@ -484,7 +484,6 @@ class ProfileContainer extends Component {
|
|||||||
|
|
||||||
if (isLoggedIn && !nextProps.isLoggedIn) {
|
if (isLoggedIn && !nextProps.isLoggedIn) {
|
||||||
navigation.navigate(ROUTES.SCREENS.LOGIN);
|
navigation.navigate(ROUTES.SCREENS.LOGIN);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ export const BottomTabNavigator = () => {
|
|||||||
iconName: 'notifications', // read in bottomTabBarView
|
iconName: 'notifications', // read in bottomTabBarView
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</Tab.Navigator>
|
</Tab.Navigator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -24,7 +24,7 @@ export const fetchMarketChart = async (
|
|||||||
interval,
|
interval,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: skipping this failsafe since for now we can only use 'daily' interval
|
* NOTE: skipping this failsafe since for now we can only use 'daily' interval
|
||||||
// failsafe for accidental invalid parameters
|
// failsafe for accidental invalid parameters
|
||||||
// ref: https://www.coingecko.com/en/api/documentation
|
// ref: https://www.coingecko.com/en/api/documentation
|
||||||
|
@ -11,7 +11,6 @@ export const convertChartItem = (rawData: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const convertMarketData = (rawData: any) => {
|
export const convertMarketData = (rawData: any) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
prices: rawData.prices ? rawData.prices.map(convertChartItem) : [],
|
prices: rawData.prices ? rawData.prices.map(convertChartItem) : [],
|
||||||
marketCaps: rawData.market_caps ? rawData.market_caps.map(convertChartItem) : [],
|
marketCaps: rawData.market_caps ? rawData.market_caps.map(convertChartItem) : [],
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
LatestQuotes,
|
LatestQuotes,
|
||||||
QuoteItem,
|
QuoteItem,
|
||||||
ReferralStat,
|
ReferralStat,
|
||||||
Draft
|
Draft,
|
||||||
} from './ecency.types';
|
} from './ecency.types';
|
||||||
|
|
||||||
export const convertReferral = (rawData: any) => {
|
export const convertReferral = (rawData: any) => {
|
||||||
@ -14,7 +14,7 @@ export const convertReferral = (rawData: any) => {
|
|||||||
_id: rawData.id || 0,
|
_id: rawData.id || 0,
|
||||||
referral: rawData.referral || '',
|
referral: rawData.referral || '',
|
||||||
referredUsername: rawData.username || '',
|
referredUsername: rawData.username || '',
|
||||||
isRewarded: rawData.rewarded ? true : false,
|
isRewarded: !!rawData.rewarded,
|
||||||
timestamp: new Date(rawData.created) || new Date(),
|
timestamp: new Date(rawData.created) || new Date(),
|
||||||
} as Referral;
|
} as Referral;
|
||||||
};
|
};
|
||||||
@ -37,23 +37,23 @@ export const convertQuoteItem = (rawData: any, currencyRate: number) => {
|
|||||||
} as QuoteItem;
|
} as QuoteItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const convertDraft = (rawData:any) => {
|
export const convertDraft = (rawData: any) => {
|
||||||
if(!rawData){
|
if (!rawData) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_id:rawData._id,
|
_id: rawData._id,
|
||||||
title:rawData.title,
|
title: rawData.title,
|
||||||
body:rawData.body,
|
body: rawData.body,
|
||||||
tags_arr:rawData.tags_arr,
|
tags_arr: rawData.tags_arr,
|
||||||
tags:rawData.tags,
|
tags: rawData.tags,
|
||||||
meta:rawData.meta,
|
meta: rawData.meta,
|
||||||
modified:rawData.modified,
|
modified: rawData.modified,
|
||||||
created:rawData.created,
|
created: rawData.created,
|
||||||
timestamp:rawData.timestamp
|
timestamp: rawData.timestamp,
|
||||||
} as Draft
|
} as Draft;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const convertLatestQuotes = (rawData: any, currencyRate: number) => {
|
export const convertLatestQuotes = (rawData: any, currencyRate: number) => {
|
||||||
return {
|
return {
|
||||||
|
@ -10,7 +10,7 @@ import { EcencyUser, UserPoint } from './ecency.types';
|
|||||||
* @param tx transaction id
|
* @param tx transaction id
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const userActivity = async (ty: number, tx: string = '', bl: string | number = '') => {
|
export const userActivity = async (ty: number, tx = '', bl: string | number = '') => {
|
||||||
try {
|
try {
|
||||||
const data: {
|
const data: {
|
||||||
ty: number;
|
ty: number;
|
||||||
|
@ -31,13 +31,13 @@ import {
|
|||||||
* ************************************
|
* ************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const getFiatHbdRate = (fiatCode:string) =>
|
export const getFiatHbdRate = (fiatCode: string) =>
|
||||||
ecencyApi
|
ecencyApi
|
||||||
.get(`/private-api/market-data/${fiatCode}/hbd`)
|
.get(`/private-api/market-data/${fiatCode}/hbd`)
|
||||||
.then((resp) => resp.data)
|
.then((resp) => resp.data)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
bugsnagInstance.notify(err);
|
bugsnagInstance.notify(err);
|
||||||
//TODO: save currency rate of offline values
|
// TODO: save currency rate of offline values
|
||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ export const getLatestQuotes = async (currencyRate: number): Promise<LatestMarke
|
|||||||
const data = convertLatestQuotes(res.data, currencyRate);
|
const data = convertLatestQuotes(res.data, currencyRate);
|
||||||
console.log('parsed quotes data', data, currencyRate);
|
console.log('parsed quotes data', data, currencyRate);
|
||||||
|
|
||||||
//TODO fetch engine quotes here
|
// TODO fetch engine quotes here
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -126,8 +126,8 @@ export const addDraft = async (draft: Object) => {
|
|||||||
const res = await ecencyApi.post('/private-api/drafts-add', newDraft);
|
const res = await ecencyApi.post('/private-api/drafts-add', newDraft);
|
||||||
const rawData = res.data?.drafts;
|
const rawData = res.data?.drafts;
|
||||||
|
|
||||||
if(!rawData){
|
if (!rawData) {
|
||||||
throw new Error("Invalid response, drafts data not returned")
|
throw new Error('Invalid response, drafts data not returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = rawData.length > 0 ? rawData.map(convertDraft) : [];
|
const data = rawData.length > 0 ? rawData.map(convertDraft) : [];
|
||||||
@ -526,7 +526,7 @@ export const searchPath = async (q: string) => {
|
|||||||
* @param random random
|
* @param random random
|
||||||
* @returns array of accounts
|
* @returns array of accounts
|
||||||
*/
|
*/
|
||||||
export const searchAccount = async (q: string = '', limit: number = 20, random: number = 0) => {
|
export const searchAccount = async (q = '', limit = 20, random = 0) => {
|
||||||
try {
|
try {
|
||||||
const data = {
|
const data = {
|
||||||
q,
|
q,
|
||||||
@ -549,7 +549,7 @@ export const searchAccount = async (q: string = '', limit: number = 20, random:
|
|||||||
* @param random random
|
* @param random random
|
||||||
* @returns array of accounts
|
* @returns array of accounts
|
||||||
*/
|
*/
|
||||||
export const searchTag = async (q: string = '', limit: number = 20, random: number = 0) => {
|
export const searchTag = async (q = '', limit = 20, random = 0) => {
|
||||||
try {
|
try {
|
||||||
const data = {
|
const data = {
|
||||||
q,
|
q,
|
||||||
@ -782,7 +782,7 @@ export const getPromotedEntries = async (username: string) => {
|
|||||||
* post inapp purchase method to call
|
* post inapp purchase method to call
|
||||||
* @param data PurchaseRequestData
|
* @param data PurchaseRequestData
|
||||||
* @returns
|
* @returns
|
||||||
**/
|
* */
|
||||||
export const purchaseOrder = (data: PurchaseRequestData) =>
|
export const purchaseOrder = (data: PurchaseRequestData) =>
|
||||||
api
|
api
|
||||||
.post('/purchase-order', data)
|
.post('/purchase-order', data)
|
||||||
|
@ -1,7 +1,20 @@
|
|||||||
|
import {
|
||||||
|
EngineMetric,
|
||||||
|
HistoryItem,
|
||||||
|
HiveEngineToken,
|
||||||
|
MarketData,
|
||||||
|
Token,
|
||||||
|
TokenBalance,
|
||||||
|
TokenMetadata,
|
||||||
|
TokenStatus,
|
||||||
|
} from './hiveEngine.types';
|
||||||
|
|
||||||
import { EngineMetric, HistoryItem, HiveEngineToken, MarketData, Token, TokenBalance, TokenMetadata, TokenStatus } from './hiveEngine.types';
|
export const convertEngineToken = (
|
||||||
|
balanceObj: TokenBalance,
|
||||||
export const convertEngineToken = (balanceObj: TokenBalance, token?: Token, metrics?: EngineMetric, tokenStatus?:TokenStatus) => {
|
token?: Token,
|
||||||
|
metrics?: EngineMetric,
|
||||||
|
tokenStatus?: TokenStatus,
|
||||||
|
) => {
|
||||||
if (!balanceObj) {
|
if (!balanceObj) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -37,50 +50,44 @@ export const convertEngineToken = (balanceObj: TokenBalance, token?: Token, metr
|
|||||||
} as HiveEngineToken;
|
} as HiveEngineToken;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const convertRewardsStatus = (rawData: any) => {
|
export const convertRewardsStatus = (rawData: any) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
symbol:rawData.symbol,
|
symbol: rawData.symbol,
|
||||||
pendingToken:rawData.pending_token,
|
pendingToken: rawData.pending_token,
|
||||||
precision:rawData.precision,
|
precision: rawData.precision,
|
||||||
pendingRewards: rawData.pending_token / Math.pow(10, rawData.precision)
|
pendingRewards: rawData.pending_token / Math.pow(10, rawData.precision),
|
||||||
} as TokenStatus
|
} as TokenStatus;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export const convertMarketData = (rawData: any) => {
|
export const convertMarketData = (rawData: any) => {
|
||||||
|
if (!rawData) {
|
||||||
if(!rawData){
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
quoteVolume:parseFloat(rawData.quoteVolume),
|
quoteVolume: parseFloat(rawData.quoteVolume),
|
||||||
baseVolume:parseFloat(rawData.baseVolume),
|
baseVolume: parseFloat(rawData.baseVolume),
|
||||||
low:parseFloat(rawData.low),
|
low: parseFloat(rawData.low),
|
||||||
close:parseFloat(rawData.close),
|
close: parseFloat(rawData.close),
|
||||||
high:parseFloat(rawData.high),
|
high: parseFloat(rawData.high),
|
||||||
open:parseFloat(rawData.open),
|
open: parseFloat(rawData.open),
|
||||||
timestamp:rawData.timestamp,
|
timestamp: rawData.timestamp,
|
||||||
} as MarketData
|
} as MarketData;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export const convertEngineHistory = (rawData: any) => {
|
export const convertEngineHistory = (rawData: any) => {
|
||||||
return {
|
return {
|
||||||
|
_id: rawData._id,
|
||||||
_id:rawData._id,
|
blockNumber: rawData.blockNumber,
|
||||||
blockNumber:rawData.blockNumber,
|
transactionId: rawData.transactionId,
|
||||||
transactionId:rawData.transactionId,
|
timestamp: rawData.timestamp * 1000,
|
||||||
timestamp:rawData.timestamp * 1000,
|
operation: rawData.operation,
|
||||||
operation:rawData.operation,
|
from: rawData.from,
|
||||||
from:rawData.from,
|
to: rawData.to,
|
||||||
to:rawData.to,
|
symbol: rawData.symbol,
|
||||||
symbol:rawData.symbol,
|
quantity: parseFloat(rawData.quantity),
|
||||||
quantity:parseFloat(rawData.quantity),
|
memo: rawData.memo,
|
||||||
memo:rawData.memo,
|
account: rawData.account,
|
||||||
account:rawData.account,
|
authorperm: rawData.authorperm,
|
||||||
authorperm:rawData.authorperm,
|
} as HistoryItem;
|
||||||
} as HistoryItem
|
};
|
||||||
}
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EngineContracts,
|
EngineContracts,
|
||||||
EngineIds,
|
EngineIds,
|
||||||
@ -15,7 +13,12 @@ import {
|
|||||||
MarketData,
|
MarketData,
|
||||||
HistoryItem,
|
HistoryItem,
|
||||||
} from './hiveEngine.types';
|
} from './hiveEngine.types';
|
||||||
import { convertEngineToken, convertRewardsStatus, convertMarketData, convertEngineHistory } from './converters';
|
import {
|
||||||
|
convertEngineToken,
|
||||||
|
convertRewardsStatus,
|
||||||
|
convertMarketData,
|
||||||
|
convertEngineHistory,
|
||||||
|
} from './converters';
|
||||||
import bugsnapInstance from '../../config/bugsnag';
|
import bugsnapInstance from '../../config/bugsnag';
|
||||||
import ecencyApi from '../../config/ecencyApi';
|
import ecencyApi from '../../config/ecencyApi';
|
||||||
|
|
||||||
@ -26,19 +29,17 @@ import ecencyApi from '../../config/ecencyApi';
|
|||||||
*/
|
*/
|
||||||
const PATH_ENGINE_CONTRACTS = '/private-api/engine-api';
|
const PATH_ENGINE_CONTRACTS = '/private-api/engine-api';
|
||||||
|
|
||||||
//proxied path for 'https://scot-api.hive-engine.com/';
|
// proxied path for 'https://scot-api.hive-engine.com/';
|
||||||
const PATH_ENGINE_REWARDS = '/private-api/engine-reward-api';
|
const PATH_ENGINE_REWARDS = '/private-api/engine-reward-api';
|
||||||
|
|
||||||
//proxied path for 'https://info-api.tribaldex.com/market/ohlcv';
|
// proxied path for 'https://info-api.tribaldex.com/market/ohlcv';
|
||||||
const PATH_ENGINE_CHART = '/private-api/engine-chart-api';
|
const PATH_ENGINE_CHART = '/private-api/engine-chart-api';
|
||||||
|
|
||||||
//sample hive history endpoint call
|
// sample hive history endpoint call
|
||||||
//docs: https://github.com/hive-engine/ssc_tokens_history/tree/hive#api-usage
|
// docs: https://github.com/hive-engine/ssc_tokens_history/tree/hive#api-usage
|
||||||
//example: https://history.hive-engine.com/accountHistory?account=demo.com&limit=10&offset=10
|
// example: https://history.hive-engine.com/accountHistory?account=demo.com&limit=10&offset=10
|
||||||
const PATH_ENGINE_ACCOUNT_HISTORY = '/private-api/engine-account-history';
|
const PATH_ENGINE_ACCOUNT_HISTORY = '/private-api/engine-account-history';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const fetchTokenBalances = (account: string): Promise<TokenBalance[]> => {
|
export const fetchTokenBalances = (account: string): Promise<TokenBalance[]> => {
|
||||||
const data: EngineRequestPayload = {
|
const data: EngineRequestPayload = {
|
||||||
jsonrpc: JSON_RPC.RPC_2,
|
jsonrpc: JSON_RPC.RPC_2,
|
||||||
@ -47,13 +48,14 @@ export const fetchTokenBalances = (account: string): Promise<TokenBalance[]> =>
|
|||||||
contract: EngineContracts.TOKENS,
|
contract: EngineContracts.TOKENS,
|
||||||
table: EngineTables.BALANCES,
|
table: EngineTables.BALANCES,
|
||||||
query: {
|
query: {
|
||||||
account: account,
|
account,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
id: EngineIds.ONE,
|
id: EngineIds.ONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ecencyApi.post(PATH_ENGINE_CONTRACTS, data)
|
return ecencyApi
|
||||||
|
.post(PATH_ENGINE_CONTRACTS, data)
|
||||||
.then((r) => r.data.result)
|
.then((r) => r.data.result)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
return [];
|
return [];
|
||||||
@ -86,17 +88,14 @@ export const fetchHiveEngineTokenBalances = async (
|
|||||||
account: string,
|
account: string,
|
||||||
): Promise<Array<HiveEngineToken | null>> => {
|
): Promise<Array<HiveEngineToken | null>> => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const balances = await fetchTokenBalances(account);
|
const balances = await fetchTokenBalances(account);
|
||||||
const symbols = balances.map((t) => t.symbol);
|
const symbols = balances.map((t) => t.symbol);
|
||||||
|
|
||||||
const tokens = await fetchTokens(symbols);
|
const tokens = await fetchTokens(symbols);
|
||||||
const metrices = await fetchMetics(symbols);
|
const metrices = await fetchMetics(symbols);
|
||||||
const unclaimed = await fetchUnclaimedRewards(account)
|
const unclaimed = await fetchUnclaimedRewards(account);
|
||||||
|
|
||||||
|
|
||||||
return balances.map((balance) => {
|
return balances.map((balance) => {
|
||||||
|
|
||||||
const token = tokens.find((t) => t.symbol == balance.symbol);
|
const token = tokens.find((t) => t.symbol == balance.symbol);
|
||||||
const metrics = metrices.find((t) => t.symbol == balance.symbol);
|
const metrics = metrices.find((t) => t.symbol == balance.symbol);
|
||||||
const pendingRewards = unclaimed.find((t) => t.symbol == balance.symbol);
|
const pendingRewards = unclaimed.find((t) => t.symbol == balance.symbol);
|
||||||
@ -109,11 +108,8 @@ export const fetchHiveEngineTokenBalances = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const fetchMetics = async (tokens?: string[]) => {
|
export const fetchMetics = async (tokens?: string[]) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
jsonrpc: JSON_RPC.RPC_2,
|
jsonrpc: JSON_RPC.RPC_2,
|
||||||
method: Methods.FIND,
|
method: Methods.FIND,
|
||||||
@ -122,94 +118,101 @@ export const fetchMetics = async (tokens?: string[]) => {
|
|||||||
table: EngineTables.METRICS,
|
table: EngineTables.METRICS,
|
||||||
query: {
|
query: {
|
||||||
symbol: { $in: tokens },
|
symbol: { $in: tokens },
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
id: EngineIds.ONE
|
id: EngineIds.ONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await ecencyApi.post(PATH_ENGINE_CONTRACTS, data)
|
const response = await ecencyApi.post(PATH_ENGINE_CONTRACTS, data);
|
||||||
if (!response.data.result) {
|
if (!response.data.result) {
|
||||||
throw new Error("No metric data returned")
|
throw new Error('No metric data returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.data.result as EngineMetric[]
|
return response.data.result as EngineMetric[];
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn('Failed to get engine metrices', err);
|
console.warn('Failed to get engine metrices', err);
|
||||||
bugsnapInstance.notify(err);
|
bugsnapInstance.notify(err);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export const fetchUnclaimedRewards = async (account: string): Promise<TokenStatus[]> => {
|
export const fetchUnclaimedRewards = async (account: string): Promise<TokenStatus[]> => {
|
||||||
try {
|
try {
|
||||||
const response = await ecencyApi.get(`${PATH_ENGINE_REWARDS}/${account}`, {
|
const response = await ecencyApi.get(`${PATH_ENGINE_REWARDS}/${account}`, {
|
||||||
params:{hive:1}
|
params: { hive: 1 },
|
||||||
})
|
});
|
||||||
const rawData = Object.values(response.data)
|
const rawData = Object.values(response.data);
|
||||||
if (!rawData || rawData.length === 0) {
|
if (!rawData || rawData.length === 0) {
|
||||||
throw new Error("No rewards data returned");
|
throw new Error('No rewards data returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = rawData.map(convertRewardsStatus);
|
const data = rawData.map(convertRewardsStatus);
|
||||||
const filteredData = data.filter(item => item && item.pendingToken > 0)
|
const filteredData = data.filter((item) => item && item.pendingToken > 0);
|
||||||
|
|
||||||
console.log('unclaimed engine rewards data', filteredData);
|
console.log('unclaimed engine rewards data', filteredData);
|
||||||
return filteredData;
|
return filteredData;
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn("failed ot get unclaimed engine rewards", err)
|
console.warn('failed ot get unclaimed engine rewards', err);
|
||||||
bugsnapInstance.notify(err);
|
bugsnapInstance.notify(err);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchEngineMarketData = async (symbol: any, vsCurrency:string = 'usd', days:number = 0, interval = 'daily') => {
|
export const fetchEngineMarketData = async (
|
||||||
|
symbol: any,
|
||||||
|
vsCurrency = 'usd',
|
||||||
|
days = 0,
|
||||||
|
interval = 'daily',
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
const response = await ecencyApi.get(PATH_ENGINE_CHART, {
|
const response = await ecencyApi.get(PATH_ENGINE_CHART, {
|
||||||
params: { symbol, interval }
|
params: { symbol, interval },
|
||||||
});
|
});
|
||||||
|
|
||||||
const rawData = response?.data;
|
const rawData = response?.data;
|
||||||
|
|
||||||
if(!rawData){
|
if (!rawData) {
|
||||||
throw new Error("No data returned");
|
throw new Error('No data returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data:MarketData[] = rawData.map(convertMarketData);
|
const data: MarketData[] = rawData.map(convertMarketData);
|
||||||
|
|
||||||
return days > 1 && data.length > days ? data.slice(data.length - days) : data;
|
return days > 1 && data.length > days ? data.slice(data.length - days) : data;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
bugsnapInstance.notify(err);
|
bugsnapInstance.notify(err);
|
||||||
console.warn("failed to get chart data", err.message);
|
console.warn('failed to get chart data', err.message);
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fetchEngineAccountHistory = async (
|
||||||
export const fetchEngineAccountHistory = async (username:string , symbol:string , startIndex:number = 0, limit:number = 20) => {
|
username: string,
|
||||||
|
symbol: string,
|
||||||
|
startIndex = 0,
|
||||||
|
limit = 20,
|
||||||
|
) => {
|
||||||
try {
|
try {
|
||||||
const response = await ecencyApi.get(PATH_ENGINE_ACCOUNT_HISTORY, {params:{
|
const response = await ecencyApi.get(PATH_ENGINE_ACCOUNT_HISTORY, {
|
||||||
account:username,
|
params: {
|
||||||
symbol:symbol,
|
account: username,
|
||||||
limit,
|
symbol,
|
||||||
offset: limit * startIndex
|
limit,
|
||||||
}})
|
offset: limit * startIndex,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const rawData = response?.data;
|
const rawData = response?.data;
|
||||||
|
|
||||||
if(!rawData){
|
if (!rawData) {
|
||||||
throw new Error("No data returned");
|
throw new Error('No data returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data:HistoryItem[] = rawData.map(convertEngineHistory);
|
const data: HistoryItem[] = rawData.map(convertEngineHistory);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
bugsnapInstance.notify(err);
|
bugsnapInstance.notify(err);
|
||||||
console.warn("failed to get engine account history", err.message);
|
console.warn('failed to get engine account history', err.message);
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export enum JSON_RPC {
|
|||||||
|
|
||||||
export enum EngineContracts {
|
export enum EngineContracts {
|
||||||
TOKENS = 'tokens',
|
TOKENS = 'tokens',
|
||||||
MARKET = 'market'
|
MARKET = 'market',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EngineActions {
|
export enum EngineActions {
|
||||||
@ -17,10 +17,9 @@ export enum EngineActions {
|
|||||||
DELEGATE = 'delegate',
|
DELEGATE = 'delegate',
|
||||||
UNDELEGATE = 'undelegate',
|
UNDELEGATE = 'undelegate',
|
||||||
UNSTAKE = 'unstake',
|
UNSTAKE = 'unstake',
|
||||||
STAKE = 'stake'
|
STAKE = 'stake',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export enum EngineTables {
|
export enum EngineTables {
|
||||||
BALANCES = 'balances',
|
BALANCES = 'balances',
|
||||||
DELEGATIONS = 'delegations',
|
DELEGATIONS = 'delegations',
|
||||||
@ -32,7 +31,6 @@ export enum EngineIds {
|
|||||||
ONE = '1',
|
ONE = '1',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface TokenBalance {
|
export interface TokenBalance {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
balance: string;
|
balance: string;
|
||||||
@ -79,7 +77,7 @@ export interface HiveEngineToken {
|
|||||||
tokenPrice?: number;
|
tokenPrice?: number;
|
||||||
percentChange?: number;
|
percentChange?: number;
|
||||||
unclaimedBalance: string;
|
unclaimedBalance: string;
|
||||||
volume24h?:number
|
volume24h?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TokenMetadata {
|
export interface TokenMetadata {
|
||||||
@ -95,21 +93,18 @@ export interface TokenStatus {
|
|||||||
pendingRewards: number;
|
pendingRewards: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export interface EngineMetric {
|
export interface EngineMetric {
|
||||||
_id: number
|
_id: number;
|
||||||
highestBid: string;
|
highestBid: string;
|
||||||
lastDayPrice: string;
|
lastDayPrice: string;
|
||||||
lastDayPriceExpiration: number;
|
lastDayPriceExpiration: number;
|
||||||
lastPrice: string;
|
lastPrice: string;
|
||||||
lowestAsk: string;
|
lowestAsk: string;
|
||||||
priceChangeHive:string;
|
priceChangeHive: string;
|
||||||
priceChangePercent:string;
|
priceChangePercent: string;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
volume: string;
|
volume: string;
|
||||||
volumeExpiration: number;
|
volumeExpiration: number;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EngineQuery {
|
interface EngineQuery {
|
||||||
@ -130,105 +125,102 @@ export interface EngineRequestPayload {
|
|||||||
id: EngineIds;
|
id: EngineIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export interface EngineActionPayload {
|
export interface EngineActionPayload {
|
||||||
to:string,
|
to: string;
|
||||||
symbol:string,
|
symbol: string;
|
||||||
quantity:string,
|
quantity: string;
|
||||||
memo?:string
|
memo?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EngineActionJSON {
|
export interface EngineActionJSON {
|
||||||
contractName:EngineContracts;
|
contractName: EngineContracts;
|
||||||
contractAction:EngineActions;
|
contractAction: EngineActions;
|
||||||
contractPayload: EngineActionPayload;
|
contractPayload: EngineActionPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface MarketData {
|
export interface MarketData {
|
||||||
quoteVolume:number;
|
quoteVolume: number;
|
||||||
baseVolume:number;
|
baseVolume: number;
|
||||||
low:number;
|
low: number;
|
||||||
close:number;
|
close: number;
|
||||||
high:number;
|
high: number;
|
||||||
open:number;
|
open: number;
|
||||||
timestamp:number;
|
timestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HistoryItem {
|
export interface HistoryItem {
|
||||||
_id:string;
|
_id: string;
|
||||||
blockNumber:number;
|
blockNumber: number;
|
||||||
transactionId:string;
|
transactionId: string;
|
||||||
timestamp:number;
|
timestamp: number;
|
||||||
operation:EngineOperations;
|
operation: EngineOperations;
|
||||||
from:string;
|
from: string;
|
||||||
to:string;
|
to: string;
|
||||||
symbol:string;
|
symbol: string;
|
||||||
quantity:number;
|
quantity: number;
|
||||||
memo:string;
|
memo: string;
|
||||||
account:string;
|
account: string;
|
||||||
authorperm?:string;
|
authorperm?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EngineOperations {
|
export enum EngineOperations {
|
||||||
TOKENS_CREATE = "tokens_create",
|
TOKENS_CREATE = 'tokens_create',
|
||||||
TOKENS_ISSUE = "tokens_issue",
|
TOKENS_ISSUE = 'tokens_issue',
|
||||||
TOKENS_TRANSFER = "tokens_transfer",
|
TOKENS_TRANSFER = 'tokens_transfer',
|
||||||
TOKENS_TRANSFER_TO_CONTRACT = "tokens_transferToContract",
|
TOKENS_TRANSFER_TO_CONTRACT = 'tokens_transferToContract',
|
||||||
TOKENS_TRANSFER_FROM_CONTRACT = "tokens_transferFromContract",
|
TOKENS_TRANSFER_FROM_CONTRACT = 'tokens_transferFromContract',
|
||||||
TOKENS_UPDATE_PRECISION = "tokens_updatePrecision",
|
TOKENS_UPDATE_PRECISION = 'tokens_updatePrecision',
|
||||||
TOKENS_UPDATE_URL = "tokens_updateUrl",
|
TOKENS_UPDATE_URL = 'tokens_updateUrl',
|
||||||
TOKENS_UPDATE_METADATA = "tokens_updateMetadata",
|
TOKENS_UPDATE_METADATA = 'tokens_updateMetadata',
|
||||||
TOKENS_TRANSFER_OWNERSHIP = "tokens_transferOwnership",
|
TOKENS_TRANSFER_OWNERSHIP = 'tokens_transferOwnership',
|
||||||
TOKENS_ENABLE_STAKING = "tokens_enableStaking",
|
TOKENS_ENABLE_STAKING = 'tokens_enableStaking',
|
||||||
TOKENS_ENABLE_DELEGATION = "tokens_enableDelegation",
|
TOKENS_ENABLE_DELEGATION = 'tokens_enableDelegation',
|
||||||
TOKENS_STAKE = "tokens_stake",
|
TOKENS_STAKE = 'tokens_stake',
|
||||||
TOKENS_UNSTAKE_START = "tokens_unstakeStart",
|
TOKENS_UNSTAKE_START = 'tokens_unstakeStart',
|
||||||
TOKENS_UNSTAKE_DONE = "tokens_unstakeDone",
|
TOKENS_UNSTAKE_DONE = 'tokens_unstakeDone',
|
||||||
TOKENS_CANCEL_UNSTAKE = "tokens_cancelUnstake",
|
TOKENS_CANCEL_UNSTAKE = 'tokens_cancelUnstake',
|
||||||
TOKENS_DELEGATE = "tokens_delegate",
|
TOKENS_DELEGATE = 'tokens_delegate',
|
||||||
TOKENS_UNDELEGATE_START = "tokens_undelegateStart",
|
TOKENS_UNDELEGATE_START = 'tokens_undelegateStart',
|
||||||
TOKENS_UNDELEGATE_DONE = "tokens_undelegateDone",
|
TOKENS_UNDELEGATE_DONE = 'tokens_undelegateDone',
|
||||||
TOKENS_TRANSFER_FEE = "tokens_transferFee",
|
TOKENS_TRANSFER_FEE = 'tokens_transferFee',
|
||||||
MARKET_CANCEL = "market_cancel",
|
MARKET_CANCEL = 'market_cancel',
|
||||||
MARKET_PLACE_ORDER = "market_placeOrder",
|
MARKET_PLACE_ORDER = 'market_placeOrder',
|
||||||
MARKET_EXPIRE = "market_expire",
|
MARKET_EXPIRE = 'market_expire',
|
||||||
MARKET_BUY = "market_buy",
|
MARKET_BUY = 'market_buy',
|
||||||
MARKET_BUY_REMAINING = "market_buyRemaining",
|
MARKET_BUY_REMAINING = 'market_buyRemaining',
|
||||||
MARKET_SELL = "market_sell",
|
MARKET_SELL = 'market_sell',
|
||||||
MARKET_SELL_REMAINING = "market_sellRemaining",
|
MARKET_SELL_REMAINING = 'market_sellRemaining',
|
||||||
MARKET_CLOSE = "market_close",
|
MARKET_CLOSE = 'market_close',
|
||||||
MINING_LOTTERY = "mining_lottery",
|
MINING_LOTTERY = 'mining_lottery',
|
||||||
WITNESSES_PROPOSE_ROUND = "witnesses_proposeRound",
|
WITNESSES_PROPOSE_ROUND = 'witnesses_proposeRound',
|
||||||
HIVEPEGGED_BUY = "hivepegged_buy",
|
HIVEPEGGED_BUY = 'hivepegged_buy',
|
||||||
HIVEPEGGED_WITHDRAW = "hivepegged_withdraw",
|
HIVEPEGGED_WITHDRAW = 'hivepegged_withdraw',
|
||||||
INFLATION_ISSUE_NEW_TOKENS = "inflation_issueNewTokens",
|
INFLATION_ISSUE_NEW_TOKENS = 'inflation_issueNewTokens',
|
||||||
NFT_TRANSFER = "nft_transfer",
|
NFT_TRANSFER = 'nft_transfer',
|
||||||
NFT_ISSUE = "nft_issue",
|
NFT_ISSUE = 'nft_issue',
|
||||||
NFT_ISSUE_MULTIPLE = "nft_issueMultiple",
|
NFT_ISSUE_MULTIPLE = 'nft_issueMultiple',
|
||||||
NFT_BURN = "nft_burn",
|
NFT_BURN = 'nft_burn',
|
||||||
NFT_DELEGATE = "nft_delegate",
|
NFT_DELEGATE = 'nft_delegate',
|
||||||
NFT_UNDELEGATE = "nft_undelegate",
|
NFT_UNDELEGATE = 'nft_undelegate',
|
||||||
NFT_UNDELEGATE_DONE = "nft_undelegateDone",
|
NFT_UNDELEGATE_DONE = 'nft_undelegateDone',
|
||||||
NFT_ENABLE_DELEGATION = "nft_enableDelegation",
|
NFT_ENABLE_DELEGATION = 'nft_enableDelegation',
|
||||||
NFT_CREATE = "nft_create",
|
NFT_CREATE = 'nft_create',
|
||||||
NFT_ADD_AUTHORIZED_ISSUING_ACCOUNTS = "nft_addAuthorizedIssuingAccounts",
|
NFT_ADD_AUTHORIZED_ISSUING_ACCOUNTS = 'nft_addAuthorizedIssuingAccounts',
|
||||||
NFT_SET_GROUP_BY = "nft_setGroupBy",
|
NFT_SET_GROUP_BY = 'nft_setGroupBy',
|
||||||
NFT_SET_PROPERTIES = "nft_setProperties",
|
NFT_SET_PROPERTIES = 'nft_setProperties',
|
||||||
NFT_ADD_PROPERTY = "nft_addProperty",
|
NFT_ADD_PROPERTY = 'nft_addProperty',
|
||||||
NFT_SET_PROPERTY_PERMISSIONS = "nft_setPropertyPermissions",
|
NFT_SET_PROPERTY_PERMISSIONS = 'nft_setPropertyPermissions',
|
||||||
NFT_UPDATE_PROPERTY_DEFINITION = "nft_updatePropertyDefinition",
|
NFT_UPDATE_PROPERTY_DEFINITION = 'nft_updatePropertyDefinition',
|
||||||
NFT_UPDATE_URL = "nft_updateUrl",
|
NFT_UPDATE_URL = 'nft_updateUrl',
|
||||||
NFT_UPDATE_METADATA = "nft_updateMetadata",
|
NFT_UPDATE_METADATA = 'nft_updateMetadata',
|
||||||
NFT_UPDATE_NAME = "nft_updateName",
|
NFT_UPDATE_NAME = 'nft_updateName',
|
||||||
NFT_UPDATE_ORG_NAME = "nft_updateOrgName",
|
NFT_UPDATE_ORG_NAME = 'nft_updateOrgName',
|
||||||
NFT_UPDATE_PRODUCT_NAME = "nft_updateProductName",
|
NFT_UPDATE_PRODUCT_NAME = 'nft_updateProductName',
|
||||||
NFT_TRANSFER_FEE = "nft_transferFee",
|
NFT_TRANSFER_FEE = 'nft_transferFee',
|
||||||
NFTMARKET_BUY = "nftmarket_buy",
|
NFTMARKET_BUY = 'nftmarket_buy',
|
||||||
NFTMARKET_TRANSFER_FEE = "nftmarket_transferFee",
|
NFTMARKET_TRANSFER_FEE = 'nftmarket_transferFee',
|
||||||
NFTMARKET_SELL = "nftmarket_sell",
|
NFTMARKET_SELL = 'nftmarket_sell',
|
||||||
NFTMARKET_CANCEL = "nftmarket_cancel",
|
NFTMARKET_CANCEL = 'nftmarket_cancel',
|
||||||
NFTMARKET_CHANGE_PRICE = "nftmarket_changePrice",
|
NFTMARKET_CHANGE_PRICE = 'nftmarket_changePrice',
|
||||||
NFTMARKET_ENABLE_MARKET = "nftmarket_enableMarket"
|
NFTMARKET_ENABLE_MARKET = 'nftmarket_enableMarket',
|
||||||
}
|
}
|
||||||
|
@ -70,13 +70,7 @@ export const limitOrderCreate = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const limitOrderCancel = (currentAccount: any, pinHash: string, orderid: number) => {
|
||||||
export const limitOrderCancel = (
|
|
||||||
currentAccount: any,
|
|
||||||
pinHash:string,
|
|
||||||
orderid: number
|
|
||||||
) => {
|
|
||||||
|
|
||||||
const digitPinCode = getDigitPinCode(pinHash);
|
const digitPinCode = getDigitPinCode(pinHash);
|
||||||
const key = getAnyPrivateKey(
|
const key = getAnyPrivateKey(
|
||||||
{
|
{
|
||||||
@ -87,13 +81,13 @@ export const limitOrderCancel = (
|
|||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
const privateKey = PrivateKey.fromString(key);
|
const privateKey = PrivateKey.fromString(key);
|
||||||
const ops:Operation[] = [
|
const ops: Operation[] = [
|
||||||
[
|
[
|
||||||
"limit_order_cancel",
|
'limit_order_cancel',
|
||||||
{
|
{
|
||||||
owner: currentAccount.username,
|
owner: currentAccount.username,
|
||||||
orderid: orderid
|
orderid,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -113,8 +107,6 @@ export const limitOrderCancel = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const generateHsLimitOrderCreatePath = (
|
export const generateHsLimitOrderCreatePath = (
|
||||||
currentAccount: any,
|
currentAccount: any,
|
||||||
amountToSell: number,
|
amountToSell: number,
|
||||||
|
@ -2154,8 +2154,8 @@ export const resolveTransaction = async (parsedTx, parsedParams, signer) => {
|
|||||||
signers: [signer],
|
signers: [signer],
|
||||||
preferred_signer: signer,
|
preferred_signer: signer,
|
||||||
});
|
});
|
||||||
tx.ref_block_num = parseInt(tx.ref_block_num + '', 10);
|
tx.ref_block_num = parseInt(`${tx.ref_block_num}`, 10);
|
||||||
tx.ref_block_prefix = parseInt(tx.ref_block_prefix + '', 10);
|
tx.ref_block_prefix = parseInt(`${tx.ref_block_prefix}`, 10);
|
||||||
|
|
||||||
return tx;
|
return tx;
|
||||||
};
|
};
|
||||||
|
@ -111,8 +111,8 @@ export interface SavingsWithdrawRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TransferDataType {
|
export interface TransferDataType {
|
||||||
fundType:string,
|
fundType: string;
|
||||||
destination:string
|
destination: string;
|
||||||
amount: string
|
amount: string;
|
||||||
memo?:string
|
memo?: string;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ interface MediaUploadVars {
|
|||||||
addToUploads: boolean;
|
addToUploads: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** GET QUERIES **/
|
/** GET QUERIES * */
|
||||||
|
|
||||||
export const useMediaQuery = () => {
|
export const useMediaQuery = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@ -57,7 +57,7 @@ export const useSnippetsQuery = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** ADD UPDATE MUTATIONS **/
|
/** ADD UPDATE MUTATIONS * */
|
||||||
|
|
||||||
export const useAddToUploadsMutation = () => {
|
export const useAddToUploadsMutation = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@ -71,7 +71,7 @@ export const useAddToUploadsMutation = () => {
|
|||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
if (error.toString().includes('code 409')) {
|
if (error.toString().includes('code 409')) {
|
||||||
//means image ware already preset, refresh to get updated order
|
// means image ware already preset, refresh to get updated order
|
||||||
queryClient.invalidateQueries([QUERIES.MEDIA.GET]);
|
queryClient.invalidateQueries([QUERIES.MEDIA.GET]);
|
||||||
} else {
|
} else {
|
||||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||||
@ -234,7 +234,7 @@ export const useSnippetsMutation = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DELETE MUTATIONS **/
|
/** DELETE MUTATIONS * */
|
||||||
|
|
||||||
export const useMediaDeleteMutation = () => {
|
export const useMediaDeleteMutation = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
@ -10,7 +10,7 @@ export const initQueryClient = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const client = new QueryClient({
|
const client = new QueryClient({
|
||||||
//Query client configurations go here...
|
// Query client configurations go here...
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
cacheTime: 1000 * 60 * 60 * 24 * 6, // 7 days cache timer
|
cacheTime: 1000 * 60 * 60 * 24 * 6, // 7 days cache timer
|
||||||
@ -18,34 +18,32 @@ export const initQueryClient = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const _shouldDehdrateQuery = (query: Query) => {
|
||||||
|
|
||||||
|
|
||||||
const _shouldDehdrateQuery = (query:Query) => {
|
|
||||||
const _isSuccess = query.state.status === 'success';
|
const _isSuccess = query.state.status === 'success';
|
||||||
|
|
||||||
if(_isSuccess){
|
if (_isSuccess) {
|
||||||
//Cherry pick whihc queries to dehydrate for persistance
|
// Cherry pick whihc queries to dehydrate for persistance
|
||||||
switch(query.queryKey[0]){
|
switch (query.queryKey[0]) {
|
||||||
case QUERIES.WAVES.GET:
|
case QUERIES.WAVES.GET:
|
||||||
return query.queryKey[3] === 0 //only dehydrate first page of waves
|
return query.queryKey[3] === 0; // only dehydrate first page of waves
|
||||||
case QUERIES.NOTIFICATIONS.GET:
|
case QUERIES.NOTIFICATIONS.GET:
|
||||||
return query.queryKey[2] === '' //only dehydrate first page of notifications
|
return query.queryKey[2] === ''; // only dehydrate first page of notifications
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("status error for dehydration", query.queryKey)
|
console.log('status error for dehydration', query.queryKey);
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
client,
|
client,
|
||||||
persistOptions: {
|
persistOptions: {
|
||||||
persister: asyncStoragePersister, dehydrateOptions: {
|
persister: asyncStoragePersister,
|
||||||
shouldDehydrateQuery: _shouldDehdrateQuery
|
dehydrateOptions: {
|
||||||
}
|
shouldDehydrateQuery: _shouldDehdrateQuery,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as PersistQueryClientProviderProps;
|
} as PersistQueryClientProviderProps;
|
||||||
};
|
};
|
||||||
@ -56,4 +54,4 @@ export * from './editorQueries';
|
|||||||
export * from './pointQueries';
|
export * from './pointQueries';
|
||||||
export * from './postQueries';
|
export * from './postQueries';
|
||||||
export * from './walletQueries';
|
export * from './walletQueries';
|
||||||
export * from './leaderboardQueries';
|
export * from './leaderboardQueries';
|
||||||
|
@ -122,7 +122,7 @@ export const useDiscussionQuery = (_author?: string, _permlink?: string) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const _data = injectPostCache(query.data, cachedComments, cachedVotes, lastCacheUpdate);
|
const _data = injectPostCache(query.data, cachedComments, cachedVotes, lastCacheUpdate);
|
||||||
setData(_data);
|
setData(_data);
|
||||||
}, [query.data, cachedComments, cachedVotes]);
|
}, [query.data, cachedComments, cachedVotes]);
|
||||||
|
|
||||||
@ -130,7 +130,6 @@ export const useDiscussionQuery = (_author?: string, _permlink?: string) => {
|
|||||||
restructureData();
|
restructureData();
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
|
|
||||||
// traverse discussion collection to curate sections
|
// traverse discussion collection to curate sections
|
||||||
const restructureData = async () => {
|
const restructureData = async () => {
|
||||||
const MAX_THREAD_LEVEL = 3;
|
const MAX_THREAD_LEVEL = 3;
|
||||||
|
@ -1,33 +1,27 @@
|
|||||||
|
import { UseMutationOptions, useMutation, useQueries, useQueryClient } from '@tanstack/react-query';
|
||||||
import {
|
|
||||||
UseMutationOptions,
|
|
||||||
useMutation,
|
|
||||||
useQueries, useQueryClient,
|
|
||||||
} from '@tanstack/react-query';
|
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { unionBy, isArray } from 'lodash';
|
import { unionBy, isArray } from 'lodash';
|
||||||
import { getDiscussionCollection } from '../../hive/dhive';
|
import { getDiscussionCollection, getAccountPosts } from '../../hive/dhive';
|
||||||
|
|
||||||
import { getAccountPosts } from '../../hive/dhive';
|
|
||||||
import QUERIES from '../queryKeys';
|
import QUERIES from '../queryKeys';
|
||||||
import { delay } from '../../../utils/editor';
|
import { delay } from '../../../utils/editor';
|
||||||
import { injectPostCache, injectVoteCache, mapDiscussionToThreads } from '../../../utils/postParser';
|
import {
|
||||||
|
injectPostCache,
|
||||||
|
injectVoteCache,
|
||||||
|
mapDiscussionToThreads,
|
||||||
|
} from '../../../utils/postParser';
|
||||||
import { useAppSelector } from '../../../hooks';
|
import { useAppSelector } from '../../../hooks';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useWavesQuery = (host: string) => {
|
export const useWavesQuery = (host: string) => {
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const cache = useAppSelector(state => state.cache);
|
const cache = useAppSelector((state) => state.cache);
|
||||||
const mutes = useAppSelector(state => state.account.currentAccount.mutes);
|
const mutes = useAppSelector((state) => state.account.currentAccount.mutes);
|
||||||
const cacheRef = useRef(cache);
|
const cacheRef = useRef(cache);
|
||||||
|
|
||||||
const cachedVotes = cache.votesCollection
|
const cachedVotes = cache.votesCollection;
|
||||||
const lastCacheUpdate = cache.lastUpdate
|
const lastCacheUpdate = cache.lastUpdate;
|
||||||
|
|
||||||
|
|
||||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
@ -35,102 +29,99 @@ export const useWavesQuery = (host: string) => {
|
|||||||
|
|
||||||
const wavesIndexCollection = useRef<{ [key: string]: string }>({});
|
const wavesIndexCollection = useRef<{ [key: string]: string }>({});
|
||||||
|
|
||||||
const _initialContainerPermlinks = useMemo(() =>
|
const _initialContainerPermlinks = useMemo(
|
||||||
queryClient.getQueryData<string[]>([QUERIES.WAVES.INITIAL_CONTAINERS, host]) || [], []);
|
() => queryClient.getQueryData<string[]>([QUERIES.WAVES.INITIAL_CONTAINERS, host]) || [],
|
||||||
|
[],
|
||||||
|
);
|
||||||
const [permlinksBucket, setPermlinksBucket] = useState<string[]>(_initialContainerPermlinks);
|
const [permlinksBucket, setPermlinksBucket] = useState<string[]>(_initialContainerPermlinks);
|
||||||
|
|
||||||
|
|
||||||
// query initialization
|
// query initialization
|
||||||
const wavesQueries = useQueries({
|
const wavesQueries = useQueries({
|
||||||
queries: activePermlinks.map((pagePermlink, index) => ({
|
queries: activePermlinks.map((pagePermlink, index) => ({
|
||||||
queryKey: [QUERIES.WAVES.GET, host, pagePermlink, index], //index at end is used to track query hydration
|
queryKey: [QUERIES.WAVES.GET, host, pagePermlink, index], // index at end is used to track query hydration
|
||||||
queryFn: () => _fetchWaves(pagePermlink),
|
queryFn: () => _fetchWaves(pagePermlink),
|
||||||
initialData: [],
|
initialData: [],
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// hook to update cache reference,
|
||||||
//hook to update cache reference,
|
// workaround required since query fucntion do get passed an
|
||||||
//workaround required since query fucntion do get passed an
|
// updated copy for states that are not part of query key and contexet while conext is not
|
||||||
//updated copy for states that are not part of query key and contexet while conext is not
|
// supported by useQueries
|
||||||
//supported by useQueries
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
cacheRef.current = cache;
|
cacheRef.current = cache;
|
||||||
}, [cache])
|
}, [cache]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
_fetchPermlinks('', true);
|
_fetchPermlinks('', true);
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!!permlinksBucket.length) {
|
if (permlinksBucket.length) {
|
||||||
//if first elements permlinks do not match, means there is a new container, push at first
|
// if first elements permlinks do not match, means there is a new container, push at first
|
||||||
if (permlinksBucket[0] !== activePermlinks[0]) {
|
if (permlinksBucket[0] !== activePermlinks[0]) {
|
||||||
activePermlinks.splice(0, 0, permlinksBucket[0]);
|
activePermlinks.splice(0, 0, permlinksBucket[0]);
|
||||||
}
|
}
|
||||||
//permlinks bucket is updated, it needs to be connect with active one to start chain again
|
// permlinks bucket is updated, it needs to be connect with active one to start chain again
|
||||||
else {
|
else {
|
||||||
activePermlinks.push(permlinksBucket[activePermlinks.length]);
|
activePermlinks.push(permlinksBucket[activePermlinks.length]);
|
||||||
}
|
}
|
||||||
setActivePermlinks([...activePermlinks]);
|
setActivePermlinks([...activePermlinks]);
|
||||||
}
|
}
|
||||||
}, [permlinksBucket])
|
}, [permlinksBucket]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const _latestData = wavesQueries.lastItem?.data;
|
const _latestData = wavesQueries.lastItem?.data;
|
||||||
if (!_latestData || _latestData.length < 10) {
|
if (!_latestData || _latestData.length < 10) {
|
||||||
_fetchNextPage();
|
_fetchNextPage();
|
||||||
}
|
}
|
||||||
}, [wavesQueries.lastItem?.data])
|
}, [wavesQueries.lastItem?.data]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//check cache is recently updated and take post path
|
// check cache is recently updated and take post path
|
||||||
if (lastCacheUpdate) {
|
if (lastCacheUpdate) {
|
||||||
const _timeElapsed = new Date().getTime() - lastCacheUpdate.updatedAt
|
const _timeElapsed = new Date().getTime() - lastCacheUpdate.updatedAt;
|
||||||
if (lastCacheUpdate.type === 'vote' && _timeElapsed < 5000) {
|
if (lastCacheUpdate.type === 'vote' && _timeElapsed < 5000) {
|
||||||
_injectPostCache(lastCacheUpdate.postPath)
|
_injectPostCache(lastCacheUpdate.postPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, [lastCacheUpdate]);
|
||||||
}, [lastCacheUpdate])
|
|
||||||
|
|
||||||
|
|
||||||
const _injectPostCache = async (postPath: string) => {
|
const _injectPostCache = async (postPath: string) => {
|
||||||
//using post path get index of query key where that post exists
|
// using post path get index of query key where that post exists
|
||||||
const _containerPermlink = wavesIndexCollection.current[postPath];
|
const _containerPermlink = wavesIndexCollection.current[postPath];
|
||||||
const _containerIndex = activePermlinks.indexOf(_containerPermlink)
|
const _containerIndex = activePermlinks.indexOf(_containerPermlink);
|
||||||
const _voteCache = cachedVotes[postPath];
|
const _voteCache = cachedVotes[postPath];
|
||||||
|
|
||||||
if (_containerIndex >= 0 && _voteCache) {
|
if (_containerIndex >= 0 && _voteCache) {
|
||||||
//mean data exist, get query data, update query data by finding post and injecting cache
|
// mean data exist, get query data, update query data by finding post and injecting cache
|
||||||
const _qData: any[] | undefined = wavesQueries[_containerIndex].data;
|
const _qData: any[] | undefined = wavesQueries[_containerIndex].data;
|
||||||
|
|
||||||
if (_qData) {
|
if (_qData) {
|
||||||
const _postIndex = _qData.findIndex((item) => lastCacheUpdate.postPath === `${item.author}/${item.permlink}`);
|
const _postIndex = _qData.findIndex(
|
||||||
|
(item) => lastCacheUpdate.postPath === `${item.author}/${item.permlink}`,
|
||||||
|
);
|
||||||
const _post = _qData[_postIndex];
|
const _post = _qData[_postIndex];
|
||||||
|
|
||||||
if (_post) {
|
if (_post) {
|
||||||
//inject cache and set query data
|
// inject cache and set query data
|
||||||
const _cPost = injectVoteCache(_post, _voteCache);
|
const _cPost = injectVoteCache(_post, _voteCache);
|
||||||
_qData.splice(_postIndex, 1, _cPost);
|
_qData.splice(_postIndex, 1, _cPost);
|
||||||
queryClient.setQueryData([QUERIES.WAVES.GET, host, _containerPermlink, _containerIndex], [..._qData]); //TODO: use container permlink as well
|
queryClient.setQueryData(
|
||||||
|
[QUERIES.WAVES.GET, host, _containerPermlink, _containerIndex],
|
||||||
|
[..._qData],
|
||||||
|
); // TODO: use container permlink as well
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _fetchPermlinks = async (startPermlink = '', refresh = false) => {
|
const _fetchPermlinks = async (startPermlink = '', refresh = false) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const query: any = {
|
const query: any = {
|
||||||
account: host,
|
account: host,
|
||||||
start_author: !!startPermlink ? host : '',
|
start_author: startPermlink ? host : '',
|
||||||
start_permlink: startPermlink,
|
start_permlink: startPermlink,
|
||||||
limit: 5,
|
limit: 5,
|
||||||
observer: '',
|
observer: '',
|
||||||
@ -139,56 +130,53 @@ export const useWavesQuery = (host: string) => {
|
|||||||
|
|
||||||
const result = await getAccountPosts(query);
|
const result = await getAccountPosts(query);
|
||||||
|
|
||||||
const _fetchedPermlinks = result.map(post => post.permlink);
|
const _fetchedPermlinks = result.map((post) => post.permlink);
|
||||||
console.log('permlinks fetched', _fetchedPermlinks);
|
console.log('permlinks fetched', _fetchedPermlinks);
|
||||||
|
|
||||||
const _permlinksBucket = refresh ? _fetchedPermlinks : [...permlinksBucket, ..._fetchedPermlinks];
|
const _permlinksBucket = refresh
|
||||||
|
? _fetchedPermlinks
|
||||||
|
: [...permlinksBucket, ..._fetchedPermlinks];
|
||||||
setPermlinksBucket(_permlinksBucket);
|
setPermlinksBucket(_permlinksBucket);
|
||||||
|
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
queryClient.setQueryData([QUERIES.WAVES.INITIAL_CONTAINERS, host], _permlinksBucket);
|
queryClient.setQueryData([QUERIES.WAVES.INITIAL_CONTAINERS, host], _permlinksBucket);
|
||||||
//precautionary delay of 200ms to let state update before concluding promise,
|
// precautionary delay of 200ms to let state update before concluding promise,
|
||||||
//it is effective for waves refresh routine.
|
// it is effective for waves refresh routine.
|
||||||
await delay(200)
|
await delay(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn("failed to fetch waves permlinks");
|
console.warn('failed to fetch waves permlinks');
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsLoading(false)
|
setIsLoading(false);
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const _fetchWaves = async (pagePermlink: string) => {
|
const _fetchWaves = async (pagePermlink: string) => {
|
||||||
console.log('fetching waves from:', host, pagePermlink);
|
console.log('fetching waves from:', host, pagePermlink);
|
||||||
const response = await getDiscussionCollection(host, pagePermlink);
|
const response = await getDiscussionCollection(host, pagePermlink);
|
||||||
|
|
||||||
//inject cache here...
|
// inject cache here...
|
||||||
const _cachedComments = cacheRef.current.commentsCollection;
|
const _cachedComments = cacheRef.current.commentsCollection;
|
||||||
const _cachedVotes = cacheRef.current.votesCollection;
|
const _cachedVotes = cacheRef.current.votesCollection;
|
||||||
const _lastCacheUpdate = cacheRef.current.lastCacheUpdate
|
const _lastCacheUpdate = cacheRef.current.lastCacheUpdate;
|
||||||
const _cResponse = injectPostCache(response, _cachedComments, _cachedVotes, _lastCacheUpdate);
|
const _cResponse = injectPostCache(response, _cachedComments, _cachedVotes, _lastCacheUpdate);
|
||||||
|
|
||||||
const _threadedComments = await mapDiscussionToThreads(_cResponse, host, pagePermlink, 1);
|
const _threadedComments = await mapDiscussionToThreads(_cResponse, host, pagePermlink, 1);
|
||||||
|
|
||||||
if (!_threadedComments) {
|
if (!_threadedComments) {
|
||||||
throw new Error("Failed to parse waves");
|
throw new Error('Failed to parse waves');
|
||||||
}
|
}
|
||||||
|
|
||||||
_threadedComments.sort((a, b) => new Date(a.created) > new Date(b.created) ? -1 : 1);
|
_threadedComments.sort((a, b) => (new Date(a.created) > new Date(b.created) ? -1 : 1));
|
||||||
_threadedComments.forEach((item) => {
|
_threadedComments.forEach((item) => {
|
||||||
wavesIndexCollection.current[`${item.author}/${item.permlink}`] = pagePermlink
|
wavesIndexCollection.current[`${item.author}/${item.permlink}`] = pagePermlink;
|
||||||
})
|
});
|
||||||
|
|
||||||
console.log('new waves fetched', _threadedComments);
|
console.log('new waves fetched', _threadedComments);
|
||||||
|
|
||||||
return _threadedComments || [];
|
return _threadedComments || [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _fetchNextPage = () => {
|
const _fetchNextPage = () => {
|
||||||
const lastPage = wavesQueries.lastItem;
|
const lastPage = wavesQueries.lastItem;
|
||||||
|
|
||||||
@ -199,17 +187,15 @@ export const useWavesQuery = (host: string) => {
|
|||||||
const _nextPagePermlink = permlinksBucket[activePermlinks.length];
|
const _nextPagePermlink = permlinksBucket[activePermlinks.length];
|
||||||
|
|
||||||
if (_nextPagePermlink && !activePermlinks.includes(_nextPagePermlink)) {
|
if (_nextPagePermlink && !activePermlinks.includes(_nextPagePermlink)) {
|
||||||
console.log("updating next page permlink", _nextPagePermlink)
|
console.log('updating next page permlink', _nextPagePermlink);
|
||||||
activePermlinks.push(_nextPagePermlink);
|
activePermlinks.push(_nextPagePermlink);
|
||||||
setActivePermlinks([...activePermlinks]);
|
setActivePermlinks([...activePermlinks]);
|
||||||
} else {
|
} else {
|
||||||
console.log("fetching new containers", permlinksBucket.lastItem)
|
console.log('fetching new containers', permlinksBucket.lastItem);
|
||||||
_fetchPermlinks(permlinksBucket.lastItem)
|
_fetchPermlinks(permlinksBucket.lastItem);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _refresh = async () => {
|
const _refresh = async () => {
|
||||||
setIsRefreshing(true);
|
setIsRefreshing(true);
|
||||||
setPermlinksBucket([]);
|
setPermlinksBucket([]);
|
||||||
@ -219,38 +205,32 @@ export const useWavesQuery = (host: string) => {
|
|||||||
setIsRefreshing(false);
|
setIsRefreshing(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _data = unionBy(...wavesQueries.map((query) => query.data), 'url');
|
const _data = unionBy(...wavesQueries.map((query) => query.data), 'url');
|
||||||
|
|
||||||
const _filteredData = useMemo(() =>
|
const _filteredData = useMemo(
|
||||||
_data.filter(post => isArray(mutes) ? mutes.indexOf(post?.author) < 0 : true),
|
() => _data.filter((post) => (isArray(mutes) ? mutes.indexOf(post?.author) < 0 : true)),
|
||||||
[mutes, _data])
|
[mutes, _data],
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const _lastestWavesFetch = async () => {
|
const _lastestWavesFetch = async () => {
|
||||||
|
|
||||||
await _fetchPermlinks('', true);
|
await _fetchPermlinks('', true);
|
||||||
const _prevLatestWave = _filteredData[0]
|
const _prevLatestWave = _filteredData[0];
|
||||||
const _firstQuery = wavesQueries[0];
|
const _firstQuery = wavesQueries[0];
|
||||||
|
|
||||||
if(!_firstQuery){
|
if (!_firstQuery) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryResponse = await _firstQuery.refetch();
|
const queryResponse = await _firstQuery.refetch();
|
||||||
|
|
||||||
const _newData:any[] = queryResponse.data || [];
|
const _newData: any[] = queryResponse.data || [];
|
||||||
|
|
||||||
//check if new waves are available
|
// check if new waves are available
|
||||||
const _lastIndex = _newData?.findIndex(item =>
|
const _lastIndex = _newData?.findIndex(
|
||||||
( item.author + item.permlink === _prevLatestWave.author + _prevLatestWave.permlink));
|
(item) => item.author + item.permlink === _prevLatestWave.author + _prevLatestWave.permlink,
|
||||||
|
);
|
||||||
|
|
||||||
let _newWaves:any[] = []
|
let _newWaves: any[] = [];
|
||||||
if (_lastIndex && _lastIndex !== 0) {
|
if (_lastIndex && _lastIndex !== 0) {
|
||||||
if (_lastIndex < 0) {
|
if (_lastIndex < 0) {
|
||||||
_newWaves = _newData?.slice(0, 5) || [];
|
_newWaves = _newData?.slice(0, 5) || [];
|
||||||
@ -259,10 +239,8 @@ export const useWavesQuery = (host: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return _newWaves;
|
||||||
return _newWaves
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: _filteredData,
|
data: _filteredData,
|
||||||
@ -274,26 +252,21 @@ export const useWavesQuery = (host: string) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const usePublishWaveMutation = () => {
|
export const usePublishWaveMutation = () => {
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
// id is options, if no id is provided program marks all notifications as read;
|
// id is options, if no id is provided program marks all notifications as read;
|
||||||
const _mutationFn = async (cachePostData: any) => {
|
const _mutationFn = async (cachePostData: any) => {
|
||||||
//TODO: lates port wave publishing here or introduce post publishing mutation;
|
// TODO: lates port wave publishing here or introduce post publishing mutation;
|
||||||
if (cachePostData) { //TODO: expand to check multiple wave hosts;{
|
if (cachePostData) {
|
||||||
|
// TODO: expand to check multiple wave hosts;{
|
||||||
const _host = cachePostData.parent_author;
|
const _host = cachePostData.parent_author;
|
||||||
|
|
||||||
console.log('returning waves host', _host);
|
console.log('returning waves host', _host);
|
||||||
return _host;
|
return _host;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("invalid mutations data")
|
throw new Error('invalid mutations data');
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _options: UseMutationOptions<string, unknown, any, void> = {
|
const _options: UseMutationOptions<string, unknown, any, void> = {
|
||||||
@ -314,11 +287,10 @@ export const usePublishWaveMutation = () => {
|
|||||||
queryData.splice(0, 0, cacheCommentData);
|
queryData.splice(0, 0, cacheCommentData);
|
||||||
queryClient.setQueryData(_queryKey, queryData);
|
queryClient.setQueryData(_queryKey, queryData);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onSuccess: async (host) => {
|
onSuccess: async (host) => {
|
||||||
//TODO: get first container permlink here from initial containers
|
// TODO: get first container permlink here from initial containers
|
||||||
const queriesData = queryClient.getQueriesData([QUERIES.WAVES.INITIAL_CONTAINERS, host]);
|
const queriesData = queryClient.getQueriesData([QUERIES.WAVES.INITIAL_CONTAINERS, host]);
|
||||||
const _queryKey = queriesData[0][0];
|
const _queryKey = queriesData[0][0];
|
||||||
queryClient.invalidateQueries(_queryKey);
|
queryClient.invalidateQueries(_queryKey);
|
||||||
@ -328,8 +300,6 @@ export const usePublishWaveMutation = () => {
|
|||||||
return useMutation(_mutationFn, _options);
|
return useMutation(_mutationFn, _options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const fetchLatestWavesContainer = async (host) => {
|
export const fetchLatestWavesContainer = async (host) => {
|
||||||
const query: any = {
|
const query: any = {
|
||||||
account: host,
|
account: host,
|
||||||
@ -346,8 +316,8 @@ export const fetchLatestWavesContainer = async (host) => {
|
|||||||
console.log('lates waves post', host, _latestPost);
|
console.log('lates waves post', host, _latestPost);
|
||||||
|
|
||||||
if (!_latestPost) {
|
if (!_latestPost) {
|
||||||
throw new Error("Lates waves container could be not fetched");
|
throw new Error('Lates waves container could be not fetched');
|
||||||
}
|
}
|
||||||
|
|
||||||
return _latestPost;
|
return _latestPost;
|
||||||
}
|
};
|
||||||
|
@ -30,8 +30,8 @@ const QUERIES = {
|
|||||||
},
|
},
|
||||||
WAVES: {
|
WAVES: {
|
||||||
GET: 'QUERY_GET_WAVES',
|
GET: 'QUERY_GET_WAVES',
|
||||||
INITIAL_CONTAINERS: 'QUERY_DATA_INITIAL_CONTAINERS'
|
INITIAL_CONTAINERS: 'QUERY_DATA_INITIAL_CONTAINERS',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default QUERIES;
|
export default QUERIES;
|
||||||
|
@ -99,10 +99,10 @@ export const setLockedOrientation = (payload: string) => ({
|
|||||||
type: SET_LOCKED_ORIENTATION,
|
type: SET_LOCKED_ORIENTATION,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const showReplyModal = ({mode, parentPost}:PostEditorModalData) => ({
|
export const showReplyModal = ({ mode, parentPost }: PostEditorModalData) => ({
|
||||||
payload: {
|
payload: {
|
||||||
mode: mode || 'comment',
|
mode: mode || 'comment',
|
||||||
parentPost
|
parentPost,
|
||||||
} as PostEditorModalData,
|
} as PostEditorModalData,
|
||||||
type: SHOW_REPLY_MODAL,
|
type: SHOW_REPLY_MODAL,
|
||||||
});
|
});
|
||||||
|
@ -63,7 +63,7 @@ export const fetchCoinQuotes = () => (dispatch, getState) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const fetchAndSetCoinsData =
|
export const fetchAndSetCoinsData =
|
||||||
(refresh: boolean = false) =>
|
(refresh = false) =>
|
||||||
async (dispatch: AppDispatch, getState: RootState) => {
|
async (dispatch: AppDispatch, getState: RootState) => {
|
||||||
const coins = getState().wallet.selectedCoins;
|
const coins = getState().wallet.selectedCoins;
|
||||||
const { quotes } = getState().wallet;
|
const { quotes } = getState().wallet;
|
||||||
|
@ -20,10 +20,9 @@ import {
|
|||||||
} from '../constants/constants';
|
} from '../constants/constants';
|
||||||
import { orientations } from '../constants/orientationsConstants';
|
import { orientations } from '../constants/orientationsConstants';
|
||||||
|
|
||||||
|
|
||||||
export interface PostEditorModalData {
|
export interface PostEditorModalData {
|
||||||
mode:'wave'|'comment'|'post',
|
mode: 'wave' | 'comment' | 'post';
|
||||||
parentPost?:any
|
parentPost?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UiState {
|
interface UiState {
|
||||||
@ -153,8 +152,8 @@ export default function (state = initialState, action): UiState {
|
|||||||
};
|
};
|
||||||
case SHOW_REPLY_MODAL:
|
case SHOW_REPLY_MODAL:
|
||||||
const _payload = action.payload as PostEditorModalData;
|
const _payload = action.payload as PostEditorModalData;
|
||||||
if(_payload.mode === 'comment' && !_payload.parentPost){
|
if (_payload.mode === 'comment' && !_payload.parentPost) {
|
||||||
throw new Error("parent post missing for showing post editor modal with comment mode")
|
throw new Error('parent post missing for showing post editor modal with comment mode');
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -2,12 +2,12 @@ import React, { ComponentType, JSXElementConstructor, ReactElement, useState } f
|
|||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { SectionList, Text, RefreshControl, ActivityIndicator } from 'react-native';
|
import { SectionList, Text, RefreshControl, ActivityIndicator } from 'react-native';
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import { Transaction } from '../../../components';
|
import { Transaction } from '../../../components';
|
||||||
import { useAppSelector } from '../../../hooks';
|
import { useAppSelector } from '../../../hooks';
|
||||||
import { CoinActivity } from '../../../redux/reducers/walletReducer';
|
import { CoinActivity } from '../../../redux/reducers/walletReducer';
|
||||||
import styles from './children.styles';
|
import styles from './children.styles';
|
||||||
import { limitOrderCancel } from '../../../providers/hive-trade/hiveTrade';
|
import { limitOrderCancel } from '../../../providers/hive-trade/hiveTrade';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
|
||||||
import QUERIES from '../../../providers/queries/queryKeys';
|
import QUERIES from '../../../providers/queries/queryKeys';
|
||||||
import TransferTypes from '../../../constants/transferTypes';
|
import TransferTypes from '../../../constants/transferTypes';
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ export default EStyleSheet.create({
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
backgroundColor: '$primaryLightBackground',
|
backgroundColor: '$primaryLightBackground',
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
iconContainer:{
|
iconContainer: {
|
||||||
marginRight:8
|
marginRight: 8,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
basicsContainer: {
|
basicsContainer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@ -18,8 +18,8 @@ export default EStyleSheet.create({
|
|||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
coinTitleContainer: {
|
coinTitleContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems:'center',
|
alignItems: 'center',
|
||||||
marginTop:8
|
marginTop: 8,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
textCoinTitle: {
|
textCoinTitle: {
|
||||||
color: '$primaryBlack',
|
color: '$primaryBlack',
|
||||||
@ -98,10 +98,8 @@ export default EStyleSheet.create({
|
|||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
//COIN ACTIONS STYLES
|
// COIN ACTIONS STYLES
|
||||||
actionBtnContainer: {
|
actionBtnContainer: {} as ViewStyle,
|
||||||
|
|
||||||
} as ViewStyle,
|
|
||||||
actionsContainer: {
|
actionsContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
|
@ -66,12 +66,9 @@ export const CoinBasics = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _renderExtraData = (args: DataPair, index: number) => {
|
const _renderExtraData = (args: DataPair, index: number) => {
|
||||||
|
|
||||||
const label = intl.formatMessage(
|
const label = intl.formatMessage(
|
||||||
{ id: `wallet.${args.dataKey || args.labelId}` },
|
{ id: `wallet.${args.dataKey || args.labelId}` },
|
||||||
args.subValue
|
args.subValue ? { subValue: args.subValue } : undefined,
|
||||||
? { subValue: args.subValue }
|
|
||||||
: undefined
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const _onPress = () => {
|
const _onPress = () => {
|
||||||
|
@ -31,11 +31,7 @@ export const CoinChart = ({ coinId, isEngine }: CoinChartProps) => {
|
|||||||
);
|
);
|
||||||
setChartData(marketData.map((item) => item.close));
|
setChartData(marketData.map((item) => item.close));
|
||||||
} else {
|
} else {
|
||||||
const marketData = await fetchMarketChart(
|
const marketData = await fetchMarketChart(coinId, currency.currency, days);
|
||||||
coinId,
|
|
||||||
currency.currency,
|
|
||||||
days
|
|
||||||
);
|
|
||||||
setChartData(marketData.prices.map((item) => item.yValue));
|
setChartData(marketData.prices.map((item) => item.yValue));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -27,7 +27,7 @@ export const CoinSummary = ({
|
|||||||
const valuePairs = [
|
const valuePairs = [
|
||||||
{
|
{
|
||||||
dataKey: 'amount_desc',
|
dataKey: 'amount_desc',
|
||||||
value: balance.toFixed(precision ? precision : 3),
|
value: balance.toFixed(precision || 3),
|
||||||
},
|
},
|
||||||
] as DataPair[];
|
] as DataPair[];
|
||||||
|
|
||||||
|
@ -52,9 +52,9 @@ export const DelegationsModal = forwardRef(({}, ref) => {
|
|||||||
}
|
}
|
||||||
}, [mode, showModal]);
|
}, [mode, showModal]);
|
||||||
|
|
||||||
const _getVestingDelegations = async (startUsername: string = '') => {
|
const _getVestingDelegations = async (startUsername = '') => {
|
||||||
let resData: any = [];
|
let resData: any = [];
|
||||||
let limit = 1000;
|
const limit = 1000;
|
||||||
|
|
||||||
const response = await getVestingDelegations(currentAccount.username, startUsername, limit);
|
const response = await getVestingDelegations(currentAccount.username, startUsername, limit);
|
||||||
resData = response.map(
|
resData = response.map(
|
||||||
@ -132,7 +132,7 @@ export const DelegationsModal = forwardRef(({}, ref) => {
|
|||||||
const title = intl.formatMessage({ id: `wallet.${mode}` });
|
const title = intl.formatMessage({ id: `wallet.${mode}` });
|
||||||
|
|
||||||
const _renderItem = ({ item, index }: { item: DelegationItem; index: number }) => {
|
const _renderItem = ({ item, index }: { item: DelegationItem; index: number }) => {
|
||||||
const value = vestsToHp(item.vestingShares, globalProps.hivePerMVests).toFixed(3) + ' HP';
|
const value = `${vestsToHp(item.vestingShares, globalProps.hivePerMVests).toFixed(3)} HP`;
|
||||||
const timeString = new Date(item.timestamp).toDateString();
|
const timeString = new Date(item.timestamp).toDateString();
|
||||||
const subRightText =
|
const subRightText =
|
||||||
mode === MODES.DELEGATEED && intl.formatMessage({ id: 'wallet.tap_update' });
|
mode === MODES.DELEGATEED && intl.formatMessage({ id: 'wallet.tap_update' });
|
||||||
|
@ -15,33 +15,34 @@ interface RangeSelectorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const RangeSelector = ({ range, minRange, onRangeChange }: RangeSelectorProps) => {
|
export const RangeSelector = ({ range, minRange, onRangeChange }: RangeSelectorProps) => {
|
||||||
|
|
||||||
const _onSelection = (range: number) => {
|
const _onSelection = (range: number) => {
|
||||||
console.log('selection', range);
|
console.log('selection', range);
|
||||||
onRangeChange(range);
|
onRangeChange(range);
|
||||||
};
|
};
|
||||||
|
|
||||||
const _renderRangeButtons = FILTERS.filter((item) => item.value >= minRange).map((item: RangeOption) => (
|
const _renderRangeButtons = FILTERS.filter((item) => item.value >= minRange).map(
|
||||||
<TouchableOpacity key={`range option-${item.value}`} onPress={() => _onSelection(item.value)}>
|
(item: RangeOption) => (
|
||||||
<View
|
<TouchableOpacity key={`range option-${item.value}`} onPress={() => _onSelection(item.value)}>
|
||||||
style={{
|
<View
|
||||||
...styles.rangeOptionWrapper,
|
|
||||||
backgroundColor: EStyleSheet.value(
|
|
||||||
item.value === range ? '$darkGrayBackground' : '$primaryLightBackground',
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
style={{
|
||||||
...styles.textRange,
|
...styles.rangeOptionWrapper,
|
||||||
color: EStyleSheet.value(item.value === range ? '$white' : '$primaryDarkText'),
|
backgroundColor: EStyleSheet.value(
|
||||||
|
item.value === range ? '$darkGrayBackground' : '$primaryLightBackground',
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.label}
|
<Text
|
||||||
</Text>
|
style={{
|
||||||
</View>
|
...styles.textRange,
|
||||||
</TouchableOpacity>
|
color: EStyleSheet.value(item.value === range ? '$white' : '$primaryDarkText'),
|
||||||
));
|
}}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return <View style={[styles.card, styles.rangeContainer]}>{_renderRangeButtons}</View>;
|
return <View style={[styles.card, styles.rangeContainer]}>{_renderRangeButtons}</View>;
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@ import EStyleSheet from 'react-native-extended-stylesheet';
|
|||||||
import getWindowDimensions from '../../../utils/getWindowDimensions';
|
import getWindowDimensions from '../../../utils/getWindowDimensions';
|
||||||
|
|
||||||
export default EStyleSheet.create({
|
export default EStyleSheet.create({
|
||||||
modalStyle:{
|
modalStyle: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '$primaryBackgroundColor',
|
backgroundColor: '$primaryBackgroundColor',
|
||||||
margin: 0,
|
margin: 0,
|
||||||
@ -23,7 +23,7 @@ export default EStyleSheet.create({
|
|||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
scrollContainer: {
|
scrollContainer: {
|
||||||
flex:1,
|
flex: 1,
|
||||||
marginTop: 16,
|
marginTop: 16,
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
@ -35,33 +35,30 @@ export default EStyleSheet.create({
|
|||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
modalContainer: {
|
modalContainer: {
|
||||||
flex:1,
|
flex: 1,
|
||||||
marginBottom: 44,
|
marginBottom: 44,
|
||||||
paddingHorizontal: 24,
|
paddingHorizontal: 24,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
sectionTextStyle : {
|
sectionTextStyle: {
|
||||||
color:'$primaryBlack',
|
color: '$primaryBlack',
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
marginHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
marginVertical:4,
|
marginVertical: 4,
|
||||||
|
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
sectionSubTextStyle : {
|
sectionSubTextStyle: {
|
||||||
color:'$iconColor',
|
color: '$iconColor',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
marginHorizontal: 16,
|
marginHorizontal: 16,
|
||||||
marginVertical:16,
|
marginVertical: 16,
|
||||||
alignSelf:'center'
|
alignSelf: 'center',
|
||||||
|
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
dragBtnContainer:{
|
dragBtnContainer: {
|
||||||
padding:8
|
padding: 8,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
title: {
|
title: {
|
||||||
@ -83,12 +80,12 @@ export default EStyleSheet.create({
|
|||||||
|
|
||||||
btnText: {
|
btnText: {
|
||||||
color: '$pureWhite',
|
color: '$pureWhite',
|
||||||
textTransform: 'uppercase'
|
textTransform: 'uppercase',
|
||||||
} as TextStyle,
|
} as TextStyle,
|
||||||
|
|
||||||
assetIconContainer:{
|
assetIconContainer: {
|
||||||
width:32,
|
width: 32,
|
||||||
marginLeft:16
|
marginLeft: 16,
|
||||||
},
|
},
|
||||||
|
|
||||||
button: {
|
button: {
|
||||||
|
@ -2,6 +2,7 @@ import React, { Fragment, useState, useEffect, useRef } from 'react';
|
|||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
||||||
|
import get from 'lodash/get';
|
||||||
import { BasicHeader, TextBoxWithCopy } from '../../components';
|
import { BasicHeader, TextBoxWithCopy } from '../../components';
|
||||||
import { useAppSelector } from '../../hooks';
|
import { useAppSelector } from '../../hooks';
|
||||||
import { getDigitPinCode } from '../../providers/hive/dhive';
|
import { getDigitPinCode } from '../../providers/hive/dhive';
|
||||||
@ -13,7 +14,6 @@ import styles from './backupKeysScreenStyles';
|
|||||||
|
|
||||||
// utils
|
// utils
|
||||||
import { decryptKey } from '../../utils/crypto';
|
import { decryptKey } from '../../utils/crypto';
|
||||||
import get from 'lodash/get';
|
|
||||||
|
|
||||||
const BackupKeysScreen = () => {
|
const BackupKeysScreen = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { View, Text, TouchableOpacity, Alert } from 'react-native';
|
import { View, Text, TouchableOpacity, Alert } from 'react-native';
|
||||||
import React, { forwardRef, useImperativeHandle, useState } from 'react';
|
import React, { forwardRef, useImperativeHandle, useState } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||||
import { Modal, TextInput } from '../../components';
|
import { Modal, TextInput } from '../../components';
|
||||||
import { useAppSelector } from '../../hooks';
|
import { useAppSelector } from '../../hooks';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
|
|
||||||
// styles
|
// styles
|
||||||
import styles from './backupKeysScreenStyles';
|
import styles from './backupKeysScreenStyles';
|
||||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
|
||||||
|
|
||||||
// redux / providers
|
// redux / providers
|
||||||
import { getUpdatedUserKeys } from '../../providers/hive/auth';
|
import { getUpdatedUserKeys } from '../../providers/hive/auth';
|
||||||
|
@ -5,7 +5,7 @@ export default EStyleSheet.create({
|
|||||||
userRibbonContainer: {
|
userRibbonContainer: {
|
||||||
borderBottomWidth: EStyleSheet.hairlineWidth,
|
borderBottomWidth: EStyleSheet.hairlineWidth,
|
||||||
borderColor: '$darkGrayBackground',
|
borderColor: '$darkGrayBackground',
|
||||||
marginBottom: 0, //without 0 margin, view will start overlapping UserRibbon
|
marginBottom: 0, // without 0 margin, view will start overlapping UserRibbon
|
||||||
paddingBottom: 32,
|
paddingBottom: 32,
|
||||||
} as ViewStyle,
|
} as ViewStyle,
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ const DraftsContainer = ({ currentAccount, navigation, route }) => {
|
|||||||
const _isCloning = isCloningDraft;
|
const _isCloning = isCloningDraft;
|
||||||
|
|
||||||
const _getUpdatedArray = (arr: string[], id: string) => {
|
const _getUpdatedArray = (arr: string[], id: string) => {
|
||||||
let _tempArr = arr.slice();
|
const _tempArr = arr.slice();
|
||||||
const index = _tempArr.findIndex((item) => item === id);
|
const index = _tempArr.findIndex((item) => item === id);
|
||||||
|
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
|
@ -2,12 +2,12 @@ import React, { useState, useRef, useEffect, useMemo } from 'react';
|
|||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
import FastImage from 'react-native-fast-image';
|
||||||
import { BasicHeader, IconButton, PostDisplay, PostOptionsModal } from '../../../components';
|
import { BasicHeader, IconButton, PostDisplay, PostOptionsModal } from '../../../components';
|
||||||
import styles from '../styles/postScreen.styles';
|
import styles from '../styles/postScreen.styles';
|
||||||
|
|
||||||
// Component
|
// Component
|
||||||
import { postQueries } from '../../../providers/queries';
|
import { postQueries } from '../../../providers/queries';
|
||||||
import FastImage from 'react-native-fast-image';
|
|
||||||
|
|
||||||
const PostScreen = ({ route }) => {
|
const PostScreen = ({ route }) => {
|
||||||
const params = route.params || {};
|
const params = route.params || {};
|
||||||
@ -22,21 +22,23 @@ const PostScreen = ({ route }) => {
|
|||||||
const getPostQuery = postQueries.useGetPostQuery(author, permlink, params.content);
|
const getPostQuery = postQueries.useGetPostQuery(author, permlink, params.content);
|
||||||
const getParentPostQuery = postQueries.useGetPostQuery();
|
const getParentPostQuery = postQueries.useGetPostQuery();
|
||||||
|
|
||||||
const isWavePost = useMemo(() => getPostQuery.data?.parent_author === 'ecency.waves', [getPostQuery.data]) //TODO: implement a better generic way to avoid parent fetching for waves
|
const isWavePost = useMemo(
|
||||||
|
() => getPostQuery.data?.parent_author === 'ecency.waves',
|
||||||
|
[getPostQuery.data],
|
||||||
|
); // TODO: implement a better generic way to avoid parent fetching for waves
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
//clears FastImage RAM, not disk usage;
|
// clears FastImage RAM, not disk usage;
|
||||||
FastImage.clearMemoryCache();
|
FastImage.clearMemoryCache();
|
||||||
}
|
};
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const post = getPostQuery.data;
|
const post = getPostQuery.data;
|
||||||
if (post) {
|
if (post) {
|
||||||
const _fetchParent = post && post.depth > 0
|
const _fetchParent =
|
||||||
&& post.parent_author && post.parent_permlink
|
post && post.depth > 0 && post.parent_author && post.parent_permlink && !isWavePost;
|
||||||
&& !isWavePost;
|
|
||||||
|
|
||||||
if (_fetchParent) {
|
if (_fetchParent) {
|
||||||
getParentPostQuery.setAuthor(post.parent_author);
|
getParentPostQuery.setAuthor(post.parent_author);
|
||||||
|
@ -313,29 +313,33 @@ class SettingsContainer extends Component {
|
|||||||
navigateTo: ROUTES.SCREENS.BACKUP_KEYS,
|
navigateTo: ROUTES.SCREENS.BACKUP_KEYS,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
dispatch(showActionModal({
|
dispatch(
|
||||||
title:intl.formatMessage({id:'alert.warning'}),
|
showActionModal({
|
||||||
body:intl.formatMessage({id:'settings.keys_warning'}),
|
title: intl.formatMessage({ id: 'alert.warning' }),
|
||||||
buttons:[{
|
body: intl.formatMessage({ id: 'settings.keys_warning' }),
|
||||||
text:intl.formatMessage({id:'alert.cancel'}),
|
buttons: [
|
||||||
onPress:()=>{},
|
{
|
||||||
type:'destructive'
|
text: intl.formatMessage({ id: 'alert.cancel' }),
|
||||||
},{
|
onPress: () => {},
|
||||||
text:intl.formatMessage({id:'settings.set_pin'}),
|
type: 'destructive',
|
||||||
onPress:()=>{
|
},
|
||||||
navigation.navigate(ROUTES.SCREENS.PINCODE, {
|
{
|
||||||
callback: () => {
|
text: intl.formatMessage({ id: 'settings.set_pin' }),
|
||||||
this._enableDefaultUnlockPin(true)
|
onPress: () => {
|
||||||
|
navigation.navigate(ROUTES.SCREENS.PINCODE, {
|
||||||
|
callback: () => {
|
||||||
|
this._enableDefaultUnlockPin(true);
|
||||||
|
},
|
||||||
|
navigateTo: ROUTES.SCREENS.BACKUP_KEYS,
|
||||||
|
isReset: true,
|
||||||
|
isOldPinVerified: true,
|
||||||
|
oldPinCode: Config.DEFAULT_PIN,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
navigateTo: ROUTES.SCREENS.BACKUP_KEYS,
|
},
|
||||||
isReset: true,
|
],
|
||||||
isOldPinVerified: true,
|
}),
|
||||||
oldPinCode: Config.DEFAULT_PIN,
|
);
|
||||||
});
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }:
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
|
||||||
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
||||||
const currency = useAppSelector((state) => state.application.currency);
|
const currency = useAppSelector((state) => state.application.currency);
|
||||||
|
|
||||||
@ -56,12 +55,10 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }:
|
|||||||
const _fromAssetId = fromAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE;
|
const _fromAssetId = fromAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE;
|
||||||
const _toAssetId = _toAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE;
|
const _toAssetId = _toAssetSymbol === MarketAsset.HBD ? ASSET_IDS.HBD : ASSET_IDS.HIVE;
|
||||||
|
|
||||||
|
|
||||||
// queres
|
// queres
|
||||||
const assetsQuery = walletQueries.useAssetsQuery();
|
const assetsQuery = walletQueries.useAssetsQuery();
|
||||||
const pendingRequestsQuery = walletQueries.usePendingRequestsQuery(_fromAssetId);
|
const pendingRequestsQuery = walletQueries.usePendingRequestsQuery(_fromAssetId);
|
||||||
|
|
||||||
|
|
||||||
// this method makes sure amount is only updated when new order book is fetched after asset change
|
// this method makes sure amount is only updated when new order book is fetched after asset change
|
||||||
// this avoid wrong from and to swap value on changing source asset
|
// this avoid wrong from and to swap value on changing source asset
|
||||||
const _onAssetChangeComplete = () => {
|
const _onAssetChangeComplete = () => {
|
||||||
@ -93,8 +90,7 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }:
|
|||||||
const _fromAssetData = assetsData[_fromAssetId];
|
const _fromAssetData = assetsData[_fromAssetId];
|
||||||
const _balance = _fromAssetData.balance;
|
const _balance = _fromAssetData.balance;
|
||||||
const _fromFiatPrice = _fromAssetData.currentPrice;
|
const _fromFiatPrice = _fromAssetData.currentPrice;
|
||||||
const _toFiatPrice =
|
const _toFiatPrice = assetsData[_toAssetId].currentPrice;
|
||||||
assetsData[_toAssetId].currentPrice;
|
|
||||||
const _marketFiatPrice = marketPrice * _toFiatPrice;
|
const _marketFiatPrice = marketPrice * _toFiatPrice;
|
||||||
|
|
||||||
const _toAmountStr = toAmount.toFixed(3);
|
const _toAmountStr = toAmount.toFixed(3);
|
||||||
@ -130,11 +126,12 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }:
|
|||||||
setFromAmount('0');
|
setFromAmount('0');
|
||||||
};
|
};
|
||||||
|
|
||||||
const _onSwapSuccess = async (hasPending:boolean) => {
|
const _onSwapSuccess = async (hasPending: boolean) => {
|
||||||
|
const _badgeColor = hasPending
|
||||||
const _badgeColor = hasPending ? EStyleSheet.value('$primaryBlue') : EStyleSheet.value('$primaryGreen');
|
? EStyleSheet.value('$primaryBlue')
|
||||||
const _badgeIcon = hasPending ? "error-outline" : "check";
|
: EStyleSheet.value('$primaryGreen');
|
||||||
const _titleId = hasPending ? 'trade.swap_pending' : 'trade.swap_successful'
|
const _badgeIcon = hasPending ? 'error-outline' : 'check';
|
||||||
|
const _titleId = hasPending ? 'trade.swap_pending' : 'trade.swap_successful';
|
||||||
const _body = hasPending ? intl.formatMessage({ id: 'trade.swap_pending_body' }) : undefined;
|
const _body = hasPending ? intl.formatMessage({ id: 'trade.swap_pending_body' }) : undefined;
|
||||||
|
|
||||||
const headerContent = (
|
const headerContent = (
|
||||||
@ -190,7 +187,7 @@ export const SwapTokenContent = ({ initialSymbol, handleHsTransfer, onSuccess }:
|
|||||||
const _existingPedingCount = pendingRequestsQuery.data?.length || 0;
|
const _existingPedingCount = pendingRequestsQuery.data?.length || 0;
|
||||||
const pendingRequests = await pendingRequestsQuery.refetch();
|
const pendingRequests = await pendingRequestsQuery.refetch();
|
||||||
const _hasPending = pendingRequests.data?.length !== _existingPedingCount;
|
const _hasPending = pendingRequests.data?.length !== _existingPedingCount;
|
||||||
|
|
||||||
onSuccess();
|
onSuccess();
|
||||||
setSwapping(false);
|
setSwapping(false);
|
||||||
_onSwapSuccess(_hasPending);
|
_onSwapSuccess(_hasPending);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user