forked from pancakeswap/pancake-frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTradingView.tsx
137 lines (123 loc) · 3.72 KB
/
TradingView.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { Box, FlexProps, useMatchBreakpoints } from '@pancakeswap/uikit'
import { useTranslation } from 'contexts/Localization'
import Script from 'next/script'
import { useEffect, useRef } from 'react'
import { DefaultTheme, useTheme } from 'styled-components'
import { ChartByLabel } from './Chart/ChartbyLabel'
/**
* When the script tag is injected the TradingView object is not immediately
* available on the window. So we listen for when it gets set
*/
const tradingViewListener = async () =>
new Promise<void>((resolve) =>
Object.defineProperty(window, 'TradingView', {
configurable: true,
set(value) {
this.tv = value
resolve(value)
},
}),
)
const initializeTradingView = (TradingViewObj: any, theme: DefaultTheme, localeCode: string, opts: any) => {
let timezone = 'Etc/UTC'
try {
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
} catch (e) {
// noop
}
/* eslint-disable new-cap */
/* eslint-disable no-new */
// @ts-ignore
return new TradingViewObj.widget({
// Advanced Chart Widget uses the legacy embedding scheme,
// an id property should be specified in the settings object
id: opts.container_id,
autosize: true,
height: '100%',
symbol: 'BINANCE:BNBBUSD',
interval: '5',
timezone,
theme: theme.isDark ? 'dark' : 'light',
style: '1',
locale: localeCode,
toolbar_bg: '#f1f3f6',
enable_publishing: false,
allow_symbol_change: true,
hide_side_toolbar: false,
enabled_features: ['header_fullscreen_button'],
...opts,
})
}
interface TradingViewProps {
id: string
symbol: string
}
const TradingView = ({ id, symbol }: TradingViewProps) => {
const { currentLanguage } = useTranslation()
const theme = useTheme()
const widgetRef = useRef<any>()
const { isMobile } = useMatchBreakpoints()
useEffect(() => {
const opts: any = {
container_id: id,
symbol,
}
if (isMobile) {
opts.hide_side_toolbar = true
}
// @ts-ignore
if (window.tv) {
// @ts-ignore
widgetRef.current = initializeTradingView(window.tv, theme, currentLanguage.code, opts)
} else {
tradingViewListener().then((tv) => {
widgetRef.current = initializeTradingView(tv, theme, currentLanguage.code, opts)
})
}
// Ignore isMobile to avoid re-render TV
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [theme, currentLanguage, id, symbol])
return (
<Box overflow="hidden" className="tradingview_container">
<Script src="https://s3.tradingview.com/tv.js" strategy="lazyOnload" id="tv.js" />
<div id={id} />
</Box>
)
}
export function useTradingViewEvent({
id,
onNoDataEvent,
onLoadedEvent,
}: {
id?: string
onNoDataEvent?: () => void
onLoadedEvent?: () => void
}) {
useEffect(() => {
const onNoDataAvailable = (event: MessageEvent) => {
const payload = event.data
if (payload.name === 'tv-widget-no-data') {
if (id && payload.frameElementId === id) {
onNoDataEvent?.()
}
}
if (payload.name === 'tv-widget-load') {
if (id && payload.frameElementId === id) {
onLoadedEvent?.()
}
}
}
window.addEventListener('message', onNoDataAvailable)
// eslint-disable-next-line consistent-return
return () => {
window.removeEventListener('message', onNoDataAvailable)
}
}, [id, onNoDataEvent, onLoadedEvent])
}
// Required to link to TradingView website for the widget
export const TradingViewLabel = ({ symbol, ...props }: { symbol: string } & FlexProps) => {
return (
<ChartByLabel link={`https://www.tradingview.com/symbols/${symbol}`} symbol={symbol} by="TradingView" {...props} />
)
}
export default TradingView