Skip to content

Commit

Permalink
feat(widget): dynamic widget height (#3261)
Browse files Browse the repository at this point in the history
  • Loading branch information
shoom3301 authored Oct 25, 2023
1 parent c232af5 commit aded5c5
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 66 deletions.
3 changes: 0 additions & 3 deletions apps/cowswap-frontend/src/cow-react/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { StrictMode } from 'react'
import { BlockNumberProvider } from '@cowprotocol/common-hooks'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { nodeRemoveChildFix } from '@cowprotocol/common-utils'
import { IframeResizer } from '@cowprotocol/common-utils'
import { jotaiStore } from '@cowprotocol/core'
import { SnackbarsWidget } from '@cowprotocol/snackbars'

Expand Down Expand Up @@ -80,8 +79,6 @@ root.render(
</HashRouter>
</AtomProvider>
</Provider>

{isInjectedWidgetMode && <IframeResizer />}
</StrictMode>
)

Expand Down
1 change: 1 addition & 0 deletions apps/cowswap-frontend/src/modules/injectedWidget/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const COW_SWAP_WIDGET_EVENT_KEY = 'cowSwapWidget'
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import { useEffect, useRef } from 'react'

const MessageType = {
IFRAME_HEIGHT: 'iframeHeight',
}
import { COW_SWAP_WIDGET_EVENT_KEY } from '../consts'
import { useInjectedWidgetParams } from '../hooks/useInjectedWidgetParams'

const TARGET_ORIGIN = '*' // Change to CoW specific origin in production

export function IframeResizer() {
const { dynamicHeightEnabled } = useInjectedWidgetParams()
const previousHeightRef = useRef(0)

useEffect(() => {
if (!dynamicHeightEnabled) return

// Initial height calculation and message
const sendHeightUpdate = () => {
const contentHeight = document.body.scrollHeight
if (contentHeight !== previousHeightRef.current) {
window.parent.postMessage({ type: MessageType.IFRAME_HEIGHT, height: contentHeight }, TARGET_ORIGIN)
window.parent.postMessage(
{ key: COW_SWAP_WIDGET_EVENT_KEY, method: 'iframeHeight', height: contentHeight },
TARGET_ORIGIN
)
previousHeightRef.current = contentHeight
}
}
Expand All @@ -32,7 +37,7 @@ export function IframeResizer() {
return () => {
observer.disconnect()
}
}, [])
}, [dynamicHeightEnabled])

return null
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { deepEqual } from '@cowprotocol/common-utils'

import { useNavigate } from 'react-router-dom'

import { IframeResizer } from './IframeResizer'

import { COW_SWAP_WIDGET_EVENT_KEY } from '../consts'
import { injectedWidgetMetaDataAtom } from '../state/injectedWidgetMetaDataAtom'
import { injectedWidgetParamsAtom } from '../state/injectedWidgetParamsAtom'

const COW_SWAP_WIDGET_EVENT_KEY = 'cowSwapWidget'

const messagesCache: { [method: string]: unknown } = {}

const getEventMethod = (event: MessageEvent) =>
Expand Down Expand Up @@ -88,5 +89,5 @@ export function InjectedWidgetUpdater() {
})
}, [processEvent])

return null
return <IframeResizer />
}

This file was deleted.

26 changes: 25 additions & 1 deletion apps/widget-configurator/src/app/configurator/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import {
import WalletIcon from '@mui/icons-material/Wallet'
import LoadingButton from '@mui/lab/LoadingButton'
import Box from '@mui/material/Box'
import Checkbox from '@mui/material/Checkbox'
import Divider from '@mui/material/Divider'
import Drawer from '@mui/material/Drawer'
import FormControlLabel from '@mui/material/FormControlLabel'
import Link from '@mui/material/Link'
import Typography from '@mui/material/Typography'

Expand Down Expand Up @@ -60,6 +62,8 @@ export function Configurator({ title }: { title: string }) {
const iframeContainerRef = useRef<HTMLDivElement>(null)
const updateWidgetRef = useRef<UpdateWidgetCallback | null>(null)

const [isDynamicHeightEnabled, setDynamicHeightEnabled] = useState(false)

useEffect(() => {
const widgetContainer = iframeContainerRef.current

Expand All @@ -84,6 +88,7 @@ export function Configurator({ title }: { title: string }) {
},
},
appParams: {
dynamicHeightEnabled: isDynamicHeightEnabled,
enabledTradeTypes,
},
}
Expand All @@ -93,7 +98,17 @@ export function Configurator({ title }: { title: string }) {
} else {
updateWidgetRef.current = cowSwapWidget(params, settings)
}
}, [chainId, enabledTradeTypes, sellToken, sellTokenAmount, buyToken, buyTokenAmount, mode, currentTradeType])
}, [
chainId,
enabledTradeTypes,
sellToken,
sellTokenAmount,
buyToken,
buyTokenAmount,
mode,
currentTradeType,
isDynamicHeightEnabled,
])

const handleWidgetRefreshClick = () => {
setMode('light')
Expand Down Expand Up @@ -143,6 +158,15 @@ export function Configurator({ title }: { title: string }) {

<CurrencyInputControl label="Buy token" tokenIdState={buyTokenState} tokenAmountState={buyTokenAmountState} />

<Divider variant="middle">Advanced</Divider>

<FormControlLabel
control={
<Checkbox checked={isDynamicHeightEnabled} onChange={(e) => setDynamicHeightEnabled(e.target.checked)} />
}
label="Dynamic widget height"
/>

<Divider variant="middle" />

{/* <LoadingButton loading={false} loadingPosition="start" startIcon={<SaveIcon />} variant="contained" onClick={handleWidgetRefreshClick}>
Expand Down
1 change: 0 additions & 1 deletion libs/common-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,3 @@ export * from './tryParseFractionalAmount'
export * from './maxAmountSpend'
export * from './capitalizeFirstLetter'
export * from './jotai/atomWithPartialUpdate'
export * from './iframeResizer'
29 changes: 24 additions & 5 deletions libs/widget-lib/src/cowSwapWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ export function cowSwapWidget(params: CowSwapWidgetParams, settings: CowSwapWidg

sendMetaData(contentWindow, params.metaData)

applyDynamicHeight(iframe, params.height)

if (provider) {
const jsonRpcManager = new JsonRpcManager(contentWindow)

jsonRpcManager.onConnect(provider)
}

return (params: CowSwapWidgetSettings) => updateWidget(params, contentWindow)
return (newSettings: CowSwapWidgetSettings) => updateWidget(newSettings, contentWindow, iframe)
}

function createIframe(params: CowSwapWidgetParams, settings: CowSwapWidgetSettings): HTMLIFrameElement {
Expand All @@ -41,9 +43,14 @@ function createIframe(params: CowSwapWidgetParams, settings: CowSwapWidgetSettin
return iframe
}

function updateWidget(params: CowSwapWidgetSettings, contentWindow: Window) {
const pathname = buildWidgetPath(params.urlParams)
const search = buildTradeAmountsQuery(params.urlParams).toString()
function updateWidget(settings: CowSwapWidgetSettings, contentWindow: Window, iframe: HTMLIFrameElement) {
const pathname = buildWidgetPath(settings.urlParams)
const search = buildTradeAmountsQuery(settings.urlParams).toString()

// Reset iframe height to default
if (!settings.appParams.dynamicHeightEnabled) {
iframe.style.height = ''
}

contentWindow.postMessage(
{
Expand All @@ -53,7 +60,7 @@ function updateWidget(params: CowSwapWidgetSettings, contentWindow: Window) {
pathname,
search,
},
appParams: params.appParams,
appParams: settings.appParams,
},
'*'
)
Expand All @@ -75,3 +82,15 @@ function sendMetaData(contentWindow: Window, metaData: CowSwapWidgetMetaData) {
)
})
}

function applyDynamicHeight(iframe: HTMLIFrameElement, defaultHeight: number) {
window.addEventListener('message', (event) => {
if (event.data.key !== COW_SWAP_WIDGET_EVENT_KEY || event.data.method !== 'iframeHeight') {
return
}

const height = event.data.height || defaultHeight

iframe.style.height = `${height}px`
})
}
1 change: 1 addition & 0 deletions libs/widget-lib/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface CowSwapWidgetAppParams {
logoUrl?: string
hideLogo?: boolean
hideNetworkSelector?: boolean
dynamicHeightEnabled?: boolean
enabledTradeTypes?: TradeType[]
}

Expand Down

0 comments on commit aded5c5

Please sign in to comment.