Skip to content

Commit

Permalink
Show hotspot location in list and detail screen.
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewcarlreetz committed Sep 15, 2023
1 parent ea4b51a commit 999be0d
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 16,220 deletions.
38 changes: 19 additions & 19 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ PODS:
- hermes-engine/Pre-built (= 0.71.5)
- hermes-engine/Pre-built (0.71.5)
- libevent (2.1.12)
- MapboxCommon (23.5.0)
- MapboxCoreMaps (10.13.1):
- MapboxCommon (~> 23.5)
- MapboxMaps (10.13.1):
- MapboxCommon (= 23.5.0)
- MapboxCoreMaps (= 10.13.1)
- MapboxCommon (23.7.0)
- MapboxCoreMaps (10.15.0):
- MapboxCommon (~> 23.7)
- MapboxMaps (10.15.0):
- MapboxCommon (= 23.7.0)
- MapboxCoreMaps (= 10.15.0)
- MapboxMobileEvents (= 1.0.10)
- Turf (~> 2.0)
- MapboxMobileEvents (1.0.10)
Expand Down Expand Up @@ -486,14 +486,14 @@ PODS:
- React
- RNLocalize (2.2.3):
- React-Core
- rnmapbox-maps (10.0.7-rc.0):
- MapboxMaps (~> 10.13.1)
- rnmapbox-maps (10.0.14):
- MapboxMaps (~> 10.15.0)
- React
- React-Core
- rnmapbox-maps/DynamicLibrary (= 10.0.7-rc.0)
- rnmapbox-maps/DynamicLibrary (= 10.0.14)
- Turf
- rnmapbox-maps/DynamicLibrary (10.0.7-rc.0):
- MapboxMaps (~> 10.13.1)
- rnmapbox-maps/DynamicLibrary (10.0.14):
- MapboxMaps (~> 10.15.0)
- React
- React-Core
- Turf
Expand Down Expand Up @@ -542,7 +542,7 @@ PODS:
- TcpSockets (3.3.2):
- React
- Toast (4.0.0)
- Turf (2.6.1)
- Turf (2.7.0)
- Yoga (1.14.0)
- ZXingObjC/Core (3.6.5)
- ZXingObjC/OneD (3.6.5):
Expand Down Expand Up @@ -841,7 +841,7 @@ SPEC CHECKSUMS:
BEMCheckBox: 5ba6e37ade3d3657b36caecc35c8b75c6c2b1a4e
boost: 57d2868c099736d80fcd648bf211b4431e51a558
BVLinearGradient: 34a999fda29036898a09c6a6b728b0b4189e1a44
Charts: 354f86803d11d9c35de280587fef50d1af063978
Charts: ce0768268078eee0336f122c3c4ca248e4e204c5
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
EXApplication: d8f53a7eee90a870a75656280e8d4b85726ea903
EXBarCodeScanner: 8e23fae8d267dbef9f04817833a494200f1fce35
Expand All @@ -865,9 +865,9 @@ SPEC CHECKSUMS:
helium-react-native-sdk: 32c0a7e3abc733a7f3d291013b2db31475fc6980
hermes-engine: 0784cadad14b011580615c496f77e0ae112eed75
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
MapboxCommon: fdf7fd31c90b7b607cd9c63e37797f023c01d860
MapboxCoreMaps: 24270c7c6b8cb71819fc2f3c549db9620ee4d019
MapboxMaps: cb76511b98d3b95c74b0771ed105bc69f30ace6b
MapboxCommon: dcbdb86acbcfc1a23efd341ed097c6c63ab532a9
MapboxCoreMaps: bcbaac14467616940187f79bba49ca491cd37906
MapboxMaps: 1fd9d97d0e8eceb7a45b9ac8bf87a8922da881a8
MapboxMobileEvents: de50b3a4de180dd129c326e09cd12c8adaaa46d6
MultiplatformBleAdapter: 5a6a897b006764392f9cef785e4360f54fb9477d
OneSignalXCFramework: 81ceac017a290f23793443323090cfbe888f74ea
Expand Down Expand Up @@ -923,7 +923,7 @@ SPEC CHECKSUMS:
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
RNICloudStore: bc6e225811637c09bd1eb055d6cd7448e61cd451
RNLocalize: a64514b46a01375fdfae9349036b4dc7130333b5
rnmapbox-maps: 3553325eec9e1501942bbb28702b3a44457961d2
rnmapbox-maps: bf91ca56e25c0f4f2a7c63aef47bbaed7d6cf169
RNOS: 6f2f9a70895bbbfbdad7196abd952e7b01d45027
RNReactNativeSharedGroupPreferences: de0121a4224c267bc7e9fb16c398f3f087c8da81
RNReanimated: cc5e3aa479cb9170bcccf8204291a6950a3be128
Expand All @@ -935,10 +935,10 @@ SPEC CHECKSUMS:
SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7
TcpSockets: 14306fb79f9750ea7d2ddd02d8bed182abb01797
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
Turf: 469ce2c3d22e5e8e4818d5a3b254699a5c89efa4
Turf: 13d1a92d969ca0311bbc26e8356cca178ce95da2
Yoga: cd7d7f509dbfac14ee7f31a6c750acb957cd5022
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb

PODFILE CHECKSUM: 315053ef8dad0ea72bc8b3d40f59c1020ede650c

COCOAPODS: 1.11.3
COCOAPODS: 1.12.1
4 changes: 2 additions & 2 deletions src/features/collectables/AssertLocationScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,15 @@ const AssertLocationScreen = () => {
return undefined
}

return parseH3BNLocation(iotInfoAcc.info.location).reverse()
return parseH3BNLocation(iotInfoAcc.info.location)?.reverse()
}, [iotInfoAcc])

const mobileLocation = useMemo(() => {
if (!mobileInfoAcc?.info?.location) {
return undefined
}

return parseH3BNLocation(mobileInfoAcc.info.location).reverse()
return parseH3BNLocation(mobileInfoAcc.info.location)?.reverse()
}, [mobileInfoAcc])

const sameLocation = useMemo(() => {
Expand Down
56 changes: 38 additions & 18 deletions src/features/collectables/HotspotCompressedListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useMint } from '@helium/helium-react-hooks'
import { Mints } from '../../utils/constants'
import { removeDashAndCapitalize } from '../../utils/hotspotNftsUtils'
import { HotspotWithPendingRewards } from '../../types/solana'
import useHotspotLocation from '../../hooks/useHotspotLocation'

export type HotspotListItemProps = {
hotspot: HotspotWithPendingRewards
Expand All @@ -32,6 +33,17 @@ const HotspotListItem = ({
content: { metadata },
} = hotspot

const eccCompact = useMemo(() => {
if (!metadata || !metadata?.attributes?.length) {
return undefined
}

return metadata.attributes.find((attr) => attr.trait_type === 'ecc_compact')
?.value
}, [metadata])

const streetAddress = useHotspotLocation(eccCompact)

const { info: iotMint } = useMint(IOT_MINT)
const { info: mobileMint } = useMint(MOBILE_MINT)

Expand Down Expand Up @@ -65,15 +77,6 @@ const HotspotListItem = ({
return formatLargeNumber(new BigNumber(num))
}, [hotspot, mobileMint])

const eccCompact = useMemo(() => {
if (!metadata || !metadata?.attributes?.length) {
return undefined
}

return metadata.attributes.find((attr) => attr.trait_type === 'ecc_compact')
?.value
}, [metadata])

const hasIotRewards = useMemo(
() => pendingIotRewards && pendingIotRewards.gt(new BN(0)),
[pendingIotRewards],
Expand Down Expand Up @@ -102,22 +105,39 @@ const HotspotListItem = ({
cache: 'force-cache',
}}
/>
<Box marginStart="m" marginVertical="s" flex={1}>
<Box
marginStart="m"
marginVertical="s"
flex={1}
justifyContent="center"
>
{metadata?.name && (
<Text textAlign="left" variant="subtitle2" adjustsFontSizeToFit>
<Text
textAlign="left"
variant="subtitle2"
numberOfLines={1}
adjustsFontSizeToFit
>
{removeDashAndCapitalize(metadata.name)}
</Text>
)}

<Box flexGrow={1} />

<Box flexDirection="row" marginEnd="s" alignItems="flex-end">
<Text variant="subtitle3" color="secondaryText">
{eccCompact ? ellipsizeAddress(eccCompact) : ''}
{streetAddress && (
<Text variant="body2" numberOfLines={1} adjustsFontSizeToFit>
{streetAddress}
</Text>
</Box>
)}

<Text
variant="subtitle3"
color="secondaryText"
numberOfLines={1}
adjustsFontSizeToFit
>
{eccCompact ? ellipsizeAddress(eccCompact) : ''}
</Text>
</Box>
<Box marginVertical="s" marginEnd="s">
<Box marginVertical="s" marginHorizontal="s">
{!!hasMobileRewards && (
<Box
marginBottom="s"
Expand Down
17 changes: 16 additions & 1 deletion src/features/collectables/HotspotDetailsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { ellipsizeAddress } from '@utils/accountUtils'
import { toNumber } from '@helium/spl-utils'
import { useEntityKey } from '@hooks/useEntityKey'
import { useIotInfo } from '@hooks/useIotInfo'
import { FadeIn } from 'react-native-reanimated'
import useHotspotLocation from '@hooks/useHotspotLocation'
import { ww } from '../../utils/layout'
import {
CollectableNavigationProp,
Expand All @@ -47,6 +49,7 @@ const HotspotDetailsScreen = () => {
const { collectable } = route.params
const entityKey = useEntityKey(collectable)
const iotInfoAcc = useIotInfo(entityKey)
const streetAddress = useHotspotLocation(entityKey)

const pendingIotRewards =
collectable &&
Expand Down Expand Up @@ -211,7 +214,19 @@ const HotspotDetailsScreen = () => {
}}
/>
</Box>
<Box marginTop="l" marginBottom="m">
{streetAddress && (
<ReAnimatedBox entering={FadeIn}>
<Text variant="body1" marginTop="l" textAlign="center">
{streetAddress || ' '}
</Text>
</ReAnimatedBox>
)}
{!streetAddress && (
<Text variant="body1" marginTop="l" textAlign="center">
{' '}
</Text>
)}
<Box marginTop="m">
<Text variant="body1" marginBottom="ms">
{t('collectablesScreen.hotspots.pendingRewardsTitle')}
</Text>
Expand Down
9 changes: 5 additions & 4 deletions src/features/collectables/HotspotList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ import { formatLargeNumber } from '../../utils/accountUtils'
import HotspotCompressedListItem from './HotspotCompressedListItem'
import HotspotListItem from './HotspotListItem'
import { NFTSkeleton } from './NftListItem'
import { CollectableNavigationProp } from './collectablesTypes'

export const DEFAULT_PAGE_AMOUNT = 20
import {
CollectableNavigationProp,
DEFAULT_PAGE_AMOUNT,
} from './collectablesTypes'

function RewardItem({
mint,
Expand Down Expand Up @@ -301,7 +302,7 @@ const HotspotList = () => {
hotspot={item}
onPress={handleNavigateToCollectable}
key={item.id}
marginBottom="xs"
marginBottom="s"
/>
)
}
Expand Down
2 changes: 2 additions & 0 deletions src/features/collectables/collectablesTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ export type CollectableStackParamList = {

export type CollectableNavigationProp =
StackNavigationProp<CollectableStackParamList>

export const DEFAULT_PAGE_AMOUNT = 20
79 changes: 79 additions & 0 deletions src/hooks/useHotspotLocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useEffect, useMemo } from 'react'
import { useSelector } from 'react-redux'
import {
iotInfoKey,
mobileInfoKey,
rewardableEntityConfigKey,
} from '@helium/helium-entity-manager-sdk'
import { useAsync } from 'react-async-hook'
import { useAppDispatch } from '../store/store'
import { getGeocodedAddress } from '../store/slices/locationSlice'
import { RootState } from '../store/rootReducer'
import { useSolana } from '../solana/SolanaProvider'
import { IOT_SUB_DAO_KEY, MOBILE_SUB_DAO_KEY } from '../utils/constants'

const useHotspotLocation = (entityKey?: string) => {
const dispatch = useAppDispatch()
const { locations } = useSelector((state: RootState) => state.location)
const { hemProgram } = useSolana()

const { result: location } = useAsync(async () => {
const [iotConfigKey] = rewardableEntityConfigKey(IOT_SUB_DAO_KEY, 'IOT')
const [iotKey] = iotInfoKey(iotConfigKey, entityKey || '')
const iotInfo = await hemProgram?.account.iotHotspotInfoV0.fetch(iotKey)
if (iotInfo?.location) {
const loc = iotInfo.location
if (loc && loc.toString('hex') !== '0') {
return loc
}
}

const [mobileConfigKey] = rewardableEntityConfigKey(
MOBILE_SUB_DAO_KEY,
'MOBILE',
)
const [mobileKey] = mobileInfoKey(mobileConfigKey, entityKey || '')
const mobileInfo = await hemProgram?.account.mobileHotspotInfoV0.fetch(
mobileKey,
)

if (mobileInfo?.location) {
const loc = mobileInfo.location
if (loc && loc.toString('hex') !== '0') {
return loc
}
}
}, [])

useEffect(() => {
if (!entityKey || !location) return
const geo = locations[location?.toString('hex') || '']
if (geo) return

dispatch(getGeocodedAddress({ location }))
}, [dispatch, entityKey, location, locations])

const streetAddress = useMemo(() => {
const geo = locations[location?.toString('hex') || '']
if (!geo || !geo.features?.length) return ''

const feature = geo.features[0]

const place = feature.context?.find((c) => c.id.includes('place'))
const region = feature.context?.find((c) => c.id.includes('region'))

if (place && region) {
return `${place.text}, ${region.text}`
}

if (place) {
return place
}

return region
}, [location, locations])

return streetAddress
}

export default useHotspotLocation
Loading

0 comments on commit 999be0d

Please sign in to comment.