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

feat(hooks-store): new design & refactoring #4859

Merged
merged 34 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a5bf768
chore: update eslint
shoom3301 Sep 3, 2024
abace98
refactor: align hook dapp files structure
shoom3301 Sep 3, 2024
50b780d
refactor: fix files structure
shoom3301 Sep 3, 2024
7c7a7a3
refactor: fix dependency inversion (hooksStore -> swap)
shoom3301 Sep 3, 2024
56b12a6
refactor: separate hooks store modal from buttons
shoom3301 Sep 3, 2024
e69d98c
chore: fix circular dependency
shoom3301 Sep 3, 2024
169354d
refactor: rename HooksStoreModal to HookRegistryList
shoom3301 Sep 3, 2024
9882f5c
refactor: make hook dapp context specific to dapp
shoom3301 Sep 4, 2024
b75237f
Merge branch 'develop' of https://github.com/cowprotocol/cowswap into…
shoom3301 Sep 4, 2024
2386d6c
refactor: extract pure components
shoom3301 Sep 4, 2024
61bd602
refactor: remove outputTokens
shoom3301 Sep 4, 2024
eac5dd8
feat(hooks-store): persist hooks into localStorage
shoom3301 Sep 4, 2024
9ea9781
feat(hooks-store): add styles
shoom3301 Sep 4, 2024
ee175c3
Merge branch 'develop' of https://github.com/cowprotocol/cowswap into…
shoom3301 Sep 5, 2024
67fc1f5
feat(hooks-store): style hook dapps
shoom3301 Sep 5, 2024
2899255
feat(hooks-store): style applied hook item
shoom3301 Sep 5, 2024
a1a22b3
chore: fix code style
shoom3301 Sep 6, 2024
b8f5ee0
chore: fix circular deps
shoom3301 Sep 6, 2024
1e49786
chore: fix code style
shoom3301 Sep 9, 2024
9a6b44e
fix(trade): hide top content for wrap flow
shoom3301 Sep 9, 2024
5671d04
fix(hooks-store): split state by chainId
shoom3301 Sep 9, 2024
04f8b85
fix(hooks-store): skip custom hooks in swap widget
shoom3301 Sep 9, 2024
a6d4fa9
chore(hooks-store): add uid to hook item title
shoom3301 Sep 9, 2024
c2c736e
fix(hooks-store): fix appData module dependencies
shoom3301 Sep 9, 2024
cb338c8
fix(hooks-store): bind state to account
shoom3301 Sep 9, 2024
58a68ad
fix(hooks-store): allow hooks in smart-contract wallets
shoom3301 Sep 10, 2024
074e6fd
chore: fix typo
shoom3301 Sep 10, 2024
5b99274
Merge branch 'develop' of https://github.com/cowprotocol/cowswap into…
shoom3301 Sep 11, 2024
aaea230
refactor: move hooks types to the module
shoom3301 Sep 11, 2024
75312cf
chore: fix lint
shoom3301 Sep 11, 2024
6b896cd
fix: permit data loading
shoom3301 Sep 11, 2024
f9a41b6
feat(hooks-store): general hooks widget styling and DnD (#4868)
fairlighteth Sep 11, 2024
b668136
chore: test commit
shoom3301 Sep 11, 2024
d9e11a5
chore: test commit
shoom3301 Sep 11, 2024
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
15 changes: 13 additions & 2 deletions apps/cowswap-frontend/src/common/pure/NewModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,22 @@ export const NewModalContentBottom = styled(NewModalContentTop)`
export interface NewModalProps {
maxWidth?: number
minHeight?: number
contentPadding?: string
title?: string
onDismiss?: Command
children?: React.ReactNode
modalMode?: boolean
}

export function NewModal({ maxWidth = 450, minHeight = 350, modalMode, title, children, onDismiss }: NewModalProps) {
export function NewModal({
maxWidth = 450,
minHeight = 350,
contentPadding,
modalMode,
title,
children,
onDismiss,
}: NewModalProps) {
const onDismissCallback = useCallback(() => onDismiss?.(), [onDismiss])

return (
Expand All @@ -180,7 +189,9 @@ export function NewModal({ maxWidth = 450, minHeight = 350, modalMode, title, ch
</Heading>
)}

<NewModalContent className={modalMode ? 'modalMode' : ''}>{children}</NewModalContent>
<NewModalContent className={modalMode ? 'modalMode' : ''} padding={contentPadding}>
{children}
</NewModalContent>
</ModalInner>
</Wrapper>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function RoutesApp() {
<Route path="profile" element={<Navigate to={RoutesEnum.ACCOUNT} />} />

{/*Swap*/}
<Route path={RoutesEnum.SWAP} element={<SwapPage hooksEnabled={false} />} />
<Route path={RoutesEnum.SWAP} element={<SwapPage />} />
<Route path={RoutesEnum.HOOKS} element={<HooksPage />} />
<Route path={RoutesEnum.SEND} element={<RedirectPathToSwapOnly />} />

Expand Down
3 changes: 0 additions & 3 deletions apps/cowswap-frontend/src/modules/hooksStore/const.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
export const HOOKS_TRAMPOLINE_ADDRESS = '0x01dcb88678aedd0c4cc9552b20f4718550250574'
export const SBC_DEPOSIT_CONTRACT_ADDRESS = '0x0B98057eA310F4d31F2a452B414647007d1645d9'

// Sorry Safe, you need to set up CORS policy :)
// TODO: run our own instance
export const TENDERLY_SIMULATE_ENDPOINT_URL =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useMemo } from 'react'

import { Command, HookDapp, HookDappContext as HookDappContextType } from '@cowprotocol/types'
import { useWalletInfo } from '@cowprotocol/wallet'

import { useAddHook } from '../../hooks/useAddHook'
import { useEditHook } from '../../hooks/useEditHook'
import { useHookById } from '../../hooks/useHookById'
import { isHookDappIframe } from '../../utils'

interface HookDappContainerProps {
dapp: HookDapp
isPreHook: boolean
onDismiss: Command
onDismissModal: Command
hookToEdit?: string
}

export function HookDappContainer({ dapp, isPreHook, onDismiss, onDismissModal, hookToEdit }: HookDappContainerProps) {
const { chainId, account } = useWalletInfo()
const addHook = useAddHook(dapp, isPreHook)
const editHook = useEditHook()

const hookToEditDetails = useHookById(hookToEdit, isPreHook)

const context = useMemo<HookDappContextType>(() => {
return {
chainId,
account,
hookToEdit: hookToEditDetails,
editHook: (...args) => {
editHook(...args)
onDismiss()
},
addHook: (hookToAdd) => {
const hook = addHook(hookToAdd)
onDismiss()

return hook
},
close: onDismissModal,
}
}, [addHook, editHook, onDismiss, onDismissModal, chainId, account, hookToEditDetails])

const dappProps = useMemo(() => ({ context, dapp, isPreHook }), [context, dapp, isPreHook])

if (isHookDappIframe(dapp)) {
// TODO: Create iFrame
return <>{dapp.name}</>
}

return dapp.component(dappProps)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { useCallback, useEffect, useMemo, useState } from 'react'

import { Command, HookDapp } from '@cowprotocol/types'
import { useWalletInfo } from '@cowprotocol/wallet'

import { NewModal } from 'common/pure/NewModal'

import { DappInfoHeader, HookDappsList, Wrapper } from './styled'

import { POST_HOOK_REGISTRY, PRE_HOOK_REGISTRY } from '../../hookRegistry'
import { useHookById } from '../../hooks/useHookById'
import { HookDappDetails } from '../../pure/HookDappDetails'
import { HookListItem } from '../../pure/HookListItem'
import { HookDappContainer } from '../HookDappContainer'

interface HookStoreModal {
onDismiss: Command
isPreHook: boolean
hookToEdit?: string
}

export function HookRegistryList({ onDismiss, isPreHook, hookToEdit }: HookStoreModal) {
const { chainId } = useWalletInfo()
const [selectedDapp, setSelectedDapp] = useState<HookDapp | null>(null)
const [dappDetails, setDappDetails] = useState<HookDapp | null>(null)

const hookToEditDetails = useHookById(hookToEdit, isPreHook)
const dapps = isPreHook ? PRE_HOOK_REGISTRY[chainId] : POST_HOOK_REGISTRY[chainId]

const title = useMemo(() => {
if (selectedDapp) return selectedDapp.name
if (dappDetails) return 'Hook description'

return 'Hook Store'
}, [selectedDapp, dappDetails])

const onDismissModal = useCallback(() => {
if (hookToEdit) {
setSelectedDapp(null)
onDismiss()
return
}

if (dappDetails) {
setDappDetails(null)
} else if (selectedDapp) {
setSelectedDapp(null)
} else {
onDismiss()
}
}, [onDismiss, selectedDapp, dappDetails, hookToEdit])

useEffect(() => {
if (!hookToEditDetails) {
setSelectedDapp(null)
} else {
setSelectedDapp(dapps.find((i) => i.name === hookToEditDetails.dapp.name) || null)
}
}, [hookToEditDetails, dapps])

return (
<Wrapper>
<NewModal modalMode={false} title={title} onDismiss={onDismissModal} contentPadding="0">
{(() => {
if (selectedDapp) {
return (
<>
<DappInfoHeader>
<img src={selectedDapp.image} alt={selectedDapp.name} />
<p>{selectedDapp.description}</p>
</DappInfoHeader>
<HookDappContainer
isPreHook={isPreHook}
onDismiss={onDismiss}
onDismissModal={onDismissModal}
dapp={selectedDapp}
hookToEdit={hookToEdit}
/>
</>
)
}

if (dappDetails) {
return <HookDappDetails dapp={dappDetails} />
}

return (
<HookDappsList>
{dapps.map((dapp) => (
<HookListItem
key={dapp.name}
dapp={dapp}
onSelect={() => setSelectedDapp(dapp)}
onOpenDetails={() => setDappDetails(dapp)}
/>
))}
</HookDappsList>
)
})()}
</NewModal>
</Wrapper>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { UI } from '@cowprotocol/ui'

import styled from 'styled-components/macro'
import { WIDGET_MAX_WIDTH } from 'theme'

export const Wrapper = styled.div`
width: 100%;
max-width: ${WIDGET_MAX_WIDTH.swap};
margin: 0 auto;
position: relative;
`

export const HookDappsList = styled.ul`
list-style: none;
padding: 0;
margin: 16px 0 0 0;
flex: 1;
`

export const DappInfoHeader = styled.div`
display: flex;
padding: 10px 0 20px 0;
margin-top: 10px;
border-bottom: 1px solid var(${UI.COLOR_TEXT_OPACITY_10});
align-items: center;

p {
padding: 0 1em;
}

> img {
width: 60px;
}
`
Loading
Loading