better sound support and fix settings
This commit is contained in:
parent
f52cb54008
commit
0447fc5d61
|
@ -31,10 +31,10 @@ import useJupiterMints from '../../hooks/useJupiterMints'
|
|||
import { RouteInfo } from 'types/jupiter'
|
||||
import useJupiterSwapData from './useJupiterSwapData'
|
||||
import { Transaction } from '@solana/web3.js'
|
||||
import useAudio from 'hooks/useAudio'
|
||||
import { SOUND_SETTINGS_KEY } from 'utils/constants'
|
||||
import { INITIAL_SOUND_SETTINGS } from 'pages/settings'
|
||||
import useLocalStorageState from 'hooks/useLocalStorageState'
|
||||
import { Howl } from 'howler'
|
||||
|
||||
type JupiterRouteInfoProps = {
|
||||
amountIn: Decimal
|
||||
|
@ -109,7 +109,10 @@ const JupiterRouteInfo = ({
|
|||
const { mangoTokens } = useJupiterMints()
|
||||
const { inputTokenInfo, outputTokenInfo } = useJupiterSwapData()
|
||||
const inputBank = mangoStore((s) => s.swap.inputBank)
|
||||
const { play } = useAudio('/sounds/swap-success.mp3')
|
||||
const successSound = new Howl({
|
||||
src: ['/sounds/swap-success.mp3'],
|
||||
volume: 0.2,
|
||||
})
|
||||
const [soundSettings] = useLocalStorageState(
|
||||
SOUND_SETTINGS_KEY,
|
||||
INITIAL_SOUND_SETTINGS
|
||||
|
@ -185,13 +188,14 @@ const JupiterRouteInfo = ({
|
|||
set((s) => {
|
||||
s.swap.success = true
|
||||
})
|
||||
if (soundSettings['swap-success'].active) {
|
||||
play()
|
||||
if (soundSettings['swap-success']) {
|
||||
successSound.play()
|
||||
}
|
||||
notify({
|
||||
title: 'Transaction confirmed',
|
||||
type: 'success',
|
||||
txid: tx,
|
||||
noSound: true,
|
||||
})
|
||||
actions.fetchGroup()
|
||||
await actions.reloadMangoAccount()
|
||||
|
|
|
@ -34,9 +34,7 @@ const SwapSuccessParticles = () => {
|
|||
}
|
||||
}, [showSwapAnimation])
|
||||
|
||||
return animationSettings['swap-success'].active &&
|
||||
showSwapAnimation &&
|
||||
tokenLogo ? (
|
||||
return animationSettings['swap-success'] && showSwapAnimation && tokenLogo ? (
|
||||
<Particles
|
||||
id="tsparticles"
|
||||
options={{
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
|
||||
const useAudio = (url: string) => {
|
||||
const [audio] = useState(new Audio(url))
|
||||
const [playing, setPlaying] = useState(false)
|
||||
|
||||
const play = () => setPlaying(true)
|
||||
|
||||
useEffect(() => {
|
||||
playing ? audio.play() : audio.pause()
|
||||
}, [playing])
|
||||
|
||||
useEffect(() => {
|
||||
audio.addEventListener('ended', () => setPlaying(false))
|
||||
return () => {
|
||||
audio.removeEventListener('ended', () => setPlaying(false))
|
||||
}
|
||||
}, [])
|
||||
|
||||
return { playing, play }
|
||||
}
|
||||
|
||||
export default useAudio
|
|
@ -22,12 +22,14 @@
|
|||
"@solflare-wallet/pfp": "^0.0.6",
|
||||
"@tanstack/react-query": "^4.10.1",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
"@types/howler": "^2.2.7",
|
||||
"@types/lodash": "^4.14.185",
|
||||
"assert": "^2.0.0",
|
||||
"big.js": "^6.2.1",
|
||||
"date-fns": "^2.29.3",
|
||||
"dayjs": "^1.11.3",
|
||||
"decimal.js": "^10.4.0",
|
||||
"howler": "^2.2.3",
|
||||
"html-react-parser": "^3.0.4",
|
||||
"immer": "^9.0.12",
|
||||
"lodash": "^4.17.21",
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
SOUND_SETTINGS_KEY,
|
||||
} from 'utils/constants'
|
||||
import Switch from '@components/forms/Switch'
|
||||
import { useCallback, useEffect, useMemo, useReducer } from 'react'
|
||||
import { useCallback, useMemo, useReducer } from 'react'
|
||||
import { CheckCircleIcon } from '@heroicons/react/20/solid'
|
||||
import Image from 'next/legacy/image'
|
||||
|
||||
|
@ -63,28 +63,22 @@ const NOTIFICATION_POSITIONS = [
|
|||
]
|
||||
|
||||
interface ReducerItems {
|
||||
[key: string]: {
|
||||
active: boolean
|
||||
}
|
||||
[key: string]: boolean
|
||||
}
|
||||
|
||||
export const INITIAL_ANIMATION_SETTINGS = {
|
||||
'orderbook-flash': {
|
||||
active: true,
|
||||
},
|
||||
'swap-success': {
|
||||
active: true,
|
||||
},
|
||||
'orderbook-flash': true,
|
||||
'swap-success': true,
|
||||
}
|
||||
|
||||
export const INITIAL_SOUND_SETTINGS = {
|
||||
'swap-success': {
|
||||
active: true,
|
||||
},
|
||||
'swap-success': true,
|
||||
'transaction-success': true,
|
||||
'transaction-fail': true,
|
||||
}
|
||||
|
||||
const settingsReducer = (state: ReducerItems, name: string) => {
|
||||
const updatedState = { ...state, [name]: { active: !state[name].active } }
|
||||
const updatedState = { ...state, [name]: !state[name] }
|
||||
return updatedState
|
||||
}
|
||||
|
||||
|
@ -109,30 +103,35 @@ const Settings: NextPage = () => {
|
|||
const themes = useMemo(() => {
|
||||
return [t('settings:light'), t('settings:mango'), t('settings:dark')]
|
||||
}, [t])
|
||||
const [sounds, soundsDispatch] = useReducer(
|
||||
settingsReducer,
|
||||
INITIAL_SOUND_SETTINGS
|
||||
)
|
||||
const [, setSoundSettings] = useLocalStorageState(
|
||||
const [, soundsDispatch] = useReducer(settingsReducer, INITIAL_SOUND_SETTINGS)
|
||||
const [soundSettings, setSoundSettings] = useLocalStorageState(
|
||||
SOUND_SETTINGS_KEY,
|
||||
INITIAL_SOUND_SETTINGS
|
||||
)
|
||||
const [animations, animationsDispatch] = useReducer(
|
||||
const [, animationsDispatch] = useReducer(
|
||||
settingsReducer,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
)
|
||||
const [, setAnimationSettings] = useLocalStorageState(
|
||||
const [animationSettings, setAnimationSettings] = useLocalStorageState(
|
||||
ANIMATION_SETTINGS_KEY,
|
||||
INITIAL_ANIMATION_SETTINGS
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setAnimationSettings(animations)
|
||||
}, [animations])
|
||||
const handleToggleAnimationSetting = (settingName: string) => {
|
||||
animationsDispatch(settingName)
|
||||
setAnimationSettings({
|
||||
...animationSettings,
|
||||
[settingName]: !animationSettings[settingName],
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setSoundSettings(sounds)
|
||||
}, [sounds])
|
||||
const handleToggleSoundSetting = (settingName: string) => {
|
||||
soundsDispatch(settingName)
|
||||
setSoundSettings({
|
||||
...soundSettings,
|
||||
[settingName]: !soundSettings[settingName],
|
||||
})
|
||||
}
|
||||
|
||||
const handleLangChange = useCallback(
|
||||
(l: string) => {
|
||||
|
@ -206,25 +205,39 @@ const Settings: NextPage = () => {
|
|||
<div className="flex items-center justify-between border-t border-th-bkg-3 py-4 md:px-4">
|
||||
<p className="mb-2 lg:mb-0">{t('settings:orderbook-flash')}</p>
|
||||
<Switch
|
||||
checked={animations['orderbook-flash'].active}
|
||||
onChange={() => animationsDispatch('orderbook-flash')}
|
||||
checked={animationSettings['orderbook-flash']}
|
||||
onChange={() => handleToggleAnimationSetting('orderbook-flash')}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-t border-th-bkg-3 py-4 md:px-4">
|
||||
<p className="mb-2 lg:mb-0">{t('settings:swap-success')}</p>
|
||||
<Switch
|
||||
checked={animations['swap-success'].active}
|
||||
onChange={() => animationsDispatch('swap-success')}
|
||||
checked={animationSettings['swap-success']}
|
||||
onChange={() => handleToggleAnimationSetting('swap-success')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-12 border-b border-th-bkg-3 pt-8 lg:col-span-8 lg:col-start-3">
|
||||
<h2 className="mb-4 text-base">{t('settings:sounds')}</h2>
|
||||
<div className="flex items-center justify-between border-t border-th-bkg-3 py-4 md:px-4">
|
||||
<p className="mb-2 lg:mb-0">{t('settings:transaction-success')}</p>
|
||||
<Switch
|
||||
checked={soundSettings['transaction-success']}
|
||||
onChange={() => handleToggleSoundSetting('transaction-success')}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-t border-th-bkg-3 py-4 md:px-4">
|
||||
<p className="mb-2 lg:mb-0">{t('settings:transaction-fail')}</p>
|
||||
<Switch
|
||||
checked={soundSettings['transaction-fail']}
|
||||
onChange={() => handleToggleSoundSetting('transaction-fail')}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between border-t border-th-bkg-3 py-4 md:px-4">
|
||||
<p className="mb-2 lg:mb-0">{t('settings:swap-success')}</p>
|
||||
<Switch
|
||||
checked={sounds['swap-success'].active}
|
||||
onChange={() => soundsDispatch('swap-success')}
|
||||
checked={soundSettings['swap-success']}
|
||||
onChange={() => handleToggleSoundSetting('swap-success')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
"sounds": "Sounds",
|
||||
"spanish": "Español",
|
||||
"swap-success": "Swap Success",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector",
|
||||
"theme": "Theme",
|
||||
"top-left": "Top-Left",
|
||||
"top-right": "Top-Right",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector"
|
||||
"transaction-fail": "Transaction Fail",
|
||||
"transaction-success": "Transaction Success"
|
||||
}
|
|
@ -23,8 +23,10 @@
|
|||
"sounds": "Sounds",
|
||||
"spanish": "Español",
|
||||
"swap-success": "Swap Success",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector",
|
||||
"theme": "Theme",
|
||||
"top-left": "Top-Left",
|
||||
"top-right": "Top-Right",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector"
|
||||
"transaction-fail": "Transaction Fail",
|
||||
"transaction-success": "Transaction Success"
|
||||
}
|
|
@ -23,8 +23,10 @@
|
|||
"sounds": "Sounds",
|
||||
"spanish": "Español",
|
||||
"swap-success": "Swap Success",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector",
|
||||
"theme": "Theme",
|
||||
"top-left": "Top-Left",
|
||||
"top-right": "Top-Right",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector"
|
||||
"transaction-fail": "Transaction Fail",
|
||||
"transaction-success": "Transaction Success"
|
||||
}
|
|
@ -23,8 +23,10 @@
|
|||
"sounds": "Sounds",
|
||||
"spanish": "Español",
|
||||
"swap-success": "Swap Success",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector",
|
||||
"theme": "Theme",
|
||||
"top-left": "Top-Left",
|
||||
"top-right": "Top-Right",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector"
|
||||
"transaction-fail": "Transaction Fail",
|
||||
"transaction-success": "Transaction Success"
|
||||
}
|
|
@ -23,8 +23,10 @@
|
|||
"sounds": "Sounds",
|
||||
"spanish": "Español",
|
||||
"swap-success": "Swap Success",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector",
|
||||
"theme": "Theme",
|
||||
"top-left": "Top-Left",
|
||||
"top-right": "Top-Right",
|
||||
"swap-trade-size-selector": "Swap/Trade Size Selector"
|
||||
"transaction-fail": "Transaction Fail",
|
||||
"transaction-success": "Transaction Success"
|
||||
}
|
Binary file not shown.
Binary file not shown.
|
@ -1,4 +1,7 @@
|
|||
import mangoStore from '@store/mangoStore'
|
||||
import { Howl } from 'howler'
|
||||
import { INITIAL_SOUND_SETTINGS } from 'pages/settings'
|
||||
import { SOUND_SETTINGS_KEY } from './constants'
|
||||
|
||||
export type Notification = {
|
||||
type: 'success' | 'info' | 'error' | 'confirm'
|
||||
|
@ -9,16 +12,51 @@ export type Notification = {
|
|||
id: number
|
||||
}
|
||||
|
||||
interface ReducerItems {
|
||||
[key: string]: {
|
||||
active: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export function notify(newNotification: {
|
||||
type?: 'success' | 'info' | 'error' | 'confirm'
|
||||
title: string
|
||||
description?: string
|
||||
txid?: string
|
||||
noSound?: boolean
|
||||
}) {
|
||||
const setMangoStore = mangoStore.getState().set
|
||||
const notifications = mangoStore.getState().notifications
|
||||
const lastId = mangoStore.getState().notificationIdCounter
|
||||
const newId = lastId + 1
|
||||
const successSound = new Howl({
|
||||
src: ['/sounds/transaction-success.mp3'],
|
||||
volume: 0.5,
|
||||
})
|
||||
const failSound = new Howl({
|
||||
src: ['/sounds/transaction-fail.mp3'],
|
||||
volume: 0.2,
|
||||
})
|
||||
const savedSoundSettings = localStorage.getItem(SOUND_SETTINGS_KEY)
|
||||
const soundSettings = savedSoundSettings
|
||||
? JSON.parse(savedSoundSettings)
|
||||
: INITIAL_SOUND_SETTINGS
|
||||
|
||||
if (newNotification.type && !newNotification.noSound) {
|
||||
switch (newNotification.type) {
|
||||
case 'success': {
|
||||
if (soundSettings['transaction-success']) {
|
||||
successSound.play()
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'error': {
|
||||
if (soundSettings['transaction-fail']) {
|
||||
failSound.play()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newNotif: Notification = {
|
||||
id: newId,
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -1516,6 +1516,11 @@
|
|||
"@types/react" "*"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
|
||||
"@types/howler@^2.2.7":
|
||||
version "2.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/howler/-/howler-2.2.7.tgz#5acfbed57f9e1d99b8dabe1b824729e1c1ea1fae"
|
||||
integrity sha512-PEZldwZqJJw1PWRTpupyC7ajVTZA8aHd8nB/Y0n6zRZi5u8ktYDntsHj13ltEiBRqWwF06pASxBEvCTxniG8eA==
|
||||
|
||||
"@types/json-schema@^7.0.9":
|
||||
version "7.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||
|
@ -3910,6 +3915,11 @@ hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
|||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
howler@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/howler/-/howler-2.2.3.tgz#a2eff9b08b586798e7a2ee17a602a90df28715da"
|
||||
integrity sha512-QM0FFkw0LRX1PR8pNzJVAY25JhIWvbKMBFM4gqk+QdV+kPXOhleWGCB6AiAF/goGjIHK2e/nIElplvjQwhr0jg==
|
||||
|
||||
html-dom-parser@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-3.1.2.tgz#c137c42df80e17d185ff35a806925d96cc73f408"
|
||||
|
|
Loading…
Reference in New Issue