diff --git a/.eslintrc.json b/.eslintrc.json index ef2f7d85f..b631b9a38 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -97,6 +97,10 @@ "ts": "never", "tsx": "never" } - ] + ], + "class-methods-use-this": "off", + "react/jsx-wrap-multilines": "off", + "jsx-one-expression-per-line": "off", + "react/jsx-one-expression-per-line": "off" } } \ No newline at end of file diff --git a/package.json b/package.json index 1b29b2072..0257e4b73 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,6 @@ "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", "@bugsnag/source-maps": "^2.3.1", - "@react-native-community/eslint-config": "^2.0.0", "@react-native/babel-preset": "0.73.19", "@react-native/eslint-config": "0.73.2", "@react-native/metro-config": "0.73.3", diff --git a/src/components/autoHeightImage/autoHeightImage.tsx b/src/components/autoHeightImage/autoHeightImage.tsx index 3f7431242..ea7abf87c 100644 --- a/src/components/autoHeightImage/autoHeightImage.tsx +++ b/src/components/autoHeightImage/autoHeightImage.tsx @@ -25,7 +25,6 @@ export const AutoHeightImage = ({ const _initialHeight = useMemo(() => { let _height = contentWidth / (16 / 9); if (metadata && metadata.image && metadata.image_ratios) { - metadata.image_ratios.forEach((_ratio, index) => { const url = metadata.image[index]; @@ -75,12 +74,7 @@ export const AutoHeightImage = ({ return ( - + ); }; diff --git a/src/components/basicUIElements/view/placeHolder/commentPlaceHolderView.js b/src/components/basicUIElements/view/placeHolder/commentPlaceHolderView.js index 90557fb3d..8d66b12d8 100644 --- a/src/components/basicUIElements/view/placeHolder/commentPlaceHolderView.js +++ b/src/components/basicUIElements/view/placeHolder/commentPlaceHolderView.js @@ -6,7 +6,6 @@ import { useSelector } from 'react-redux'; import styles from './listItemPlaceHolderStyles'; const CommentPlaceHolderView = () => { - const _width = 300; const animationStyle = { diff --git a/src/components/basicUIElements/view/placeHolder/postCardPlaceHolderView.js b/src/components/basicUIElements/view/placeHolder/postCardPlaceHolderView.js index 1f5384add..796e12818 100644 --- a/src/components/basicUIElements/view/placeHolder/postCardPlaceHolderView.js +++ b/src/components/basicUIElements/view/placeHolder/postCardPlaceHolderView.js @@ -10,7 +10,7 @@ const PostCardPlaceHolder = () => { const animationStyle = { width: _width, - height: _width * 2 + height: _width * 2, }; const isDarkTheme = useSelector((state) => state.application.isDarkTheme); diff --git a/src/components/basicUIElements/view/placeHolder/postPlaceHolderView.js b/src/components/basicUIElements/view/placeHolder/postPlaceHolderView.js index e1dbe79a8..bafaef1aa 100644 --- a/src/components/basicUIElements/view/placeHolder/postPlaceHolderView.js +++ b/src/components/basicUIElements/view/placeHolder/postPlaceHolderView.js @@ -9,9 +9,8 @@ const PostPlaceHolder = () => { const isDarkTheme = useSelector((state) => state.application.isDarkTheme); const color = isDarkTheme ? '#2e3d51' : '#f5f5f5'; - const width = getWindowDimensions().nativeWidth - 36; - const height = width * 1.65 ; + const height = width * 1.65; return ( diff --git a/src/components/checkbox/view/checkboxView.tsx b/src/components/checkbox/view/checkboxView.tsx index 544422581..5ea7af4fd 100644 --- a/src/components/checkbox/view/checkboxView.tsx +++ b/src/components/checkbox/view/checkboxView.tsx @@ -9,7 +9,7 @@ interface CheckBoxProps { locked?: boolean; isRound?: boolean; style?: ViewStyle; - clicked: (val: string, isChecked: boolean) => void, + clicked: (val: string, isChecked: boolean) => void; } const CheckBoxView = ({ clicked, value, isChecked, style, locked, isRound }: CheckBoxProps) => { @@ -27,12 +27,12 @@ const CheckBoxView = ({ clicked, value, isChecked, style, locked, isRound }: Che } }; - const containerStyle = [styles.bigSquare, style, isRound && { borderRadius: 10 }] + const containerStyle = [styles.bigSquare, style, isRound && { borderRadius: 10 }]; const innerStyle = [ styles.smallSquare, isCheck && styles.checked, - isRound && { borderRadius: 5 } - ] + isRound && { borderRadius: 5 }, + ]; return ( diff --git a/src/components/draftListItem/view/draftListItemView.tsx b/src/components/draftListItem/view/draftListItemView.tsx index 0bac95062..84a11949c 100644 --- a/src/components/draftListItem/view/draftListItemView.tsx +++ b/src/components/draftListItem/view/draftListItemView.tsx @@ -185,11 +185,7 @@ const DraftListItemView = ({ {image !== null && ( - + )} {title !== '' && {title}} diff --git a/src/components/editAvatar/editAvatar.tsx b/src/components/editAvatar/editAvatar.tsx index 934c4b5bd..02413cb40 100644 --- a/src/components/editAvatar/editAvatar.tsx +++ b/src/components/editAvatar/editAvatar.tsx @@ -19,7 +19,7 @@ const EditAvatar = ({ username, avatarUrl, showImageUploadActions, isUploading } /> { + const intl = useIntl(); + // intl.formatMessage({ id: 'post.copy_link' }), + // intl.formatMessage({ id: 'post.gallery_mode' }), + // intl.formatMessage({ id: 'post.save_to_local' }), -export const ImageViewer = forwardRef(({ }, ref) => { - const intl = useIntl(); - const dispatch = useDispatch(); - // intl.formatMessage({ id: 'post.copy_link' }), - // intl.formatMessage({ id: 'post.gallery_mode' }), - // intl.formatMessage({ id: 'post.save_to_local' }), + const [visible, setVisible] = useState(false); + const [imageUrls, setImageUrls] = useState([]); + const [selectedIndex, setSelectedIndex] = useState(0); - const [visible, setVisible] = useState(false); - const [imageUrls, setImageUrls] = useState([]); - const [selectedIndex, setSelectedIndex] = useState(0); + useImperativeHandle(ref, () => ({ + show(selectedUrl: string, _imageUrls: string[]) { + setImageUrls(_imageUrls); + setSelectedIndex(_imageUrls.indexOf(selectedUrl)); + setVisible(true); + if (Platform.OS === 'ios') { + ExpoImage.prefetch(_imageUrls, 'memory'); + } + }, + })); - useImperativeHandle(ref, () => ({ - show(selectedUrl: string, _imageUrls: string[]) { - setImageUrls(_imageUrls) - setSelectedIndex(_imageUrls.indexOf(selectedUrl)) - setVisible(true); - - if (Platform.OS === 'ios') { - ExpoImage.prefetch(_imageUrls, "memory"); - } - - }, - })); - - const checkAndroidPermission = async () => { - try { - const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE; - await PermissionsAndroid.request(permission); - Promise.resolve(); - } catch (error) { - Promise.reject(error); - } - }; - - - const _downloadImage = async (uri: string) => { - 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); - }); - }; - - - const _onSavePress = async (index: number) => { - - try { - if (Platform.OS === 'android') { - await checkAndroidPermission(); - } - - const url = imageUrls[index]; - - const imagePath = Platform.select({ - ios: await ExpoImage.getCachePathAsync(url), - android: await _downloadImage(url) - }) - - if (!imagePath) { - return; - } - - const uri = `file://${imagePath}` - await CameraRoll.saveAsset(uri, { album: 'Ecency' }) - - Alert.alert(intl.formatMessage({ id: "post.image_saved" })); - - - } catch (err) { - console.warn("fail to save image", err.message) - } - }; - - - - const _onCopyPress = (index: number) => { - const url = imageUrls[index] - Share.share(Platform.OS === 'ios' ? - { url } : { message: url }) + const checkAndroidPermission = async () => { + try { + const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE; + await PermissionsAndroid.request(permission); + Promise.resolve(); + } catch (error) { + Promise.reject(error); } + }; + const _downloadImage = async (uri: string) => { + return RNFetchBlob.config({ + fileCache: true, + appendExt: 'jpg', + }) + .fetch('GET', uri) + .then((res) => { + const { status } = res.info(); - const _renderIconButton = (iconName: string, onPress: () => void) => ( - - ) + if (status == 200) { + return res.path(); + } else { + Promise.reject(); + } + }) + .catch((errorMessage) => { + Promise.reject(errorMessage); + }); + }; + const _onSavePress = async (index: number) => { + try { + if (Platform.OS === 'android') { + await checkAndroidPermission(); + } - const _renderImageViewerHeader = (imageIndex: number) => { - return ( - - - - {_renderIconButton('close', _onCloseImageViewer)} - { - `Preview (${imageIndex + 1}/${imageUrls.length})`} - + const url = imageUrls[index]; - - {_renderIconButton('content-copy', () => _onCopyPress(imageIndex))} - {_renderIconButton('download', () => _onSavePress(imageIndex))} - + const imagePath = Platform.select({ + ios: await ExpoImage.getCachePathAsync(url), + android: await _downloadImage(url), + }); - - - ); - }; + if (!imagePath) { + return; + } + const uri = `file://${imagePath}`; + await CameraRoll.saveAsset(uri, { album: 'Ecency' }); - const _onCloseImageViewer = () => { - setVisible(false); - setImageUrls([]) + Alert.alert(intl.formatMessage({ id: 'post.image_saved' })); + } catch (err) { + console.warn('fail to save image', err.message); } + }; + const _onCopyPress = (index: number) => { + const url = imageUrls[index]; + Share.share(Platform.OS === 'ios' ? { url } : { message: url }); + }; + const _renderIconButton = (iconName: string, onPress: () => void) => ( + + ); + + const _renderImageViewerHeader = (imageIndex: number) => { return ( - ({ uri: url }))} - imageIndex={selectedIndex} - visible={visible} - animationType="slide" - swipeToCloseEnabled - onRequestClose={_onCloseImageViewer} - HeaderComponent={(data) => _renderImageViewerHeader(data.imageIndex)} - /> + + + + {_renderIconButton('close', _onCloseImageViewer)} + + {`Preview (${imageIndex + 1}/${imageUrls.length})`} + + + + + {_renderIconButton('content-copy', () => _onCopyPress(imageIndex))} + {_renderIconButton('download', () => _onSavePress(imageIndex))} + + + ); + }; + + const _onCloseImageViewer = () => { + setVisible(false); + setImageUrls([]); + }; + + return ( + ({ uri: url }))} + imageIndex={selectedIndex} + visible={visible} + animationType="slide" + swipeToCloseEnabled + onRequestClose={_onCloseImageViewer} + HeaderComponent={(data) => _renderImageViewerHeader(data.imageIndex)} + /> + ); }); - - diff --git a/src/components/imageViewer/index.ts b/src/components/imageViewer/index.ts index beb695cfc..11832407d 100644 --- a/src/components/imageViewer/index.ts +++ b/src/components/imageViewer/index.ts @@ -1 +1 @@ -export * from './imageViewer'; \ No newline at end of file +export * from './imageViewer'; diff --git a/src/components/index.tsx b/src/components/index.tsx index ddfe103da..4eac84911 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -260,5 +260,5 @@ export { WebViewModal, OrDivider, PostTranslationModal, - ImageViewer + ImageViewer, }; diff --git a/src/components/markdownEditor/children/editorToolbar.tsx b/src/components/markdownEditor/children/editorToolbar.tsx index c23d7c4fd..366c3d6cf 100644 --- a/src/components/markdownEditor/children/editorToolbar.tsx +++ b/src/components/markdownEditor/children/editorToolbar.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from 'react'; -import { Keyboard, Text, View, ViewStyle } from 'react-native'; +import { Keyboard, View, ViewStyle } from 'react-native'; import { FlatList, Gesture, @@ -279,4 +279,4 @@ export const EditorToolbar = ({ )} ); -}; \ No newline at end of file +}; diff --git a/src/components/postCard/children/postCardActionsPanel.tsx b/src/components/postCard/children/postCardActionsPanel.tsx index ac7b060ea..8929a5368 100644 --- a/src/components/postCard/children/postCardActionsPanel.tsx +++ b/src/components/postCard/children/postCardActionsPanel.tsx @@ -44,7 +44,6 @@ export const PostCardActionsPanel = ({ content, handleCardInteraction }: Props) permlink, }, }); - }; return ( diff --git a/src/components/postCard/children/postCardContent.tsx b/src/components/postCard/children/postCardContent.tsx index be324d1b3..918178ad7 100644 --- a/src/components/postCard/children/postCardContent.tsx +++ b/src/components/postCard/children/postCardContent.tsx @@ -1,13 +1,7 @@ import React, { useMemo, useState } from 'react'; - import { TouchableOpacity, Text, View } from 'react-native'; - // Utils - import { Image as ExpoImage } from 'expo-image'; - - -import { get } from 'lodash'; import { useIntl } from 'react-intl'; // Components @@ -47,16 +41,17 @@ export const PostCardContent = ({ const [calcImgHeight, setCalcImgHeight] = useState(imageRatio ? imgWidth / imageRatio : 300); const resizeMode = useMemo(() => { - return calcImgHeight < dim.height ? "contain" : "cover"; + return calcImgHeight < dim.height ? 'contain' : 'cover'; }, [dim.height]); - - //featured text can be used to add more labels in future by just inserting text as array item + // featured text can be used to add more labels in future by just inserting text as array item const _featuredText = [ - content?.is_promoted && intl.formatMessage({ id: 'post.promoted' }), - content?.json_metadata?.content_type === ContentType.POLL && intl.formatMessage({ id: 'post.poll' }) - ].filter(i => !!i).join(' | ') - + content?.is_promoted && intl.formatMessage({ id: 'post.promoted' }), + content?.json_metadata?.content_type === ContentType.POLL && + intl.formatMessage({ id: 'post.poll' }), + ] + .filter((i) => !!i) + .join(' | '); const _onPress = () => { handleCardInteraction(PostCardActionIds.NAVIGATE, { @@ -107,9 +102,7 @@ export const PostCardContent = ({ )} - {!!_featuredText && ( - {_featuredText} - )} + {!!_featuredText && {_featuredText}} {content.title} {content.summary} diff --git a/src/components/postCard/children/postCardHeader.tsx b/src/components/postCard/children/postCardHeader.tsx index 77890b801..012b71a7d 100644 --- a/src/components/postCard/children/postCardHeader.tsx +++ b/src/components/postCard/children/postCardHeader.tsx @@ -64,7 +64,12 @@ export const PostCardHeader = ({ intl, content, isHideImage, handleCardInteracti )} {(content?.stats?.is_pinned || content?.stats?.is_pinned_blog) && ( - + )} diff --git a/src/components/postCard/children/postCardStyles.js b/src/components/postCard/children/postCardStyles.js index 502d7adc0..50d15d9c7 100644 --- a/src/components/postCard/children/postCardStyles.js +++ b/src/components/postCard/children/postCardStyles.js @@ -80,7 +80,7 @@ export default EStyleSheet.create({ flexDirection: 'row', alignItems: 'center', marginRight: -8, - paddingBottom:5 + paddingBottom: 5, }, pushPinIcon: { color: '$primaryRed', diff --git a/src/components/postElements/body/view/postBodyView.js b/src/components/postElements/body/view/postBodyView.js index 6e4ae8c0b..dc4b8a01d 100644 --- a/src/components/postElements/body/view/postBodyView.js +++ b/src/components/postElements/body/view/postBodyView.js @@ -1,6 +1,6 @@ import React, { Fragment, useState, useEffect, useRef } from 'react'; import { PermissionsAndroid, Platform, View } from 'react-native'; -import {CameraRoll} from '@react-native-camera-roll/camera-roll'; +import { CameraRoll } from '@react-native-camera-roll/camera-roll'; import { useIntl } from 'react-intl'; import EStyleSheet from 'react-native-extended-stylesheet'; import RNFetchBlob from 'rn-fetch-blob'; @@ -64,7 +64,6 @@ const PostBody = ({ body, metadata, onLoadEnd, width }) => { } }; - const handleLinkPress = (ind) => { if (ind === 1) { // open link @@ -231,18 +230,14 @@ const PostBody = ({ body, metadata, onLoadEnd, width }) => { }; const _handleSetSelectedImage = (imageLink, postImgUrls) => { - if(imageViewerRef.current){ + if (imageViewerRef.current) { imageViewerRef.current.show(imageLink, postImgUrls); } }; - return ( - - + { - console.log('Post Type', postType) + console.log('Post Type', postType); const navigation = useNavigation(); const dispatch = useDispatch(); @@ -40,7 +40,7 @@ export const PostHtmlInteractionHandler = forwardRef( useImperativeHandle(ref, () => ({ handleImagePress: (url: string, postImgUrls: string[]) => { - if(imageViewerRef.current){ + if (imageViewerRef.current) { imageViewerRef.current.show(url, postImgUrls); } }, @@ -69,9 +69,6 @@ export const PostHtmlInteractionHandler = forwardRef( }, })); - - - const _handleLinkOptionPress = (ind) => { if (ind === 1) { // open link @@ -103,10 +100,7 @@ export const PostHtmlInteractionHandler = forwardRef( return ( - - + void; handleVotersPress: (optionNum: number) => void; } - - export const PollChoices = ({ choices, metadata, @@ -42,101 +40,110 @@ export const PollChoices = ({ handleChoiceSelect, handleVotersPress, }: PollChoicesProps) => { - const intl = useIntl() + const intl = useIntl(); - const [_choices, setChoices] = useState( - choices || mapMetaChoicesToPollChoices(metadata.choices)); - + const [_choices, setChoices] = useState(choices || mapMetaChoicesToPollChoices(metadata.choices)); const totalVotes = useMemo( - () => _choices.reduce( - (prevVal, option) => prevVal + get(option.votes, interpretationToken ? 'hive_hp_incl_proxied':'total_votes', 0), 0) - , [_choices, interpretationToken]); - + () => + _choices.reduce( + (prevVal, option) => + prevVal + + get(option.votes, interpretationToken ? 'hive_hp_incl_proxied' : 'total_votes', 0), + 0, + ), + [_choices, interpretationToken], + ); useEffect(() => { if (!loading && !!choices) { - setChoices(choices) + setChoices(choices); } - }, [loading, choices]) - - - const _isModeSelect = mode === PollModes.SELECT + }, [loading, choices]); + const _isModeSelect = mode === PollModes.SELECT; const _handleChoiceSelect = (choiceNum: number) => { handleChoiceSelect(choiceNum); - } - + }; const _renderProgressBar = (option: PollChoice) => { + const _isVoted = + !_isModeSelect && userVote?.choices && userVote.choices.includes(option.choice_num); + const _isSelected = selection.includes(option.choice_num); - const _isVoted = !_isModeSelect && userVote?.choices && userVote.choices.includes(option.choice_num); - const _isSelected = selection.includes(option.choice_num) + const votes = + Math.round( + get(option.votes, interpretationToken ? 'hive_hp_incl_proxied' : 'total_votes', 0) * 1000, + ) / 1000; - const votes = Math.round(get(option.votes, interpretationToken ? 'hive_hp_incl_proxied':'total_votes', 0) * 1000 ) / 1000; - - const percentage = (!_isModeSelect && !!totalVotes) ? (votes / totalVotes) * 100 : 0; //TODO: adjust logic here + const percentage = !_isModeSelect && !!totalVotes ? (votes / totalVotes) * 100 : 0; // TODO: adjust logic here const _barWidth = getWindowDimensions().width - 64; const _barStyle = { ...styles.progressBar, - borderColor: EStyleSheet.value(_isSelected ? '$primaryBlue' : 'transparent') - } - + borderColor: EStyleSheet.value(_isSelected ? '$primaryBlue' : 'transparent'), + }; const _onVotersPress = () => { - handleVotersPress(option.choice_num) - } + handleVotersPress(option.choice_num); + }; return ( - - {option.choice_text} + + + {option.choice_text} + - {!_isModeSelect && + {!_isModeSelect && ( - } - + text={`${votes} ${intl.formatMessage({ + id: interpretationToken ? 'post_poll.hp' : 'post_poll.voted', + })}`} + onPress={_onVotersPress} + /> + )} ); }; - const renderOptions = () => { return _choices.map((option, index) => { - return ( - _handleChoiceSelect(option.choice_num)}> - - {_renderProgressBar(option)} - + _handleChoiceSelect(option.choice_num)} + > + {_renderProgressBar(option)} ); }); }; - - - return ( - - {renderOptions()} - - ); + return {renderOptions()}; }; diff --git a/src/components/postPoll/children/pollHeader.tsx b/src/components/postPoll/children/pollHeader.tsx index 2c807b49b..baf5e98cc 100644 --- a/src/components/postPoll/children/pollHeader.tsx +++ b/src/components/postPoll/children/pollHeader.tsx @@ -1,60 +1,59 @@ import React from 'react'; import { View, Text } from 'react-native'; -import styles from '../styles/pollHeader.styles'; - -import { Icon, PopoverWrapper } from '../../'; -import { getTimeFromNow } from '../../../utils/time'; import EStyleSheet from 'react-native-extended-stylesheet'; import { useIntl } from 'react-intl'; +import styles from '../styles/pollHeader.styles'; + +import { Icon, PopoverWrapper } from '../..'; +import { getTimeFromNow } from '../../../utils/time'; import { PollPreferredInterpretation, PostMetadata } from '../../../providers/hive/hive.types'; interface PollHeaderProps { - metadata: PostMetadata - expired: boolean; + metadata: PostMetadata; + expired: boolean; } export const PollHeader = ({ metadata, expired }: PollHeaderProps) => { - const intl = useIntl(); + const intl = useIntl(); - const _endDate = new Date(metadata.end_time * 1000); - const formattedEndTime = expired - ? intl.formatMessage({ id: "post_poll.ended" }) - : intl.formatMessage({ id: "post_poll.ends" }, { inTime: getTimeFromNow(_endDate) }) + const _endDate = new Date(metadata.end_time * 1000); + const formattedEndTime = expired + ? intl.formatMessage({ id: 'post_poll.ended' }) + : intl.formatMessage({ id: 'post_poll.ends' }, { inTime: getTimeFromNow(_endDate) }); + const _ageLimit = metadata?.filters?.account_age || 0; + const _interpretationToken = + metadata?.preferred_interpretation === PollPreferredInterpretation.TOKENS || false; + const _maxChoicesVotable = metadata?.max_choices_voted || 1; - const _ageLimit = metadata?.filters?.account_age || 0; - const _interpretationToken = metadata?.preferred_interpretation === PollPreferredInterpretation.TOKENS || false; - const _maxChoicesVotable = metadata?.max_choices_voted || 1; - - const _renderSubText = (text) => ( - - {text} - - ) + const _renderSubText = (text) => {text}; - return ( - - - {metadata.question} - - - {formattedEndTime} - - - - - - {!!_ageLimit && _renderSubText(intl.formatMessage({ id: "post_poll.age_limit" }, { days: _ageLimit }))} - {_interpretationToken && _renderSubText(intl.formatMessage({ id: "post_poll.interpretation_token" }))} - {_maxChoicesVotable > 1 && _renderSubText(intl.formatMessage({ id: "post_poll.max_choices" }, { choices: _maxChoicesVotable }))} - - - ); + return ( + + + {metadata.question} + + + {formattedEndTime} + + + + + {!!_ageLimit && + _renderSubText(intl.formatMessage({ id: 'post_poll.age_limit' }, { days: _ageLimit }))} + {_interpretationToken && + _renderSubText(intl.formatMessage({ id: 'post_poll.interpretation_token' }))} + {_maxChoicesVotable > 1 && + _renderSubText( + intl.formatMessage({ id: 'post_poll.max_choices' }, { choices: _maxChoicesVotable }), + )} + + ); }; diff --git a/src/components/postPoll/container/postPoll.tsx b/src/components/postPoll/container/postPoll.tsx index d3e374c34..f283b4372 100644 --- a/src/components/postPoll/container/postPoll.tsx +++ b/src/components/postPoll/container/postPoll.tsx @@ -1,212 +1,207 @@ -import React, { useEffect, useMemo, useState } from 'react' -import { View } from 'react-native' -import { ContentType, PollPreferredInterpretation, PostMetadata } from '../../../providers/hive/hive.types'; +import React, { useEffect, useMemo, useState } from 'react'; +import { View } from 'react-native'; +import { useNavigation } from '@react-navigation/native'; +import { useIntl } from 'react-intl'; +import { + ContentType, + PollPreferredInterpretation, + PostMetadata, +} from '../../../providers/hive/hive.types'; import { PollChoices, PollHeader } from '../children'; import styles from '../styles/postPoll.styles'; import { pollQueries } from '../../../providers/queries'; import { useAppSelector } from '../../../hooks'; import { MainButton, TextButton } from '../..'; -import { useNavigation } from '@react-navigation/native'; import ROUTES from '../../../constants/routeNames'; -import { useIntl } from 'react-intl'; import { getDaysPassedSince } from '../../../utils/time'; - export enum PollModes { - LOADING = 0, - SELECT = 1, - RESULT = 2, + LOADING = 0, + SELECT = 1, + RESULT = 2, } interface PostPoll { - author: string; - permlink: string; - metadata: PostMetadata; + author: string; + permlink: string; + metadata: PostMetadata; } -export const PostPoll = ({ - author, - permlink, - metadata -}: PostPoll) => { +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const PostPoll = ({ author, permlink, metadata }: PostPoll) => { + if (metadata.content_type !== ContentType.POLL) { + return null; + } + const intl = useIntl(); + const navigation = useNavigation(); - if (metadata.content_type !== ContentType.POLL) { - return null; + const currentAccount = useAppSelector((state) => state.account.currentAccount); + const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn); + + const [selection, setSelection] = useState([]); + const [mode, setMode] = useState(PollModes.LOADING); + const [interpretation, setInterpretation] = useState( + metadata.preferred_interpretation || PollPreferredInterpretation.NUMBER_OF_VOTES, + ); + + const _isModeSelect = mode === PollModes.SELECT; + const _isInterpretationToken = interpretation === PollPreferredInterpretation.TOKENS; + const _isPollAuthor = author === currentAccount?.username; + + const pollsQuery = pollQueries.useGetPollQuery(author, permlink, metadata); + const votePollMutation = pollQueries.useVotePollMutation(pollsQuery.data); + const _accAgeLimit = + pollsQuery.data?.filter_account_age_days || metadata.filters?.account_age || 0; + + const userVote = useMemo(() => { + if (pollsQuery.data) { + return pollsQuery.data.poll_voters.find((voter) => voter.name === currentAccount.username); + } + }, [pollsQuery.data?.poll_voters, currentAccount.username]); + + const _expired = useMemo( + () => new Date(metadata.end_time * 1000).getTime() < new Date().getTime(), + [metadata], + ); + + const _hideVoters = useMemo( + () => metadata.hide_votes && !_isPollAuthor, + [metadata, _isPollAuthor], + ); + const _voteDisabled = useMemo(() => { + const _ageLimitApllies = + currentAccount && _accAgeLimit + ? getDaysPassedSince(currentAccount.created) < _accAgeLimit + : false; + + const _noVoteChange = + metadata.vote_change !== undefined ? !metadata.vote_change && !!userVote : false; + + return _expired || !isLoggedIn || _noVoteChange || _ageLimitApllies; + }, [metadata, userVote]); + + useEffect(() => { + if (pollsQuery.isSuccess) { + setMode(!!userVote || _expired ? PollModes.RESULT : PollModes.SELECT); + setInterpretation( + pollsQuery.data?.preferred_interpretation || PollPreferredInterpretation.NUMBER_OF_VOTES, + ); + } + }, [pollsQuery.isLoading, userVote]); + + const _handleCastVote = () => { + votePollMutation.mutate({ choices: selection }); + setSelection([]); + }; + + const _handleChoiceSelect = (choiceNum: number) => { + const _maxSelectable = pollsQuery.data?.max_choices_voted || 1; + + if (_maxSelectable > 1) { + // handle multiple choice selection + const _maxSelected = pollsQuery.data + ? selection.length >= pollsQuery.data?.max_choices_voted + : 1; + + const index = selection.indexOf(choiceNum); + if (index >= 0) { + selection.splice(index, 1); + } else if (!_maxSelected) { + selection.push(choiceNum); + } + setSelection([...selection]); + } else { + // if only one choice allowed, overwrite selection + setSelection([choiceNum]); + } + }; + + const _handleModeToggle = () => { + setMode(_isModeSelect ? PollModes.RESULT : PollModes.SELECT); + }; + + const _handleVotersPress = (choiceNum: number) => { + const _voters = pollsQuery.data?.poll_voters; + if (!_voters) { + return; } - const intl = useIntl(); - const navigation = useNavigation(); + const _filteredVoters = _voters + .filter((item) => item.choices.includes(choiceNum)) + .map((voter) => ({ account: voter.name })); + navigation.navigate(ROUTES.MODALS.ACCOUNT_LIST, { + title: intl.formatMessage({ id: 'post_poll.voters' }), + users: _filteredVoters, + }); + }; - const currentAccount = useAppSelector(state => state.account.currentAccount) - const isLoggedIn = useAppSelector(state => state.application.isLoggedIn); + const _switchInterpretation = () => { + setInterpretation( + _isInterpretationToken + ? PollPreferredInterpretation.NUMBER_OF_VOTES + : PollPreferredInterpretation.TOKENS, + ); + }; - const [selection, setSelection] = useState([]); - const [mode, setMode] = useState(PollModes.LOADING) - const [interpretation, setInterpretation] = useState(metadata.preferred_interpretation || PollPreferredInterpretation.NUMBER_OF_VOTES); + const _authorPanel = _isPollAuthor && ( + + - const _isModeSelect = mode === PollModes.SELECT; - const _isInterpretationToken = interpretation === PollPreferredInterpretation.TOKENS; - const _isPollAuthor = author === currentAccount?.username; + {!_isModeSelect && ( + + )} + + ); - const pollsQuery = pollQueries.useGetPollQuery(author, permlink, metadata) - const votePollMutation = pollQueries.useVotePollMutation(pollsQuery.data); - const _accAgeLimit = pollsQuery.data?.filter_account_age_days || metadata.filters?.account_age || 0; + const _actionPanel = !_voteDisabled && ( + + + + ); + return ( + + - const userVote = useMemo(() => { - if (pollsQuery.data) { - return pollsQuery.data.poll_voters.find(voter => voter.name === currentAccount.username) - } - }, [pollsQuery.data?.poll_voters, currentAccount.username]) + - const _expired = useMemo( - () => new Date(metadata.end_time * 1000).getTime() < new Date().getTime(), - [metadata]); - - - const _hideVoters = useMemo(() => metadata.hide_votes && !_isPollAuthor, [metadata, _isPollAuthor]); - const _voteDisabled = useMemo(() => { - - const _ageLimitApllies = currentAccount && _accAgeLimit - ? getDaysPassedSince(currentAccount.created) < _accAgeLimit : false; - - const _noVoteChange = metadata.vote_change !== undefined - ? !metadata.vote_change && !!userVote - : false; - - return _expired || !isLoggedIn || _noVoteChange || _ageLimitApllies - }, [metadata, userVote]); - - - - - useEffect(() => { - if (pollsQuery.isSuccess) { - setMode(!!userVote || _expired ? PollModes.RESULT : PollModes.SELECT); - setInterpretation(pollsQuery.data?.preferred_interpretation || PollPreferredInterpretation.NUMBER_OF_VOTES) - } - }, [pollsQuery.isLoading, userVote]) - - - const _handleCastVote = () => { - votePollMutation.mutate({ choices: selection }) - setSelection([]); - } - - - const _handleChoiceSelect = (choiceNum: number) => { - - const _maxSelectable = pollsQuery.data?.max_choices_voted || 1 - - if (_maxSelectable > 1) { - //handle multiple choice selection - const _maxSelected = pollsQuery.data - ? selection.length >= pollsQuery.data?.max_choices_voted : 1 - - const index = selection.indexOf(choiceNum) - if (index >= 0) { - selection.splice(index, 1); - } else if (!_maxSelected) { - selection.push(choiceNum) - } - setSelection([...selection]); - } else { - //if only one choice allowed, overwrite selection - setSelection([choiceNum]); - } - - } - - const _handleModeToggle = () => { - setMode(_isModeSelect ? PollModes.RESULT : PollModes.SELECT); - } - - const _handleVotersPress = (choiceNum: number) => { - const _voters = pollsQuery.data?.poll_voters; - if (!_voters) { - return; - } - - const _filteredVoters = _voters - .filter(item => item.choices.includes(choiceNum)) - .map(voter => ({ account: voter.name })) - - navigation.navigate(ROUTES.MODALS.ACCOUNT_LIST, { - title: intl.formatMessage({ id: 'post_poll.voters' }), - users: _filteredVoters, - }); - - } - - - const _switchInterpretation = () => { - setInterpretation(_isInterpretationToken - ? PollPreferredInterpretation.NUMBER_OF_VOTES - : PollPreferredInterpretation.TOKENS - ) - } - - const _authorPanel = _isPollAuthor && ( - - - - {!_isModeSelect && ( - - )} - - - ) - - const _actionPanel = !_voteDisabled && ( - - - - ) - - - return ( - - - - - - {_authorPanel} - {_actionPanel} - - - ) -} + {_authorPanel} + {_actionPanel} + + ); +}; diff --git a/src/components/postPoll/index.ts b/src/components/postPoll/index.ts index c95cfacfb..889f08647 100644 --- a/src/components/postPoll/index.ts +++ b/src/components/postPoll/index.ts @@ -1 +1 @@ -export * from './container/postPoll'; \ No newline at end of file +export * from './container/postPoll'; diff --git a/src/components/postPoll/styles/pollChoices.styles.ts b/src/components/postPoll/styles/pollChoices.styles.ts index 7a7559de8..ff23b8bb0 100644 --- a/src/components/postPoll/styles/pollChoices.styles.ts +++ b/src/components/postPoll/styles/pollChoices.styles.ts @@ -2,41 +2,42 @@ import { TextStyle, ViewStyle } from 'react-native'; import EStyleSheet from 'react-native-extended-stylesheet'; export default EStyleSheet.create({ - choiceWrapper: { - marginBottom: 8 - }, - progressBar: { - borderRadius: 12, - borderWidth: 2, - alignSelf: 'stretch', - marginHorizontal: 8, - } as ViewStyle, - progressContentWrapper: { - position: 'absolute', - left: 24, right: 24, - top: 0, bottom: 0, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between' - } as ViewStyle, - choiceLabelWrapper: { - flexDirection: 'row', - alignItems: 'center', - flexShrink:1 - } as ViewStyle, - label: { - marginLeft: 8, - fontSize: 12, - color: '$primaryBlack', - flexShrink:1, - } as TextStyle, - count: { - fontSize: 12, - marginLeft: 8, - color: '$primaryDarkGray', - } as TextStyle, - checkContainerStyle: { - backgroundColor: '$white', - - } as ViewStyle -}); \ No newline at end of file + choiceWrapper: { + marginBottom: 8, + }, + progressBar: { + borderRadius: 12, + borderWidth: 2, + alignSelf: 'stretch', + marginHorizontal: 8, + } as ViewStyle, + progressContentWrapper: { + position: 'absolute', + left: 24, + right: 24, + top: 0, + bottom: 0, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + } as ViewStyle, + choiceLabelWrapper: { + flexDirection: 'row', + alignItems: 'center', + flexShrink: 1, + } as ViewStyle, + label: { + marginLeft: 8, + fontSize: 12, + color: '$primaryBlack', + flexShrink: 1, + } as TextStyle, + count: { + fontSize: 12, + marginLeft: 8, + color: '$primaryDarkGray', + } as TextStyle, + checkContainerStyle: { + backgroundColor: '$white', + } as ViewStyle, +}); diff --git a/src/components/postPoll/styles/pollHeader.styles.ts b/src/components/postPoll/styles/pollHeader.styles.ts index bdfc47faf..183c13e13 100644 --- a/src/components/postPoll/styles/pollHeader.styles.ts +++ b/src/components/postPoll/styles/pollHeader.styles.ts @@ -2,33 +2,31 @@ import { TextStyle, ViewStyle } from 'react-native'; import EStyleSheet from 'react-native-extended-stylesheet'; export default EStyleSheet.create({ - - headerWrapper: { - flexWrap: 'wrap', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginHorizontal: 8, - marginBottom: 12 - } as ViewStyle, - question: { - fontSize: 16, - fontWeight: '600', - color: "$primaryBlack", - } as TextStyle, - timeContainer:{ - flexDirection:'row', - alignItems:'center' - } as ViewStyle, - clockIcon:{ - marginLeft:4 - }, - timeText:{ - color:'$primaryDarkText', - } as TextStyle, - subText:{ - color:'$primaryDarkText', - marginBottom:8, - } as TextStyle - -}); \ No newline at end of file + headerWrapper: { + flexWrap: 'wrap', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginHorizontal: 8, + marginBottom: 12, + } as ViewStyle, + question: { + fontSize: 16, + fontWeight: '600', + color: '$primaryBlack', + } as TextStyle, + timeContainer: { + flexDirection: 'row', + alignItems: 'center', + } as ViewStyle, + clockIcon: { + marginLeft: 4, + }, + timeText: { + color: '$primaryDarkText', + } as TextStyle, + subText: { + color: '$primaryDarkText', + marginBottom: 8, + } as TextStyle, +}); diff --git a/src/components/postPoll/styles/postPoll.styles.ts b/src/components/postPoll/styles/postPoll.styles.ts index 0825768c7..9bf45de14 100644 --- a/src/components/postPoll/styles/postPoll.styles.ts +++ b/src/components/postPoll/styles/postPoll.styles.ts @@ -2,58 +2,60 @@ import { TextStyle, ViewStyle } from 'react-native'; import EStyleSheet from 'react-native-extended-stylesheet'; export default EStyleSheet.create({ - container: { - marginTop:16, - borderRadius: 12, - borderWidth: EStyleSheet.hairlineWidth, - borderColor: '$iconColor', - padding:8 - } as ViewStyle, - headerWrapper:{ - flexWrap:'wrap', - flexDirection:'row', - alignItems:'center', - justifyContent:'space-between', - marginHorizontal:8, - marginBottom:12 - } as ViewStyle, - question:{ - fontSize:16, - fontWeight:'600', - color: "$primaryBlack", - } as TextStyle, - countdonw:{ - fontSize:12, - color: "$primaryBlack", - } as TextStyle, - optionsTextWrapper: { - position: 'absolute', - left: 24, right: 24, - top: 0, bottom: 0, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between' - } as ViewStyle, - authorPanel:{ - flexDirection:'row', - alignItems:'center', - justifyContent:'space-between', - marginBottom:8 - } as ViewStyle, - actionPanel:{ - flexDirection:'row-reverse', - alignItems:'center', - } as ViewStyle, - voteButton:{ - width: 140, - height: 44, - alignItems:'center', - justifyContent:'center' - } as ViewStyle, - viewVotesBtn:{ - color: '$primaryDarkGray', - fontSize: 14, - marginHorizontal:8, - fontWeight: '500', - } as ViewStyle -}); \ No newline at end of file + container: { + marginTop: 16, + borderRadius: 12, + borderWidth: EStyleSheet.hairlineWidth, + borderColor: '$iconColor', + padding: 8, + } as ViewStyle, + headerWrapper: { + flexWrap: 'wrap', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginHorizontal: 8, + marginBottom: 12, + } as ViewStyle, + question: { + fontSize: 16, + fontWeight: '600', + color: '$primaryBlack', + } as TextStyle, + countdonw: { + fontSize: 12, + color: '$primaryBlack', + } as TextStyle, + optionsTextWrapper: { + position: 'absolute', + left: 24, + right: 24, + top: 0, + bottom: 0, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + } as ViewStyle, + authorPanel: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginBottom: 8, + } as ViewStyle, + actionPanel: { + flexDirection: 'row-reverse', + alignItems: 'center', + } as ViewStyle, + voteButton: { + width: 140, + height: 44, + alignItems: 'center', + justifyContent: 'center', + } as ViewStyle, + viewVotesBtn: { + color: '$primaryDarkGray', + fontSize: 14, + marginHorizontal: 8, + fontWeight: '500', + } as ViewStyle, +}); diff --git a/src/components/postView/container/postDisplayContainer.tsx b/src/components/postView/container/postDisplayContainer.tsx index 32f4952dc..23e403821 100644 --- a/src/components/postView/container/postDisplayContainer.tsx +++ b/src/components/postView/container/postDisplayContainer.tsx @@ -67,14 +67,14 @@ const PostDisplayContainer = ({ }; const _handleOnReblogsPress = () => { - navigation.navigate({ - name: ROUTES.SCREENS.REBLOGS, - params: { - author, - permlink, - }, - key: post.permlink + post.reblogs.length, - } as never); + navigation.navigate({ + name: ROUTES.SCREENS.REBLOGS, + params: { + author, + permlink, + }, + key: post.permlink + post.reblogs.length, + } as never); }; const _handleOnReplyPress = () => { diff --git a/src/components/postView/view/postDisplayView.tsx b/src/components/postView/view/postDisplayView.tsx index 33a158a65..a5d49e2cc 100644 --- a/src/components/postView/view/postDisplayView.tsx +++ b/src/components/postView/view/postDisplayView.tsx @@ -7,6 +7,7 @@ import get from 'lodash/get'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; // Utils +import { useQueryClient } from '@tanstack/react-query'; import { getTimeFromNow } from '../../../utils/time'; // Components @@ -28,7 +29,6 @@ import { PostComments } from '../../postComments'; import { UpvoteButton } from '../../postCard/children/upvoteButton'; import UpvotePopover from '../../upvotePopover'; import { PostPoll } from '../../postPoll'; -import { useQueryClient } from '@tanstack/react-query'; import QUERIES from '../../../providers/queries/queryKeys'; const WIDTH = getWindowDimensions().width; @@ -284,11 +284,8 @@ const PostDisplayView = ({ metadata={post.json_metadata} onLoadEnd={_handleOnPostBodyLoad} /> - - + + {!postBodyLoading && ( @@ -299,7 +296,7 @@ const PostDisplayView = ({ { username: author || post.author, appname: post?.json_metadata?.app - ? capitalize((post?.json_metadata?.app).split('/')[0]) + ? capitalize(post?.json_metadata?.app?.split('/')[0]) : 'Ecency', }, )} diff --git a/src/components/profileEditForm/profileEditFormView.tsx b/src/components/profileEditForm/profileEditFormView.tsx index ab30aa0b7..6df93f369 100644 --- a/src/components/profileEditForm/profileEditFormView.tsx +++ b/src/components/profileEditForm/profileEditFormView.tsx @@ -1,12 +1,11 @@ import React from 'react'; -import { View, TouchableOpacity, Text, Platform, ActivityIndicator } from 'react-native'; +import { View, TouchableOpacity, Text, Platform } from 'react-native'; import Animated, { BounceInRight } from 'react-native-reanimated'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import { injectIntl, useIntl } from 'react-intl'; // Images import { Image as ExpoImage } from 'expo-image'; -import EStyleSheet from 'react-native-extended-stylesheet'; import LIGHT_COVER_IMAGE from '../../assets/default_cover_image.png'; import DARK_COVER_IMAGE from '../../assets/dark_cover_image.png'; @@ -77,7 +76,7 @@ const ProfileEditFormView = ({ } /> { const codeScanner = useCodeScanner({ codeTypes: ['qr'], onCodeScanned: (codes) => { - console.log(`Scanned ${codes.length} codes!`, codes) - handleLink({data:codes[0].value}); - } - }) + console.log(`Scanned ${codes.length} codes!`, codes); + handleLink({ data: codes[0].value }); + }, + }); // TODO: make sure to properly clean uri processing code to process uri from deep links and notifications const deepLinkToHandle = useAppSelector((state) => state.ui.deepLinkToHandle); @@ -291,7 +291,6 @@ export const QRModal = () => { ); }; - return ( { indicatorStyle={styles.indicator} > - { - - if(isSubmitting){ + if (isSubmitting) { return; } diff --git a/src/components/toggleSwitch/view/toggleSwitchStyles.js b/src/components/toggleSwitch/view/toggleSwitchStyles.js index b3d640e61..f8b2f6ba8 100644 --- a/src/components/toggleSwitch/view/toggleSwitchStyles.js +++ b/src/components/toggleSwitch/view/toggleSwitchStyles.js @@ -28,4 +28,4 @@ export default EStyleSheet.create({ }, elevation: 3, }, -}); \ No newline at end of file +}); diff --git a/src/components/toggleSwitch/view/toggleSwitchView.tsx b/src/components/toggleSwitch/view/toggleSwitchView.tsx index 4aa44632a..cb41ac81f 100644 --- a/src/components/toggleSwitch/view/toggleSwitchView.tsx +++ b/src/components/toggleSwitch/view/toggleSwitchView.tsx @@ -71,4 +71,4 @@ const ToggleSwitchView = ({ onColor, offColor, latchBack, onToggle, ...props }: ); }; -export default ToggleSwitchView; \ No newline at end of file +export default ToggleSwitchView; diff --git a/src/components/uploadsGalleryModal/children/uploadsGalleryContent.tsx b/src/components/uploadsGalleryModal/children/uploadsGalleryContent.tsx index 7b39b4b1a..78566ab29 100644 --- a/src/components/uploadsGalleryModal/children/uploadsGalleryContent.tsx +++ b/src/components/uploadsGalleryModal/children/uploadsGalleryContent.tsx @@ -65,7 +65,7 @@ const UploadsGalleryContent = ({ animatedHeight.value = withTiming(COMPACT_HEIGHT, { easing: Easing.inOut(Easing.cubic), }); - }, []) + }, []); const isDeleting = mode === Modes.MODE_IMAGE @@ -247,8 +247,8 @@ const UploadsGalleryContent = ({ {mode === Modes.MODE_IMAGE ? _renderSelectButtons : isAddingToUploads - ? _renderSelectButton('progress-upload', 'Uploading', handleOpenSpeakUploader) - : _renderSelectButtons} + ? _renderSelectButton('progress-upload', 'Uploading', handleOpenSpeakUploader) + : _renderSelectButtons} { component={AssetsSelect} options={{ presentation: 'modal' }} /> - + ); diff --git a/src/providers/ecency/ecency.ts b/src/providers/ecency/ecency.ts index fef6c3de8..2e685421e 100644 --- a/src/providers/ecency/ecency.ts +++ b/src/providers/ecency/ecency.ts @@ -966,8 +966,7 @@ export const getCommentHistory = async ( export const getAnnouncements = async (accessToken: string) => { try { - - const params = accessToken ? { code:accessToken } : null + const params = accessToken ? { code: accessToken } : null; const res = await ecencyApi.get('/private-api/announcements', { params }); console.log('announcements fetcehd', res.data); diff --git a/src/providers/hive/auth.js b/src/providers/hive/auth.js index a94a749ea..06a529203 100644 --- a/src/providers/hive/auth.js +++ b/src/providers/hive/auth.js @@ -333,22 +333,22 @@ export const getUpdatedUserData = (userData, data) => { : get(userData, 'masterKey', ''), postingKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || - get(userData, 'authType', '') === AUTH_TYPE.POSTING_KEY + get(userData, 'authType', '') === AUTH_TYPE.POSTING_KEY ? encryptKey(get(privateKeys, 'postingKey', '').toString(), get(data, 'pinCode')) : get(userData, 'postingKey', ''), activeKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || - get(userData, 'authType', '') === AUTH_TYPE.ACTIVE_KEY + get(userData, 'authType', '') === AUTH_TYPE.ACTIVE_KEY ? encryptKey(get(privateKeys, 'activeKey', '').toString(), get(data, 'pinCode')) : get(userData, 'activeKey', ''), memoKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || - get(userData, 'authType', '') === AUTH_TYPE.MEMO_KEY + get(userData, 'authType', '') === AUTH_TYPE.MEMO_KEY ? encryptKey(get(privateKeys, 'memoKey', '').toString(), get(data, 'pinCode')) : get(userData, 'memoKey', ''), ownerKey: get(userData, 'authType', '') === AUTH_TYPE.MASTER_KEY || - get(userData, 'authType', '') === AUTH_TYPE.OWNER_KEY + get(userData, 'authType', '') === AUTH_TYPE.OWNER_KEY ? encryptKey(get(privateKeys, 'ownerKey', '').toString(), get(data, 'pinCode')) : get(userData, 'ownerKey', ''), }; @@ -382,25 +382,23 @@ export const getUpdatedUserKeys = async (currentAccountData, data) => { } }); - - if (loginFlag) { - const _prevAuthType = currentAccountData.authType + const _prevAuthType = currentAccountData.authType; const _localData = { ...currentAccountData.local, - authType - } - const _userData = getUpdatedUserData(_localData, data) + authType, + }; + const _userData = getUpdatedUserData(_localData, data); - //sustain appropriate authType; - if(_prevAuthType === AUTH_TYPE.STEEM_CONNECT){ + // sustain appropriate authType; + if (_prevAuthType === AUTH_TYPE.STEEM_CONNECT) { _userData.authType = _prevAuthType; } - + await setUserData(_userData); - currentAccountData.local = _userData - + currentAccountData.local = _userData; + return currentAccountData; } return Promise.reject(new Error('auth.invalid_credentials')); diff --git a/src/providers/hive/dhive.js b/src/providers/hive/dhive.js index a3b62b3be..7e7f4edf0 100644 --- a/src/providers/hive/dhive.js +++ b/src/providers/hive/dhive.js @@ -371,7 +371,7 @@ export const getUser = async (user, loggedIn = true) => { getCache('rcPower'); await setCache('rcPower', rcPower); - _account.reputation = await getUserReputation(user) + _account.reputation = await getUserReputation(user); _account.username = _account.name; _account.unread_activity_count = unreadActivityCount; _account.vp_manabar = client.rc.calculateVPMana(_account); @@ -422,13 +422,11 @@ export const getUserReputation = async (author) => { }; return parseReputation(_account.reputation); - } catch (error) { - bugsnagInstance.notify(error) + bugsnagInstance.notify(error); return 0; } -} - +}; const cache = {}; const patt = /hive-\d\w+/g; @@ -746,11 +744,11 @@ export const getPost = async (author, permlink, currentUserName = null, isPromot try { console.log('Getting post: ', author, permlink); const post = await client.call('bridge', 'get_post', { author, permlink }); - console.log("post fetched", post?.post_id) + console.log('post fetched', post?.post_id); return post ? parsePost(post, currentUserName, isPromoted) : null; } catch (error) { - console.warn(error) - bugsnagInstance.notify(error) + console.warn(error); + bugsnagInstance.notify(error); return error; } }; @@ -1759,25 +1757,20 @@ export const reblog = (account, pinCode, author, permlink, undo = false) => return resp; }); - const _reblog = async (account, pinCode, author, permlink, undo = false) => { - const json = [ 'reblog', { account: account.name, author, permlink, - delete: undo ? 'delete' : undefined + delete: undo ? 'delete' : undefined, }, ]; - - return broadcastPostingJSON('follow', json, account, pinCode) - + return broadcastPostingJSON('follow', json, account, pinCode); }; - export const claimRewardBalance = (account, pinCode, rewardHive, rewardHbd, rewardVests) => { const pin = getDigitPinCode(pinCode); const key = getAnyPrivateKey(get(account, 'local'), pin); diff --git a/src/providers/hive/hive.types.ts b/src/providers/hive/hive.types.ts index 65799b5ed..374f26e15 100644 --- a/src/providers/hive/hive.types.ts +++ b/src/providers/hive/hive.types.ts @@ -5,11 +5,11 @@ export enum ContentType { export enum PollPreferredInterpretation { NUMBER_OF_VOTES = 'number_of_votes', - TOKENS = 'tokens' + TOKENS = 'tokens', } export interface PostMetadata { - //GENERAL + // GENERAL tags: string[]; token: string; content_type: ContentType; @@ -18,23 +18,22 @@ export interface PostMetadata { version: number; app: string; - //IMAGE + // IMAGE image: string[]; image_ratios: number[]; - //POLL + // POLL question: string; preferred_interpretation: PollPreferredInterpretation; max_choices_voted: number; choices: string[]; filters: { - account_age: number - } + account_age: number; + }; end_time: number; - //ECENCY SPECIFIC POLL OPTIONS + // ECENCY SPECIFIC POLL OPTIONS vote_change: boolean; hide_votes: boolean; - } export interface Vote { @@ -155,4 +154,3 @@ export interface TransferDataType { amount: string; memo?: string; } - diff --git a/src/providers/polls/converters.ts b/src/providers/polls/converters.ts index a5e4c5161..b90b87e81 100644 --- a/src/providers/polls/converters.ts +++ b/src/providers/polls/converters.ts @@ -1,114 +1,115 @@ -import { Poll, PollChoice, PollStats, PollVoter } from "./polls.types"; +import { Poll, PollChoice, PollStats, PollVoter } from './polls.types'; -//conveter generated by ChatGPT +// conveter generated by ChatGPT export const convertPoll = (rawData: any): Poll | null => { - if (!rawData) return null; + if (!rawData) return null; - const { - post_title, - post_body, - author, - created, - permlink, - parent_permlink, - tags, - image, - protocol_version, - question, - preferred_interpretation, - token, - end_time, - status, - max_choices_voted, - filter_account_age_days, - ui_hide_res_until_voted, - platform, - poll_trx_id, - poll_choices, - poll_voters, - poll_stats - } = rawData; + const { + post_title, + post_body, + author, + created, + permlink, + parent_permlink, + tags, + image, + protocol_version, + question, + preferred_interpretation, + token, + end_time, + status, + max_choices_voted, + filter_account_age_days, + ui_hide_res_until_voted, + platform, + poll_trx_id, + poll_choices, + poll_voters, + poll_stats, + } = rawData; - // Ensure required properties are present - if (!question || !end_time || !poll_choices || !poll_stats) { - return null; - } + // Ensure required properties are present + if (!question || !end_time || !poll_choices || !poll_stats) { + return null; + } - // Parsing poll choices - const parsedPollChoices: PollChoice[] = poll_choices.map((choice: any) => ({ - choice_num: choice.choice_num, - choice_text: choice.choice_text, - votes: { - total_votes: choice.votes?.total_votes || 0, - hive_hp: choice.votes?.hive_hp || 0, - hive_proxied_hp: choice.votes?.hive_proxied_hp || 0, - hive_hp_incl_proxied: choice.votes?.hive_hp_incl_proxied || 0 - } - })); + // Parsing poll choices + const parsedPollChoices: PollChoice[] = poll_choices.map((choice: any) => ({ + choice_num: choice.choice_num, + choice_text: choice.choice_text, + votes: { + total_votes: choice.votes?.total_votes || 0, + hive_hp: choice.votes?.hive_hp || 0, + hive_proxied_hp: choice.votes?.hive_proxied_hp || 0, + hive_hp_incl_proxied: choice.votes?.hive_hp_incl_proxied || 0, + }, + })); - // Parsing poll voters - const parsedPollVoters: PollVoter[] = poll_voters ? poll_voters.map((voter: any) => ({ + // Parsing poll voters + const parsedPollVoters: PollVoter[] = poll_voters + ? poll_voters.map((voter: any) => ({ name: voter.name, choices: voter.choices, hive_hp: voter.hive_hp || 0, hive_proxied_hp: voter.hive_proxied_hp || 0, - hive_hp_incl_proxied: voter.hive_hp_incl_proxied || 0 - })) : []; + hive_hp_incl_proxied: voter.hive_hp_incl_proxied || 0, + })) + : []; + // Parsing poll stats + const parsedPollStats: PollStats = { + total_voting_accounts_num: poll_stats.total_voting_accounts_num || 0, + total_hive_hp: poll_stats.total_hive_hp || 0, + total_hive_proxied_hp: poll_stats.total_hive_proxied_hp || 0, + total_hive_hp_incl_proxied: poll_stats.total_hive_hp_incl_proxied || 0, + }; - // Parsing poll stats - const parsedPollStats: PollStats = { - total_voting_accounts_num: poll_stats.total_voting_accounts_num || 0, - total_hive_hp: poll_stats.total_hive_hp || 0, - total_hive_proxied_hp: poll_stats.total_hive_proxied_hp || 0, - total_hive_hp_incl_proxied: poll_stats.total_hive_hp_incl_proxied || 0 - }; - - - - // Constructing the parsed poll response - const parsedResponse: Poll = { - post_title: post_title || "", - post_body: post_body || "", - author, - created, - permlink, - parent_permlink, - tags: tags || [], - image: image || [], - protocol_version: protocol_version || 0, - question, - preferred_interpretation, - token, - end_time, - status, - max_choices_voted: max_choices_voted || 1, - filter_account_age_days: filter_account_age_days || 0, - ui_hide_res_until_voted, // Assuming this field can be null, otherwise adjust accordingly - platform, // Assuming this field can be null, otherwise adjust accordingly - poll_trx_id, - poll_choices: parsedPollChoices, - poll_voters: parsedPollVoters, - poll_stats: parsedPollStats - }; - - return parsedResponse; -} + // Constructing the parsed poll response + const parsedResponse: Poll = { + post_title: post_title || '', + post_body: post_body || '', + author, + created, + permlink, + parent_permlink, + tags: tags || [], + image: image || [], + protocol_version: protocol_version || 0, + question, + preferred_interpretation, + token, + end_time, + status, + max_choices_voted: max_choices_voted || 1, + filter_account_age_days: filter_account_age_days || 0, + ui_hide_res_until_voted, // Assuming this field can be null, otherwise adjust accordingly + platform, // Assuming this field can be null, otherwise adjust accordingly + poll_trx_id, + poll_choices: parsedPollChoices, + poll_voters: parsedPollVoters, + poll_stats: parsedPollStats, + }; + return parsedResponse; +}; export const mapMetaChoicesToPollChoices = (metaChoices: string[]) => { - if (!metaChoices) { - return [] as PollChoice[] - } + if (!metaChoices) { + return [] as PollChoice[]; + } - return metaChoices.map(((choice, index) => ({ + return metaChoices.map( + (choice, index) => + ({ choice_num: index + 1, choice_text: choice, votes: { - total_votes: 0, - hive_hp: 0, - hive_proxied_hp: 0, - hive_hp_incl_proxied: 0, - } - } as PollChoice))) -} \ No newline at end of file + total_votes: 0, + hive_hp: 0, + hive_proxied_hp: 0, + hive_hp_incl_proxied: 0, + }, + } as PollChoice), + ); +}; diff --git a/src/providers/polls/polls.ts b/src/providers/polls/polls.ts index 07c46ce89..186c74096 100644 --- a/src/providers/polls/polls.ts +++ b/src/providers/polls/polls.ts @@ -1,109 +1,113 @@ -import axios from "axios"; +import axios from 'axios'; +import { Operation, PrivateKey } from '@esteemapp/dhive'; import bugsnagInstance from '../../config/bugsnag'; -import { Poll } from "./polls.types"; -import { convertPoll } from "./converters"; -import { getActiveKey, getDigitPinCode, sendHiveOperations } from "../hive/dhive"; -import { Operation, PrivateKey } from "@esteemapp/dhive"; - +import { Poll } from './polls.types'; +import { convertPoll } from './converters'; +import { getActiveKey, getDigitPinCode, sendHiveOperations } from '../hive/dhive'; /** - * + * * swapper importable api url * https://polls-beta.hivehub.dev/ - * + * * hive polls docs reference: * https://gitlab.com/peakd/hive-open-polls - * + * */ const POLLS_BASE_URL = 'https://polls.hivehub.dev/'; -const PATH_RPC = 'rpc' -const PATH_POLL = 'poll' +const PATH_RPC = 'rpc'; +const PATH_POLL = 'poll'; const pollsApi = axios.create({ - baseURL: POLLS_BASE_URL, + baseURL: POLLS_BASE_URL, }); - const executePollAction = (id: string, json: any, currentAccount: any, pinHash: string) => { - const pin = getDigitPinCode(pinHash); - const key = getActiveKey(currentAccount.local, pin); - const username = currentAccount.name; + const pin = getDigitPinCode(pinHash); + const key = getActiveKey(currentAccount.local, pin); + const username = currentAccount.name; - if (key) { - const privateKey = PrivateKey.fromString(key); + if (key) { + const privateKey = PrivateKey.fromString(key); - const op = { - id, - json: JSON.stringify(json), - required_auths: [username], - required_posting_auths: [], - }; - const opArray: Operation[] = [['custom_json', op]]; - return sendHiveOperations(opArray, privateKey); - } + const op = { + id, + json: JSON.stringify(json), + required_auths: [username], + required_posting_auths: [], + }; + const opArray: Operation[] = [['custom_json', op]]; + return sendHiveOperations(opArray, privateKey); + } - return Promise.reject( - new Error('Check private key permission! Required private active key or above.'), - ); + return Promise.reject( + new Error('Check private key permission! Required private active key or above.'), + ); }; - export const getPollData = async (author: string, permlink: string): Promise => { - try { - if (!author || !permlink) { - throw new Error("author and permlink are requied for fetching polls data"); - } - - //prefix (eq.) is a requirement from api implementation - const params = { - author: `eq.${author}`, - permlink: `eq.${permlink}` - } - - const res = await pollsApi.get(`/${PATH_RPC}/${PATH_POLL}`, { params }); - - console.log('poll data fetcehd', res.data); - if (!res.data || !res.data[0]) { - throw new Error('No poll data found!'); - } - - const data = convertPoll(res.data[0]); - - if (!data) { - throw new Error('Failed to parse poll resposne data'); - } - - return data - - } catch (error) { - bugsnagInstance.notify(error); - throw error; + try { + if (!author || !permlink) { + throw new Error('author and permlink are requied for fetching polls data'); } + + // prefix (eq.) is a requirement from api implementation + const params = { + author: `eq.${author}`, + permlink: `eq.${permlink}`, + }; + + const res = await pollsApi.get(`/${PATH_RPC}/${PATH_POLL}`, { params }); + + console.log('poll data fetcehd', res.data); + if (!res.data || !res.data[0]) { + throw new Error('No poll data found!'); + } + + const data = convertPoll(res.data[0]); + + if (!data) { + throw new Error('Failed to parse poll resposne data'); + } + + return data; + } catch (error) { + bugsnagInstance.notify(error); + throw error; + } }; - -export const castPollVote = async (postId: string, choices: number[], currentAccount: any, pinHash: string) => { - try { - if (!postId || !currentAccount) { - throw new Error("Failed to register vote") - } - - if (!choices || !choices.length) { - throw new Error("Invalid vote") - } - - await executePollAction("polls", { - poll: postId, - action: "vote", - choices: choices - }, currentAccount, pinHash); - - return true; - - } catch (error) { - bugsnagInstance.notify(error); - throw error; +export const castPollVote = async ( + postId: string, + choices: number[], + currentAccount: any, + pinHash: string, +) => { + try { + if (!postId || !currentAccount) { + throw new Error('Failed to register vote'); } -} + + if (!choices || !choices.length) { + throw new Error('Invalid vote'); + } + + await executePollAction( + 'polls', + { + poll: postId, + action: 'vote', + choices, + }, + currentAccount, + pinHash, + ); + + return true; + } catch (error) { + bugsnagInstance.notify(error); + throw error; + } +}; diff --git a/src/providers/polls/polls.types.ts b/src/providers/polls/polls.types.ts index 7434504ae..01a627d78 100644 --- a/src/providers/polls/polls.types.ts +++ b/src/providers/polls/polls.types.ts @@ -1,54 +1,53 @@ -import { PollPreferredInterpretation } from "../hive/hive.types"; +import { PollPreferredInterpretation } from '../hive/hive.types'; - -//types generated by ChatGPT +// types generated by ChatGPT export interface PollChoice { - choice_num: number; - choice_text: string; - votes: { - total_votes: number; - hive_hp: number; - hive_proxied_hp: number; - hive_hp_incl_proxied: number; - }; -} - -export interface PollVoter { - name: string; - choices: number[]; + choice_num: number; + choice_text: string; + votes: { + total_votes: number; hive_hp: number; hive_proxied_hp: number; hive_hp_incl_proxied: number; + }; +} + +export interface PollVoter { + name: string; + choices: number[]; + hive_hp: number; + hive_proxied_hp: number; + hive_hp_incl_proxied: number; } export interface PollStats { - total_voting_accounts_num: number; - total_hive_hp: number; - total_hive_proxied_hp: number; - total_hive_hp_incl_proxied: number; + total_voting_accounts_num: number; + total_hive_hp: number; + total_hive_proxied_hp: number; + total_hive_hp_incl_proxied: number; } export interface Poll { - post_title: string; - post_body: string; - author: string; - created: string; - permlink: string; - parent_permlink: string; - tags: string[]; - image: any[]; // Adjust this type according to your data structure - protocol_version: number; - question: string; - preferred_interpretation: PollPreferredInterpretation; - token: string; - end_time: string; - max_choices_voted: number; - status: string; - filter_account_age_days: number; - ui_hide_res_until_voted: any; // Adjust this type according to your data structure - platform: any; // Adjust this type according to your data structure - poll_trx_id: string; - poll_choices: PollChoice[]; - poll_voters: PollVoter[]; - poll_stats: PollStats; -} \ No newline at end of file + post_title: string; + post_body: string; + author: string; + created: string; + permlink: string; + parent_permlink: string; + tags: string[]; + image: any[]; // Adjust this type according to your data structure + protocol_version: number; + question: string; + preferred_interpretation: PollPreferredInterpretation; + token: string; + end_time: string; + max_choices_voted: number; + status: string; + filter_account_age_days: number; + ui_hide_res_until_voted: any; // Adjust this type according to your data structure + platform: any; // Adjust this type according to your data structure + poll_trx_id: string; + poll_choices: PollChoice[]; + poll_voters: PollVoter[]; + poll_stats: PollStats; +} diff --git a/src/providers/queries/announcementsQueries.ts b/src/providers/queries/announcementsQueries.ts index 1602b309f..741f020e3 100644 --- a/src/providers/queries/announcementsQueries.ts +++ b/src/providers/queries/announcementsQueries.ts @@ -2,8 +2,8 @@ import { useQuery } from '@tanstack/react-query'; import { useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { useEffect, useMemo } from 'react'; -import { getAnnouncements } from '../ecency/ecency'; import VersionNumber from 'react-native-version-number'; +import { getAnnouncements } from '../ecency/ecency'; import QUERIES from './queryKeys'; import { useAppSelector } from '../../hooks'; import { updateAnnoucementsMeta } from '../../redux/actions/cacheActions'; @@ -24,48 +24,42 @@ export const useAnnouncementsQuery = () => { const pinHash = useAppSelector((state) => state.application.pin); const lastAppVersion = useAppSelector((state) => state.application.lastAppVersion); - const appVersion = useMemo(() => VersionNumber.appVersion, []) + const appVersion = useMemo(() => VersionNumber.appVersion, []); const currentAccount = useAppSelector((state) => state.account.currentAccount); const announcementsMeta = useAppSelector((state) => state.cache.announcementsMeta); - const announcmentsQuery = useQuery([QUERIES.ANNOUNCEMENTS.GET], () => { const encToken = currentAccount?.local?.accessToken; const token = !!encToken && decryptKey(encToken, getDigitPinCode(pinHash)); - return getAnnouncements(token) + return getAnnouncements(token); }); - useEffect(() => { - - //bypass if it's first launch after new version install/update + // bypass if it's first launch after new version install/update const _isNewVersionLaunch = - !lastAppVersion || parseVersionNumber(lastAppVersion) < parseVersionNumber(appVersion) + !lastAppVersion || parseVersionNumber(lastAppVersion) < parseVersionNumber(appVersion); if (_isNewVersionLaunch) { return; } - //bypass if logged in user is required for announcement, skip otherwise + // bypass if logged in user is required for announcement, skip otherwise const firstAnnounce = announcementsMeta.data && announcmentsQuery.data[0]; if (!firstAnnounce || (firstAnnounce?.auth && !currentAccount?.username)) { return; } - //prepare annoucmnet data + // prepare annoucmnet data const _metaId = `${firstAnnounce.id}_${currentAccount?.username || 'guest'}`; const _meta = announcementsMeta && announcementsMeta[_metaId]; const curTime = new Date().getTime(); - //bypass if already processed or last prompt limit now expired - if (_meta?.processed || - _meta?.lastSeen + PROMPT_AGAIN_INTERVAL > curTime) { + // bypass if already processed or last prompt limit now expired + if (_meta?.processed || _meta?.lastSeen + PROMPT_AGAIN_INTERVAL > curTime) { return; } - _showAnnouncement(firstAnnounce, _metaId); - }, [announcmentsQuery.data, currentAccount.username, lastAppVersion]); const _showAnnouncement = async (data, metaId) => { @@ -111,4 +105,3 @@ export const useAnnouncementsQuery = () => { ); }; }; - diff --git a/src/providers/queries/notificationQueries.ts b/src/providers/queries/notificationQueries.ts index d883ca267..563ec4ef5 100644 --- a/src/providers/queries/notificationQueries.ts +++ b/src/providers/queries/notificationQueries.ts @@ -55,7 +55,6 @@ export const useNotificationsQuery = (filter: NotificationFilters) => { }; const _fetchNextPage = () => { - if (!_lastPage || _lastPage.isFetching) { return; } @@ -69,7 +68,6 @@ export const useNotificationsQuery = (filter: NotificationFilters) => { const _dataArrs = notificationQueries.map((query) => query.data); - return { data: unionBy(..._dataArrs, 'id'), isRefreshing, diff --git a/src/providers/queries/postQueries/pollQueries.ts b/src/providers/queries/postQueries/pollQueries.ts index 77936d759..bb1cb5db3 100644 --- a/src/providers/queries/postQueries/pollQueries.ts +++ b/src/providers/queries/postQueries/pollQueries.ts @@ -1,255 +1,249 @@ -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import QUERIES from "../queryKeys"; -import { castPollVote, getPollData } from "../../polls/polls"; -import { PostMetadata } from "../../hive/hive.types"; -import { useEffect, useMemo, useState } from "react"; -import { Poll, PollChoice } from "../../polls/polls.types"; -import { useAppSelector } from "../../../hooks"; -import parseToken from "../../../utils/parseToken"; -import { vestsToHp } from "../../../utils/conversions"; -import { updatePollVoteCache } from "../../../redux/actions/cacheActions"; -import { useDispatch } from "react-redux"; -import { CacheStatus, PollVoteCache } from "../../../redux/reducers/cacheReducer"; -import { toastNotification } from "../../../redux/actions/uiAction"; -import { useIntl } from "react-intl"; - +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useEffect, useMemo, useState } from 'react'; +import { useDispatch } from 'react-redux'; +import { useIntl } from 'react-intl'; +import QUERIES from '../queryKeys'; +import { castPollVote, getPollData } from '../../polls/polls'; +import { PostMetadata } from '../../hive/hive.types'; +import { Poll, PollChoice } from '../../polls/polls.types'; +import { useAppSelector } from '../../../hooks'; +import parseToken from '../../../utils/parseToken'; +import { vestsToHp } from '../../../utils/conversions'; +import { updatePollVoteCache } from '../../../redux/actions/cacheActions'; +import { CacheStatus, PollVoteCache } from '../../../redux/reducers/cacheReducer'; +import { toastNotification } from '../../../redux/actions/uiAction'; /** hook used to return post poll */ export const useGetPollQuery = (_author?: string, _permlink?: string, metadata?: PostMetadata) => { + const [author, setAuthor] = useState(_author); + const [permlink, setPermlink] = useState(_permlink); - const [author, setAuthor] = useState(_author); - const [permlink, setPermlink] = useState(_permlink); + // post process initial post if available + const _initialPollData = useMemo(() => { + // TODO: convert metadata to Poll data; - // post process initial post if available - const _initialPollData = useMemo(() => { - - //TODO: convert metadata to Poll data; + return null; + }, [metadata]); + const query = useQuery( + [QUERIES.POST.GET_POLL, author, permlink], + async () => { + if (!author || !permlink) { return null; - }, [metadata]); + } - const query = useQuery( - [QUERIES.POST.GET_POLL, author, permlink], - async () => { - if (!author || !permlink) { - return null; - } + try { + const pollData = await getPollData(author, permlink); + if (!pollData) { + new Error('Poll data unavailable'); + } - try { - const pollData = await getPollData(author, permlink); - if (!pollData) { - new Error('Poll data unavailable'); - } + return pollData; + } catch (err) { + console.warn('Failed to get post', err); + throw err; + } + }, + { + initialData: _initialPollData, + cacheTime: 30 * 60 * 1000, // keeps cache for 30 minutes + }, + ); - return pollData - } catch (err) { - console.warn('Failed to get post', err); - throw err; - } - }, - { - initialData: _initialPollData, - cacheTime: 30 * 60 * 1000, // keeps cache for 30 minutes - }, - ); + // TODO: use injectPollVoteCache here for simplifity and code reuseability + const data = useInjectPollVoteCache(query.data); - //TODO: use injectPollVoteCache here for simplifity and code reuseability - const data = useInjectPollVoteCache(query.data); - - return { - ...query, - data, - setAuthor, - setPermlink, - }; + return { + ...query, + data, + setAuthor, + setPermlink, + }; }; - - - export function useVotePollMutation(poll: Poll | null) { - // const { activeUser } = useMappedStore(); - const intl = useIntl(); - const dispatch = useDispatch(); - const queryClient = useQueryClient() - const currentAccount = useAppSelector(state => state.account.currentAccount); - const pollVotesCollection = useAppSelector(state => state.cache.pollVotesCollection); - const pinHash = useAppSelector(state => state.application.pin); - const globalProps = useAppSelector(state => state.account.globalProps) + // const { activeUser } = useMappedStore(); + const intl = useIntl(); + const dispatch = useDispatch(); + const queryClient = useQueryClient(); + const currentAccount = useAppSelector((state) => state.account.currentAccount); + const pollVotesCollection = useAppSelector((state) => state.cache.pollVotesCollection); + const pinHash = useAppSelector((state) => state.application.pin); + const globalProps = useAppSelector((state) => state.account.globalProps); + return useMutation({ + mutationKey: [QUERIES.POST.SIGN_POLL_VOTE, poll?.author, poll?.permlink], + mutationFn: async ({ choices }: { choices: number[] }) => { + if (!poll || !currentAccount) { + throw new Error('Failed to register vote'); + } - return useMutation({ - mutationKey: [QUERIES.POST.SIGN_POLL_VOTE, poll?.author, poll?.permlink], - mutationFn: async ({ choices }: { choices: number[] }) => { + if (!(choices instanceof Array)) { + throw new Error('Invalid vote'); + } + // eslint-disable-next-line no-return-await + return await castPollVote(poll.poll_trx_id, choices, currentAccount, pinHash); + }, + retry: 3, + onMutate: ({ choices }) => { + // update redux + const userHp = + Math.round( + vestsToHp(parseToken(currentAccount.vesting_shares), globalProps.hivePerMVests) * 1000, + ) / 1000; + const postPath = `${poll?.author || ''}/${poll?.permlink || ''}`; + const curTime = new Date().getTime(); + const vote = { + choices, + userHp, + username: currentAccount.username, + votedAt: curTime, + expiresAt: curTime + 120000, + status: CacheStatus.PENDING, + } as PollVoteCache; + dispatch(updatePollVoteCache(postPath, vote)); + }, - if (!poll || !currentAccount) { - throw new Error("Failed to register vote") - } + onSuccess: (status) => { + console.log('vote response', status); + // update poll cache here + const postPath = `${poll?.author || ''}/${poll?.permlink || ''}`; + const voteCache: PollVoteCache = pollVotesCollection[postPath]; + if (voteCache) { + voteCache.status = status ? CacheStatus.PUBLISHED : CacheStatus.FAILED; + dispatch(updatePollVoteCache(postPath, voteCache)); + } + }, + onError: (err) => { + // reverse mutation here + const postPath = `${poll?.author || ''}/${poll?.permlink || ''}`; + const voteCache: PollVoteCache = pollVotesCollection[postPath]; + if (voteCache) { + voteCache.status = CacheStatus.FAILED; + dispatch(updatePollVoteCache(postPath, voteCache)); + } - if (!(choices instanceof Array)) { - throw new Error("Invalid vote") - } + dispatch(toastNotification(`${intl.formateMessage({ id: 'alert.fail' })}. ${err.message}`)); - return await castPollVote(poll.poll_trx_id, choices, currentAccount, pinHash) - }, - retry: 3, - onMutate: ({ choices }) => { - - // update redux - const userHp = Math.round(vestsToHp(parseToken(currentAccount.vesting_shares), globalProps.hivePerMVests) * 1000) / 1000; - const postPath = `${poll?.author || ''}/${poll?.permlink || ''}`; - const curTime = new Date().getTime(); - const vote = { - choices, - userHp, - username: currentAccount.username, - votedAt: curTime, - expiresAt: curTime + 120000, - status: CacheStatus.PENDING, - } as PollVoteCache; - dispatch(updatePollVoteCache(postPath, vote)); - }, - - onSuccess: (status) => { - console.log("vote response", status); - //update poll cache here - const postPath = `${poll?.author || ''}/${poll?.permlink || ''}`; - const voteCache: PollVoteCache = pollVotesCollection[postPath]; - if (voteCache) { - voteCache.status = status ? CacheStatus.PUBLISHED : CacheStatus.FAILED; - dispatch(updatePollVoteCache(postPath, voteCache)) - } - }, - onError: (err) => { - //reverse mutation here - const postPath = `${poll?.author || ''}/${poll?.permlink || ''}`; - const voteCache: PollVoteCache = pollVotesCollection[postPath]; - if (voteCache) { - voteCache.status = CacheStatus.FAILED - dispatch(updatePollVoteCache(postPath, voteCache)) - } - - dispatch(toastNotification(`${intl.formateMessage({ id: 'alert.fail' })}. ${err.message}`)) - - queryClient.invalidateQueries([QUERIES.POST.GET_POLL, poll?.author, poll?.permlink]) - } - - - }); + queryClient.invalidateQueries([QUERIES.POST.GET_POLL, poll?.author, poll?.permlink]); + }, + }); } - -//used to create, update and remove poll vote entry from votes data +// used to create, update and remove poll vote entry from votes data const useInjectPollVoteCache = (pollData: Poll | null) => { + const pollVotesCollection = useAppSelector((state) => state.cache.pollVotesCollection); + const lastUpdate = useAppSelector((state) => state.cache.lastUpdate); + const [retData, setRetData] = useState(null); - const pollVotesCollection = useAppSelector((state) => state.cache.pollVotesCollection); - const lastUpdate = useAppSelector((state) => state.cache.lastUpdate); - const [retData, setRetData] = useState(null); + useEffect(() => { + if (pollData && lastUpdate && lastUpdate.type === 'poll-vote') { + const _postPath = lastUpdate.postPath; + const _voteCache = pollVotesCollection[_postPath]; - useEffect(() => { - if (pollData && lastUpdate && lastUpdate.type === 'poll-vote') { - const _postPath = lastUpdate.postPath; - const _voteCache = pollVotesCollection[_postPath]; + const _comparePath = (item) => _postPath === `${item.author}/${item.permlink}`; + const _pathMatched = pollData && _comparePath(pollData); - const _comparePath = (item) => _postPath === `${item.author}/${item.permlink}`; - let _pathMatched = pollData && _comparePath(pollData) + // if poll available, inject cache and update state + if (_pathMatched) { + console.log('Injection: on cache change: ', _voteCache); + const data = injectPollVoteCache(pollData, _voteCache); - // if poll available, inject cache and update state - if (_pathMatched) { - console.log("Injection: on cache change: ", _voteCache) - const data = injectPollVoteCache(pollData, _voteCache); + console.log('updating data', data); + setRetData({ ...data }); + } + } + }, [pollVotesCollection]); - console.log('updating data', data); - setRetData({ ...data }); - } - } - }, [pollVotesCollection]); + useEffect(() => { + if (!pollData) { + setRetData(null); + return; + } - useEffect(() => { - if (!pollData) { - setRetData(null); - return; - } + const _path = `${pollData.author}/${pollData.permlink}`; + const voteCache = pollVotesCollection[_path]; - const _path = `${pollData.author}/${pollData.permlink}`; - const voteCache = pollVotesCollection[_path]; + const _cData = injectPollVoteCache(pollData, voteCache); - const _cData = injectPollVoteCache(pollData, voteCache); + // check if data follows old schema, migrate if nesseary + if (_cData.poll_voters instanceof Array && !!_cData.poll_voters[0].choice_num) { + _cData.poll_voters = _cData.poll_voters.map((voter) => ({ + ...voter, + choices: [voter.choice_num], + })); + } - //check if data follows old schema, migrate if nesseary - if(_cData.poll_voters instanceof Array && !!_cData.poll_voters[0].choice_num){ - _cData.poll_voters = _cData.poll_voters.map(voter => ({...voter, choices:[voter.choice_num]})) - } - - setRetData(_cData); - }, [pollData]); - - return retData || pollData; -} + setRetData(_cData); + }, [pollData]); + return retData || pollData; +}; const injectPollVoteCache = (data: Poll, voteCache: PollVoteCache) => { - if (!data || !voteCache) { - return data; - } + if (!data || !voteCache) { + return data; + } - const { userHp, choices, username, status } = voteCache; + const { userHp, choices, username, status } = voteCache; - if (status === CacheStatus.FAILED) { - return data; - } + if (status === CacheStatus.FAILED) { + return data; + } + // extract previously votes choices and new choices + const existingVote = data.poll_voters?.find((pv) => pv.name === username); + const previousUserChoices = data.poll_choices?.filter((pc) => + existingVote?.choices.includes(pc.choice_num), + ); + // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain + const selectedChoices = data.poll_choices.filter((pc) => choices.includes(pc.choice_num))!; - //extract previously votes choices and new choices - const existingVote = data.poll_voters?.find((pv) => pv.name === username); - const previousUserChoices = data.poll_choices?.filter((pc) => existingVote?.choices.includes(pc.choice_num)); - const selectedChoices = data.poll_choices?.filter((pc) => choices.includes(pc.choice_num))!!; + // filtered list to separate untoched multiple choice e.g from old [1,2,3] new [3,4,5], removed would be [1, 2] , new would be [4, 5] + const removedChoices = previousUserChoices.filter( + (pc) => !selectedChoices.some((element) => element.choice_num === pc.choice_num), + ); + const newChoices = selectedChoices.filter( + (pc) => !previousUserChoices.some((element) => element.choice_num === pc.choice_num), + ); - //filtered list to separate untoched multiple choice e.g from old [1,2,3] new [3,4,5], removed would be [1, 2] , new would be [4, 5] - const removedChoices = previousUserChoices.filter(pc => !selectedChoices.some(element => element.choice_num === pc.choice_num)); - const newChoices = selectedChoices.filter(pc => !previousUserChoices.some(element => element.choice_num === pc.choice_num)); + // votes that were not affected by new vote + const notTouchedChoices = data.poll_choices?.filter( + (pc) => + ![ + ...removedChoices.map((pc) => pc.choice_num), + ...newChoices.map((pc) => pc.choice_num), + ].includes(pc.choice_num), + ); - //votes that were not affected by new vote - const notTouchedChoices = data.poll_choices?.filter( - (pc) => ![ - ...removedChoices.map(pc => pc.choice_num), - ...newChoices.map(pc => pc.choice_num) - ].includes(pc.choice_num) - ); + const otherVoters = data.poll_voters?.filter((pv) => pv.name !== username) ?? []; - const otherVoters = - data.poll_voters?.filter((pv) => pv.name !== username) ?? []; + let { poll_choices } = data; + poll_choices = [ + ...notTouchedChoices, + ...removedChoices.map((pc) => ({ + ...pc, + votes: { + total_votes: (pc?.votes?.total_votes ?? 0) - 1, + hive_hp: (pc?.votes?.hive_hp ?? 0) - userHp, + hive_hp_incl_proxied: (pc?.votes?.hive_hp ?? 0) - userHp, + }, + })), + ...newChoices.map((pc) => ({ + ...pc, + votes: { + total_votes: (pc?.votes?.total_votes ?? 0) + 1, + hive_hp: (pc?.votes?.hive_hp ?? 0) + userHp, + hive_hp_incl_proxied: (pc?.votes?.hive_hp ?? 0) + userHp, + }, + })), + ] + .filter((el) => !!el) + .sort((a, b) => (a?.choice_num < b?.choice_num ? -1 : 1)) as PollChoice[]; - - let poll_choices = data.poll_choices; - poll_choices = [ - ...notTouchedChoices, - ...removedChoices.map(pc => ({ - ...pc, - votes: { - total_votes: (pc?.votes?.total_votes ?? 0) - 1, - hive_hp: (pc?.votes?.hive_hp ?? 0) - userHp, - hive_hp_incl_proxied: (pc?.votes?.hive_hp ?? 0) - userHp - } - })), - ...newChoices.map((pc => ({ - ...pc, - votes: { - total_votes: (pc?.votes?.total_votes ?? 0) + 1, - hive_hp: (pc?.votes?.hive_hp ?? 0) + userHp, - hive_hp_incl_proxied: (pc?.votes?.hive_hp ?? 0) + userHp - } - }))) - ].filter((el) => !!el).sort(((a, b) => a?.choice_num < b?.choice_num ? -1 : 1)) as PollChoice[] - - - - return { - ...data, - poll_choices, - poll_voters: [ - ...otherVoters, - { name: username, choices } - ] - } as Poll; -} \ No newline at end of file + return { + ...data, + poll_choices, + poll_voters: [...otherVoters, { name: username, choices }], + } as Poll; +}; diff --git a/src/providers/queries/postQueries/reblogQueries.ts b/src/providers/queries/postQueries/reblogQueries.ts index 8e40c0fab..a14473bfd 100644 --- a/src/providers/queries/postQueries/reblogQueries.ts +++ b/src/providers/queries/postQueries/reblogQueries.ts @@ -1,128 +1,112 @@ -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import QUERIES from "../queryKeys"; -import { useAppSelector } from "../../../hooks"; -import { useDispatch } from "react-redux"; -import { setRcOffer, toastNotification } from "../../../redux/actions/uiAction"; -import { useIntl } from "react-intl"; -import { getPostReblogs, reblog } from "../../hive/dhive"; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useDispatch } from 'react-redux'; +import { useIntl } from 'react-intl'; import { get } from 'lodash'; -import { PointActivityIds } from "../../ecency/ecency.types"; -import { useUserActivityMutation } from "../pointQueries"; - - +import QUERIES from '../queryKeys'; +import { useAppSelector } from '../../../hooks'; +import { setRcOffer, toastNotification } from '../../../redux/actions/uiAction'; +import { getPostReblogs, reblog } from '../../hive/dhive'; +import { PointActivityIds } from '../../ecency/ecency.types'; +import { useUserActivityMutation } from '../pointQueries'; /** hook used to return post poll */ export const useGetReblogsQuery = (author: string, permlink: string) => { + const query = useQuery( + [QUERIES.POST.GET_REBLOGS, author, permlink], + async () => { + if (!author || !permlink) { + return null; + } - - const query = useQuery( - [QUERIES.POST.GET_REBLOGS, author, permlink], - async () => { - if (!author || !permlink) { - return null; - } - - try { - const reblogs = await getPostReblogs(author, permlink); - if (!reblogs) { - new Error('Reblog data unavailable'); - } - - return reblogs - } catch (err) { - console.warn('Failed to get post', err); - return [] - } - }, - { - initialData: [], - cacheTime: 30 * 60 * 1000, // keeps cache for 30 minutes - }, - ); - - return query; -}; - - - - -export function useReblogMutation(author: string, permlink: string) { - // const { activeUser } = useMappedStore(); - const intl = useIntl(); - const dispatch = useDispatch(); - const queryClient = useQueryClient() - const currentAccount = useAppSelector(state => state.account.currentAccount); - const pinHash = useAppSelector(state => state.application.pin); - - const userActivityMutation = useUserActivityMutation(); - - - return useMutation({ - mutationKey: [QUERIES.POST.REBLOG_POST], - mutationFn: async ({ undo }:{undo:boolean}) => { - - if (!author || !permlink || !currentAccount) { - throw new Error("Not enough data to reblog post") - } - - const resp = await reblog(currentAccount, pinHash, author, permlink, undo) - - // track user activity points ty=130 - userActivityMutation.mutate({ - pointsTy: PointActivityIds.REBLOG, - transactionId: resp.id, - - }); - - return resp; - - }, - retry: 3, - - onSuccess: (resp, vars) => { - console.log("reblog response", resp); - //update poll cache here - queryClient.setQueryData["data"]>( - [QUERIES.POST.GET_REBLOGS, author, permlink], - (data) => { - if (!data || !resp) { - return data; - } - - const _curIndex = data.indexOf(currentAccount.username) - if(vars.undo){ - data.splice(_curIndex, 1) - } - else if (_curIndex < 0) { - data.splice(0, 0, currentAccount.username); - } - - return [...data] as ReturnType["data"]; - } - ) - }, - onError: (error) => { - if (String(get(error, 'jse_shortmsg', '')).indexOf('has already reblogged') > -1) { - dispatch( - toastNotification( - intl.formatMessage({ - id: 'alert.already_rebloged', - }), - ), - ); - } else { - if (error && error.jse_shortmsg.split(': ')[1].includes('wait to transact')) { - // when RC is not enough, offer boosting account - dispatch(setRcOffer(true)); - } else { - // when other errors - dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' }))); - } - } + try { + const reblogs = await getPostReblogs(author, permlink); + if (!reblogs) { + new Error('Reblog data unavailable'); } + return reblogs; + } catch (err) { + console.warn('Failed to get post', err); + return []; + } + }, + { + initialData: [], + cacheTime: 30 * 60 * 1000, // keeps cache for 30 minutes + }, + ); - }); + return query; +}; + +export function useReblogMutation(author: string, permlink: string) { + // const { activeUser } = useMappedStore(); + const intl = useIntl(); + const dispatch = useDispatch(); + const queryClient = useQueryClient(); + const currentAccount = useAppSelector((state) => state.account.currentAccount); + const pinHash = useAppSelector((state) => state.application.pin); + + const userActivityMutation = useUserActivityMutation(); + + return useMutation({ + mutationKey: [QUERIES.POST.REBLOG_POST], + mutationFn: async ({ undo }: { undo: boolean }) => { + if (!author || !permlink || !currentAccount) { + throw new Error('Not enough data to reblog post'); + } + + const resp = await reblog(currentAccount, pinHash, author, permlink, undo); + + // track user activity points ty=130 + userActivityMutation.mutate({ + pointsTy: PointActivityIds.REBLOG, + transactionId: resp.id, + }); + + return resp; + }, + retry: 3, + + onSuccess: (resp, vars) => { + console.log('reblog response', resp); + // update poll cache here + queryClient.setQueryData['data']>( + [QUERIES.POST.GET_REBLOGS, author, permlink], + (data) => { + if (!data || !resp) { + return data; + } + + const _curIndex = data.indexOf(currentAccount.username); + if (vars.undo) { + data.splice(_curIndex, 1); + } else if (_curIndex < 0) { + data.splice(0, 0, currentAccount.username); + } + + return [...data] as ReturnType['data']; + }, + ); + }, + onError: (error) => { + if (String(get(error, 'jse_shortmsg', '')).indexOf('has already reblogged') > -1) { + dispatch( + toastNotification( + intl.formatMessage({ + id: 'alert.already_rebloged', + }), + ), + ); + } else { + if (error && error.jse_shortmsg.split(': ')[1].includes('wait to transact')) { + // when RC is not enough, offer boosting account + dispatch(setRcOffer(true)); + } else { + // when other errors + dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' }))); + } + } + }, + }); } - - diff --git a/src/providers/queries/postQueries/wavesQueries.ts b/src/providers/queries/postQueries/wavesQueries.ts index fde7f1c38..df9dd62e3 100644 --- a/src/providers/queries/postQueries/wavesQueries.ts +++ b/src/providers/queries/postQueries/wavesQueries.ts @@ -1,4 +1,10 @@ -import { QueryKey, UseMutationOptions, useMutation, useQueries, useQueryClient } from '@tanstack/react-query'; +import { + QueryKey, + UseMutationOptions, + useMutation, + useQueries, + useQueryClient, +} from '@tanstack/react-query'; import { useEffect, useMemo, useRef, useState } from 'react'; import { unionBy, isArray } from 'lodash'; @@ -169,7 +175,9 @@ export const useWavesQuery = (host: string) => { throw new Error('Failed to parse waves'); } - _threadedComments.filter((item) => item.net_rshares >= 0 && !item.stats?.gray && !item.stats.hide); + _threadedComments.filter( + (item) => item.net_rshares >= 0 && !item.stats?.gray && !item.stats.hide, + ); _threadedComments.sort((a, b) => (new Date(a.created) > new Date(b.created) ? -1 : 1)); _threadedComments.forEach((item) => { wavesIndexCollection.current[`${item.author}/${item.permlink}`] = pagePermlink; @@ -181,14 +189,12 @@ export const useWavesQuery = (host: string) => { }; const _fetchNextPage = () => { - if (!_lastItem || _lastItem.isFetching) { return; } const _nextPagePermlink = permlinksBucket[activePermlinks.length]; - if (_nextPagePermlink && !activePermlinks.includes(_nextPagePermlink)) { console.log('updating next page permlink', _nextPagePermlink); activePermlinks.push(_nextPagePermlink); @@ -211,23 +217,22 @@ export const useWavesQuery = (host: string) => { const _data = unionBy(...wavesQueries.map((query) => query.data), 'url'); const _filteredData = useMemo( - - () => _data.filter((post) => - { + () => + _data.filter((post) => { let _status = true; - //discard wave if author is muted + // discard wave if author is muted if (isArray(mutes) && mutes.indexOf(post?.author) > 0) { _status = false; - } - - //discard if wave is downvoted or marked gray - else if (post.net_rshares < 0 || post.stats?.gray || post.stats?.hide) { - _status = false } - - return _status + + // discard if wave is downvoted or marked gray + else if (post.net_rshares < 0 || post.stats?.gray || post.stats?.hide) { + _status = false; + } + + return _status; }), - // (isArray(mutes) ? mutes.indexOf(post?.author) < 0 : true)), + // (isArray(mutes) ? mutes.indexOf(post?.author) < 0 : true)), [mutes, _data], ); @@ -296,16 +301,19 @@ export const usePublishWaveMutation = () => { const _host = cacheCommentData.parent_author; // update query data - const containerQueriesData: [QueryKey, string[] | undefined][] = queryClient.getQueriesData([QUERIES.WAVES.INITIAL_CONTAINERS, _host]); + const containerQueriesData: [QueryKey, string[] | undefined][] = queryClient.getQueriesData([ + QUERIES.WAVES.INITIAL_CONTAINERS, + _host, + ]); if (!containerQueriesData[0][1]) { return; } - //get query data of first waves container + // get query data of first waves container const _containerKey: string = containerQueriesData[0][1][0]; - const _queryKey = [QUERIES.WAVES.GET, _host, _containerKey, 0] - const queryData: any[] | undefined = queryClient.getQueryData(_queryKey) + const _queryKey = [QUERIES.WAVES.GET, _host, _containerKey, 0]; + const queryData: any[] | undefined = queryClient.getQueryData(_queryKey); console.log('query data', queryData); diff --git a/src/providers/queries/queryKeys.ts b/src/providers/queries/queryKeys.ts index 3ac50c877..475c19273 100644 --- a/src/providers/queries/queryKeys.ts +++ b/src/providers/queries/queryKeys.ts @@ -28,9 +28,9 @@ const QUERIES = { GET: 'QUERY_GET_POST', GET_POLL: 'QUERY_GET_POLL', GET_DISCUSSION: 'QUERY_GET_DISCUSSION', - SIGN_POLL_VOTE:"SIGN_POLL_VOTE", - GET_REBLOGS:"GET_REBLOGS", - REBLOG_POST:"REBLOG_POST" + SIGN_POLL_VOTE: 'SIGN_POLL_VOTE', + GET_REBLOGS: 'GET_REBLOGS', + REBLOG_POST: 'REBLOG_POST', }, LEADERBOARD: { GET: 'QUERY_GET_LEADERBOARD', diff --git a/src/providers/queries/walletQueries/walletQueries.ts b/src/providers/queries/walletQueries/walletQueries.ts index 78b678db5..0f7f420a2 100644 --- a/src/providers/queries/walletQueries/walletQueries.ts +++ b/src/providers/queries/walletQueries/walletQueries.ts @@ -297,7 +297,7 @@ export const useActivitiesQuery = (assetId: string) => { })), }); - const _lastItem = queries[queries.length - 1] + const _lastItem = queries[queries.length - 1]; const _refresh = async () => { setIsRefreshing(true); @@ -336,7 +336,6 @@ export const useActivitiesQuery = (assetId: string) => { return unionBy(..._dataArrs, 'trxIndex'); }, [_lastItem?.data]); - return { data: _data, isRefreshing, diff --git a/src/redux/reducers/cacheReducer.ts b/src/redux/reducers/cacheReducer.ts index 3c81f4d97..2b4fc3ff7 100644 --- a/src/redux/reducers/cacheReducer.ts +++ b/src/redux/reducers/cacheReducer.ts @@ -14,7 +14,7 @@ import { UPDATE_CLAIM_CACHE, DELETE_CLAIM_CACHE_ENTRY, UPDATE_ANNOUNCEMENTS_META, - UPDATE_POLL_VOTE_CACHE + UPDATE_POLL_VOTE_CACHE, } from '../constants/constants'; export enum CacheStatus { @@ -39,7 +39,7 @@ export interface VoteCache { export interface PollVoteCache { choices: number[]; - userHp:number; + userHp: number; username: string; votedAt: number; expiresAt: number; @@ -169,7 +169,10 @@ const cacheReducer = (state = initialState, action) => { if (!state.pollVotesCollection) { state.pollVotesCollection = {}; } - state.pollVotesCollection = { ...state.pollVotesCollection, [payload.postPath]: payload.pollVote }; + state.pollVotesCollection = { + ...state.pollVotesCollection, + [payload.postPath]: payload.pollVote, + }; return { ...state, // spread operator in requried here, otherwise persist do not register change lastUpdate: { diff --git a/src/redux/store/store.ts b/src/redux/store/store.ts index 24966be8e..926489843 100644 --- a/src/redux/store/store.ts +++ b/src/redux/store/store.ts @@ -52,11 +52,10 @@ let enhancers; if (__DEV__) { // eslint-disable-next-line @typescript-eslint/no-var-requires const createDebugger = require('redux-flipper').default; + // eslint-disable-next-line @typescript-eslint/no-var-requires const Reactotron = require('../../../reactotron-config').default; middleware.push(createDebugger()); - enhancers = compose( - applyMiddleware(...middleware), - Reactotron.createEnhancer()); + enhancers = compose(applyMiddleware(...middleware), Reactotron.createEnhancer()); } else { enhancers = applyMiddleware(...middleware); } diff --git a/src/screens/accountList/screen/accountList.tsx b/src/screens/accountList/screen/accountList.tsx index d7ccb42af..b57d4bf8b 100644 --- a/src/screens/accountList/screen/accountList.tsx +++ b/src/screens/accountList/screen/accountList.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React from 'react'; import { FlatList, SafeAreaView } from 'react-native'; import { useIntl } from 'react-intl'; @@ -13,51 +13,49 @@ import AccountListContainer from '../../../containers/accountListContainer'; import globalStyles from '../../../globalStyles'; import { getTimeFromNow } from '../../../utils/time'; - - const AccountList = ({ route }) => { - const intl = useIntl(); + const intl = useIntl(); - const users = route.params?.users || []; + const users = route.params?.users || []; - const headerTitle = route.params?.title || intl.formatMessage({ - id: 'account_list.title', + const headerTitle = + route.params?.title || + intl.formatMessage({ + id: 'account_list.title', }); - - return ( - - {({ data, filterResult, handleSearch, handleOnUserPress }) => ( - - handleSearch(text, 'account')} - /> - item.account} - removeClippedSubviews={false} - renderItem={({ item, index }) => renderUserListItem(item, index, handleOnUserPress)} - /> - - )} - - ); + return ( + + {({ data, filterResult, handleSearch, handleOnUserPress }) => ( + + handleSearch(text, 'account')} + /> + item.account} + removeClippedSubviews={false} + renderItem={({ item, index }) => renderUserListItem(item, index, handleOnUserPress)} + /> + + )} + + ); }; export default gestureHandlerRootHOC(AccountList); - const renderUserListItem = (item, index, handleOnUserPress) => { - return ( - handleOnUserPress(item.account)} - isClickable - /> - ); -}; \ No newline at end of file + return ( + handleOnUserPress(item.account)} + isClickable + /> + ); +}; diff --git a/src/screens/assetDetails/screen/assetDetailsScreen.tsx b/src/screens/assetDetails/screen/assetDetailsScreen.tsx index 503f0b77b..594fb2c23 100644 --- a/src/screens/assetDetails/screen/assetDetailsScreen.tsx +++ b/src/screens/assetDetails/screen/assetDetailsScreen.tsx @@ -47,7 +47,7 @@ const AssetDetailsScreen = ({ navigation, route }: AssetDetailsScreenProps) => { const quote: QuoteItem = useAppSelector((state) => state.wallet.quotes ? state.wallet.quotes[coinId] : {}, ); - const username = useAppSelector(state => state.wallet.username); + const username = useAppSelector((state) => state.wallet.username); const isPinCodeOpen = useAppSelector((state) => state.application.isPinCodeOpen); // state @@ -154,7 +154,8 @@ const AssetDetailsScreen = ({ navigation, route }: AssetDetailsScreenProps) => { if (baseActivity) { navigateParams = { ...navigateParams, - referredUsername: baseActivity.receiver !== username ? baseActivity.receiver : baseActivity.sender, + referredUsername: + baseActivity.receiver !== username ? baseActivity.receiver : baseActivity.sender, initialAmount: `${Math.abs(parseAsset(baseActivity.value.trim()).amount)}`, initialMemo: baseActivity.memo, }; diff --git a/src/screens/feed/screen/feedScreen.tsx b/src/screens/feed/screen/feedScreen.tsx index abdaacd4d..5aebf412d 100644 --- a/src/screens/feed/screen/feedScreen.tsx +++ b/src/screens/feed/screen/feedScreen.tsx @@ -4,7 +4,7 @@ import get from 'lodash/get'; // Components import { gestureHandlerRootHOC } from 'react-native-gesture-handler'; -import { EmptyScreen, Header, PostCard, PostCardPlaceHolder, PostPlaceHolder, TabbedPosts } from '../../../components'; +import { Header, TabbedPosts } from '../../../components'; // Container import { AccountContainer } from '../../../containers'; @@ -15,8 +15,6 @@ import styles from './feedStyles'; import { getDefaultFilters, getFilterMap } from '../../../constants/options/filters'; import { useAppSelector } from '../../../hooks'; -import LaunchScreen from '../../launch/screen/launchScreen'; -import { CommentPlaceHolder } from '../../../components/basicUIElements'; const FeedScreen = () => { const mainTabs = useAppSelector( diff --git a/src/screens/login/screen/loginScreen.js b/src/screens/login/screen/loginScreen.js index 38b7384b4..cfd77d3e2 100644 --- a/src/screens/login/screen/loginScreen.js +++ b/src/screens/login/screen/loginScreen.js @@ -123,78 +123,78 @@ const LoginScreen = ({ }} /> - - _checkUsernameIsValid(username)} - /> - - - handleOnPressLogin(username, password)} - iconName="person" - iconColor="white" - text={intl.formatMessage({ - id: 'login.login', - })} - textStyle={styles.mainBtnText} - isDisable={!isUsernameValid || password.length < 2 || username.length < 2} - isLoading={isLoading} - wrapperStyle={styles.loginBtnWrapper} - bodyWrapperStyle={styles.loginBtnBodyWrapper} - height={50} - iconStyle={styles.loginBtnIconStyle} - /> - - _handleOnModalToggle()} - renderIcon={_renderHiveicon()} - text={intl.formatMessage({ - id: 'login.login_with_hs', - })} - textStyle={styles.hsLoginBtnText} - wrapperStyle={styles.loginBtnWrapper} - bodyWrapperStyle={styles.loginBtnBodyWrapper} - height={48} - style={styles.hsLoginBtnStyle} - /> - + + _checkUsernameIsValid(username)} + /> + + + handleOnPressLogin(username, password)} + iconName="person" + iconColor="white" + text={intl.formatMessage({ + id: 'login.login', + })} + textStyle={styles.mainBtnText} + isDisable={!isUsernameValid || password.length < 2 || username.length < 2} + isLoading={isLoading} + wrapperStyle={styles.loginBtnWrapper} + bodyWrapperStyle={styles.loginBtnBodyWrapper} + height={50} + iconStyle={styles.loginBtnIconStyle} + /> + + _handleOnModalToggle()} + renderIcon={_renderHiveicon()} + text={intl.formatMessage({ + id: 'login.login_with_hs', + })} + textStyle={styles.hsLoginBtnText} + wrapperStyle={styles.loginBtnWrapper} + bodyWrapperStyle={styles.loginBtnBodyWrapper} + height={48} + style={styles.hsLoginBtnStyle} + /> + {intl.formatMessage({ @@ -207,8 +207,8 @@ const LoginScreen = ({ })} - - + + { return ( @@ -40,15 +39,12 @@ const ReblogScreen = ({ route }) => { const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn); const isDarkTheme = useAppSelector((state) => state.application.isDarkTheme); - const [isReblogging, setIsReblogging] = useState(false); - const reblogsQuery = reblogQueries.useGetReblogsQuery(author, permlink); const reblogMutation = reblogQueries.useReblogMutation(author, permlink); - - //map reblogs data for account list + // map reblogs data for account list const { reblogs, deleteEnabled } = useMemo(() => { let _reblogs: any[] = []; let _deleteEnabled = false; @@ -58,18 +54,18 @@ const ReblogScreen = ({ route }) => { } return { reblogs: _reblogs, - deleteEnabled: _deleteEnabled - } - }, [reblogsQuery.data?.length]) - - + deleteEnabled: _deleteEnabled, + }; + }, [reblogsQuery.data?.length]); const headerTitle = intl.formatMessage({ id: 'reblog.title', }); - const _actionBtnTitle = intl.formatMessage({ id: deleteEnabled ? 'reblog.reblog_delete' : 'reblog.reblog_post' }) - const _actionBtnIcon = deleteEnabled ? "repeat-off" : "repeat"; + const _actionBtnTitle = intl.formatMessage({ + id: deleteEnabled ? 'reblog.reblog_delete' : 'reblog.reblog_post', + }); + const _actionBtnIcon = deleteEnabled ? 'repeat-off' : 'repeat'; const _handleReblogPost = async () => { if (!isLoggedIn) { @@ -79,15 +75,12 @@ const ReblogScreen = ({ route }) => { if (isLoggedIn) { setIsReblogging(true); - await reblogMutation.mutateAsync({ undo:deleteEnabled }); + await reblogMutation.mutateAsync({ undo: deleteEnabled }); setIsReblogging(false); } - - } - + }; const _renderFloatingButton = () => { - return ( { ); }; - - - return ( {({ data, filterResult, handleSearch, handleOnUserPress }) => ( - - {/* Your content goes here */} { data={filterResult || data} keyExtractor={(item) => item.account} removeClippedSubviews={false} - renderItem={({ item, index }) => - renderUserListItem(item, index, handleOnUserPress) - } + renderItem={({ item, index }) => renderUserListItem(item, index, handleOnUserPress)} refreshControl={ { tintColor={!isDarkTheme ? '#357ce6' : '#96c0ff'} titleColor="#fff" colors={['#fff']} - />} + /> + } /> {_renderFloatingButton()} - - ) - } - + )} + ); }; diff --git a/src/screens/reblogs/styles/reblogScreen.styles.ts b/src/screens/reblogs/styles/reblogScreen.styles.ts index 62f422a3e..92b7c54e8 100644 --- a/src/screens/reblogs/styles/reblogScreen.styles.ts +++ b/src/screens/reblogs/styles/reblogScreen.styles.ts @@ -1,9 +1,9 @@ import EStyleSheet from 'react-native-extended-stylesheet'; export default EStyleSheet.create({ - floatingContainer: { - position: 'absolute', - right: 16, - bottom: 56, - } -}) \ No newline at end of file + floatingContainer: { + position: 'absolute', + right: 16, + bottom: 56, + }, +}); diff --git a/src/screens/redeem/screen/redeemScreen.tsx b/src/screens/redeem/screen/redeemScreen.tsx index 1b86516b0..66ae2bb37 100644 --- a/src/screens/redeem/screen/redeemScreen.tsx +++ b/src/screens/redeem/screen/redeemScreen.tsx @@ -1,12 +1,12 @@ -import React, { PureComponent, Fragment } from 'react'; +import React, { PureComponent } from 'react'; import { StyleSheet, View } from 'react-native'; import { gestureHandlerRootHOC } from 'react-native-gesture-handler'; +import Animated, { SlideInRight } from 'react-native-reanimated'; import { RedeemContainer, PointsContainer } from '../../../containers'; import { Promote, PostBoost } from '../../../components'; import BoostPlus from '../children/boostPlus'; import styles from '../styles/redeemScreen.styles'; -import Animated, { Easing, SlideInDown, SlideInRight, SlideInUp } from 'react-native-reanimated'; class RedeemScreen extends PureComponent { constructor(props) { @@ -34,54 +34,59 @@ class RedeemScreen extends PureComponent { }) => ( {({ handleOnSubmit, SCPath, isSCModalOpen, handleOnSCModalClose, isLoading }) => { - let _retView = null; switch (redeemType) { case 'promote': - _retView = + _retView = ( + + ); break; case 'boost': - _retView = + _retView = ( + + ); break; case 'boost_plus': - _retView = + _retView = ( + + ); break; } @@ -89,7 +94,7 @@ class RedeemScreen extends PureComponent { {_retView} - ) + ); }} )} diff --git a/src/screens/redeem/styles/redeemScreen.styles.ts b/src/screens/redeem/styles/redeemScreen.styles.ts index 612137003..200facecd 100644 --- a/src/screens/redeem/styles/redeemScreen.styles.ts +++ b/src/screens/redeem/styles/redeemScreen.styles.ts @@ -1,8 +1,8 @@ import EStyleSheet from 'react-native-extended-stylesheet'; export default EStyleSheet.create({ - container: { - flex: 1, - backgroundColor: '$primaryBackgroundColor' - }, -}) \ No newline at end of file + container: { + flex: 1, + backgroundColor: '$primaryBackgroundColor', + }, +}); diff --git a/src/screens/wallet/children/assetCard.tsx b/src/screens/wallet/children/assetCard.tsx index 76423f242..5afe993a0 100644 --- a/src/screens/wallet/children/assetCard.tsx +++ b/src/screens/wallet/children/assetCard.tsx @@ -165,9 +165,9 @@ export const AssetCard = ({ chartData.length > 0 ? ( {`${currencySymbol} ${currentValue.toFixed(2)}`} - 0 ? styles.textDiffPositive : styles.textDiffNegative}>{`${ - changePercent >= 0 ? '+' : '' - }${changePercent.toFixed(1)}%`} + 0 ? styles.textDiffPositive : styles.textDiffNegative}> + {`${changePercent >= 0 ? '+' : ''}${changePercent.toFixed(1)}%`} + ) : ( diff --git a/src/screens/welcome/screen/WelcomeScreen.tsx b/src/screens/welcome/screen/WelcomeScreen.tsx index 998296691..30fc971f8 100644 --- a/src/screens/welcome/screen/WelcomeScreen.tsx +++ b/src/screens/welcome/screen/WelcomeScreen.tsx @@ -17,10 +17,9 @@ import LaunchScreen from '../../launch'; import styles from '../children/WelcomeScreenStyles'; const WelcomeScreen = () => { - - //NOTE: I have no logical explanation for this, but only this solution - //makes sure first screen is renderd from stack, otherwise it's always - //blank white screen no matter what we try. + // NOTE: I have no logical explanation for this, but only this solution + // makes sure first screen is renderd from stack, otherwise it's always + // blank white screen no matter what we try. require('@esteemapp/dhive'); const intl = useIntl(); diff --git a/src/utils/migrationHelpers.ts b/src/utils/migrationHelpers.ts index c8ae19c53..d16e97022 100644 --- a/src/utils/migrationHelpers.ts +++ b/src/utils/migrationHelpers.ts @@ -303,7 +303,7 @@ const reduxMigrations = { 8: (state) => { state.cache.pollVotesCollection = {}; return state; - } + }, }; export default { diff --git a/src/utils/postParser.tsx b/src/utils/postParser.tsx index 55e6f0814..56cd7024a 100644 --- a/src/utils/postParser.tsx +++ b/src/utils/postParser.tsx @@ -50,7 +50,7 @@ export const parsePost = ( // extract cover image and thumbnail from post body post.image = catchPostImage(post, 600, 500, webp ? 'webp' : 'match'); - post.thumbnail = catchPostImage(post, 10, 7, webp ? 'webp' : 'match'); + post.thumbnail = catchPostImage(post, 10, 7, webp ? 'webp' : 'match'); // find and inject thumbnail ratio if (post.json_metadata.image_ratios) { diff --git a/src/utils/time.js b/src/utils/time.js index 98fc0879d..9a66e6f3f 100644 --- a/src/utils/time.js +++ b/src/utils/time.js @@ -87,7 +87,6 @@ export const getTimeFromNow = (value, isWithoutUtc) => { return moment.utc(value).fromNow(); }; - export const getDaysPassedSince = (value) => { if (!value) { return 0; @@ -95,7 +94,7 @@ export const getDaysPassedSince = (value) => { const created = moment(value); return moment().diff(created, 'days'); - } +}; export const getFormatedCreatedDate = (value) => { if (!value) { diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts index a8ba54f82..ebcb182ba 100644 --- a/src/utils/wallet.ts +++ b/src/utils/wallet.ts @@ -248,7 +248,7 @@ export const groomingEngineHistory = (transaction: HistoryItem): CoinActivity | receiver: to, icon: 'local-activity', expires: '', - repeatable : RepeatableTransfers[operation] || false + repeatable: RepeatableTransfers[operation] || false, }; switch (result.textKey) { @@ -1113,7 +1113,7 @@ export const groomingPointsTransactionData = (transaction) => { result.trxIndex = transaction.id; result.repeatable = RepeatableTransfers[transaction.textKey] || false; result.sender = transaction.sender; - result.receiver = transaction.receiver; + result.receiver = transaction.receiver; return result; }; diff --git a/yarn.lock b/yarn.lock index 7f4607b3b..8feac6247 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2759,30 +2759,6 @@ prompts "^2.4.2" semver "^7.5.2" -"@react-native-community/eslint-config@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@react-native-community/eslint-config/-/eslint-config-2.0.0.tgz#35dcc529a274803fc4e0a6b3d6c274551fb91774" - integrity sha512-vHaMMfvMp9BWCQQ0lNIXibOJTcXIbYUQ8dSUsMOsrXgVkeVQJj88OwrKS00rQyqwMaC4/a6HuDiFzYUkGKOpVg== - dependencies: - "@react-native-community/eslint-plugin" "^1.1.0" - "@typescript-eslint/eslint-plugin" "^3.1.0" - "@typescript-eslint/parser" "^3.1.0" - babel-eslint "^10.1.0" - eslint-config-prettier "^6.10.1" - eslint-plugin-eslint-comments "^3.1.2" - eslint-plugin-flowtype "2.50.3" - eslint-plugin-jest "22.4.1" - eslint-plugin-prettier "3.1.2" - eslint-plugin-react "^7.20.0" - eslint-plugin-react-hooks "^4.0.4" - eslint-plugin-react-native "^3.8.1" - prettier "^2.0.2" - -"@react-native-community/eslint-plugin@^1.1.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.3.0.tgz#9e558170c106bbafaa1ef502bd8e6d4651012bf9" - integrity sha512-+zDZ20NUnSWghj7Ku5aFphMzuM9JulqCW+aPXT6IfIXFbb8tzYTTOSeRFOtuekJ99ibW2fUCSsjuKNlwDIbHFg== - "@react-native-community/netinfo@^11.1.1": version "11.2.1" resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-11.2.1.tgz#177f5409f2ac41fd51ede6e4994307bb0edb2178" @@ -3507,18 +3483,6 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^3.1.0": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz#7e061338a1383f59edc204c605899f93dc2e2c8f" - integrity sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ== - dependencies: - "@typescript-eslint/experimental-utils" "3.10.1" - debug "^4.1.1" - functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - "@typescript-eslint/eslint-plugin@^5.57.1": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz#aeef0328d172b9e37d9bab6dbc13b87ed88977db" @@ -3544,17 +3508,6 @@ "@typescript-eslint/typescript-estree" "1.13.0" eslint-scope "^4.0.0" -"@typescript-eslint/experimental-utils@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" - integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - "@typescript-eslint/parser@^1.10.2": version "1.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.13.0.tgz#61ac7811ea52791c47dc9fd4dd4a184fae9ac355" @@ -3565,17 +3518,6 @@ "@typescript-eslint/typescript-estree" "1.13.0" eslint-visitor-keys "^1.0.0" -"@typescript-eslint/parser@^3.1.0": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" - integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.10.1" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-visitor-keys "^1.1.0" - "@typescript-eslint/parser@^5.57.1": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7" @@ -3604,11 +3546,6 @@ debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" - integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== - "@typescript-eslint/types@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" @@ -3622,20 +3559,6 @@ lodash.unescape "4.0.1" semver "5.5.0" -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b" @@ -3663,13 +3586,6 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== - dependencies: - eslint-visitor-keys "^1.1.0" - "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e" @@ -4225,7 +4141,7 @@ babel-core@^7.0.0-bridge.0: resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== -babel-eslint@^10.0.1, babel-eslint@^10.1.0: +babel-eslint@^10.0.1: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== @@ -6258,7 +6174,7 @@ eslint-config-airbnb@^17.1.0: object.assign "^4.1.0" object.entries "^1.1.0" -eslint-config-prettier@^6.10.1, eslint-config-prettier@^6.7.0: +eslint-config-prettier@^6.7.0: version "6.15.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== @@ -6286,7 +6202,7 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" -eslint-plugin-eslint-comments@^3.1.1, eslint-plugin-eslint-comments@^3.1.2, eslint-plugin-eslint-comments@^3.2.0: +eslint-plugin-eslint-comments@^3.1.1, eslint-plugin-eslint-comments@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz#9e1cd7b4413526abb313933071d7aba05ca12ffa" integrity sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ== @@ -6294,13 +6210,6 @@ eslint-plugin-eslint-comments@^3.1.1, eslint-plugin-eslint-comments@^3.1.2, esli escape-string-regexp "^1.0.5" ignore "^5.0.5" -eslint-plugin-flowtype@2.50.3: - version "2.50.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.3.tgz#61379d6dce1d010370acd6681740fd913d68175f" - integrity sha512-X+AoKVOr7Re0ko/yEXyM5SSZ0tazc6ffdIOocp2fFUlWoDt7DV0Bz99mngOkAFLOAWjqRA5jPwqUCbrx13XoxQ== - dependencies: - lodash "^4.17.10" - eslint-plugin-ft-flow@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz#3b3c113c41902bcbacf0e22b536debcfc3c819e8" @@ -6332,11 +6241,6 @@ eslint-plugin-import@^2.17.2: semver "^6.3.1" tsconfig-paths "^3.14.2" -eslint-plugin-jest@22.4.1: - version "22.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.4.1.tgz#a5fd6f7a2a41388d16f527073b778013c5189a9c" - integrity sha512-gcLfn6P2PrFAVx3AobaOzlIEevpAEf9chTpFZz7bYfc7pz8XRv7vuKTIE4hxPKZSha6XWKKplDQ0x9Pq8xX2mg== - eslint-plugin-jest@^22.5.1: version "22.21.0" resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.21.0.tgz#8137294645866636160487d9764224b9a43e2eb1" @@ -6373,13 +6277,6 @@ eslint-plugin-jsx-a11y@^6.2.1: object.entries "^1.1.7" object.fromentries "^2.0.7" -eslint-plugin-prettier@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" - integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== - dependencies: - prettier-linter-helpers "^1.0.0" - eslint-plugin-prettier@^3.1.1: version "3.4.1" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" @@ -6399,7 +6296,7 @@ eslint-plugin-react-hooks@^2.3.0: resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.5.1.tgz#4ef5930592588ce171abeb26f400c7fbcbc23cd0" integrity sha512-Y2c4b55R+6ZzwtTppKwSmK/Kar8AdLiC2f9NADCuxbcTgPPg41Gyqa6b9GppgXSvCtkRw43ZE86CT5sejKC6/g== -eslint-plugin-react-hooks@^4.0.4, eslint-plugin-react-hooks@^4.6.0: +eslint-plugin-react-hooks@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== @@ -6409,7 +6306,7 @@ eslint-plugin-react-native-globals@^0.1.1: resolved "https://registry.yarnpkg.com/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz#ee1348bc2ceb912303ce6bdbd22e2f045ea86ea2" integrity sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g== -eslint-plugin-react-native@^3.7.0, eslint-plugin-react-native@^3.8.1: +eslint-plugin-react-native@^3.7.0: version "3.11.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-native/-/eslint-plugin-react-native-3.11.0.tgz#c73b0886abb397867e5e6689d3a6a418682e6bac" integrity sha512-7F3OTwrtQPfPFd+VygqKA2VZ0f2fz0M4gJmry/TRE18JBb94/OtMxwbL7Oqwu7FGyrdeIOWnXQbBAveMcSTZIA== @@ -6424,7 +6321,7 @@ eslint-plugin-react-native@^4.0.0: dependencies: eslint-plugin-react-native-globals "^0.1.1" -eslint-plugin-react@^7.13.0, eslint-plugin-react@^7.20.0, eslint-plugin-react@^7.30.1: +eslint-plugin-react@^7.13.0, eslint-plugin-react@^7.30.1: version "7.33.2" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== @@ -6446,7 +6343,7 @@ eslint-plugin-react@^7.13.0, eslint-plugin-react@^7.20.0, eslint-plugin-react@^7 semver "^6.3.1" string.prototype.matchall "^4.0.8" -eslint-scope@5.1.1, eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -6485,13 +6382,6 @@ eslint-utils@^1.3.1: dependencies: eslint-visitor-keys "^1.1.0" -eslint-utils@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" @@ -9510,7 +9400,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@>4.17.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5: +lodash@>4.17.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -11030,7 +10920,7 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@2.8.8, prettier@^2.0.2: +prettier@2.8.8: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== @@ -12214,11 +12104,6 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpp@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - regexpu-core@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" @@ -12584,7 +12469,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: +semver@^7.0.0, semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -13749,7 +13634,7 @@ tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tsutils@^3.17.1, tsutils@^3.21.0: +tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==