[Glitch] Fix audio/video/images/cards not reacting to window resizes in web UI
Port bb9ca8a587 to glitch-soc
Co-authored-by: Yamagishi Kazutoshi <ykzts@desire.sh>
Co-authored-by: Yamagishi Kazutoshi <ykzts@desire.sh>
Signed-off-by: Thibaut Girka <thib@sitedethib.com>
			
			
This commit is contained in:
		
							parent
							
								
									1c58420831
								
							
						
					
					
						commit
						06309129be
					
				| 
						 | 
				
			
			@ -8,6 +8,7 @@ import { isIOS } from 'flavours/glitch/util/is_mobile';
 | 
			
		|||
import classNames from 'classnames';
 | 
			
		||||
import { autoPlayGif, displayMedia, useBlurhash } from 'flavours/glitch/util/initial_state';
 | 
			
		||||
import { decode } from 'blurhash';
 | 
			
		||||
import { debounce } from 'lodash';
 | 
			
		||||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  hidden: {
 | 
			
		||||
| 
						 | 
				
			
			@ -289,6 +290,14 @@ class MediaGallery extends React.PureComponent {
 | 
			
		|||
    width: this.props.defaultWidth,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  componentDidMount () {
 | 
			
		||||
    window.addEventListener('resize', this.handleResize, { passive: true });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillUnmount () {
 | 
			
		||||
    window.removeEventListener('resize', this.handleResize);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillReceiveProps (nextProps) {
 | 
			
		||||
    if (!is(nextProps.media, this.props.media) && nextProps.visible === undefined) {
 | 
			
		||||
      this.setState({ visible: displayMedia !== 'hide_all' && !nextProps.sensitive || displayMedia === 'show_all' });
 | 
			
		||||
| 
						 | 
				
			
			@ -305,6 +314,14 @@ class MediaGallery extends React.PureComponent {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleResize = debounce(() => {
 | 
			
		||||
    if (this.node) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }, 250, {
 | 
			
		||||
    trailing: true,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  handleOpen = () => {
 | 
			
		||||
    if (this.props.onToggleVisibility) {
 | 
			
		||||
      this.props.onToggleVisibility();
 | 
			
		||||
| 
						 | 
				
			
			@ -319,11 +336,23 @@ class MediaGallery extends React.PureComponent {
 | 
			
		|||
 | 
			
		||||
  handleRef = (node) => {
 | 
			
		||||
    this.node = node;
 | 
			
		||||
    if (node && node.offsetWidth && node.offsetWidth != this.state.width) {
 | 
			
		||||
      if (this.props.cacheWidth) this.props.cacheWidth(node.offsetWidth);
 | 
			
		||||
 | 
			
		||||
    if (this.node) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _setDimensions () {
 | 
			
		||||
    const width = this.node.offsetWidth;
 | 
			
		||||
 
 | 
			
		||||
    if (width && width != this.state.width) {
 | 
			
		||||
      // offsetWidth triggers a layout, so only calculate when we need to
 | 
			
		||||
      if (this.props.cacheWidth) {
 | 
			
		||||
        this.props.cacheWidth(width);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.setState({
 | 
			
		||||
        width: node.offsetWidth,
 | 
			
		||||
        width: width,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import classNames from 'classnames';
 | 
			
		|||
import { throttle } from 'lodash';
 | 
			
		||||
import { encode, decode } from 'blurhash';
 | 
			
		||||
import { getPointerPosition, fileNameFromURL } from 'flavours/glitch/features/video';
 | 
			
		||||
import { debounce } from 'lodash';
 | 
			
		||||
 | 
			
		||||
const digitCharacters = [
 | 
			
		||||
  '0',
 | 
			
		||||
| 
						 | 
				
			
			@ -172,18 +173,22 @@ class Audio extends React.PureComponent {
 | 
			
		|||
  setPlayerRef = c => {
 | 
			
		||||
    this.player = c;
 | 
			
		||||
 | 
			
		||||
    if (c) {
 | 
			
		||||
      const width  = c.offsetWidth;
 | 
			
		||||
      const height = width / (16/9);
 | 
			
		||||
 | 
			
		||||
      if (this.props.cacheWidth) {
 | 
			
		||||
        this.props.cacheWidth(width);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.setState({ width, height });
 | 
			
		||||
    if (this.player) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _setDimensions () {
 | 
			
		||||
    const width  = this.player.offsetWidth;
 | 
			
		||||
    const height = width / (16/9);
 | 
			
		||||
 | 
			
		||||
    if (this.props.cacheWidth) {
 | 
			
		||||
      this.props.cacheWidth(width);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.setState({ width, height });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setSeekRef = c => {
 | 
			
		||||
    this.seek = c;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -213,6 +218,8 @@ class Audio extends React.PureComponent {
 | 
			
		|||
  }
 | 
			
		||||
 
 | 
			
		||||
  componentDidMount () {
 | 
			
		||||
    window.addEventListener('resize', this.handleResize, { passive: true });
 | 
			
		||||
 | 
			
		||||
    const img = new Image();
 | 
			
		||||
    img.crossOrigin = 'anonymous';
 | 
			
		||||
    img.onload = () => this.handlePosterLoad(img);
 | 
			
		||||
| 
						 | 
				
			
			@ -239,6 +246,10 @@ class Audio extends React.PureComponent {
 | 
			
		|||
    this._draw();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillUnmount () {
 | 
			
		||||
    window.removeEventListener('resize', this.handleResize);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  togglePlay = () => {
 | 
			
		||||
    if (this.state.paused) {
 | 
			
		||||
      this.setState({ paused: false }, () => this.audio.play());
 | 
			
		||||
| 
						 | 
				
			
			@ -247,6 +258,14 @@ class Audio extends React.PureComponent {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleResize = debounce(() => {
 | 
			
		||||
    if (this.player) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }, 250, {
 | 
			
		||||
    trailing: true,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  handlePlay = () => {
 | 
			
		||||
    this.setState({ paused: false });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -545,14 +564,13 @@ class Audio extends React.PureComponent {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  _drawTick (x1, y1, x2, y2) {
 | 
			
		||||
    const radius = this._getRadius();
 | 
			
		||||
    const cx = parseInt(this.state.width / 2);
 | 
			
		||||
    const cy = parseInt(radius + (PADDING * this._getScaleCoefficient()));
 | 
			
		||||
    const cx = this._getCX();
 | 
			
		||||
    const cy = this._getCY();
 | 
			
		||||
 | 
			
		||||
    const dx1 = parseInt(cx + x1);
 | 
			
		||||
    const dy1 = parseInt(cy + y1);
 | 
			
		||||
    const dx2 = parseInt(cx + x2);
 | 
			
		||||
    const dy2 = parseInt(cy + y2);
 | 
			
		||||
    const dx1 = Math.ceil(cx + x1);
 | 
			
		||||
    const dy1 = Math.ceil(cy + y1);
 | 
			
		||||
    const dx2 = Math.ceil(cx + x2);
 | 
			
		||||
    const dy2 = Math.ceil(cy + y2);
 | 
			
		||||
 | 
			
		||||
    const gradient = this.canvasContext.createLinearGradient(dx1, dy1, dx2, dy2);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -571,6 +589,14 @@ class Audio extends React.PureComponent {
 | 
			
		|||
    this.canvasContext.stroke();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _getCX() {
 | 
			
		||||
    return Math.floor(this.state.width / 2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _getCY() {
 | 
			
		||||
    return Math.floor(this._getRadius() + (PADDING * this._getScaleCoefficient()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _getColor () {
 | 
			
		||||
    return `rgb(${this.state.color.r}, ${this.state.color.g}, ${this.state.color.b})`;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -619,7 +645,7 @@ class Audio extends React.PureComponent {
 | 
			
		|||
          alt=''
 | 
			
		||||
          width={(this._getRadius() - TICK_SIZE) * 2}
 | 
			
		||||
          height={(this._getRadius() - TICK_SIZE) * 2}
 | 
			
		||||
          style={{ position: 'absolute', left: parseInt(this.state.width / 2), top: parseInt(this._getRadius() + (PADDING * this._getScaleCoefficient())), transform: 'translate(-50%, -50%)', borderRadius: '50%', pointerEvents: 'none' }}
 | 
			
		||||
          style={{ position: 'absolute', left: this._getCX(), top: this._getCY(), transform: 'translate(-50%, -50%)', borderRadius: '50%', pointerEvents: 'none' }}
 | 
			
		||||
        />
 | 
			
		||||
 | 
			
		||||
        <div className='video-player__seek' onMouseDown={this.handleMouseDown} ref={this.setSeekRef}>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import { decode as decodeIDNA } from 'flavours/glitch/util/idna';
 | 
			
		|||
import Icon from 'flavours/glitch/components/icon';
 | 
			
		||||
import { useBlurhash } from 'flavours/glitch/util/initial_state';
 | 
			
		||||
import { decode } from 'blurhash';
 | 
			
		||||
import { debounce } from 'lodash';
 | 
			
		||||
 | 
			
		||||
const getHostname = url => {
 | 
			
		||||
  const parser = document.createElement('a');
 | 
			
		||||
| 
						 | 
				
			
			@ -83,13 +84,20 @@ export default class Card extends React.PureComponent {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  componentDidMount () {
 | 
			
		||||
    window.addEventListener('resize', this.handleResize, { passive: true });
 | 
			
		||||
 | 
			
		||||
    if (this.props.card && this.props.card.get('blurhash')) {
 | 
			
		||||
      this._decode();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillUnmount () {
 | 
			
		||||
    window.removeEventListener('resize', this.handleResize);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentDidUpdate (prevProps) {
 | 
			
		||||
    const { card } = this.props;
 | 
			
		||||
 | 
			
		||||
    if (card.get('blurhash') && (!prevProps.card || prevProps.card.get('blurhash') !== card.get('blurhash'))) {
 | 
			
		||||
      this._decode();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +117,24 @@ export default class Card extends React.PureComponent {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _setDimensions () {
 | 
			
		||||
    const width = this.node.offsetWidth;
 | 
			
		||||
 | 
			
		||||
    if (this.props.cacheWidth) {
 | 
			
		||||
      this.props.cacheWidth(width);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.setState({ width });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleResize = debounce(() => {
 | 
			
		||||
    if (this.node) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }, 250, {
 | 
			
		||||
    trailing: true,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  handlePhotoClick = () => {
 | 
			
		||||
    const { card, onOpenMedia } = this.props;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -141,9 +167,10 @@ export default class Card extends React.PureComponent {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  setRef = c => {
 | 
			
		||||
    if (c) {
 | 
			
		||||
      if (this.props.cacheWidth) this.props.cacheWidth(c.offsetWidth);
 | 
			
		||||
      this.setState({ width: c.offsetWidth });
 | 
			
		||||
    this.node = c;
 | 
			
		||||
 | 
			
		||||
    if (this.node) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@ import React from 'react';
 | 
			
		|||
import PropTypes from 'prop-types';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import { fromJS, is } from 'immutable';
 | 
			
		||||
import { throttle } from 'lodash';
 | 
			
		||||
import { throttle, debounce } from 'lodash';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
import { isFullscreen, requestFullscreen, exitFullscreen } from 'flavours/glitch/util/fullscreen';
 | 
			
		||||
import { displayMedia, useBlurhash } from 'flavours/glitch/util/initial_state';
 | 
			
		||||
| 
						 | 
				
			
			@ -144,10 +144,21 @@ class Video extends React.PureComponent {
 | 
			
		|||
  setPlayerRef = c => {
 | 
			
		||||
    this.player = c;
 | 
			
		||||
 | 
			
		||||
    if (c && c.offsetWidth && c.offsetWidth != this.state.containerWidth) {
 | 
			
		||||
      if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth);
 | 
			
		||||
    if (this.player) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _setDimensions () {
 | 
			
		||||
    const width = this.player.offsetWidth;
 | 
			
		||||
 | 
			
		||||
    if (width && width != this.state.containerWidth) {
 | 
			
		||||
      if (this.props.cacheWidth) {
 | 
			
		||||
        this.props.cacheWidth(width);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.setState({
 | 
			
		||||
        containerWidth: c.offsetWidth,
 | 
			
		||||
        containerWidth: width,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -293,12 +304,16 @@ class Video extends React.PureComponent {
 | 
			
		|||
    document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
 | 
			
		||||
    document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
 | 
			
		||||
 | 
			
		||||
    window.addEventListener('resize', this.handleResize, { passive: true });
 | 
			
		||||
 | 
			
		||||
    if (this.props.blurhash) {
 | 
			
		||||
      this._decode();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  componentWillUnmount () {
 | 
			
		||||
    window.removeEventListener('resize', this.handleResize);
 | 
			
		||||
 | 
			
		||||
    document.removeEventListener('fullscreenchange', this.handleFullscreenChange, true);
 | 
			
		||||
    document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
 | 
			
		||||
    document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
 | 
			
		||||
| 
						 | 
				
			
			@ -334,6 +349,14 @@ class Video extends React.PureComponent {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleResize = debounce(() => {
 | 
			
		||||
    if (this.player) {
 | 
			
		||||
      this._setDimensions();
 | 
			
		||||
    }
 | 
			
		||||
  }, 250, {
 | 
			
		||||
    trailing: true,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  handleFullscreenChange = () => {
 | 
			
		||||
    this.setState({ fullscreen: isFullscreen() });
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -612,7 +612,7 @@
 | 
			
		|||
    &.active {
 | 
			
		||||
      overflow: visible;
 | 
			
		||||
      width: 50px;
 | 
			
		||||
      margin-right: 10px;
 | 
			
		||||
      margin-right: 16px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &::before {
 | 
			
		||||
| 
						 | 
				
			
			@ -649,10 +649,17 @@
 | 
			
		|||
      left: 0;
 | 
			
		||||
      margin-left: -6px;
 | 
			
		||||
      transform: translate(0, -50%);
 | 
			
		||||
      transition: opacity .1s ease;
 | 
			
		||||
      background: lighten($ui-highlight-color, 8%);
 | 
			
		||||
      box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
 | 
			
		||||
      pointer-events: none;
 | 
			
		||||
      opacity: 0;
 | 
			
		||||
 | 
			
		||||
      .no-reduce-motion & {
 | 
			
		||||
        transition: opacity 100ms linear;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.active &__handle {
 | 
			
		||||
      opacity: 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -712,10 +719,12 @@
 | 
			
		|||
      height: 12px;
 | 
			
		||||
      top: 6px;
 | 
			
		||||
      margin-left: -6px;
 | 
			
		||||
      transition: opacity .1s ease;
 | 
			
		||||
      background: lighten($ui-highlight-color, 8%);
 | 
			
		||||
      box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
 | 
			
		||||
      pointer-events: none;
 | 
			
		||||
 | 
			
		||||
      .no-reduce-motion & {
 | 
			
		||||
        transition: opacity .1s ease;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &.active {
 | 
			
		||||
        opacity: 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue