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 && } } /** * @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`; fjs.parentNode.insertBefore(js, fjs); })(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: `
` } } 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
} } 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 }