Add gif auto-play/pause preference
This introduces a new per-user preference called "Auto-play animated GIFs", which is enabled by default. When a user disables this setting, gifs in toots become click-to-play. Previews of animated gifs were changed to display the video play button so that users can distinguish them from regular images. This setting also affects account avatars in the detailed account view, which was changed to use the same hover-to-play mechanism that is used for animated avatars in timelines. Fixes #1652
This commit is contained in:
		
							parent
							
								
									1955a3f444
								
							
						
					
					
						commit
						ffb99325ca
					
				@ -78,7 +78,8 @@ const Item = React.createClass({
 | 
				
			|||||||
    attachment: ImmutablePropTypes.map.isRequired,
 | 
					    attachment: ImmutablePropTypes.map.isRequired,
 | 
				
			||||||
    index: React.PropTypes.number.isRequired,
 | 
					    index: React.PropTypes.number.isRequired,
 | 
				
			||||||
    size: React.PropTypes.number.isRequired,
 | 
					    size: React.PropTypes.number.isRequired,
 | 
				
			||||||
    onClick: React.PropTypes.func.isRequired
 | 
					    onClick: React.PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    autoPlayGif: React.PropTypes.bool.isRequired
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mixins: [PureRenderMixin],
 | 
					  mixins: [PureRenderMixin],
 | 
				
			||||||
@ -158,17 +159,25 @@ const Item = React.createClass({
 | 
				
			|||||||
        />
 | 
					        />
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    } else if (attachment.get('type') === 'gifv') {
 | 
					    } else if (attachment.get('type') === 'gifv') {
 | 
				
			||||||
 | 
					      if (isIOS() || !this.props.autoPlayGif) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					          <div  key={attachment.get('id')} style={{ ...itemStyle, background: `url(${attachment.get('preview_url')}) no-repeat center`, left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }} onClick={this.handleClick}>
 | 
				
			||||||
 | 
					            <div style={{ position: 'absolute', top: '50%', left: '50%', fontSize: '36px', transform: 'translate(-50%, -50%)', padding: '5px', borderRadius: '100px', color: 'rgba(255, 255, 255, 0.8)' }}><i className='fa fa-play' /></div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
        thumbnail = (
 | 
					        thumbnail = (
 | 
				
			||||||
            <video
 | 
					            <video
 | 
				
			||||||
              src={attachment.get('url')}
 | 
					              src={attachment.get('url')}
 | 
				
			||||||
              onClick={this.handleClick}
 | 
					              onClick={this.handleClick}
 | 
				
			||||||
          autoPlay={!isIOS()}
 | 
					              autoPlay
 | 
				
			||||||
              loop={true}
 | 
					              loop={true}
 | 
				
			||||||
              muted={true}
 | 
					              muted={true}
 | 
				
			||||||
              style={gifvThumbStyle}
 | 
					              style={gifvThumbStyle}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div key={attachment.get('id')} style={{ ...itemStyle, left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}>
 | 
					      <div key={attachment.get('id')} style={{ ...itemStyle, left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}>
 | 
				
			||||||
@ -192,7 +201,8 @@ const MediaGallery = React.createClass({
 | 
				
			|||||||
    media: ImmutablePropTypes.list.isRequired,
 | 
					    media: ImmutablePropTypes.list.isRequired,
 | 
				
			||||||
    height: React.PropTypes.number.isRequired,
 | 
					    height: React.PropTypes.number.isRequired,
 | 
				
			||||||
    onOpenMedia: React.PropTypes.func.isRequired,
 | 
					    onOpenMedia: React.PropTypes.func.isRequired,
 | 
				
			||||||
    intl: React.PropTypes.object.isRequired
 | 
					    intl: React.PropTypes.object.isRequired,
 | 
				
			||||||
 | 
					    autoPlayGif: React.PropTypes.bool.isRequired
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mixins: [PureRenderMixin],
 | 
					  mixins: [PureRenderMixin],
 | 
				
			||||||
@ -227,7 +237,7 @@ const MediaGallery = React.createClass({
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      const size = media.take(4).size;
 | 
					      const size = media.take(4).size;
 | 
				
			||||||
      children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} />);
 | 
					      children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} autoPlayGif={this.props.autoPlayGif} index={i} size={size} />);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,7 @@ const Status = React.createClass({
 | 
				
			|||||||
    onBlock: React.PropTypes.func,
 | 
					    onBlock: React.PropTypes.func,
 | 
				
			||||||
    me: React.PropTypes.number,
 | 
					    me: React.PropTypes.number,
 | 
				
			||||||
    boostModal: React.PropTypes.bool,
 | 
					    boostModal: React.PropTypes.bool,
 | 
				
			||||||
 | 
					    autoPlayGif: React.PropTypes.bool,
 | 
				
			||||||
    muted: React.PropTypes.bool
 | 
					    muted: React.PropTypes.bool
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,7 +80,7 @@ const Status = React.createClass({
 | 
				
			|||||||
      if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
 | 
					      if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
 | 
				
			||||||
        media = <VideoPlayer media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />;
 | 
					        media = <VideoPlayer media={status.getIn(['media_attachments', 0])} sensitive={status.get('sensitive')} onOpenVideo={this.props.onOpenVideo} />;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        media = <MediaGallery media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} />;
 | 
					        media = <MediaGallery media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,8 @@ const makeMapStateToProps = () => {
 | 
				
			|||||||
  const mapStateToProps = (state, props) => ({
 | 
					  const mapStateToProps = (state, props) => ({
 | 
				
			||||||
    status: getStatus(state, props.id),
 | 
					    status: getStatus(state, props.id),
 | 
				
			||||||
    me: state.getIn(['meta', 'me']),
 | 
					    me: state.getIn(['meta', 'me']),
 | 
				
			||||||
    boostModal: state.getIn(['meta', 'boost_modal'])
 | 
					    boostModal: state.getIn(['meta', 'boost_modal']),
 | 
				
			||||||
 | 
					    autoPlayGif: state.getIn(['meta', 'auto_play_gif'])
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return mapStateToProps;
 | 
					  return mapStateToProps;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ import escapeTextContentForBrowser from 'escape-html';
 | 
				
			|||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
					import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
				
			||||||
import IconButton from '../../../components/icon_button';
 | 
					import IconButton from '../../../components/icon_button';
 | 
				
			||||||
import { Motion, spring } from 'react-motion';
 | 
					import { Motion, spring } from 'react-motion';
 | 
				
			||||||
 | 
					import { connect } from 'react-redux';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
 | 
					  unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
 | 
				
			||||||
@ -12,10 +13,19 @@ const messages = defineMessages({
 | 
				
			|||||||
  requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }
 | 
					  requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const makeMapStateToProps = () => {
 | 
				
			||||||
 | 
					  const mapStateToProps = (state, props) => ({
 | 
				
			||||||
 | 
					    autoPlayGif: state.getIn(['meta', 'auto_play_gif'])
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return mapStateToProps;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Avatar = React.createClass({
 | 
					const Avatar = React.createClass({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  propTypes: {
 | 
					  propTypes: {
 | 
				
			||||||
    account: ImmutablePropTypes.map.isRequired
 | 
					    account: ImmutablePropTypes.map.isRequired,
 | 
				
			||||||
 | 
					    autoPlayGif: React.PropTypes.bool.isRequired
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getInitialState () {
 | 
					  getInitialState () {
 | 
				
			||||||
@ -37,7 +47,7 @@ const Avatar = React.createClass({
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { account }   = this.props;
 | 
					    const { account, autoPlayGif }   = this.props;
 | 
				
			||||||
    const { isHovered } = this.state;
 | 
					    const { isHovered } = this.state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
@ -53,7 +63,7 @@ const Avatar = React.createClass({
 | 
				
			|||||||
            onMouseOut={this.handleMouseOut}
 | 
					            onMouseOut={this.handleMouseOut}
 | 
				
			||||||
            onFocus={this.handleMouseOver}
 | 
					            onFocus={this.handleMouseOver}
 | 
				
			||||||
            onBlur={this.handleMouseOut}>
 | 
					            onBlur={this.handleMouseOut}>
 | 
				
			||||||
            <img src={account.get('avatar')} alt={account.get('acct')} style={{ display: 'block', width: '90px', height: '90px' }} />
 | 
					            <img src={autoPlayGif || isHovered ? account.get('avatar') : account.get('avatar_static')} alt={account.get('acct')} style={{ display: 'block', width: '90px', height: '90px' }} />
 | 
				
			||||||
          </a>
 | 
					          </a>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      </Motion>
 | 
					      </Motion>
 | 
				
			||||||
@ -68,7 +78,8 @@ const Header = React.createClass({
 | 
				
			|||||||
    account: ImmutablePropTypes.map,
 | 
					    account: ImmutablePropTypes.map,
 | 
				
			||||||
    me: React.PropTypes.number.isRequired,
 | 
					    me: React.PropTypes.number.isRequired,
 | 
				
			||||||
    onFollow: React.PropTypes.func.isRequired,
 | 
					    onFollow: React.PropTypes.func.isRequired,
 | 
				
			||||||
    intl: React.PropTypes.object.isRequired
 | 
					    intl: React.PropTypes.object.isRequired,
 | 
				
			||||||
 | 
					    autoPlayGif: React.PropTypes.bool.isRequired
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mixins: [PureRenderMixin],
 | 
					  mixins: [PureRenderMixin],
 | 
				
			||||||
@ -119,7 +130,7 @@ const Header = React.createClass({
 | 
				
			|||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}>
 | 
					      <div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}>
 | 
				
			||||||
        <div style={{ padding: '20px 10px' }}>
 | 
					        <div style={{ padding: '20px 10px' }}>
 | 
				
			||||||
          <Avatar account={account} />
 | 
					          <Avatar account={account} autoPlayGif={this.props.autoPlayGif} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <span style={{ display: 'inline-block', fontSize: '20px', lineHeight: '27px', fontWeight: '500' }} className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} />
 | 
					          <span style={{ display: 'inline-block', fontSize: '20px', lineHeight: '27px', fontWeight: '500' }} className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} />
 | 
				
			||||||
          <span className='account__header__username' style={{ fontSize: '14px', fontWeight: '400', display: 'block', marginBottom: '10px' }}>@{account.get('acct')} {lockedIcon}</span>
 | 
					          <span className='account__header__username' style={{ fontSize: '14px', fontWeight: '400', display: 'block', marginBottom: '10px' }}>@{account.get('acct')} {lockedIcon}</span>
 | 
				
			||||||
@ -134,4 +145,4 @@ const Header = React.createClass({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default injectIntl(Header);
 | 
					export default connect(makeMapStateToProps)(injectIntl(Header));
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,7 @@ const DetailedStatus = React.createClass({
 | 
				
			|||||||
    status: ImmutablePropTypes.map.isRequired,
 | 
					    status: ImmutablePropTypes.map.isRequired,
 | 
				
			||||||
    onOpenMedia: React.PropTypes.func.isRequired,
 | 
					    onOpenMedia: React.PropTypes.func.isRequired,
 | 
				
			||||||
    onOpenVideo: React.PropTypes.func.isRequired,
 | 
					    onOpenVideo: React.PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    autoPlayGif: React.PropTypes.bool,
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mixins: [PureRenderMixin],
 | 
					  mixins: [PureRenderMixin],
 | 
				
			||||||
@ -42,7 +43,7 @@ const DetailedStatus = React.createClass({
 | 
				
			|||||||
      if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
 | 
					      if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
 | 
				
			||||||
        media = <VideoPlayer sensitive={status.get('sensitive')} media={status.getIn(['media_attachments', 0])} width={300} height={150} onOpenVideo={this.props.onOpenVideo} autoplay />;
 | 
					        media = <VideoPlayer sensitive={status.get('sensitive')} media={status.getIn(['media_attachments', 0])} width={300} height={150} onOpenVideo={this.props.onOpenVideo} autoplay />;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        media = <MediaGallery sensitive={status.get('sensitive')} media={status.get('media_attachments')} height={300} onOpenMedia={this.props.onOpenMedia} />;
 | 
					        media = <MediaGallery sensitive={status.get('sensitive')} media={status.get('media_attachments')} height={300} onOpenMedia={this.props.onOpenMedia} autoPlayGif={this.props.autoPlayGif} />;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      media = <CardContainer statusId={status.get('id')} />;
 | 
					      media = <CardContainer statusId={status.get('id')} />;
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,8 @@ const makeMapStateToProps = () => {
 | 
				
			|||||||
    ancestorsIds: state.getIn(['timelines', 'ancestors', Number(props.params.statusId)]),
 | 
					    ancestorsIds: state.getIn(['timelines', 'ancestors', Number(props.params.statusId)]),
 | 
				
			||||||
    descendantsIds: state.getIn(['timelines', 'descendants', Number(props.params.statusId)]),
 | 
					    descendantsIds: state.getIn(['timelines', 'descendants', Number(props.params.statusId)]),
 | 
				
			||||||
    me: state.getIn(['meta', 'me']),
 | 
					    me: state.getIn(['meta', 'me']),
 | 
				
			||||||
    boostModal: state.getIn(['meta', 'boost_modal'])
 | 
					    boostModal: state.getIn(['meta', 'boost_modal']),
 | 
				
			||||||
 | 
					    autoPlayGif: state.getIn(['meta', 'auto_play_gif'])
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return mapStateToProps;
 | 
					  return mapStateToProps;
 | 
				
			||||||
@ -57,7 +58,8 @@ const Status = React.createClass({
 | 
				
			|||||||
    ancestorsIds: ImmutablePropTypes.list,
 | 
					    ancestorsIds: ImmutablePropTypes.list,
 | 
				
			||||||
    descendantsIds: ImmutablePropTypes.list,
 | 
					    descendantsIds: ImmutablePropTypes.list,
 | 
				
			||||||
    me: React.PropTypes.number,
 | 
					    me: React.PropTypes.number,
 | 
				
			||||||
    boostModal: React.PropTypes.bool
 | 
					    boostModal: React.PropTypes.bool,
 | 
				
			||||||
 | 
					    autoPlayGif: React.PropTypes.bool
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mixins: [PureRenderMixin],
 | 
					  mixins: [PureRenderMixin],
 | 
				
			||||||
@ -126,7 +128,7 @@ const Status = React.createClass({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    let ancestors, descendants;
 | 
					    let ancestors, descendants;
 | 
				
			||||||
    const { status, ancestorsIds, descendantsIds, me } = this.props;
 | 
					    const { status, ancestorsIds, descendantsIds, me, autoPlayGif } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (status === null) {
 | 
					    if (status === null) {
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
@ -155,7 +157,7 @@ const Status = React.createClass({
 | 
				
			|||||||
          <div className='scrollable'>
 | 
					          <div className='scrollable'>
 | 
				
			||||||
            {ancestors}
 | 
					            {ancestors}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <DetailedStatus status={status} me={me} onOpenVideo={this.handleOpenVideo} onOpenMedia={this.handleOpenMedia} />
 | 
					            <DetailedStatus status={status} autoPlayGif={autoPlayGif} me={me} onOpenVideo={this.handleOpenVideo} onOpenMedia={this.handleOpenMedia} />
 | 
				
			||||||
            <ActionBar status={status} me={me} onReply={this.handleReplyClick} onFavourite={this.handleFavouriteClick} onReblog={this.handleReblogClick} onDelete={this.handleDeleteClick} onMention={this.handleMentionClick} onReport={this.handleReport} />
 | 
					            <ActionBar status={status} me={me} onReply={this.handleReplyClick} onFavourite={this.handleFavouriteClick} onReblog={this.handleReblogClick} onDelete={this.handleDeleteClick} onMention={this.handleMentionClick} onReport={this.handleReport} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            {descendants}
 | 
					            {descendants}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,8 +24,9 @@ class Settings::PreferencesController < ApplicationController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    current_user.settings['default_privacy'] = user_params[:setting_default_privacy]
 | 
					    current_user.settings['default_privacy'] = user_params[:setting_default_privacy]
 | 
				
			||||||
    current_user.settings['boost_modal'] = user_params[:setting_boost_modal] == '1'
 | 
					    current_user.settings['boost_modal'] = user_params[:setting_boost_modal] == '1'
 | 
				
			||||||
 | 
					    current_user.settings['auto_play_gif'] = user_params[:setting_auto_play_gif] == '1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if current_user.update(user_params.except(:notification_emails, :interactions, :setting_default_privacy, :setting_boost_modal))
 | 
					    if current_user.update(user_params.except(:notification_emails, :interactions, :setting_default_privacy, :setting_boost_modal, :setting_auto_play_gif))
 | 
				
			||||||
      redirect_to settings_preferences_path, notice: I18n.t('generic.changes_saved_msg')
 | 
					      redirect_to settings_preferences_path, notice: I18n.t('generic.changes_saved_msg')
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      render action: :show
 | 
					      render action: :show
 | 
				
			||||||
@ -35,6 +36,6 @@ class Settings::PreferencesController < ApplicationController
 | 
				
			|||||||
  private
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def user_params
 | 
					  def user_params
 | 
				
			||||||
    params.require(:user).permit(:locale, :setting_default_privacy, :setting_boost_modal, notification_emails: [:follow, :follow_request, :reblog, :favourite, :mention, :digest], interactions: [:must_be_follower, :must_be_following])
 | 
					    params.require(:user).permit(:locale, :setting_default_privacy, :setting_boost_modal, :setting_auto_play_gif, notification_emails: [:follow, :follow_request, :reblog, :favourite, :mention, :digest], interactions: [:must_be_follower, :must_be_following])
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -32,4 +32,8 @@ class User < ApplicationRecord
 | 
				
			|||||||
  def setting_boost_modal
 | 
					  def setting_boost_modal
 | 
				
			||||||
    settings.boost_modal
 | 
					    settings.boost_modal
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def setting_auto_play_gif
 | 
				
			||||||
 | 
					    settings.auto_play_gif
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ node(:meta) do
 | 
				
			|||||||
    me: current_account.id,
 | 
					    me: current_account.id,
 | 
				
			||||||
    admin: @admin.try(:id),
 | 
					    admin: @admin.try(:id),
 | 
				
			||||||
    boost_modal: current_account.user.setting_boost_modal,
 | 
					    boost_modal: current_account.user.setting_boost_modal,
 | 
				
			||||||
 | 
					    auto_play_gif: current_account.user.setting_auto_play_gif,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,5 +25,8 @@
 | 
				
			|||||||
  .fields-group
 | 
					  .fields-group
 | 
				
			||||||
    = f.input :setting_boost_modal, as: :boolean, wrapper: :with_label
 | 
					    = f.input :setting_boost_modal, as: :boolean, wrapper: :with_label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .fields-group
 | 
				
			||||||
 | 
					    = f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .actions
 | 
					  .actions
 | 
				
			||||||
    = f.button :button, t('generic.save_changes'), type: :submit
 | 
					    = f.button :button, t('generic.save_changes'), type: :submit
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@ en:
 | 
				
			|||||||
        note: Bio
 | 
					        note: Bio
 | 
				
			||||||
        otp_attempt: Two-factor code
 | 
					        otp_attempt: Two-factor code
 | 
				
			||||||
        password: Password
 | 
					        password: Password
 | 
				
			||||||
 | 
					        setting_auto_play_gif: Auto-play animated GIFs
 | 
				
			||||||
        setting_boost_modal: Show confirmation dialog before boosting
 | 
					        setting_boost_modal: Show confirmation dialog before boosting
 | 
				
			||||||
        setting_default_privacy: Post privacy
 | 
					        setting_default_privacy: Post privacy
 | 
				
			||||||
        severity: Severity
 | 
					        severity: Severity
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@ defaults: &defaults
 | 
				
			|||||||
  open_registrations: true
 | 
					  open_registrations: true
 | 
				
			||||||
  closed_registrations_message: ''
 | 
					  closed_registrations_message: ''
 | 
				
			||||||
  boost_modal: false
 | 
					  boost_modal: false
 | 
				
			||||||
 | 
					  auto_play_gif: true
 | 
				
			||||||
  notification_emails:
 | 
					  notification_emails:
 | 
				
			||||||
    follow: false
 | 
					    follow: false
 | 
				
			||||||
    reblog: false
 | 
					    reblog: false
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user