mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-13 23:16:47 +00:00
287 lines
7.9 KiB
JavaScript
287 lines
7.9 KiB
JavaScript
import { Component, useEffect, useState } from 'react'
|
||
import PropTypes from 'prop-types'
|
||
import { siteConfig } from '@/lib/config'
|
||
|
||
export default function Messenger() {
|
||
const pageId = siteConfig('FACEBOOK_PAGE_ID')
|
||
const appId = siteConfig('FACEBOOK_APP_ID')
|
||
const language = siteConfig('LANG').replace('-', '_')
|
||
|
||
// 新增一个状态变量用于追踪是否已经滚动过
|
||
const [showMessenger, setShowMessenger] = useState(false);
|
||
|
||
const showTheComponent = () => {
|
||
window.removeEventListener('scroll', showTheComponent);
|
||
if (!showMessenger) {
|
||
setShowMessenger(true);
|
||
}
|
||
};
|
||
|
||
// 延时7秒,或页面滚动时加载该组件
|
||
useEffect(() => {
|
||
window.addEventListener('scroll', showTheComponent);
|
||
setTimeout(() => {
|
||
showTheComponent()
|
||
}, 7000);
|
||
return () => {
|
||
window.removeEventListener('scroll', showTheComponent);
|
||
};
|
||
}, []);
|
||
|
||
return <>
|
||
{showMessenger && <MessengerCustomerChat
|
||
pageId={pageId}
|
||
appId={appId}
|
||
language={language}
|
||
shouldShowDialog={true}
|
||
/>}
|
||
</>
|
||
}
|
||
|
||
/**
|
||
* @see https://github.com/Yoctol/react-messenger-customer-chat
|
||
*/
|
||
class MessengerCustomerChat extends Component {
|
||
constructor(props) {
|
||
super(props)
|
||
this.state = {
|
||
fbLoaded: false,
|
||
shouldShowDialog: undefined
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 初始化
|
||
*/
|
||
componentDidMount() {
|
||
this.setFbAsyncInit()
|
||
this.reloadSDKAsynchronously()
|
||
}
|
||
|
||
componentDidUpdate(prevProps) {
|
||
if (
|
||
prevProps.pageId !== this.props.pageId ||
|
||
prevProps.appId !== this.props.appId ||
|
||
prevProps.shouldShowDialog !== this.props.shouldShowDialog ||
|
||
prevProps.htmlRef !== this.props.htmlRef ||
|
||
prevProps.minimized !== this.props.minimized ||
|
||
prevProps.themeColor !== this.props.themeColor ||
|
||
prevProps.loggedInGreeting !== this.props.loggedInGreeting ||
|
||
prevProps.loggedOutGreeting !== this.props.loggedOutGreeting ||
|
||
prevProps.greetingDialogDisplay !== this.props.greetingDialogDisplay ||
|
||
prevProps.greetingDialogDelay !== this.props.greetingDialogDelay ||
|
||
prevProps.autoLogAppEvents !== this.props.autoLogAppEvents ||
|
||
prevProps.xfbml !== this.props.xfbml ||
|
||
prevProps.version !== this.props.version ||
|
||
prevProps.language !== this.props.language
|
||
) {
|
||
this.setFbAsyncInit()
|
||
this.reloadSDKAsynchronously()
|
||
}
|
||
}
|
||
|
||
componentWillUnmount() {
|
||
if (window.FB !== undefined) {
|
||
window.FB.CustomerChat.hide()
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 初始化
|
||
*/
|
||
setFbAsyncInit() {
|
||
const { appId, autoLogAppEvents, xfbml, version } = this.props
|
||
|
||
window.fbAsyncInit = () => {
|
||
window.FB.init({
|
||
appId,
|
||
autoLogAppEvents,
|
||
xfbml,
|
||
version: `v${version}`
|
||
})
|
||
|
||
this.setState({ fbLoaded: true })
|
||
}
|
||
}
|
||
|
||
loadSDKAsynchronously() {
|
||
const { language } = this.props;
|
||
/* eslint-disable */
|
||
(function (d, s, id) {
|
||
var js,
|
||
fjs = d.getElementsByTagName(s)[0];
|
||
if (d.getElementById(id)) {
|
||
return;
|
||
}
|
||
js = d.createElement(s);
|
||
js.id = id;
|
||
js.src = `https://connect.facebook.net/${language}/sdk/xfbml.customerchat.js`;
|
||
if (fjs && fjs.parentNode && fjs.parentNode.contains(fjs)) {
|
||
fjs.parentNode.insertBefore(js, fjs);
|
||
} else {
|
||
document.body.appendChild(js);
|
||
}
|
||
})(document, 'script', 'facebook-jssdk');
|
||
/* eslint-enable */
|
||
}
|
||
|
||
removeFacebookSDK() {
|
||
removeElementByIds(['facebook-jssdk', 'fb-root'])
|
||
|
||
delete window.FB
|
||
}
|
||
|
||
reloadSDKAsynchronously() {
|
||
this.removeFacebookSDK()
|
||
this.loadSDKAsynchronously()
|
||
}
|
||
|
||
controlPlugin() {
|
||
const { shouldShowDialog } = this.props
|
||
|
||
if (shouldShowDialog) {
|
||
window.FB.CustomerChat.showDialog()
|
||
} else {
|
||
window.FB.CustomerChat.hideDialog()
|
||
}
|
||
}
|
||
|
||
subscribeEvents() {
|
||
const { onCustomerChatDialogShow, onCustomerChatDialogHide } = this.props
|
||
|
||
if (onCustomerChatDialogShow) {
|
||
window.FB.Event.subscribe(
|
||
'customerchat.dialogShow',
|
||
onCustomerChatDialogShow
|
||
)
|
||
}
|
||
|
||
if (onCustomerChatDialogHide) {
|
||
window.FB.Event.subscribe(
|
||
'customerchat.dialogHide',
|
||
onCustomerChatDialogHide
|
||
)
|
||
}
|
||
}
|
||
|
||
createMarkup() {
|
||
const {
|
||
pageId,
|
||
htmlRef,
|
||
minimized,
|
||
themeColor,
|
||
loggedInGreeting,
|
||
loggedOutGreeting,
|
||
greetingDialogDisplay,
|
||
greetingDialogDelay
|
||
} = this.props
|
||
|
||
const refAttribute = htmlRef !== undefined ? `ref="${htmlRef}"` : ''
|
||
const minimizedAttribute =
|
||
minimized !== undefined ? `minimized="${minimized}"` : ''
|
||
const themeColorAttribute =
|
||
themeColor !== undefined ? `theme_color="${themeColor}"` : ''
|
||
const loggedInGreetingAttribute =
|
||
loggedInGreeting !== undefined
|
||
? `logged_in_greeting="${loggedInGreeting}"`
|
||
: ''
|
||
const loggedOutGreetingAttribute =
|
||
loggedOutGreeting !== undefined
|
||
? `logged_out_greeting="${loggedOutGreeting}"`
|
||
: ''
|
||
const greetingDialogDisplayAttribute =
|
||
greetingDialogDisplay !== undefined
|
||
? `greeting_dialog_display="${greetingDialogDisplay}"`
|
||
: ''
|
||
const greetingDialogDelayAttribute =
|
||
greetingDialogDelay !== undefined
|
||
? `greeting_dialog_delay="${greetingDialogDelay}"`
|
||
: ''
|
||
|
||
return {
|
||
__html: `<div
|
||
class="fb-customerchat"
|
||
page_id="${pageId}"
|
||
${refAttribute}
|
||
${minimizedAttribute}
|
||
${themeColorAttribute}
|
||
${loggedInGreetingAttribute}
|
||
${loggedOutGreetingAttribute}
|
||
${greetingDialogDisplayAttribute}
|
||
${greetingDialogDelayAttribute}
|
||
></div>`
|
||
}
|
||
}
|
||
|
||
render() {
|
||
const { fbLoaded, shouldShowDialog } = this.state
|
||
|
||
if (fbLoaded && shouldShowDialog !== this.props.shouldShowDialog) {
|
||
document.addEventListener(
|
||
'DOMNodeInserted',
|
||
(event) => {
|
||
const element = event.target
|
||
if (
|
||
element.className &&
|
||
typeof element.className === 'string' &&
|
||
element.className.includes('fb_dialog')
|
||
) {
|
||
this.controlPlugin()
|
||
}
|
||
},
|
||
false
|
||
)
|
||
this.subscribeEvents()
|
||
}
|
||
// Add a random key to rerender. Reference:
|
||
// https://stackoverflow.com/questions/30242530/dangerouslysetinnerhtml-doesnt-update-during-render
|
||
return <div key={Date()} dangerouslySetInnerHTML={this.createMarkup()} />
|
||
}
|
||
}
|
||
|
||
const removeElementByIds = (ids) => {
|
||
ids.forEach((id) => {
|
||
const element = document.getElementById(id)
|
||
if (element && element.parentNode) {
|
||
element.parentNode.removeChild(element)
|
||
}
|
||
})
|
||
}
|
||
|
||
MessengerCustomerChat.propTypes = {
|
||
pageId: PropTypes.string.isRequired,
|
||
appId: PropTypes.string,
|
||
shouldShowDialog: PropTypes.bool,
|
||
htmlRef: PropTypes.string,
|
||
minimized: PropTypes.bool,
|
||
themeColor: PropTypes.string,
|
||
loggedInGreeting: PropTypes.string,
|
||
loggedOutGreeting: PropTypes.string,
|
||
greetingDialogDisplay: PropTypes.oneOf(['show', 'hide', 'fade']),
|
||
greetingDialogDelay: PropTypes.number,
|
||
autoLogAppEvents: PropTypes.bool,
|
||
xfbml: PropTypes.bool,
|
||
version: PropTypes.string,
|
||
language: PropTypes.string,
|
||
onCustomerChatDialogShow: PropTypes.func,
|
||
onCustomerChatDialogHide: PropTypes.func
|
||
}
|
||
|
||
MessengerCustomerChat.defaultProps = {
|
||
appId: null,
|
||
shouldShowDialog: false,
|
||
htmlRef: undefined,
|
||
minimized: undefined,
|
||
themeColor: undefined,
|
||
loggedInGreeting: undefined,
|
||
loggedOutGreeting: undefined,
|
||
greetingDialogDisplay: undefined,
|
||
greetingDialogDelay: undefined,
|
||
autoLogAppEvents: true,
|
||
xfbml: true,
|
||
version: '11.0',
|
||
language: 'en_US',
|
||
onCustomerChatDialogShow: undefined,
|
||
onCustomerChatDialogHide: undefined
|
||
}
|