import styles from './index.less'import { PureComponent, createRef } from 'react'import QRCode from 'qrcode'import html2canvas from 'html2canvas'import classnames from 'classnames'import preventScroll from 'prevent-scroll'import growingService from '@xb/services/growing'import MaskBasic from '@xb/components/Mask/Basic'import MaskCenter from '@xb/components/Mask/Center'import ButtonBasic from '@xb/components/Button/Basic'import Line from '@xb/components/Line/Basic'import { MountPoint, sleep } from '@xb/utils/dom'import { device } from '@xb/utils/userAgent'import creditService from '@xb/services/credit'import iconLogoComplete from '@xb/assets/icons/icon-logo-complete.png'import ellipseBg from '@xb/assets/ellipse-bg.png'import userImg from '@xb/assets/user.png'class ModalComponent extends PureComponent {  constructor(props) {    super(props)    const { onClick, uniqueId, noteId } = this.props    this.onClick = onClick    this.node = createRef()    this.container = createRef()    this.saveImage = createRef()    this.avatar = createRef()    this.startTime = ''    this.endTime = ''    const link = `${window.location.origin}/course/note/landing/${uniqueId}/${noteId}?sourceType=h5wxshare`    this.action.generateQR(link)    this.state = {      once: true,      qrcode: false,    }  }  action = {    generateQR: async url => {      try {        const baseImage = await QRCode.toDataURL(url)        const image = new Image()        image.src = baseImage        this.node.current.appendChild(image)        this.setState({ qrcode: true })      } catch (err) {        console.error(err)      }    },    generateImage: async () => {      const canvas = this.action.drawCanvas(this.container.current)      await sleep(300)      html2canvas(this.container.current, {        useCORS: true,        logging: false,        canvas,        scale: 10,        letterRendering: true,      }).then(canvas => {        const image = new Image()        image.src = canvas.toDataURL('image/png')        this.saveImage.current.appendChild(image)      })    },    checkPicture: async url => {      return new Promise(resolve => {        const image = new Image()        image.src = url        image.onload = () => {          resolve(url)        }        image.onerror = () => {          resolve(userImg)        }      })    },    DPR: () => {      if (window.devicePixelRatio && window.devicePixelRatio > 1) {        return window.devicePixelRatio      }      return 1    },    parseValue: value => {      return parseInt(value, 10)    },    drawCanvas: node => {      const box = window.getComputedStyle(node)      // DOM 节点计算后宽高      const width = this.action.parseValue(box.width)      const height = this.action.parseValue(box.height)      // 获取像素比      const scaleBy = this.action.DPR()      // 创建自定义 canvas 元素      const canvas = document.createElement('canvas')      // 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比      canvas.width = width * scaleBy      canvas.height = height * scaleBy      // 设定 canvas css宽高为 DOM 节点宽高      canvas.style.width = `${width}px`      canvas.style.height = `${height}px`      // 获取画笔      const context = canvas.getContext('2d')      // 【重要】关闭抗锯齿      context.mozImageSmoothingEnabled = false      context.msImageSmoothingEnabled = false      context.imageSmoothingEnabled = false      // 将所有绘制内容放大像素比倍      context.scale(scaleBy, scaleBy)      return canvas    },    touchstart: () => {      this.startTime = +new Date()    },    touchend: () => {      this.endTime = +new Date()      const { uniqueId } = this.props      if (this.endTime - this.startTime > 700) {        const { payload } = this.props        growingService.noteShareImage(payload)        try {          creditService.shareNote(uniqueId)        } catch (error) {          console.error(error)        }      }    },  }  render() {    const { userUrl, userName, createdTime, content, productTitle } = this.props    const { once, qrcode } = this.state    const isIOSBox = device.isIOS ? styles.isIOSBox : ''    const isIOSNote = device.isIOS ? styles.isIOSNote : ''    const avatar = this.action.checkPicture(userUrl)    avatar.then(url => {      this.avatar.current.src = url      if (once && qrcode) {        this.action.generateImage()        this.setState({ once: false })      }    })    return (      <MaskBasic onClick={this.onClick}>        <MaskCenter>          <div className={classnames(styles.box, isIOSBox)} onClick={e => e.stopPropagation()}>            <div              ref={this.saveImage}              className={styles.containerImage}              onTouchStart={this.action.touchstart}              onTouchEnd={this.action.touchend}            />            <div ref={this.container} className={styles.container}>              <img className={styles.logo} src={iconLogoComplete} />              <img className={styles.ellipse} src={ellipseBg} />              <div className={styles.content}>                <div className={styles.product}>                  <span>来自课程</span>                  <p>{productTitle}</p>                </div>                <div className={styles.userInfo}>                  <img ref={this.avatar} className={styles.avatar} crossOrigin='anonymous' />                  <div className={styles.user}>                    <h3>{userName}</h3>                    <p>{createdTime}</p>                  </div>                </div>                <p className={classnames(styles.note, isIOSNote)}>{content}</p>                <Line className={styles.line} size={15} />                <div className={styles.qrcodeInfo}>                  <div className={styles.qrcode} ref={this.node} />                  <div className={styles.description}>                    <h3>长按识别二维码</h3>                    <p>查看完整笔记,亦可点赞评论</p>                  </div>                </div>              </div>            </div>            <div className={styles.button}>              <ButtonBasic style={{ width: '100%', color: '#222222', fontWeight: 400, boxShadow: 'none' }}>长按按钮分享笔记</ButtonBasic>            </div>          </div>          <div className={styles.close} />        </MaskCenter>      </MaskBasic>    )  }}class GlobalModalSharePicture extends MountPoint {  hide = () => {    preventScroll.off()    this.removeMountPoint()  }  show = options => {    preventScroll.on()    this.render(<ModalComponent onClick={this.hide} {...options} />)  }}export default new GlobalModalSharePicture()