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