From 5e4810add2325772ad61d61a8983ed3582a86404 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 23 Oct 2023 14:37:15 +0600 Subject: [PATCH 01/12] feat: halloween theme --- apps/cowswap-frontend/index.html | 1 + .../src/legacy/components/Header/styled.tsx | 23 ++++++++++- .../src/legacy/state/cowToken/middleware.ts | 8 +++- .../orders/middleware/soundMiddleware.ts | 41 ++++++++++++++----- .../src/legacy/theme/cowSwapAssets.ts | 10 ++--- libs/common-utils/src/sound.ts | 27 +++++++----- 6 files changed, 82 insertions(+), 28 deletions(-) diff --git a/apps/cowswap-frontend/index.html b/apps/cowswap-frontend/index.html index 37517addc5..03c75102a9 100644 --- a/apps/cowswap-frontend/index.html +++ b/apps/cowswap-frontend/index.html @@ -3,6 +3,7 @@ CoW Swap | The smartest way to trade cryptocurrencies + ` width: 100%; + // Halloween temporary + ${({ theme }) => + theme.darkMode && + css` + &::after { + content: ''; + display: block; + background: url(${SpiderRag}) no-repeat center/contain; + height: 200px; + width: 200px; + position: fixed; + right: -42px; + top: 90px; + ${({ theme }) => theme.mediaWidth.upToSmall` + display: none; + content: none; + `}; + } + `} + ${HeaderFrame} { padding: 16px; display: flex; @@ -247,7 +268,7 @@ export const Wrapper = styled.div<{ isMobileMenuOpen: boolean }>` ${ isMobileMenuOpen && css` - position: absolute; + position: fixed; top: 0; z-index: 3; diff --git a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts index 89852f3350..380b244760 100644 --- a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts @@ -19,6 +19,10 @@ export const cowTokenMiddleware: Middleware, AppState> = const { chainId, hash } = action.payload const transaction = store.getState().transactions[chainId][hash] + // Halloween temporary + const { userDarkMode, matchesDarkMode } = store.getState().user + const isDarkMode = userDarkMode === null ? matchesDarkMode : userDarkMode + if (transaction.swapVCow || transaction.swapLockedGNOvCow) { const status = transaction.receipt?.status @@ -28,13 +32,13 @@ export const cowTokenMiddleware: Middleware, AppState> = ) if (status === 1 && transaction.replacementType !== 'cancel') { - cowSound = getCowSoundSuccess() + cowSound = getCowSoundSuccess(isDarkMode) if (transaction.swapVCow) { store.dispatch(setSwapVCowStatus(SwapVCowStatus.CONFIRMED)) } } else { - cowSound = getCowSoundError() + cowSound = getCowSoundError(isDarkMode) if (transaction.swapVCow) { store.dispatch(setSwapVCowStatus(SwapVCowStatus.INITIAL)) diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts index 23eb9683de..483c3768c4 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts @@ -1,5 +1,5 @@ // On each Pending, Expired, Fulfilled order action a corresponding sound is dispatched -import { getCowSoundError, getCowSoundSend, getCowSoundSuccess } from '@cowprotocol/common-utils' +import { getCowSoundError, getCowSoundSend, getCowSoundSuccess, isMobile } from '@cowprotocol/common-utils' import { isAnyOf } from '@reduxjs/toolkit' import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux' @@ -28,6 +28,16 @@ const isBatchCancelOrderAction = isAnyOf(OrderActions.cancelOrdersBatch) const isFulfillOrderAction = isAnyOf(OrderActions.addPendingOrder, OrderActions.fulfillOrdersBatch) const isAddPopup = isAnyOf(addPopup) +function removeLightningEffect() { + document.body.classList.remove('lightning') +} +function addLightningEffect() { + document.body.classList.add('lightning') + setTimeout(() => { + removeLightningEffect() + }, 3000) +} + export const soundMiddleware: Middleware, AppState> = (store) => (next) => (action) => { const result = next(action) @@ -47,27 +57,38 @@ export const soundMiddleware: Middleware, AppState> = (s } } - let cowSound + // Halloween temporary + const { userDarkMode, matchesDarkMode } = store.getState().user + const isDarkMode = userDarkMode === null ? matchesDarkMode : userDarkMode + + let cowSound, + showLighningEffect = false if (isPendingOrderAction(action)) { if (_shouldPlayPendingOrderSound(action.payload)) { - cowSound = getCowSoundSend() + cowSound = getCowSoundSend(isDarkMode) + showLighningEffect = isDarkMode && !isMobile } } else if (isFulfillOrderAction(action)) { - cowSound = getCowSoundSuccess() + cowSound = getCowSoundSuccess(isDarkMode) + showLighningEffect = isDarkMode && !isMobile } else if (isBatchExpireOrderAction(action)) { if (_shouldPlayExpiredOrderSound(action.payload, store)) { - cowSound = getCowSoundError() + cowSound = getCowSoundError(isDarkMode) } } else if (isBatchCancelOrderAction(action)) { - cowSound = getCowSoundError() + cowSound = getCowSoundError(isDarkMode) } else if (isFailedTxAction(action)) { - cowSound = getCowSoundError() + cowSound = getCowSoundError(isDarkMode) } else if (isUpdateOrderAction(action)) { - cowSound = _getUpdatedOrderSound(action.payload) + cowSound = _getUpdatedOrderSound(action.payload, isDarkMode) } if (cowSound) { + if (showLighningEffect) { + setTimeout(addLightningEffect, 300) + } cowSound.play().catch((e) => { + removeLightningEffect() console.error('🐮 Moooooo sound cannot be played', e) }) } @@ -94,10 +115,10 @@ function _shouldPlayExpiredOrderSound( }) } -function _getUpdatedOrderSound(payload: UpdateOrderParams) { +function _getUpdatedOrderSound(payload: UpdateOrderParams, isDarkMode: boolean) { if (!payload.order.isHidden) { // Trigger COW sound when an order is being updated to a non-hidden state - return getCowSoundSend() + return getCowSoundSend(isDarkMode) } return undefined } diff --git a/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts b/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts index 1997b9dce5..ff08830b3b 100644 --- a/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts +++ b/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts @@ -1,12 +1,12 @@ export function cowSwapLogo(darkMode: boolean): string { // Halloween version - // const darkModeLogo = ` - // ` + const darkModeLogo = ` + ` // Regular Dark mode logo - const darkModeLogo = ` - - ` + // const darkModeLogo = ` + // + // ` // Regular Light mode logo const lightModeLogo = `` diff --git a/libs/common-utils/src/sound.ts b/libs/common-utils/src/sound.ts index a73d2607b5..c527b14572 100644 --- a/libs/common-utils/src/sound.ts +++ b/libs/common-utils/src/sound.ts @@ -1,6 +1,13 @@ type SoundType = 'SEND' | 'SUCCESS' | 'SUCCESS_CLAIM' | 'ERROR' type Sounds = Record +const COW_SOUNDS_HALLOWEEN: Sounds = { + SEND: '/audio/halloween.mp3', + SUCCESS: '/audio/halloween.mp3', + SUCCESS_CLAIM: '/audio/success-claim.mp3', + ERROR: '/audio/error.mp3', +} + const COW_SOUNDS: Sounds = { SEND: '/audio/send.mp3', SUCCESS: '/audio/success.mp3', @@ -10,8 +17,8 @@ const COW_SOUNDS: Sounds = { const SOUND_CACHE: Record = {} -function getAudio(type: SoundType): HTMLAudioElement { - const soundPath = COW_SOUNDS[type] +function getAudio(useHalloween: boolean, type: SoundType): HTMLAudioElement { + const soundPath = useHalloween ? COW_SOUNDS_HALLOWEEN[type] : COW_SOUNDS[type] let sound = SOUND_CACHE[soundPath] if (!sound) { @@ -22,18 +29,18 @@ function getAudio(type: SoundType): HTMLAudioElement { return sound } -export function getCowSoundSend(): HTMLAudioElement { - return getAudio('SEND') +export function getCowSoundSend(useHalloween: boolean): HTMLAudioElement { + return getAudio(useHalloween, 'SEND') } -export function getCowSoundSuccess(): HTMLAudioElement { - return getAudio('SUCCESS') +export function getCowSoundSuccess(useHalloween: boolean): HTMLAudioElement { + return getAudio(useHalloween, 'SUCCESS') } -export function getCowSoundSuccessClaim(): HTMLAudioElement { - return getAudio('SUCCESS_CLAIM') +export function getCowSoundSuccessClaim(useHalloween: boolean): HTMLAudioElement { + return getAudio(useHalloween, 'SUCCESS_CLAIM') } -export function getCowSoundError(): HTMLAudioElement { - return getAudio('ERROR') +export function getCowSoundError(useHalloween: boolean): HTMLAudioElement { + return getAudio(useHalloween, 'ERROR') } From 4464bd41b24bcf263ce4ffa5361da432d1d1ce5a Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 23 Oct 2023 15:52:38 +0600 Subject: [PATCH 02/12] chore: fix build --- .../src/modules/twap/hooks/useCreateTwapOrder.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts index 72eb4716fb..5843a4fc96 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts @@ -12,6 +12,7 @@ import { Nullish } from 'types' import { cowSwapStore } from 'legacy/state' import { dispatchPresignedOrderPosted } from 'legacy/state/orders/middleware/updateOrderPopup' +import { useIsDarkMode } from 'legacy/state/user/hooks' import { getOrderSubmitSummary } from 'legacy/utils/trade' import { updateAdvancedOrdersAtom, useAdvancedOrdersDerivedState } from 'modules/advancedOrders' @@ -55,6 +56,9 @@ export function useCreateTwapOrder() { const { priceImpact } = useTradePriceImpact() const { confirmPriceImpactWithoutFee } = useConfirmPriceImpactWithoutFee() + // Halloween temporary + const darkMode = useIsDarkMode() + return useCallback( async (fallbackHandlerIsNotSet: boolean) => { if (!chainId || !account) return @@ -123,7 +127,7 @@ export function useCreateTwapOrder() { outputAmount: twapOrder.buyAmount, feeAmount: undefined, }) - getCowSoundSend().play() + getCowSoundSend(darkMode).play() dispatchPresignedOrderPosted(cowSwapStore, safeTxHash, summary, OrderClass.LIMIT, 'composable-order') uploadAppData({ chainId, orderId, appData: appDataInfo }) @@ -156,6 +160,7 @@ export function useCreateTwapOrder() { addTwapOrderToList, recipient, updateAdvancedOrdersState, + darkMode, ] ) } From d3b96de04358a1d8452bb1acd216c127538ff813 Mon Sep 17 00:00:00 2001 From: Alexandr Kazachenko Date: Mon, 23 Oct 2023 16:07:55 +0600 Subject: [PATCH 03/12] chore: fix test --- .../legacy/state/orders/middleware/soundMiddleware.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts index 76ba9c1439..f124150f29 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.test.ts @@ -21,6 +21,7 @@ describe('soundMiddleware', () => { orders: { 1: 'mock orders', }, + user: { userDarkMode: false }, } as any) jest.clearAllMocks() }) @@ -31,6 +32,7 @@ describe('soundMiddleware', () => { when(actionMock.type).thenReturn('order/fullfillOrdersBatch') when(mockStore.getState()).thenReturn({ orders: {}, + user: { userDarkMode: false }, } as any) soundMiddleware(instance(mockStore))(nextMock)(instance(actionMock)) @@ -114,6 +116,7 @@ describe('soundMiddleware', () => { }, }, }, + user: { userDarkMode: false }, } as any) soundMiddleware(instance(mockStore))(nextMock)(instance(actionMock)) @@ -139,6 +142,7 @@ describe('soundMiddleware', () => { }, }, }, + user: { userDarkMode: false }, } as any) soundMiddleware(instance(mockStore))(nextMock)(instance(actionMock)) From d52fcef5eac1f9585ac1d63e5ffe9d4064f88c7e Mon Sep 17 00:00:00 2001 From: fairlight <31534717+fairlighteth@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:29:36 +0100 Subject: [PATCH 04/12] feat: refactor halloween theme (#3266) * feat: refactor halloween theme * feat: refactor halloween theme * feat: refactor halloween theme * feat: refactor halloween theme --- apps/cowswap-frontend/index.html | 1 - apps/cowswap-frontend/public/halloween.css | 14 -- .../src/assets/images}/fortune-cookie.png | Bin .../assets/images/fortuneCookieHalloween.svg | 1 + .../src/common/constants/theme.ts | 137 +++++++++++++++++- .../src/legacy/components/Footer/index.tsx | 3 +- .../src/legacy/components/Header/styled.tsx | 6 +- .../src/legacy/state/cowToken/middleware.ts | 1 - .../orders/middleware/soundMiddleware.ts | 29 ++-- .../src/legacy/theme/baseTheme.tsx | 22 +++ .../src/legacy/theme/cowSwapAssets.ts | 30 ++-- .../containers/FortuneWidget/index.tsx | 4 +- .../modules/twap/hooks/useCreateTwapOrder.ts | 1 - libs/assets/src/cow-swap/halloween-spider.svg | 2 +- 14 files changed, 203 insertions(+), 48 deletions(-) delete mode 100644 apps/cowswap-frontend/public/halloween.css rename {libs/assets/src/cow-swap => apps/cowswap-frontend/src/assets/images}/fortune-cookie.png (100%) create mode 100644 apps/cowswap-frontend/src/assets/images/fortuneCookieHalloween.svg diff --git a/apps/cowswap-frontend/index.html b/apps/cowswap-frontend/index.html index 03c75102a9..37517addc5 100644 --- a/apps/cowswap-frontend/index.html +++ b/apps/cowswap-frontend/index.html @@ -3,7 +3,6 @@ CoW Swap | The smartest way to trade cryptocurrencies - \ No newline at end of file diff --git a/apps/cowswap-frontend/src/common/constants/theme.ts b/apps/cowswap-frontend/src/common/constants/theme.ts index 6f4442824d..233b06488e 100644 --- a/apps/cowswap-frontend/src/common/constants/theme.ts +++ b/apps/cowswap-frontend/src/common/constants/theme.ts @@ -1,3 +1,9 @@ +import fortuneCookieRegular from 'assets/images/fortune-cookie.png' +import fortuneCookieHalloween from 'assets/images/fortuneCookieHalloween.svg' + +// Enable to activate halloween theme elements for dark mode +export const HALLOWEEN_MODE = true + export enum UI { // Colors COLOR_WHITE = '--cow-color-white', @@ -15,13 +21,13 @@ export enum UI { COLOR_BORDER = '--cow-color-border', COLOR_CONTAINER_BG_01 = '--cow-container-bg-01', COLOR_CONTAINER_BG_02 = '--cow-container-bg-02', - + // Misc MODAL_BACKDROP = '--cow-modal-backdrop', BORDER_RADIUS_NORMAL = '--cow-border-radius-normal', PADDING_NORMAL = '--cow-padding-normal', BOX_SHADOW_NORMAL = '--cow-box-shadow-normal', - + // Icons ICON_SIZE_NORMAL = '--cow-icon-size-normal', ICON_SIZE_LARGE = '--cow-icon-size-large', @@ -63,3 +69,130 @@ export enum UI { FONT_SIZE_LARGER = '--cow-font-size-larger', FONT_SIZE_LARGEST = '--cow-font-size-largest', } + +export function cowSwapLogo(darkMode: boolean): string { + // Halloween version + const halloweenModeLogo = ` + ` + + // Regular Dark mode logo + const darkModeLogo = ` + + ` + + // Regular Light mode logo + const lightModeLogo = `` + + return darkMode && HALLOWEEN_MODE ? halloweenModeLogo : darkMode ? darkModeLogo : lightModeLogo +} + +// Footer cows image +export function footerImage(darkMode: boolean): string { + const lightModeImage = `` + + const darkModeImage = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ` + + const halloweenImage = `` + + return darkMode && HALLOWEEN_MODE ? halloweenImage : darkMode ? darkModeImage : lightModeImage +} + +// Fortune cookie image +export function fortuneCookieImage(darkMode: boolean): string { + const lightModeImage = fortuneCookieRegular + const darkModeImage = fortuneCookieRegular + const halloweenImage = fortuneCookieHalloween + + return darkMode && HALLOWEEN_MODE ? halloweenImage : darkMode ? darkModeImage : lightModeImage +} diff --git a/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx b/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx index d3df8aa993..538f7a2b90 100644 --- a/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Footer/index.tsx @@ -3,7 +3,8 @@ import styled from 'styled-components/macro' import { Polling } from 'legacy/components/Header/Polling' import { useIsDarkMode } from 'legacy/state/user/hooks' -import { footerImage } from 'legacy/theme/cowSwapAssets' + +import { footerImage } from 'common/constants/theme' import { Version } from '../Version' diff --git a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx index 979da4872c..c64895f502 100644 --- a/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx +++ b/apps/cowswap-frontend/src/legacy/components/Header/styled.tsx @@ -11,6 +11,7 @@ import styled, { css } from 'styled-components/macro' import { MenuFlyout, MenuSection, Content as MenuContent, MenuTitle } from 'legacy/components/MenuDropdown/styled' +import { HALLOWEEN_MODE } from 'common/constants/theme' import { UI } from 'common/constants/theme' const activeClassName = 'active' @@ -238,8 +239,9 @@ export const HeaderElement = styled(HeaderElementUni)` export const Wrapper = styled.div<{ isMobileMenuOpen: boolean }>` width: 100%; - // Halloween temporary + // Halloween spider rag ${({ theme }) => + HALLOWEEN_MODE && theme.darkMode && css` &::after { @@ -445,7 +447,7 @@ export const HeaderLinks = styled(HeaderLinksMod)<{ isMobileMenuOpen: boolean }> display: flex; ` } - `}; + `} ` export const TwitterLink = styled(StyledMenuButton)` diff --git a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts index 380b244760..a1212abec9 100644 --- a/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/cowToken/middleware.ts @@ -19,7 +19,6 @@ export const cowTokenMiddleware: Middleware, AppState> = const { chainId, hash } = action.payload const transaction = store.getState().transactions[chainId][hash] - // Halloween temporary const { userDarkMode, matchesDarkMode } = store.getState().user const isDarkMode = userDarkMode === null ? matchesDarkMode : userDarkMode diff --git a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts index 483c3768c4..86c12e784c 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/middleware/soundMiddleware.ts @@ -4,6 +4,8 @@ import { getCowSoundError, getCowSoundSend, getCowSoundSuccess, isMobile } from import { isAnyOf } from '@reduxjs/toolkit' import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux' +import { HALLOWEEN_MODE } from 'common/constants/theme' + import { addPopup } from '../../application/reducer' import { AppState } from '../../index' import { AddPendingOrderParams, BatchOrdersUpdateParams, UpdateOrderParams } from '../actions' @@ -57,30 +59,31 @@ export const soundMiddleware: Middleware, AppState> = (s } } - // Halloween temporary const { userDarkMode, matchesDarkMode } = store.getState().user const isDarkMode = userDarkMode === null ? matchesDarkMode : userDarkMode - let cowSound, - showLighningEffect = false + let cowSound + let showLighningEffect = false + const isHalloweenMode = HALLOWEEN_MODE && isDarkMode + const isHalloweenModeDesktop = HALLOWEEN_MODE && isDarkMode && !isMobile if (isPendingOrderAction(action)) { if (_shouldPlayPendingOrderSound(action.payload)) { - cowSound = getCowSoundSend(isDarkMode) - showLighningEffect = isDarkMode && !isMobile + cowSound = getCowSoundSend(isHalloweenMode) + showLighningEffect = isHalloweenModeDesktop } } else if (isFulfillOrderAction(action)) { - cowSound = getCowSoundSuccess(isDarkMode) - showLighningEffect = isDarkMode && !isMobile + cowSound = getCowSoundSuccess(isHalloweenMode) + showLighningEffect = isHalloweenModeDesktop } else if (isBatchExpireOrderAction(action)) { if (_shouldPlayExpiredOrderSound(action.payload, store)) { - cowSound = getCowSoundError(isDarkMode) + cowSound = getCowSoundError(isHalloweenMode) } } else if (isBatchCancelOrderAction(action)) { - cowSound = getCowSoundError(isDarkMode) + cowSound = getCowSoundError(isHalloweenMode) } else if (isFailedTxAction(action)) { - cowSound = getCowSoundError(isDarkMode) + cowSound = getCowSoundError(isHalloweenMode) } else if (isUpdateOrderAction(action)) { - cowSound = _getUpdatedOrderSound(action.payload, isDarkMode) + cowSound = _getUpdatedOrderSound(action.payload, isHalloweenMode) } if (cowSound) { @@ -115,10 +118,10 @@ function _shouldPlayExpiredOrderSound( }) } -function _getUpdatedOrderSound(payload: UpdateOrderParams, isDarkMode: boolean) { +function _getUpdatedOrderSound(payload: UpdateOrderParams, isHalloweenMode: boolean) { if (!payload.order.isHidden) { // Trigger COW sound when an order is being updated to a non-hidden state - return getCowSoundSend(isDarkMode) + return getCowSoundSend(isHalloweenMode) } return undefined } diff --git a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx index a7b9aff9c3..1fa48280fa 100644 --- a/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx +++ b/apps/cowswap-frontend/src/legacy/theme/baseTheme.tsx @@ -11,6 +11,7 @@ import { colorsUniswap } from 'legacy/theme/colorsUniswap' import { Colors } from 'legacy/theme/styled' import { UI } from 'common/constants/theme' +import { HALLOWEEN_MODE } from 'common/constants/theme' // TODO: This shouldn't be in the base theme // Modal override items @@ -536,4 +537,25 @@ export const ThemedGlobalStyle = createGlobalStyle` } } + // Halloween theme elements + ${ + HALLOWEEN_MODE && + css` + @keyframes blinker { + 50% { + background: black; + } + + 100% { + background: white; + } + } + + body.lightning { + filter: invert(1) grayscale(1); + animation: blinker 333ms linear infinite; + } + ` + } + // ======================== ` diff --git a/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts b/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts index ff08830b3b..1d8946d201 100644 --- a/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts +++ b/apps/cowswap-frontend/src/legacy/theme/cowSwapAssets.ts @@ -1,23 +1,27 @@ +import FORTUNE_COOKIE_IMAGE_REGULAR from 'assets/images/fortune-cookie.png' +import FORTUNE_COOKIE_IMAGE_HALLOWEEN from 'assets/images/fortuneCookieHalloween.svg' + +import { HALLOWEEN_MODE } from 'common/constants/theme' + export function cowSwapLogo(darkMode: boolean): string { // Halloween version - const darkModeLogo = ` - ` + const halloweenModeLogo = ` + ` // Regular Dark mode logo - // const darkModeLogo = ` - // - // ` + const darkModeLogo = ` + + ` // Regular Light mode logo const lightModeLogo = `` - return darkMode ? darkModeLogo : lightModeLogo + return darkMode && HALLOWEEN_MODE ? halloweenModeLogo : darkMode ? darkModeLogo : lightModeLogo } // Footer cows image export function footerImage(darkMode: boolean): string { const lightModeImage = `` - const darkModeImage = ` @@ -108,8 +112,14 @@ export function footerImage(darkMode: boolean): string { - - ` + ` + const halloweenImage = `` + + return darkMode && HALLOWEEN_MODE ? halloweenImage : darkMode ? darkModeImage : lightModeImage +} - return darkMode ? darkModeImage : lightModeImage +// Fortune cookie image +export function fortuneCookieImage(darkMode: boolean): string { + if (darkMode && HALLOWEEN_MODE) return FORTUNE_COOKIE_IMAGE_HALLOWEEN + return darkMode ? FORTUNE_COOKIE_IMAGE_REGULAR : FORTUNE_COOKIE_IMAGE_REGULAR } diff --git a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx index 2ec8e3ab9f..1b0df006d4 100644 --- a/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/fortune/containers/FortuneWidget/index.tsx @@ -3,7 +3,6 @@ import { useSetAtom } from 'jotai' import { useCallback, useMemo, useRef, useState } from 'react' import { openFortuneCookieAnalytics, shareFortuneTwitterAnalytics } from '@cowprotocol/analytics' -import fortuneCookieImage from '@cowprotocol/assets/cow-swap/fortune-cookie.png' import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg' import { useInterval } from '@cowprotocol/common-hooks' import { addBodyClass, removeBodyClass } from '@cowprotocol/common-utils' @@ -24,6 +23,7 @@ import { updateOpenFortuneAtom, } from 'modules/fortune/state/fortuneStateAtom' +import { fortuneCookieImage } from 'common/constants/theme' import { UI } from 'common/constants/theme' import { SuccessBanner } from 'pages/Claim/styled' @@ -77,7 +77,7 @@ const FortuneButton = styled.div<{ isDailyFortuneChecked: boolean }>` --size: 90%; content: ''; display: block; - background: url(${fortuneCookieImage}) no-repeat center 100% / contain; + background: ${({ theme }) => `url(${fortuneCookieImage(theme.darkMode)}) no-repeat center 100% / contain`}; width: var(--size); height: var(--size); transition: transform 0.3s ease-in-out; diff --git a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts index 5843a4fc96..a7f0e59583 100644 --- a/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts +++ b/apps/cowswap-frontend/src/modules/twap/hooks/useCreateTwapOrder.ts @@ -56,7 +56,6 @@ export function useCreateTwapOrder() { const { priceImpact } = useTradePriceImpact() const { confirmPriceImpactWithoutFee } = useConfirmPriceImpactWithoutFee() - // Halloween temporary const darkMode = useIsDarkMode() return useCallback( diff --git a/libs/assets/src/cow-swap/halloween-spider.svg b/libs/assets/src/cow-swap/halloween-spider.svg index d4754a21a2..d84e2a0aab 100644 --- a/libs/assets/src/cow-swap/halloween-spider.svg +++ b/libs/assets/src/cow-swap/halloween-spider.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 3e8a18c9e850805e3bce76278dad2938ac6a3853 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Tue, 24 Oct 2023 18:52:03 +0100 Subject: [PATCH 05/12] feat: integrate layer3 --- apps/cowswap-frontend/index.html | 1 + .../modules/limitOrders/containers/LimitOrdersWidget/index.tsx | 1 + .../src/modules/swap/containers/SwapWidget/index.tsx | 1 + 3 files changed, 3 insertions(+) diff --git a/apps/cowswap-frontend/index.html b/apps/cowswap-frontend/index.html index 37517addc5..33d3e4f84f 100644 --- a/apps/cowswap-frontend/index.html +++ b/apps/cowswap-frontend/index.html @@ -77,5 +77,6 @@
+ diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx index a416b9bbb4..db5aacf7ed 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx @@ -264,6 +264,7 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { outputCurrencyInfo={outputCurrencyPreviewInfo} /> )} +
{isUnlocked && } ) diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx index 07a12bff92..3f2e97915a 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx @@ -272,6 +272,7 @@ export function SwapWidget() { inputCurrencyInfo={inputCurrencyInfo} outputCurrencyInfo={outputCurrencyInfo} /> +
From e74752436a9193e0b33c48db7edaeb21b41117e4 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Wed, 25 Oct 2023 16:31:59 +0100 Subject: [PATCH 06/12] feat: create banner component --- apps/cowswap-frontend/index.html | 3 +-- .../containers/LimitOrdersWidget/index.tsx | 3 ++- .../src/modules/swap/containers/SwapWidget/index.tsx | 3 ++- libs/ui/src/index.ts | 1 + libs/ui/src/pure/Layer3Banner/index.tsx | 12 ++++++++++++ 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 libs/ui/src/pure/Layer3Banner/index.tsx diff --git a/apps/cowswap-frontend/index.html b/apps/cowswap-frontend/index.html index 33d3e4f84f..e5dc2fa973 100644 --- a/apps/cowswap-frontend/index.html +++ b/apps/cowswap-frontend/index.html @@ -76,7 +76,6 @@
- - + diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx index db5aacf7ed..b06304d6d6 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx @@ -2,6 +2,7 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai' import React, { useMemo } from 'react' import { OrderKind } from '@cowprotocol/cow-sdk' +import { Layer3Banner } from '@cowprotocol/ui' import { Field } from 'legacy/state/types' @@ -264,7 +265,7 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { outputCurrencyInfo={outputCurrencyPreviewInfo} /> )} -
+ {isUnlocked && } ) diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx index 3f2e97915a..76d10e2717 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx @@ -1,6 +1,7 @@ import React, { useMemo, useState } from 'react' import { isFractionFalsy } from '@cowprotocol/common-utils' +import { Layer3Banner } from '@cowprotocol/ui' import { useIsSafeViaWc, useWalletDetails, useWalletInfo } from '@cowprotocol/wallet' import { NetworkAlert } from 'legacy/components/NetworkAlert/NetworkAlert' @@ -272,7 +273,7 @@ export function SwapWidget() { inputCurrencyInfo={inputCurrencyInfo} outputCurrencyInfo={outputCurrencyInfo} /> -
+ diff --git a/libs/ui/src/index.ts b/libs/ui/src/index.ts index f4df9da04b..b37656d5f5 100644 --- a/libs/ui/src/index.ts +++ b/libs/ui/src/index.ts @@ -9,4 +9,5 @@ export * from './pure/SelectDropdown' export * from './pure/Tooltip' export * from './pure/Popover' export * from './pure/ExternalLink' +export * from './pure/Layer3Banner' export * from './enum' diff --git a/libs/ui/src/pure/Layer3Banner/index.tsx b/libs/ui/src/pure/Layer3Banner/index.tsx new file mode 100644 index 0000000000..bb8deda44d --- /dev/null +++ b/libs/ui/src/pure/Layer3Banner/index.tsx @@ -0,0 +1,12 @@ +import { Helmet } from 'react-helmet' + +export function Layer3Banner() { + return ( + <> + + + +
+ + ) +} From 61eee04f827496d0bc1897204562367566bb7a6e Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Wed, 25 Oct 2023 18:13:44 +0100 Subject: [PATCH 07/12] feat: add style --- .../containers/LimitOrdersWidget/index.tsx | 2 +- libs/ui/src/pure/Layer3Banner/index.tsx | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx index b06304d6d6..3fbe39a0a6 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx @@ -257,6 +257,7 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { inputCurrencyInfo={inputCurrencyInfo} outputCurrencyInfo={outputCurrencyInfo} /> + {tradeContext && ( { outputCurrencyInfo={outputCurrencyPreviewInfo} /> )} - {isUnlocked && } ) diff --git a/libs/ui/src/pure/Layer3Banner/index.tsx b/libs/ui/src/pure/Layer3Banner/index.tsx index bb8deda44d..a0ba00611a 100644 --- a/libs/ui/src/pure/Layer3Banner/index.tsx +++ b/libs/ui/src/pure/Layer3Banner/index.tsx @@ -1,12 +1,21 @@ import { Helmet } from 'react-helmet' +import styled from 'styled-components/macro' -export function Layer3Banner() { +const Wrapper = styled.div` + ${({ addMargin = false }) => addMargin && 'margin: 15px 0;'} +` + +export interface Layer3BannerProps { + addMargin?: boolean +} + +export function Layer3Banner(props: Layer3BannerProps) { return ( - <> + - +
- +
) } From cd98e356826147ab274b4960361dd3949ae69f67 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Wed, 25 Oct 2023 18:14:09 +0100 Subject: [PATCH 08/12] test: test adding fortunes --- .../src/modules/fortune/state/fortunesListAtom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts index e19fa38250..9f5099fd1f 100644 --- a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts +++ b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts @@ -5,7 +5,7 @@ import { RAW_CODE_LINK } from '@cowprotocol/common-const' import { FortuneItem } from 'modules/fortune/types' -const FILE_PATH = '/configuration/config/fortunes.json' +const FILE_PATH = '/gogonimago-patch-1/config/fortunes.json' const fortuneFetchAtom = atom(async () => { const fortunes: FortuneItem[] = await fetch(RAW_CODE_LINK + FILE_PATH).then((res) => res.json()) From bb2f29e4b13a23d346e7dd8193c52e71b89b3c15 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Wed, 25 Oct 2023 18:24:48 +0100 Subject: [PATCH 09/12] fix: fix marging --- .../src/modules/swap/containers/SwapWidget/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx index 76d10e2717..a41db37b96 100644 --- a/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/swap/containers/SwapWidget/index.tsx @@ -273,7 +273,7 @@ export function SwapWidget() { inputCurrencyInfo={inputCurrencyInfo} outputCurrencyInfo={outputCurrencyInfo} /> - + From b5e1cdd0142af8f42b7f6def834623f9f28f89c0 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Wed, 25 Oct 2023 19:52:02 +0100 Subject: [PATCH 10/12] feat: add feature flag --- .../limitOrders/containers/LimitOrdersWidget/index.tsx | 5 ++++- .../src/modules/swap/containers/SwapWidget/index.tsx | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx index 3fbe39a0a6..1e76af9b36 100644 --- a/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx +++ b/apps/cowswap-frontend/src/modules/limitOrders/containers/LimitOrdersWidget/index.tsx @@ -16,6 +16,7 @@ import { BulletListItem, UnlockWidgetScreen } from 'modules/trade/pure/UnlockWid import { TradeFormValidation, useGetTradeFormValidation } from 'modules/tradeFormValidation' import { useSetTradeQuoteParams, useTradeQuote } from 'modules/tradeQuote' +import { FeatureGuard } from 'common/containers/FeatureGuard' import { useRateInfoParams } from 'common/hooks/useRateInfoParams' import { CurrencyInfo } from 'common/pure/CurrencyInputPanel/types' @@ -257,7 +258,9 @@ const LimitOrders = React.memo((props: LimitOrdersProps) => { inputCurrencyInfo={inputCurrencyInfo} outputCurrencyInfo={outputCurrencyInfo} /> - + + + {tradeContext && ( - + + + + From 3a82bacc0693834aaec33559a359324e97f47fdd Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Thu, 26 Oct 2023 16:33:00 +0100 Subject: [PATCH 11/12] chore: revert change. Point to configuration branch --- .../src/modules/fortune/state/fortunesListAtom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts index 9f5099fd1f..e19fa38250 100644 --- a/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts +++ b/apps/cowswap-frontend/src/modules/fortune/state/fortunesListAtom.ts @@ -5,7 +5,7 @@ import { RAW_CODE_LINK } from '@cowprotocol/common-const' import { FortuneItem } from 'modules/fortune/types' -const FILE_PATH = '/gogonimago-patch-1/config/fortunes.json' +const FILE_PATH = '/configuration/config/fortunes.json' const fortuneFetchAtom = atom(async () => { const fortunes: FortuneItem[] = await fetch(RAW_CODE_LINK + FILE_PATH).then((res) => res.json()) From 89525475d8c0fbb7ead073e0d94de649adf9bc07 Mon Sep 17 00:00:00 2001 From: Anxo Rodriguez Date: Thu, 26 Oct 2023 16:35:20 +0100 Subject: [PATCH 12/12] chore: remove empty spaces --- apps/cowswap-frontend/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/cowswap-frontend/index.html b/apps/cowswap-frontend/index.html index e5dc2fa973..37517addc5 100644 --- a/apps/cowswap-frontend/index.html +++ b/apps/cowswap-frontend/index.html @@ -76,6 +76,6 @@
- +