Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move configuration to a single context #190

Merged
merged 2 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
}
60 changes: 7 additions & 53 deletions components/Discovery.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,20 @@
import useSWR from 'swr'
import { sortByAddress } from '../helpers/services'
import { LOCAL_STORAGE_KEYS, PATHS, SUPPORTED_VERSIONS } from '../helpers/constants'
import { LOCAL_STORAGE_KEYS, SUPPORTED_VERSIONS } from '../helpers/constants'
import ServiceCard from './ServiceCard'
import Header from './Headers/Header'
import { useLocalStorage } from '../hooks/useLocalStorage'
import { getUserAgent } from '../helpers/userAgent'
import { Container, Text, Stack } from '@chakra-ui/react'
import { Service, Strategy } from '../types'
import { Container, Stack } from '@chakra-ui/react'
import Features from './Features'
import { isGreaterThanOrEqualToVersion } from '../helpers/version'
import { useWallets } from '../hooks/useWallets'
import { useConfig } from '../contexts/ConfigContext'

const fetcher = (url, opts) => {
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(opts),
}).then(d => d.json())
}

type Props = {
network: string
appVersion: string
extensions: Service[]
walletInclude: string[]
clientServices: Service[]
supportedStrategies: Strategy[]
clientConfig: { [key: string]: any }
port: number
}

export const Discovery = ({
network,
appVersion,
extensions,
walletInclude,
clientServices,
supportedStrategies,
clientConfig,
port,
}: Props) => {
const requestUrl = `/api${PATHS[network.toUpperCase()]}?discoveryType=UI`
const { data, error } = useSWR(requestUrl, url =>
fetcher(url, {
type: ['authn'],
fclVersion: appVersion,
include: walletInclude,
features: {
suggested: clientConfig?.discoveryFeaturesSuggested || []
},
extensions,
userAgent: getUserAgent(),
clientServices, // TODO: maybe combine this with extensions except version support then needs to be fixed in later step
supportedStrategies,
network,
port,
})
)
export const Discovery = () => {
const { wallets: data, error } = useWallets()
const [lastUsed, _] = useLocalStorage(LOCAL_STORAGE_KEYS.LAST_INSTALLED, null)
const services = sortByAddress(data, lastUsed)

const { appVersion } = useConfig()
const isFeaturesSupported = isGreaterThanOrEqualToVersion(
appVersion,
SUPPORTED_VERSIONS.SUGGESTED_FEATURES
Expand Down
57 changes: 32 additions & 25 deletions components/Features.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,44 @@
import { Box, HStack, Tag, Text, IconButton } from '@chakra-ui/react'
import { CheckIcon } from '@chakra-ui/icons'
import { useFCL } from '../hooks/useFCL'
import FEATURES_LIST from '../data/features.json'
import { useConfig } from '../contexts/ConfigContext'

export default function Features() {
const { clientConfig } = useFCL()
const { clientConfig } = useConfig()
const featuresListKeys = FEATURES_LIST.map(f => f.name)
const suggestedFeatures = clientConfig?.discoveryFeaturesSuggested?.filter(f => featuresListKeys.includes(f)) || []
const suggestedFeatures =
clientConfig?.discoveryFeaturesSuggested?.filter(f =>
featuresListKeys.includes(f)
) || []
const hasSuggestedFeatures = suggestedFeatures.length > 0

return (
<Box mb={5}>
{hasSuggestedFeatures &&
<>
<HStack mb={3}>
<Text fontSize='sm' as='b'>Wallet Requirements</Text>
<IconButton
isRound={true}
variant='solid'
colorScheme='teal'
aria-label='Done'
fontSize='sm'
size={'xs'}
icon={<CheckIcon />}
/>
</HStack>
<HStack>
{suggestedFeatures.map((suggestion, index) => (
<Tag key={index} size='sm'>{suggestion}</Tag>
))}
</HStack>
</>
}
{hasSuggestedFeatures && (
<>
<HStack mb={3}>
<Text fontSize="sm" as="b">
Wallet Requirements
</Text>
<IconButton
isRound={true}
variant="solid"
colorScheme="teal"
aria-label="Done"
fontSize="sm"
size={'xs'}
icon={<CheckIcon />}
/>
</HStack>
<HStack>
{suggestedFeatures.map((suggestion, index) => (
<Tag key={index} size="sm">
{suggestion}
</Tag>
))}
</HStack>
</>
)}
</Box>
)
}
}
4 changes: 2 additions & 2 deletions components/Headers/AppHeader.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Image, Text, Heading, HStack, Stack } from '@chakra-ui/react'
import { useFCL } from '../../hooks/useFCL'
import { useConfig } from '../../contexts/ConfigContext'

export default function AppHeader() {
const { appConfig, clientConfig } = useFCL()
const { appConfig, clientConfig } = useConfig()
const title = appConfig?.title ? `Connect to ${appConfig?.title}` : 'Connect'

return (
Expand Down
4 changes: 2 additions & 2 deletions components/Headers/Header.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import FlowHeader from './FlowHeader'
import AppHeader from './AppHeader'
import DeveloperMessage from '../DeveloperMessage'
import { useFCL } from '../../hooks/useFCL'
import { isGreaterThanOrEqualToVersion } from '../../helpers/version'
import { SUPPORTED_VERSIONS } from '../../helpers/constants'
import { isTestnet as isTestnetFn } from '../../helpers/networks'
import { useConfig } from '../../contexts/ConfigContext'

export default function Header() {
const isTestnet = isTestnetFn()
const { appConfig, appVersion } = useFCL()
const { appConfig, appVersion } = useConfig()
const isMissingConfig = !(appConfig?.icon && appConfig?.title)
const showDeveloperMessage =
isTestnet &&
Expand Down
55 changes: 26 additions & 29 deletions components/Headers/__tests__/AppHeader.test.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
import { render } from '@testing-library/react'
import { render as defaultRender } from '@testing-library/react'
import AppHeader from '../AppHeader'
import { useFCL } from '../../../hooks/useFCL'
jest.mock('../../../hooks/useFCL')
import { ConfigProvider } from '../../../contexts/ConfigContext'

describe('Component: AppHeader', () => {
test('should render the the component with icon', () => {
useFCL.mockImplementation(() => {
return {
appConfig: {
title: 'Test App',
icon: 'test.png',
},
clientConfig: {
hostname: 'www.onflow.org',
},
}
})
const render = config => component => {
return defaultRender(
<ConfigProvider {...config}>{component}</ConfigProvider>
)
}

const { container } = render(<AppHeader />)
test('should render the the component with icon', () => {
const { container } = render({
appConfig: {
title: 'Test App',
icon: 'test.png',
},
clientConfig: {
hostname: 'www.onflow.org',
},
})(<AppHeader />)
expect(container.firstChild).toMatchSnapshot()
})

test('should handle missing info and show unknown if no data', () => {
useFCL.mockImplementation(() => {
return {
appConfig: {
title: null,
icon: null,
},
clientConfig: {
hostname: null,
},
}
})

const { container } = render(<AppHeader />)
const { container } = render({
appConfig: {
title: null,
icon: null,
},
clientConfig: {
hostname: null,
},
})(<AppHeader />)
expect(container.firstChild).toMatchSnapshot()
})
})
83 changes: 38 additions & 45 deletions components/Headers/__tests__/Header.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { render } from '@testing-library/react'
import { render as defaultRender } from '@testing-library/react'
import Header from '../Header'
import { useFCL } from '../../../hooks/useFCL'
jest.mock('../../../hooks/useFCL')
import { ConfigProvider } from '../../../contexts/ConfigContext'

jest.mock(
'../../helpers/networks',
Expand All @@ -12,57 +11,51 @@ jest.mock(
)

describe('Component: Header', () => {
test('should render the configurable component if version is old enough', () => {
useFCL.mockImplementation(() => {
return {
appVersion: '1.0.0',
appConfig: {
title: 'Test App',
icon: 'test.png',
},
clientConfig: {
hostname: 'www.onflow.org',
},
}
})
const render = config => component => {
return defaultRender(
<ConfigProvider {...config}>{component}</ConfigProvider>
)
}

const { container } = render(<Header />)
test('should render the configurable component if version is old enough', () => {
const { container } = render({
appVersion: '1.0.0',
appConfig: {
title: 'Test App',
icon: 'test.png',
},
clientConfig: {
hostname: 'www.onflow.org',
},
})(<Header />)
expect(container.firstChild).toMatchSnapshot()
})

test('should NOT render the configurable component if version is too low', () => {
useFCL.mockImplementation(() => {
return {
appVersion: '0.0.77',
appConfig: {
title: 'Test App',
icon: 'test.png',
},
clientConfig: {
hostname: 'www.onflow.org',
},
}
})

const { container } = render(<Header />)
const { container } = render({
appVersion: '0.0.77',
appConfig: {
title: 'Test App',
icon: 'test.png',
},
clientConfig: {
hostname: 'www.onflow.org',
},
})(<Header />)
expect(container.firstChild).toMatchSnapshot()
})

test('should show the DeveloperMessage if config is missing', () => {
useFCL.mockImplementation(() => {
return {
appVersion: '1.0.0',
appConfig: {
title: null,
icon: null,
},
clientConfig: {
hostname: null,
},
}
})

const { container } = render(<Header />)
const { container } = render({
appVersion: '1.0.0',
appConfig: {
title: null,
icon: null,
},
clientConfig: {
hostname: null,
},
})(<Header />)
expect(container.firstChild).toMatchSnapshot()
})
})
17 changes: 3 additions & 14 deletions components/Headers/__tests__/__snapshots__/AppHeader.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@ exports[`Component: AppHeader should render the the component with icon 1`] = `
}

.emotion-3 {
border-radius: 50px;
width: 25px;
height: 25px;
}

.emotion-4 {
color: grey;
}

Expand All @@ -96,20 +90,15 @@ exports[`Component: AppHeader should render the the component with icon 1`] = `
<h2
class="chakra-heading emotion-1"
>
Connect to Test App
Connect
</h2>
<div
class="chakra-stack emotion-2"
>
<img
alt="Logo"
class="chakra-image emotion-3"
src="test.png"
/>
<p
class="chakra-text emotion-4"
class="chakra-text emotion-3"
>
www.onflow.org
Unknown
</p>
</div>
</div>
Expand Down
Loading
Loading