Merge pull request #1453 from ThibG/glitch-soc/merge-upstream
Merge upstream changes
This commit is contained in:
commit
cfb16b9b70
|
@ -104,7 +104,7 @@ GEM
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
blurhash (0.1.4)
|
blurhash (0.1.4)
|
||||||
ffi (~> 1.10.0)
|
ffi (~> 1.10.0)
|
||||||
bootsnap (1.4.8)
|
bootsnap (1.4.9)
|
||||||
msgpack (~> 1.0)
|
msgpack (~> 1.0)
|
||||||
brakeman (4.10.0)
|
brakeman (4.10.0)
|
||||||
browser (4.2.0)
|
browser (4.2.0)
|
||||||
|
@ -424,7 +424,7 @@ GEM
|
||||||
pry-rails (0.3.9)
|
pry-rails (0.3.9)
|
||||||
pry (>= 0.10.4)
|
pry (>= 0.10.4)
|
||||||
public_suffix (4.0.6)
|
public_suffix (4.0.6)
|
||||||
puma (5.0.2)
|
puma (5.0.4)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pundit (2.1.0)
|
pundit (2.1.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
|
@ -574,7 +574,7 @@ GEM
|
||||||
sidekiq (>= 3)
|
sidekiq (>= 3)
|
||||||
thwait
|
thwait
|
||||||
tilt (>= 1.4.0)
|
tilt (>= 1.4.0)
|
||||||
sidekiq-unique-jobs (6.0.24)
|
sidekiq-unique-jobs (6.0.25)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||||
sidekiq (>= 4.0, < 7.0)
|
sidekiq (>= 4.0, < 7.0)
|
||||||
thor (>= 0.20, < 2.0)
|
thor (>= 0.20, < 2.0)
|
||||||
|
|
|
@ -53,6 +53,13 @@ module Admin
|
||||||
redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.destroyed_msg', username: @account.acct)
|
redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.destroyed_msg', username: @account.acct)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unsensitive
|
||||||
|
authorize @account, :unsensitive?
|
||||||
|
@account.unsensitize!
|
||||||
|
log_action :unsensitive, @account
|
||||||
|
redirect_to admin_account_path(@account.id)
|
||||||
|
end
|
||||||
|
|
||||||
def unsilence
|
def unsilence
|
||||||
authorize @account, :unsilence?
|
authorize @account, :unsilence?
|
||||||
@account.unsilence!
|
@account.unsilence!
|
||||||
|
|
|
@ -71,7 +71,7 @@ class Admin::AnnouncementsController < Admin::BaseController
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_announcements
|
def set_announcements
|
||||||
@announcements = AnnouncementFilter.new(filter_params).results.page(params[:page])
|
@announcements = AnnouncementFilter.new(filter_params).results.reverse_chronological.page(params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_announcement
|
def set_announcement
|
||||||
|
|
|
@ -22,6 +22,7 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
||||||
active
|
active
|
||||||
pending
|
pending
|
||||||
disabled
|
disabled
|
||||||
|
sensitized
|
||||||
silenced
|
silenced
|
||||||
suspended
|
suspended
|
||||||
username
|
username
|
||||||
|
@ -68,6 +69,13 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
||||||
render json: @account, serializer: REST::Admin::AccountSerializer
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def unsensitive
|
||||||
|
authorize @account, :unsensitive?
|
||||||
|
@account.unsensitize!
|
||||||
|
log_action :unsensitive, @account
|
||||||
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
def unsilence
|
def unsilence
|
||||||
authorize @account, :unsilence?
|
authorize @account, :unsilence?
|
||||||
@account.unsilence!
|
@account.unsilence!
|
||||||
|
|
|
@ -4,8 +4,12 @@ module StatusesHelper
|
||||||
EMBEDDED_CONTROLLER = 'statuses'
|
EMBEDDED_CONTROLLER = 'statuses'
|
||||||
EMBEDDED_ACTION = 'embed'
|
EMBEDDED_ACTION = 'embed'
|
||||||
|
|
||||||
def link_to_more(url)
|
def link_to_newer(url)
|
||||||
link_to t('statuses.show_more'), url, class: 'load-more load-gap'
|
link_to t('statuses.show_newer'), url, class: 'load-more load-gap'
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_to_older(url)
|
||||||
|
link_to t('statuses.show_older'), url, class: 'load-more load-gap'
|
||||||
end
|
end
|
||||||
|
|
||||||
def nothing_here(extra_classes = '')
|
def nothing_here(extra_classes = '')
|
||||||
|
@ -117,6 +121,14 @@ module StatusesHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sensitized?(status, account)
|
||||||
|
if !account.nil? && account.id == status.account_id
|
||||||
|
status.sensitive
|
||||||
|
else
|
||||||
|
status.account.sensitized? || status.sensitive
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def simplified_text(text)
|
def simplified_text(text)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { scrollTop } from 'flavours/glitch/util/scroll';
|
import { scrollTop } from 'flavours/glitch/util/scroll';
|
||||||
|
|
||||||
export default class Column extends React.PureComponent {
|
export default class Column extends React.PureComponent {
|
||||||
|
@ -37,9 +37,9 @@ export default class Column extends React.PureComponent {
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
if (this.props.bindToDocument) {
|
if (this.props.bindToDocument) {
|
||||||
document.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
} else {
|
} else {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ import IconButton from './icon_button';
|
||||||
import Overlay from 'react-overlays/lib/Overlay';
|
import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import Motion from 'flavours/glitch/util/optional_motion';
|
import Motion from 'flavours/glitch/util/optional_motion';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
|
|
||||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||||
let id = 0;
|
let id = 0;
|
||||||
|
|
||||||
class DropdownMenu extends React.PureComponent {
|
class DropdownMenu extends React.PureComponent {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { EmojiPicker as EmojiPickerAsync } from 'flavours/glitch/util/async-comp
|
||||||
import Overlay from 'react-overlays/lib/Overlay';
|
import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { buildCustomEmojis, categoriesFromEmojis } from 'flavours/glitch/util/emoji';
|
import { buildCustomEmojis, categoriesFromEmojis } from 'flavours/glitch/util/emoji';
|
||||||
import { useSystemEmojiFont } from 'flavours/glitch/util/initial_state';
|
import { useSystemEmojiFont } from 'flavours/glitch/util/initial_state';
|
||||||
import { assetHost } from 'flavours/glitch/util/config';
|
import { assetHost } from 'flavours/glitch/util/config';
|
||||||
|
@ -109,7 +109,7 @@ const mapDispatchToProps = (dispatch, { onPickEmoji }) => ({
|
||||||
let EmojiPicker, Emoji; // load asynchronously
|
let EmojiPicker, Emoji; // load asynchronously
|
||||||
|
|
||||||
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
|
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
|
||||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||||
|
|
||||||
class ModifierPickerMenu extends React.PureComponent {
|
class ModifierPickerMenu extends React.PureComponent {
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ import Icon from 'flavours/glitch/components/icon';
|
||||||
import ComposePanel from './compose_panel';
|
import ComposePanel from './compose_panel';
|
||||||
import NavigationPanel from './navigation_panel';
|
import NavigationPanel from './navigation_panel';
|
||||||
|
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { scrollRight } from 'flavours/glitch/util/scroll';
|
import { scrollRight } from 'flavours/glitch/util/scroll';
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
|
@ -80,7 +80,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.singleColumn) {
|
if (!this.props.singleColumn) {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
|
@ -97,7 +97,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) {
|
if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
this.setState({ shouldAnimate: true });
|
this.setState({ shouldAnimate: true });
|
||||||
|
|
|
@ -113,7 +113,8 @@ class ZoomableImage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
scale: MIN_SCALE,
|
scale: MIN_SCALE,
|
||||||
zoomMatrix: {
|
zoomMatrix: {
|
||||||
type: null, // 'full-width' 'full-height'
|
type: null, // 'width' 'height'
|
||||||
|
fullScreen: null, // bool
|
||||||
rate: null, // full screen scale rate
|
rate: null, // full screen scale rate
|
||||||
clientWidth: null,
|
clientWidth: null,
|
||||||
clientHeight: null,
|
clientHeight: null,
|
||||||
|
@ -122,12 +123,15 @@ class ZoomableImage extends React.PureComponent {
|
||||||
clientHeightFixed: null,
|
clientHeightFixed: null,
|
||||||
scrollTop: null,
|
scrollTop: null,
|
||||||
scrollLeft: null,
|
scrollLeft: null,
|
||||||
|
translateX: null,
|
||||||
|
translateY: null,
|
||||||
},
|
},
|
||||||
zoomState: 'expand', // 'expand' 'compress'
|
zoomState: 'expand', // 'expand' 'compress'
|
||||||
navigationHidden: false,
|
navigationHidden: false,
|
||||||
dragPosition: { top: 0, left: 0, x: 0, y: 0 },
|
dragPosition: { top: 0, left: 0, x: 0, y: 0 },
|
||||||
dragged: false,
|
dragged: false,
|
||||||
lockScroll: { x: 0, y: 0 },
|
lockScroll: { x: 0, y: 0 },
|
||||||
|
lockTranslate: { x: 0, y: 0 },
|
||||||
}
|
}
|
||||||
|
|
||||||
removers = [];
|
removers = [];
|
||||||
|
@ -168,18 +172,24 @@ class ZoomableImage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate () {
|
componentDidUpdate () {
|
||||||
|
this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' });
|
||||||
|
|
||||||
|
if (this.state.scale === MIN_SCALE) {
|
||||||
|
this.container.style.removeProperty('cursor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UNSAFE_componentWillReceiveProps () {
|
||||||
|
// reset when slide to next image
|
||||||
if (this.props.zoomButtonHidden) {
|
if (this.props.zoomButtonHidden) {
|
||||||
this.setState({ scale: MIN_SCALE }, () => {
|
this.setState({
|
||||||
|
scale: MIN_SCALE,
|
||||||
|
lockTranslate: { x: 0, y: 0 },
|
||||||
|
}, () => {
|
||||||
this.container.scrollLeft = 0;
|
this.container.scrollLeft = 0;
|
||||||
this.container.scrollTop = 0;
|
this.container.scrollTop = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' });
|
|
||||||
|
|
||||||
if (this.state.scale === 1) {
|
|
||||||
this.container.style.removeProperty('cursor');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeEventListeners () {
|
removeEventListeners () {
|
||||||
|
@ -192,7 +202,7 @@ class ZoomableImage extends React.PureComponent {
|
||||||
|
|
||||||
const event = normalizeWheel(e);
|
const event = normalizeWheel(e);
|
||||||
|
|
||||||
if (this.state.zoomMatrix.type === 'full-width') {
|
if (this.state.zoomMatrix.type === 'width') {
|
||||||
// full width, scroll vertical
|
// full width, scroll vertical
|
||||||
this.container.scrollTop = Math.max(this.container.scrollTop + event.pixelY, this.state.lockScroll.y);
|
this.container.scrollTop = Math.max(this.container.scrollTop + event.pixelY, this.state.lockScroll.y);
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,7 +278,7 @@ class ZoomableImage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
zoom(nextScale, midpoint) {
|
zoom(nextScale, midpoint) {
|
||||||
const { scale } = this.state;
|
const { scale, zoomMatrix } = this.state;
|
||||||
const { scrollLeft, scrollTop } = this.container;
|
const { scrollLeft, scrollTop } = this.container;
|
||||||
|
|
||||||
// math memo:
|
// math memo:
|
||||||
|
@ -283,6 +293,15 @@ class ZoomableImage extends React.PureComponent {
|
||||||
this.setState({ scale: nextScale }, () => {
|
this.setState({ scale: nextScale }, () => {
|
||||||
this.container.scrollLeft = nextScrollLeft;
|
this.container.scrollLeft = nextScrollLeft;
|
||||||
this.container.scrollTop = nextScrollTop;
|
this.container.scrollTop = nextScrollTop;
|
||||||
|
// reset the translateX/Y constantly
|
||||||
|
if (nextScale < zoomMatrix.rate) {
|
||||||
|
this.setState({
|
||||||
|
lockTranslate: {
|
||||||
|
x: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateX * ((nextScale - MIN_SCALE) / (zoomMatrix.rate - MIN_SCALE)),
|
||||||
|
y: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateY * ((nextScale - MIN_SCALE) / (zoomMatrix.rate - MIN_SCALE)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,14 +326,18 @@ class ZoomableImage extends React.PureComponent {
|
||||||
const { offsetWidth, offsetHeight } = this.image;
|
const { offsetWidth, offsetHeight } = this.image;
|
||||||
const clientHeightFixed = clientHeight - NAV_BAR_HEIGHT;
|
const clientHeightFixed = clientHeight - NAV_BAR_HEIGHT;
|
||||||
|
|
||||||
const type = width/height < clientWidth / clientHeightFixed ? 'full-width' : 'full-height';
|
const type = width / height < clientWidth / clientHeightFixed ? 'width' : 'height';
|
||||||
const rate = type === 'full-width' ? clientWidth / offsetWidth : clientHeightFixed / offsetHeight;
|
const fullScreen = type === 'width' ? width > clientWidth : height > clientHeightFixed;
|
||||||
const scrollTop = type === 'full-width' ? (clientHeight - offsetHeight) / 2 - NAV_BAR_HEIGHT : (clientHeightFixed - offsetHeight) / 2;
|
const rate = type === 'width' ? Math.min(clientWidth, width) / offsetWidth : Math.min(clientHeightFixed, height) / offsetHeight;
|
||||||
|
const scrollTop = type === 'width' ? (clientHeight - offsetHeight) / 2 - NAV_BAR_HEIGHT : (clientHeightFixed - offsetHeight) / 2;
|
||||||
const scrollLeft = (clientWidth - offsetWidth) / 2;
|
const scrollLeft = (clientWidth - offsetWidth) / 2;
|
||||||
|
const translateX = type === 'width' ? (width - offsetWidth) / (2 * rate) : 0;
|
||||||
|
const translateY = type === 'height' ? (height - offsetHeight) / (2 * rate) : 0;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
zoomMatrix: {
|
zoomMatrix: {
|
||||||
type: type,
|
type: type,
|
||||||
|
fullScreen: fullScreen,
|
||||||
rate: rate,
|
rate: rate,
|
||||||
clientWidth: clientWidth,
|
clientWidth: clientWidth,
|
||||||
clientHeight: clientHeight,
|
clientHeight: clientHeight,
|
||||||
|
@ -323,6 +346,8 @@ class ZoomableImage extends React.PureComponent {
|
||||||
clientHeightFixed: clientHeightFixed,
|
clientHeightFixed: clientHeightFixed,
|
||||||
scrollTop: scrollTop,
|
scrollTop: scrollTop,
|
||||||
scrollLeft: scrollLeft,
|
scrollLeft: scrollLeft,
|
||||||
|
translateX: translateX,
|
||||||
|
translateY: translateY,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -340,6 +365,10 @@ class ZoomableImage extends React.PureComponent {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
},
|
},
|
||||||
|
lockTranslate: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
}, () => {
|
}, () => {
|
||||||
this.container.scrollLeft = 0;
|
this.container.scrollLeft = 0;
|
||||||
this.container.scrollTop = 0;
|
this.container.scrollTop = 0;
|
||||||
|
@ -351,6 +380,10 @@ class ZoomableImage extends React.PureComponent {
|
||||||
x: zoomMatrix.scrollLeft,
|
x: zoomMatrix.scrollLeft,
|
||||||
y: zoomMatrix.scrollTop,
|
y: zoomMatrix.scrollTop,
|
||||||
},
|
},
|
||||||
|
lockTranslate: {
|
||||||
|
x: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateX,
|
||||||
|
y: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateY,
|
||||||
|
},
|
||||||
}, () => {
|
}, () => {
|
||||||
this.container.scrollLeft = zoomMatrix.scrollLeft;
|
this.container.scrollLeft = zoomMatrix.scrollLeft;
|
||||||
this.container.scrollTop = zoomMatrix.scrollTop;
|
this.container.scrollTop = zoomMatrix.scrollTop;
|
||||||
|
@ -371,15 +404,15 @@ class ZoomableImage extends React.PureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { alt, src, width, height, intl } = this.props;
|
const { alt, src, width, height, intl } = this.props;
|
||||||
const { scale } = this.state;
|
const { scale, lockTranslate } = this.state;
|
||||||
const overflow = scale === 1 ? 'hidden' : 'scroll';
|
const overflow = scale === MIN_SCALE ? 'hidden' : 'scroll';
|
||||||
const zoomButtonSshouldHide = !this.state.navigationHidden && !this.props.zoomButtonHidden ? '' : 'media-modal__zoom-button--hidden';
|
const zoomButtonShouldHide = this.state.navigationHidden || this.props.zoomButtonHidden || this.state.zoomMatrix.rate <= MIN_SCALE ? 'media-modal__zoom-button--hidden' : '';
|
||||||
const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand);
|
const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<IconButton
|
<IconButton
|
||||||
className={`media-modal__zoom-button ${zoomButtonSshouldHide}`}
|
className={`media-modal__zoom-button ${zoomButtonShouldHide}`}
|
||||||
title={zoomButtonTitle}
|
title={zoomButtonTitle}
|
||||||
icon={this.state.zoomState}
|
icon={this.state.zoomState}
|
||||||
onClick={this.handleZoomClick}
|
onClick={this.handleZoomClick}
|
||||||
|
@ -402,7 +435,7 @@ class ZoomableImage extends React.PureComponent {
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={{
|
style={{
|
||||||
transform: `scale(${scale})`,
|
transform: `scale(${scale}) translate(-${lockTranslate.x}px, -${lockTranslate.y}px)`,
|
||||||
transformOrigin: '0 0',
|
transformOrigin: '0 0',
|
||||||
}}
|
}}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// Package imports.
|
// Package imports.
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
|
|
||||||
// This will either be a passive lister options object (if passive
|
// This will either be a passive lister options object (if passive
|
||||||
// events are supported), or `false`.
|
// events are supported), or `false`.
|
||||||
export const withPassive = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
export const withPassive = supportsPassiveEvents ? { passive: true } : false;
|
||||||
|
|
||||||
// Focuses the root element.
|
// Focuses the root element.
|
||||||
export function focusRoot () {
|
export function focusRoot () {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { forceSingleColumn } from 'flavours/glitch/util/initial_state';
|
import { forceSingleColumn } from 'flavours/glitch/util/initial_state';
|
||||||
|
|
||||||
const LAYOUT_BREAKPOINT = 630;
|
const LAYOUT_BREAKPOINT = 630;
|
||||||
|
@ -17,7 +17,7 @@ export function isMobile(width, columns) {
|
||||||
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||||
|
|
||||||
let userTouching = false;
|
let userTouching = false;
|
||||||
let listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
let listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||||
|
|
||||||
function touchListener() {
|
function touchListener() {
|
||||||
userTouching = true;
|
userTouching = true;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { scrollTop } from '../scroll';
|
import { scrollTop } from '../scroll';
|
||||||
|
|
||||||
export default class Column extends React.PureComponent {
|
export default class Column extends React.PureComponent {
|
||||||
|
@ -35,9 +35,9 @@ export default class Column extends React.PureComponent {
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
if (this.props.bindToDocument) {
|
if (this.props.bindToDocument) {
|
||||||
document.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
} else {
|
} else {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ import IconButton from './icon_button';
|
||||||
import Overlay from 'react-overlays/lib/Overlay';
|
import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import Motion from '../features/ui/util/optional_motion';
|
import Motion from '../features/ui/util/optional_motion';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
|
|
||||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||||
let id = 0;
|
let id = 0;
|
||||||
|
|
||||||
class DropdownMenu extends React.PureComponent {
|
class DropdownMenu extends React.PureComponent {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'
|
||||||
import Overlay from 'react-overlays/lib/Overlay';
|
import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
|
import { buildCustomEmojis, categoriesFromEmojis } from '../../emoji/emoji';
|
||||||
import { assetHost } from 'mastodon/utils/config';
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ const messages = defineMessages({
|
||||||
let EmojiPicker, Emoji; // load asynchronously
|
let EmojiPicker, Emoji; // load asynchronously
|
||||||
|
|
||||||
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
|
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
|
||||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||||
|
|
||||||
class ModifierPickerMenu extends React.PureComponent {
|
class ModifierPickerMenu extends React.PureComponent {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import IconButton from '../../../components/icon_button';
|
||||||
import Overlay from 'react-overlays/lib/Overlay';
|
import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import Motion from '../../ui/util/optional_motion';
|
import Motion from '../../ui/util/optional_motion';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ const messages = defineMessages({
|
||||||
change_privacy: { id: 'privacy.change', defaultMessage: 'Adjust status privacy' },
|
change_privacy: { id: 'privacy.change', defaultMessage: 'Adjust status privacy' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||||
|
|
||||||
class PrivacyDropdownMenu extends React.PureComponent {
|
class PrivacyDropdownMenu extends React.PureComponent {
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import Icon from 'mastodon/components/icon';
|
||||||
import ComposePanel from './compose_panel';
|
import ComposePanel from './compose_panel';
|
||||||
import NavigationPanel from './navigation_panel';
|
import NavigationPanel from './navigation_panel';
|
||||||
|
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
import { scrollRight } from '../../../scroll';
|
import { scrollRight } from '../../../scroll';
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
|
@ -80,7 +80,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.singleColumn) {
|
if (!this.props.singleColumn) {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
|
@ -97,7 +97,7 @@ class ColumnsArea extends ImmutablePureComponent {
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) {
|
if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) {
|
||||||
this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||||
}
|
}
|
||||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||||
this.setState({ shouldAnimate: true });
|
this.setState({ shouldAnimate: true });
|
||||||
|
|
|
@ -113,7 +113,8 @@ class ZoomableImage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
scale: MIN_SCALE,
|
scale: MIN_SCALE,
|
||||||
zoomMatrix: {
|
zoomMatrix: {
|
||||||
type: null, // 'full-width' 'full-height'
|
type: null, // 'width' 'height'
|
||||||
|
fullScreen: null, // bool
|
||||||
rate: null, // full screen scale rate
|
rate: null, // full screen scale rate
|
||||||
clientWidth: null,
|
clientWidth: null,
|
||||||
clientHeight: null,
|
clientHeight: null,
|
||||||
|
@ -122,12 +123,15 @@ class ZoomableImage extends React.PureComponent {
|
||||||
clientHeightFixed: null,
|
clientHeightFixed: null,
|
||||||
scrollTop: null,
|
scrollTop: null,
|
||||||
scrollLeft: null,
|
scrollLeft: null,
|
||||||
|
translateX: null,
|
||||||
|
translateY: null,
|
||||||
},
|
},
|
||||||
zoomState: 'expand', // 'expand' 'compress'
|
zoomState: 'expand', // 'expand' 'compress'
|
||||||
navigationHidden: false,
|
navigationHidden: false,
|
||||||
dragPosition: { top: 0, left: 0, x: 0, y: 0 },
|
dragPosition: { top: 0, left: 0, x: 0, y: 0 },
|
||||||
dragged: false,
|
dragged: false,
|
||||||
lockScroll: { x: 0, y: 0 },
|
lockScroll: { x: 0, y: 0 },
|
||||||
|
lockTranslate: { x: 0, y: 0 },
|
||||||
}
|
}
|
||||||
|
|
||||||
removers = [];
|
removers = [];
|
||||||
|
@ -168,18 +172,24 @@ class ZoomableImage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate () {
|
componentDidUpdate () {
|
||||||
|
this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' });
|
||||||
|
|
||||||
|
if (this.state.scale === MIN_SCALE) {
|
||||||
|
this.container.style.removeProperty('cursor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UNSAFE_componentWillReceiveProps () {
|
||||||
|
// reset when slide to next image
|
||||||
if (this.props.zoomButtonHidden) {
|
if (this.props.zoomButtonHidden) {
|
||||||
this.setState({ scale: MIN_SCALE }, () => {
|
this.setState({
|
||||||
|
scale: MIN_SCALE,
|
||||||
|
lockTranslate: { x: 0, y: 0 },
|
||||||
|
}, () => {
|
||||||
this.container.scrollLeft = 0;
|
this.container.scrollLeft = 0;
|
||||||
this.container.scrollTop = 0;
|
this.container.scrollTop = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ zoomState: this.state.scale >= this.state.zoomMatrix.rate ? 'compress' : 'expand' });
|
|
||||||
|
|
||||||
if (this.state.scale === 1) {
|
|
||||||
this.container.style.removeProperty('cursor');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeEventListeners () {
|
removeEventListeners () {
|
||||||
|
@ -192,7 +202,7 @@ class ZoomableImage extends React.PureComponent {
|
||||||
|
|
||||||
const event = normalizeWheel(e);
|
const event = normalizeWheel(e);
|
||||||
|
|
||||||
if (this.state.zoomMatrix.type === 'full-width') {
|
if (this.state.zoomMatrix.type === 'width') {
|
||||||
// full width, scroll vertical
|
// full width, scroll vertical
|
||||||
this.container.scrollTop = Math.max(this.container.scrollTop + event.pixelY, this.state.lockScroll.y);
|
this.container.scrollTop = Math.max(this.container.scrollTop + event.pixelY, this.state.lockScroll.y);
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,7 +278,7 @@ class ZoomableImage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
zoom(nextScale, midpoint) {
|
zoom(nextScale, midpoint) {
|
||||||
const { scale } = this.state;
|
const { scale, zoomMatrix } = this.state;
|
||||||
const { scrollLeft, scrollTop } = this.container;
|
const { scrollLeft, scrollTop } = this.container;
|
||||||
|
|
||||||
// math memo:
|
// math memo:
|
||||||
|
@ -283,6 +293,15 @@ class ZoomableImage extends React.PureComponent {
|
||||||
this.setState({ scale: nextScale }, () => {
|
this.setState({ scale: nextScale }, () => {
|
||||||
this.container.scrollLeft = nextScrollLeft;
|
this.container.scrollLeft = nextScrollLeft;
|
||||||
this.container.scrollTop = nextScrollTop;
|
this.container.scrollTop = nextScrollTop;
|
||||||
|
// reset the translateX/Y constantly
|
||||||
|
if (nextScale < zoomMatrix.rate) {
|
||||||
|
this.setState({
|
||||||
|
lockTranslate: {
|
||||||
|
x: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateX * ((nextScale - MIN_SCALE) / (zoomMatrix.rate - MIN_SCALE)),
|
||||||
|
y: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateY * ((nextScale - MIN_SCALE) / (zoomMatrix.rate - MIN_SCALE)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,14 +326,18 @@ class ZoomableImage extends React.PureComponent {
|
||||||
const { offsetWidth, offsetHeight } = this.image;
|
const { offsetWidth, offsetHeight } = this.image;
|
||||||
const clientHeightFixed = clientHeight - NAV_BAR_HEIGHT;
|
const clientHeightFixed = clientHeight - NAV_BAR_HEIGHT;
|
||||||
|
|
||||||
const type = width/height < clientWidth / clientHeightFixed ? 'full-width' : 'full-height';
|
const type = width / height < clientWidth / clientHeightFixed ? 'width' : 'height';
|
||||||
const rate = type === 'full-width' ? clientWidth / offsetWidth : clientHeightFixed / offsetHeight;
|
const fullScreen = type === 'width' ? width > clientWidth : height > clientHeightFixed;
|
||||||
const scrollTop = type === 'full-width' ? (clientHeight - offsetHeight) / 2 - NAV_BAR_HEIGHT : (clientHeightFixed - offsetHeight) / 2;
|
const rate = type === 'width' ? Math.min(clientWidth, width) / offsetWidth : Math.min(clientHeightFixed, height) / offsetHeight;
|
||||||
|
const scrollTop = type === 'width' ? (clientHeight - offsetHeight) / 2 - NAV_BAR_HEIGHT : (clientHeightFixed - offsetHeight) / 2;
|
||||||
const scrollLeft = (clientWidth - offsetWidth) / 2;
|
const scrollLeft = (clientWidth - offsetWidth) / 2;
|
||||||
|
const translateX = type === 'width' ? (width - offsetWidth) / (2 * rate) : 0;
|
||||||
|
const translateY = type === 'height' ? (height - offsetHeight) / (2 * rate) : 0;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
zoomMatrix: {
|
zoomMatrix: {
|
||||||
type: type,
|
type: type,
|
||||||
|
fullScreen: fullScreen,
|
||||||
rate: rate,
|
rate: rate,
|
||||||
clientWidth: clientWidth,
|
clientWidth: clientWidth,
|
||||||
clientHeight: clientHeight,
|
clientHeight: clientHeight,
|
||||||
|
@ -323,6 +346,8 @@ class ZoomableImage extends React.PureComponent {
|
||||||
clientHeightFixed: clientHeightFixed,
|
clientHeightFixed: clientHeightFixed,
|
||||||
scrollTop: scrollTop,
|
scrollTop: scrollTop,
|
||||||
scrollLeft: scrollLeft,
|
scrollLeft: scrollLeft,
|
||||||
|
translateX: translateX,
|
||||||
|
translateY: translateY,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -340,6 +365,10 @@ class ZoomableImage extends React.PureComponent {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
},
|
},
|
||||||
|
lockTranslate: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
}, () => {
|
}, () => {
|
||||||
this.container.scrollLeft = 0;
|
this.container.scrollLeft = 0;
|
||||||
this.container.scrollTop = 0;
|
this.container.scrollTop = 0;
|
||||||
|
@ -351,6 +380,10 @@ class ZoomableImage extends React.PureComponent {
|
||||||
x: zoomMatrix.scrollLeft,
|
x: zoomMatrix.scrollLeft,
|
||||||
y: zoomMatrix.scrollTop,
|
y: zoomMatrix.scrollTop,
|
||||||
},
|
},
|
||||||
|
lockTranslate: {
|
||||||
|
x: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateX,
|
||||||
|
y: zoomMatrix.fullScreen ? 0 : zoomMatrix.translateY,
|
||||||
|
},
|
||||||
}, () => {
|
}, () => {
|
||||||
this.container.scrollLeft = zoomMatrix.scrollLeft;
|
this.container.scrollLeft = zoomMatrix.scrollLeft;
|
||||||
this.container.scrollTop = zoomMatrix.scrollTop;
|
this.container.scrollTop = zoomMatrix.scrollTop;
|
||||||
|
@ -371,15 +404,15 @@ class ZoomableImage extends React.PureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { alt, src, width, height, intl } = this.props;
|
const { alt, src, width, height, intl } = this.props;
|
||||||
const { scale } = this.state;
|
const { scale, lockTranslate } = this.state;
|
||||||
const overflow = scale === 1 ? 'hidden' : 'scroll';
|
const overflow = scale === MIN_SCALE ? 'hidden' : 'scroll';
|
||||||
const zoomButtonSshouldHide = !this.state.navigationHidden && !this.props.zoomButtonHidden ? '' : 'media-modal__zoom-button--hidden';
|
const zoomButtonShouldHide = this.state.navigationHidden || this.props.zoomButtonHidden || this.state.zoomMatrix.rate <= MIN_SCALE ? 'media-modal__zoom-button--hidden' : '';
|
||||||
const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand);
|
const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<IconButton
|
<IconButton
|
||||||
className={`media-modal__zoom-button ${zoomButtonSshouldHide}`}
|
className={`media-modal__zoom-button ${zoomButtonShouldHide}`}
|
||||||
title={zoomButtonTitle}
|
title={zoomButtonTitle}
|
||||||
icon={this.state.zoomState}
|
icon={this.state.zoomState}
|
||||||
onClick={this.handleZoomClick}
|
onClick={this.handleZoomClick}
|
||||||
|
@ -402,7 +435,7 @@ class ZoomableImage extends React.PureComponent {
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={{
|
style={{
|
||||||
transform: `scale(${scale})`,
|
transform: `scale(${scale}) translate(-${lockTranslate.x}px, -${lockTranslate.y}px)`,
|
||||||
transformOrigin: '0 0',
|
transformOrigin: '0 0',
|
||||||
}}
|
}}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import detectPassiveEvents from 'detect-passive-events';
|
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||||
|
|
||||||
const LAYOUT_BREAKPOINT = 630;
|
const LAYOUT_BREAKPOINT = 630;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export function isMobile(width) {
|
||||||
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||||
|
|
||||||
let userTouching = false;
|
let userTouching = false;
|
||||||
let listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
let listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||||
|
|
||||||
function touchListener() {
|
function touchListener() {
|
||||||
userTouching = true;
|
userTouching = true;
|
||||||
|
|
|
@ -111,7 +111,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||||
created_at: @object['published'],
|
created_at: @object['published'],
|
||||||
override_timestamps: @options[:override_timestamps],
|
override_timestamps: @options[:override_timestamps],
|
||||||
reply: @object['inReplyTo'].present?,
|
reply: @object['inReplyTo'].present?,
|
||||||
sensitive: @object['sensitive'] || false,
|
sensitive: @account.sensitized? || @object['sensitive'] || false,
|
||||||
visibility: visibility_from_audience,
|
visibility: visibility_from_audience,
|
||||||
thread: replied_to_status,
|
thread: replied_to_status,
|
||||||
conversation: conversation_from_uri(@object['conversation']),
|
conversation: conversation_from_uri(@object['conversation']),
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
# avatar_storage_schema_version :integer
|
# avatar_storage_schema_version :integer
|
||||||
# header_storage_schema_version :integer
|
# header_storage_schema_version :integer
|
||||||
# devices_url :string
|
# devices_url :string
|
||||||
|
# sensitized_at :datetime
|
||||||
#
|
#
|
||||||
|
|
||||||
class Account < ApplicationRecord
|
class Account < ApplicationRecord
|
||||||
|
@ -96,6 +97,7 @@ class Account < ApplicationRecord
|
||||||
scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
|
scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
|
||||||
scope :silenced, -> { where.not(silenced_at: nil) }
|
scope :silenced, -> { where.not(silenced_at: nil) }
|
||||||
scope :suspended, -> { where.not(suspended_at: nil) }
|
scope :suspended, -> { where.not(suspended_at: nil) }
|
||||||
|
scope :sensitized, -> { where.not(sensitized_at: nil) }
|
||||||
scope :without_suspended, -> { where(suspended_at: nil) }
|
scope :without_suspended, -> { where(suspended_at: nil) }
|
||||||
scope :without_silenced, -> { where(silenced_at: nil) }
|
scope :without_silenced, -> { where(silenced_at: nil) }
|
||||||
scope :recent, -> { reorder(id: :desc) }
|
scope :recent, -> { reorder(id: :desc) }
|
||||||
|
@ -238,6 +240,18 @@ class Account < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sensitized?
|
||||||
|
sensitized_at.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def sensitize!(date = Time.now.utc)
|
||||||
|
update!(sensitized_at: date)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsensitize!
|
||||||
|
update!(sensitized_at: nil)
|
||||||
|
end
|
||||||
|
|
||||||
def memorialize!
|
def memorialize!
|
||||||
update!(memorial: true)
|
update!(memorial: true)
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
class AccountWarning < ApplicationRecord
|
class AccountWarning < ApplicationRecord
|
||||||
enum action: %i(none disable silence suspend), _suffix: :action
|
enum action: %i(none disable sensitive silence suspend), _suffix: :action
|
||||||
|
|
||||||
belongs_to :account, inverse_of: :account_warnings
|
belongs_to :account, inverse_of: :account_warnings
|
||||||
belongs_to :target_account, class_name: 'Account', inverse_of: :targeted_account_warnings
|
belongs_to :target_account, class_name: 'Account', inverse_of: :targeted_account_warnings
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Admin::AccountAction
|
||||||
TYPES = %w(
|
TYPES = %w(
|
||||||
none
|
none
|
||||||
disable
|
disable
|
||||||
|
sensitive
|
||||||
silence
|
silence
|
||||||
suspend
|
suspend
|
||||||
).freeze
|
).freeze
|
||||||
|
@ -64,6 +65,8 @@ class Admin::AccountAction
|
||||||
case type
|
case type
|
||||||
when 'disable'
|
when 'disable'
|
||||||
handle_disable!
|
handle_disable!
|
||||||
|
when 'sensitive'
|
||||||
|
handle_sensitive!
|
||||||
when 'silence'
|
when 'silence'
|
||||||
handle_silence!
|
handle_silence!
|
||||||
when 'suspend'
|
when 'suspend'
|
||||||
|
@ -109,6 +112,12 @@ class Admin::AccountAction
|
||||||
target_account.user&.disable!
|
target_account.user&.disable!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_sensitive!
|
||||||
|
authorize(target_account, :sensitive?)
|
||||||
|
log_action(:sensitive, target_account)
|
||||||
|
target_account.sensitize!
|
||||||
|
end
|
||||||
|
|
||||||
def handle_silence!
|
def handle_silence!
|
||||||
authorize(target_account, :silence?)
|
authorize(target_account, :silence?)
|
||||||
log_action(:silence, target_account)
|
log_action(:silence, target_account)
|
||||||
|
|
|
@ -35,9 +35,11 @@ class Admin::ActionLogFilter
|
||||||
reopen_report: { target_type: 'Report', action: 'reopen' }.freeze,
|
reopen_report: { target_type: 'Report', action: 'reopen' }.freeze,
|
||||||
reset_password_user: { target_type: 'User', action: 'reset_password' }.freeze,
|
reset_password_user: { target_type: 'User', action: 'reset_password' }.freeze,
|
||||||
resolve_report: { target_type: 'Report', action: 'resolve' }.freeze,
|
resolve_report: { target_type: 'Report', action: 'resolve' }.freeze,
|
||||||
|
sensitive_account: { target_type: 'Account', action: 'sensitive' }.freeze,
|
||||||
silence_account: { target_type: 'Account', action: 'silence' }.freeze,
|
silence_account: { target_type: 'Account', action: 'silence' }.freeze,
|
||||||
suspend_account: { target_type: 'Account', action: 'suspend' }.freeze,
|
suspend_account: { target_type: 'Account', action: 'suspend' }.freeze,
|
||||||
unassigned_report: { target_type: 'Report', action: 'unassigned' }.freeze,
|
unassigned_report: { target_type: 'Report', action: 'unassigned' }.freeze,
|
||||||
|
unsensitive_account: { target_type: 'Account', action: 'unsensitive' }.freeze,
|
||||||
unsilence_account: { target_type: 'Account', action: 'unsilence' }.freeze,
|
unsilence_account: { target_type: 'Account', action: 'unsilence' }.freeze,
|
||||||
unsuspend_account: { target_type: 'Account', action: 'unsuspend' }.freeze,
|
unsuspend_account: { target_type: 'Account', action: 'unsuspend' }.freeze,
|
||||||
update_announcement: { target_type: 'Announcement', action: 'update' }.freeze,
|
update_announcement: { target_type: 'Announcement', action: 'update' }.freeze,
|
||||||
|
|
|
@ -22,6 +22,7 @@ class Announcement < ApplicationRecord
|
||||||
scope :published, -> { where(published: true) }
|
scope :published, -> { where(published: true) }
|
||||||
scope :without_muted, ->(account) { joins("LEFT OUTER JOIN announcement_mutes ON announcement_mutes.announcement_id = announcements.id AND announcement_mutes.account_id = #{account.id}").where('announcement_mutes.id IS NULL') }
|
scope :without_muted, ->(account) { joins("LEFT OUTER JOIN announcement_mutes ON announcement_mutes.announcement_id = announcements.id AND announcement_mutes.account_id = #{account.id}").where('announcement_mutes.id IS NULL') }
|
||||||
scope :chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) ASC')) }
|
scope :chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) ASC')) }
|
||||||
|
scope :reverse_chronological, -> { order(Arel.sql('COALESCE(announcements.starts_at, announcements.scheduled_at, announcements.published_at, announcements.created_at) DESC')) }
|
||||||
|
|
||||||
has_many :announcement_mutes, dependent: :destroy
|
has_many :announcement_mutes, dependent: :destroy
|
||||||
has_many :announcement_reactions, dependent: :destroy
|
has_many :announcement_reactions, dependent: :destroy
|
||||||
|
|
|
@ -25,6 +25,14 @@ class AccountPolicy < ApplicationPolicy
|
||||||
staff?
|
staff?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sensitive?
|
||||||
|
staff? && !record.user&.staff?
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsensitive?
|
||||||
|
staff?
|
||||||
|
end
|
||||||
|
|
||||||
def silence?
|
def silence?
|
||||||
staff? && !record.user&.staff?
|
staff? && !record.user&.staff?
|
||||||
end
|
end
|
||||||
|
|
|
@ -110,6 +110,10 @@ class ActivityPub::NoteSerializer < ActivityPub::Serializer
|
||||||
ActivityPub::TagManager.instance.cc(object)
|
ActivityPub::TagManager.instance.cc(object)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sensitive
|
||||||
|
object.account.sensitized? || object.sensitive
|
||||||
|
end
|
||||||
|
|
||||||
def virtual_tags
|
def virtual_tags
|
||||||
object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis
|
object.active_mentions.to_a.sort_by(&:id) + object.tags + object.emojis
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,6 +60,14 @@ class REST::StatusSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sensitive
|
||||||
|
if current_user? && current_user.account_id == object.account_id
|
||||||
|
object.sensitive
|
||||||
|
else
|
||||||
|
object.account.sensitized? || object.sensitive
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def uri
|
def uri
|
||||||
ActivityPub::TagManager.instance.uri_for(object)
|
ActivityPub::TagManager.instance.uri_for(object)
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ class SuspendAccountService < BaseService
|
||||||
|
|
||||||
def unmerge_from_home_timelines!
|
def unmerge_from_home_timelines!
|
||||||
@account.followers_for_local_distribution.find_each do |follower|
|
@account.followers_for_local_distribution.find_each do |follower|
|
||||||
FeedManager.instance.unmerge_from_timeline(@account, follower)
|
FeedManager.instance.unmerge_from_home(@account, follower)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -39,11 +39,15 @@ class SuspendAccountService < BaseService
|
||||||
styles.each do |style|
|
styles.each do |style|
|
||||||
case Paperclip::Attachment.default_options[:storage]
|
case Paperclip::Attachment.default_options[:storage]
|
||||||
when :s3
|
when :s3
|
||||||
attachment.s3_object(style).acl.put(:private)
|
attachment.s3_object(style).acl.put(acl: 'private')
|
||||||
when :fog
|
when :fog
|
||||||
# Not supported
|
# Not supported
|
||||||
when :filesystem
|
when :filesystem
|
||||||
FileUtils.chmod(0o600 & ~File.umask, attachment.path(style))
|
begin
|
||||||
|
FileUtils.chmod(0o600 & ~File.umask, attachment.path(style)) unless attachment.path(style).nil?
|
||||||
|
rescue Errno::ENOENT
|
||||||
|
Rails.logger.warn "Tried to change permission on non-existent file #{attachment.path(style)}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ class UnsuspendAccountService < BaseService
|
||||||
|
|
||||||
def merge_into_home_timelines!
|
def merge_into_home_timelines!
|
||||||
@account.followers_for_local_distribution.find_each do |follower|
|
@account.followers_for_local_distribution.find_each do |follower|
|
||||||
FeedManager.instance.merge_into_timeline(@account, follower)
|
FeedManager.instance.merge_into_home(@account, follower)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -39,11 +39,15 @@ class UnsuspendAccountService < BaseService
|
||||||
styles.each do |style|
|
styles.each do |style|
|
||||||
case Paperclip::Attachment.default_options[:storage]
|
case Paperclip::Attachment.default_options[:storage]
|
||||||
when :s3
|
when :s3
|
||||||
attachment.s3_object(style).acl.put(Paperclip::Attachment.default_options[:s3_permissions])
|
attachment.s3_object(style).acl.put(acl: Paperclip::Attachment.default_options[:s3_permissions])
|
||||||
when :fog
|
when :fog
|
||||||
# Not supported
|
# Not supported
|
||||||
when :filesystem
|
when :filesystem
|
||||||
FileUtils.chmod(0o666 & ~File.umask, attachment.path(style))
|
begin
|
||||||
|
FileUtils.chmod(0o666 & ~File.umask, attachment.path(style)) unless attachment.path(style).nil?
|
||||||
|
rescue Errno::ENOENT
|
||||||
|
Rails.logger.warn "Tried to change permission on non-existent file #{attachment.path(style)}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,12 +39,12 @@
|
||||||
= render partial: 'statuses/status', collection: @pinned_statuses, as: :status, locals: { pinned: true }
|
= render partial: 'statuses/status', collection: @pinned_statuses, as: :status, locals: { pinned: true }
|
||||||
|
|
||||||
- if @newer_url
|
- if @newer_url
|
||||||
.entry= link_to_more @newer_url
|
.entry= link_to_newer @newer_url
|
||||||
|
|
||||||
= render partial: 'statuses/status', collection: @statuses, as: :status
|
= render partial: 'statuses/status', collection: @statuses, as: :status
|
||||||
|
|
||||||
- if @older_url
|
- if @older_url
|
||||||
.entry= link_to_more @older_url
|
.entry= link_to_older @older_url
|
||||||
|
|
||||||
.column-1
|
.column-1
|
||||||
- if @account.memorial?
|
- if @account.memorial?
|
||||||
|
|
|
@ -69,6 +69,8 @@
|
||||||
= t('admin.accounts.confirming')
|
= t('admin.accounts.confirming')
|
||||||
- elsif @account.local? && !@account.user_approved?
|
- elsif @account.local? && !@account.user_approved?
|
||||||
= t('admin.accounts.pending')
|
= t('admin.accounts.pending')
|
||||||
|
- elsif @account.sensitized?
|
||||||
|
= t('admin.accounts.sensitive')
|
||||||
- else
|
- else
|
||||||
= t('admin.accounts.no_limits_imposed')
|
= t('admin.accounts.no_limits_imposed')
|
||||||
.dashboard__counters__label= t 'admin.accounts.login_status'
|
.dashboard__counters__label= t 'admin.accounts.login_status'
|
||||||
|
@ -192,6 +194,11 @@
|
||||||
- else
|
- else
|
||||||
= link_to t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable'), class: 'button' if can?(:disable, @account.user)
|
= link_to t('admin.accounts.disable'), new_admin_account_action_path(@account.id, type: 'disable'), class: 'button' if can?(:disable, @account.user)
|
||||||
|
|
||||||
|
- if @account.sensitized?
|
||||||
|
= link_to t('admin.accounts.undo_sensitized'), unsensitive_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsensitive, @account)
|
||||||
|
- elsif !@account.local? || @account.user_approved?
|
||||||
|
= link_to t('admin.accounts.sensitive'), new_admin_account_action_path(@account.id, type: 'sensitive'), class: 'button' if can?(:sensitive, @account)
|
||||||
|
|
||||||
- if @account.silenced?
|
- if @account.silenced?
|
||||||
= link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account)
|
= link_to t('admin.accounts.undo_silenced'), unsilence_admin_account_path(@account.id), method: :post, class: 'button' if can?(:unsilence, @account)
|
||||||
- elsif !@account.local? || @account.user_approved?
|
- elsif !@account.local? || @account.user_approved?
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
- content_for :header_tags do
|
- content_for :header_tags do
|
||||||
= preload_link_tag asset_pack_path('features/getting_started.js'), crossorigin: 'anonymous'
|
= preload_pack_asset 'features/getting_started.js', crossorigin: 'anonymous'
|
||||||
= preload_link_tag asset_pack_path('features/compose.js'), crossorigin: 'anonymous'
|
= preload_pack_asset 'features/compose.js', crossorigin: 'anonymous'
|
||||||
= preload_link_tag asset_pack_path('features/home_timeline.js'), crossorigin: 'anonymous'
|
= preload_pack_asset 'features/home_timeline.js', crossorigin: 'anonymous'
|
||||||
= preload_link_tag asset_pack_path('features/notifications.js'), crossorigin: 'anonymous'
|
= preload_pack_asset 'features/notifications.js', crossorigin: 'anonymous'
|
||||||
|
|
||||||
%meta{name: 'applicationServerKey', content: Rails.configuration.x.vapid_public_key}
|
%meta{name: 'applicationServerKey', content: Rails.configuration.x.vapid_public_key}
|
||||||
= render_initial_state
|
= render_initial_state
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
- if theme[:pack] != 'common' && theme[:common]
|
- if theme[:pack] != 'common' && theme[:common]
|
||||||
= render partial: 'layouts/theme', object: theme[:common]
|
= render partial: 'layouts/theme', object: theme[:common]
|
||||||
- if theme[:pack]
|
- if theme[:pack]
|
||||||
= javascript_pack_tag theme[:flavour] ? "flavours/#{theme[:flavour]}/#{theme[:pack]}" : "core/#{theme[:pack]}", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag theme[:flavour] ? "flavours/#{theme[:flavour]}/#{theme[:pack]}" : "core/#{theme[:pack]}", crossorigin: 'anonymous'
|
||||||
- if theme[:skin]
|
- if theme[:skin]
|
||||||
- if !theme[:flavour] || theme[:skin] == 'default'
|
- if !theme[:flavour] || theme[:skin] == 'default'
|
||||||
= stylesheet_pack_tag theme[:flavour] ? "flavours/#{theme[:flavour]}/#{theme[:pack]}" : "core/#{theme[:pack]}", integrity: true, media: 'all'
|
= stylesheet_pack_tag theme[:flavour] ? "flavours/#{theme[:flavour]}/#{theme[:pack]}" : "core/#{theme[:pack]}", media: 'all', crossorigin: 'anonymous'
|
||||||
- else
|
- else
|
||||||
= stylesheet_pack_tag "skins/#{theme[:flavour]}/#{theme[:skin]}/#{theme[:pack]}"
|
= stylesheet_pack_tag "skins/#{theme[:flavour]}/#{theme[:skin]}/#{theme[:pack]}", crossorigin: 'anonymous'
|
||||||
- if theme[:preload]
|
- if theme[:preload]
|
||||||
- theme[:preload].each do |link|
|
- theme[:preload].each do |link|
|
||||||
%link{ href: asset_pack_path("#{link}.js"), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
%link{ href: asset_pack_path("#{link}.js"), crossorigin: 'anonymous', rel: 'preload', as: 'script' }/
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
|
|
||||||
%title= content_for?(:page_title) ? safe_join([yield(:page_title).chomp.html_safe, title], ' - ') : title
|
%title= content_for?(:page_title) ? safe_join([yield(:page_title).chomp.html_safe, title], ' - ') : title
|
||||||
|
|
||||||
= javascript_pack_tag "locales", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales", crossorigin: 'anonymous'
|
||||||
- if @theme
|
- if @theme
|
||||||
- if @theme[:supported_locales].include? I18n.locale.to_s
|
- if @theme[:supported_locales].include? I18n.locale.to_s
|
||||||
= javascript_pack_tag "locales/#{@theme[:flavour]}/#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales/#{@theme[:flavour]}/#{I18n.locale}", crossorigin: 'anonymous'
|
||||||
- elsif @theme[:supported_locales].include? 'en'
|
- elsif @theme[:supported_locales].include? 'en'
|
||||||
= javascript_pack_tag "locales/#{@theme[:flavour]}/en", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales/#{@theme[:flavour]}/en", crossorigin: 'anonymous'
|
||||||
= csrf_meta_tags
|
= csrf_meta_tags
|
||||||
%meta{ name: 'style-nonce', content: request.content_security_policy_nonce }
|
%meta{ name: 'style-nonce', content: request.content_security_policy_nonce }
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
%link{ rel: 'dns-prefetch', href: storage_host }/
|
%link{ rel: 'dns-prefetch', href: storage_host }/
|
||||||
|
|
||||||
= render_initial_state
|
= render_initial_state
|
||||||
= javascript_pack_tag "locales", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales", crossorigin: 'anonymous'
|
||||||
- if @theme
|
- if @theme
|
||||||
- if @theme[:supported_locales].include? I18n.locale.to_s
|
- if @theme[:supported_locales].include? I18n.locale.to_s
|
||||||
= javascript_pack_tag "locales/#{@theme[:flavour]}/#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales/#{@theme[:flavour]}/#{I18n.locale}", crossorigin: 'anonymous'
|
||||||
- elsif @theme[:supported_locales].include? 'en'
|
- elsif @theme[:supported_locales].include? 'en'
|
||||||
= javascript_pack_tag "locales/#{@theme[:flavour]}/en", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales/#{@theme[:flavour]}/en", crossorigin: 'anonymous'
|
||||||
= render partial: 'layouts/theme', object: @core
|
= render partial: 'layouts/theme', object: @core
|
||||||
= render partial: 'layouts/theme', object: @theme
|
= render partial: 'layouts/theme', object: @theme
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
%meta{ charset: 'utf-8' }/
|
%meta{ charset: 'utf-8' }/
|
||||||
%title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ')
|
%title= safe_join([yield(:page_title), Setting.default_settings['site_title']], ' - ')
|
||||||
%meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/
|
%meta{ content: 'width=device-width,initial-scale=1', name: 'viewport' }/
|
||||||
= javascript_pack_tag "locales", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales", crossorigin: 'anonymous'
|
||||||
= render partial: 'layouts/theme', object: (@core || { pack: 'common' })
|
= render partial: 'layouts/theme', object: (@core || { pack: 'common' })
|
||||||
= render partial: 'layouts/theme', object: (@theme || { pack: 'error', flavour: 'glitch', common: { pack: 'common', flavour: 'glitch', skin: 'default' } })
|
= render partial: 'layouts/theme', object: (@theme || { pack: 'error', flavour: 'glitch', common: { pack: 'common', flavour: 'glitch', skin: 'default' } })
|
||||||
%body.error
|
%body.error
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
- content_for :header_tags do
|
- content_for :header_tags do
|
||||||
= render_initial_state
|
= render_initial_state
|
||||||
= javascript_pack_tag "locales", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales", crossorigin: 'anonymous'
|
||||||
- if @theme
|
- if @theme
|
||||||
- if @theme[:supported_locales].include? I18n.locale.to_s
|
- if @theme[:supported_locales].include? I18n.locale.to_s
|
||||||
= javascript_pack_tag "locales/#{@theme[:flavour]}/#{I18n.locale}", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales/#{@theme[:flavour]}/#{I18n.locale}", crossorigin: 'anonymous'
|
||||||
- elsif @theme[:supported_locales].include? 'en'
|
- elsif @theme[:supported_locales].include? 'en'
|
||||||
= javascript_pack_tag "locales/#{@theme[:flavour]}/en", integrity: true, crossorigin: 'anonymous'
|
= javascript_pack_tag "locales/#{@theme[:flavour]}/en", crossorigin: 'anonymous'
|
||||||
= render partial: 'layouts/theme', object: @core
|
= render partial: 'layouts/theme', object: @core
|
||||||
= render partial: 'layouts/theme', object: @theme
|
= render partial: 'layouts/theme', object: @theme
|
||||||
|
|
||||||
|
|
|
@ -29,17 +29,17 @@
|
||||||
- if !status.media_attachments.empty?
|
- if !status.media_attachments.empty?
|
||||||
- if status.media_attachments.first.video?
|
- if status.media_attachments.first.video?
|
||||||
- video = status.media_attachments.first
|
- video = status.media_attachments.first
|
||||||
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: status.sensitive?, width: 670, height: 380, detailed: true, inline: true, alt: video.description do
|
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 670, height: 380, detailed: true, inline: true, alt: video.description do
|
||||||
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- elsif status.media_attachments.first.audio?
|
- elsif status.media_attachments.first.audio?
|
||||||
- audio = status.media_attachments.first
|
- audio = status.media_attachments.first
|
||||||
= react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 670, height: 380, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do
|
= react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 670, height: 380, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do
|
||||||
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- else
|
- else
|
||||||
= react_component :media_gallery, height: 380, sensitive: status.sensitive?, standalone: true, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
|
= react_component :media_gallery, height: 380, sensitive: sensitized?(status, current_account), standalone: true, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
|
||||||
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- elsif status.preview_card
|
- elsif status.preview_card
|
||||||
= react_component :card, sensitive: status.sensitive?, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
= react_component :card, sensitive: sensitized?(status, current_account), 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
||||||
|
|
||||||
.detailed-status__meta
|
.detailed-status__meta
|
||||||
%data.dt-published{ value: status.created_at.to_time.iso8601 }
|
%data.dt-published{ value: status.created_at.to_time.iso8601 }
|
||||||
|
|
|
@ -35,17 +35,17 @@
|
||||||
- if !status.media_attachments.empty?
|
- if !status.media_attachments.empty?
|
||||||
- if status.media_attachments.first.video?
|
- if status.media_attachments.first.video?
|
||||||
- video = status.media_attachments.first
|
- video = status.media_attachments.first
|
||||||
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: status.sensitive?, width: 610, height: 343, inline: true, alt: video.description do
|
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 610, height: 343, inline: true, alt: video.description do
|
||||||
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- elsif status.media_attachments.first.audio?
|
- elsif status.media_attachments.first.audio?
|
||||||
- audio = status.media_attachments.first
|
- audio = status.media_attachments.first
|
||||||
= react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 610, height: 343, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do
|
= react_component :audio, src: full_asset_url(audio.file.url(:original)), poster: full_asset_url(audio.thumbnail.present? ? audio.thumbnail.url : status.account.avatar_static_url), backgroundColor: audio.file.meta.dig('colors', 'background'), foregroundColor: audio.file.meta.dig('colors', 'foreground'), accentColor: audio.file.meta.dig('colors', 'accent'), width: 610, height: 343, alt: audio.description, duration: audio.file.meta.dig('original', 'duration') do
|
||||||
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- else
|
- else
|
||||||
= react_component :media_gallery, height: 343, sensitive: status.sensitive?, autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
|
= react_component :media_gallery, height: 343, sensitive: sensitized?(status, current_account), autoplay: autoplay, media: status.media_attachments.map { |a| ActiveModelSerializers::SerializableResource.new(a, serializer: REST::MediaAttachmentSerializer).as_json } do
|
||||||
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
|
||||||
- elsif status.preview_card
|
- elsif status.preview_card
|
||||||
= react_component :card, sensitive: status.sensitive?, 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
= react_component :card, sensitive: sensitized?(status, current_account), 'maxDescription': 160, card: ActiveModelSerializers::SerializableResource.new(status.preview_card, serializer: REST::PreviewCardSerializer).as_json
|
||||||
|
|
||||||
- if !status.in_reply_to_id.nil? && status.in_reply_to_account_id == status.account.id
|
- if !status.in_reply_to_id.nil? && status.in_reply_to_account_id == status.account.id
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__content__read-more-button', target: stream_link_target, rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'status__content__read-more-button', target: stream_link_target, rel: 'noopener noreferrer' do
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
- if status.reply? && include_threads
|
- if status.reply? && include_threads
|
||||||
- if @next_ancestor
|
- if @next_ancestor
|
||||||
.entry{ class: entry_classes }
|
.entry{ class: entry_classes }
|
||||||
= link_to_more ActivityPub::TagManager.instance.url_for(@next_ancestor)
|
= link_to_older ActivityPub::TagManager.instance.url_for(@next_ancestor)
|
||||||
|
|
||||||
= render partial: 'statuses/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }, autoplay: autoplay
|
= render partial: 'statuses/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }, autoplay: autoplay
|
||||||
|
|
||||||
|
@ -44,16 +44,16 @@
|
||||||
- if include_threads
|
- if include_threads
|
||||||
- if @since_descendant_thread_id
|
- if @since_descendant_thread_id
|
||||||
.entry{ class: entry_classes }
|
.entry{ class: entry_classes }
|
||||||
= link_to_more short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
|
= link_to_newer short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
|
||||||
- @descendant_threads.each do |thread|
|
- @descendant_threads.each do |thread|
|
||||||
= render partial: 'statuses/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }, autoplay: autoplay
|
= render partial: 'statuses/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }, autoplay: autoplay
|
||||||
|
|
||||||
- if thread[:next_status]
|
- if thread[:next_status]
|
||||||
.entry{ class: entry_classes }
|
.entry{ class: entry_classes }
|
||||||
= link_to_more ActivityPub::TagManager.instance.url_for(thread[:next_status])
|
= link_to_newer ActivityPub::TagManager.instance.url_for(thread[:next_status])
|
||||||
- if @next_descendant_thread
|
- if @next_descendant_thread
|
||||||
.entry{ class: entry_classes }
|
.entry{ class: entry_classes }
|
||||||
= link_to_more short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)
|
= link_to_newer short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)
|
||||||
|
|
||||||
- if include_threads && !embedded_view? && !user_signed_in?
|
- if include_threads && !embedded_view? && !user_signed_in?
|
||||||
.entry{ class: entry_classes }
|
.entry{ class: entry_classes }
|
||||||
|
|
|
@ -22,6 +22,8 @@ require_relative '../lib/mastodon/version'
|
||||||
require_relative '../lib/devise/two_factor_ldap_authenticatable'
|
require_relative '../lib/devise/two_factor_ldap_authenticatable'
|
||||||
require_relative '../lib/devise/two_factor_pam_authenticatable'
|
require_relative '../lib/devise/two_factor_pam_authenticatable'
|
||||||
require_relative '../lib/chewy/strategy/custom_sidekiq'
|
require_relative '../lib/chewy/strategy/custom_sidekiq'
|
||||||
|
require_relative '../lib/webpacker/manifest_extensions'
|
||||||
|
require_relative '../lib/webpacker/helper_extensions'
|
||||||
|
|
||||||
Dotenv::Railtie.load
|
Dotenv::Railtie.load
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ Warden::Manager.after_set_user except: :fetch do |user, warden|
|
||||||
expires: 1.year.from_now,
|
expires: 1.year.from_now,
|
||||||
httponly: true,
|
httponly: true,
|
||||||
secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'),
|
secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'),
|
||||||
|
same_site: :lax,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ Warden::Manager.after_fetch do |user, warden|
|
||||||
expires: 1.year.from_now,
|
expires: 1.year.from_now,
|
||||||
httponly: true,
|
httponly: true,
|
||||||
secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'),
|
secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'),
|
||||||
|
same_site: :lax,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
warden.logout
|
warden.logout
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Makara::Cookie::DEFAULT_OPTIONS[:same_site] = :lax
|
||||||
|
Makara::Cookie::DEFAULT_OPTIONS[:secure] = Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'
|
|
@ -1,3 +1,7 @@
|
||||||
# Be sure to restart your server when you modify this file.
|
# Be sure to restart your server when you modify this file.
|
||||||
|
|
||||||
Rails.application.config.session_store :cookie_store, key: '_mastodon_session', secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true')
|
Rails.application.config.session_store :cookie_store, {
|
||||||
|
key: '_mastodon_session',
|
||||||
|
secure: (Rails.env.production? || ENV['LOCAL_HTTPS'] == 'true'),
|
||||||
|
same_site: :lax,
|
||||||
|
}
|
||||||
|
|
|
@ -188,6 +188,8 @@ en:
|
||||||
search: Search
|
search: Search
|
||||||
search_same_email_domain: Other users with the same e-mail domain
|
search_same_email_domain: Other users with the same e-mail domain
|
||||||
search_same_ip: Other users with the same IP
|
search_same_ip: Other users with the same IP
|
||||||
|
sensitive: Sensitive
|
||||||
|
sensitized: marked as sensitive
|
||||||
shared_inbox_url: Shared inbox URL
|
shared_inbox_url: Shared inbox URL
|
||||||
show:
|
show:
|
||||||
created_reports: Made reports
|
created_reports: Made reports
|
||||||
|
@ -202,6 +204,7 @@ en:
|
||||||
time_in_queue: Waiting in queue %{time}
|
time_in_queue: Waiting in queue %{time}
|
||||||
title: Accounts
|
title: Accounts
|
||||||
unconfirmed_email: Unconfirmed email
|
unconfirmed_email: Unconfirmed email
|
||||||
|
undo_sensitized: Undo sensitive
|
||||||
undo_silenced: Undo silence
|
undo_silenced: Undo silence
|
||||||
undo_suspension: Undo suspension
|
undo_suspension: Undo suspension
|
||||||
unsilenced_msg: Successfully unlimited %{username}'s account
|
unsilenced_msg: Successfully unlimited %{username}'s account
|
||||||
|
@ -243,9 +246,11 @@ en:
|
||||||
reopen_report: Reopen Report
|
reopen_report: Reopen Report
|
||||||
reset_password_user: Reset Password
|
reset_password_user: Reset Password
|
||||||
resolve_report: Resolve Report
|
resolve_report: Resolve Report
|
||||||
|
sensitive_account: Mark the media in your account as sensitive
|
||||||
silence_account: Silence Account
|
silence_account: Silence Account
|
||||||
suspend_account: Suspend Account
|
suspend_account: Suspend Account
|
||||||
unassigned_report: Unassign Report
|
unassigned_report: Unassign Report
|
||||||
|
unsensitive_account: Unmark the media in your account as sensitive
|
||||||
unsilence_account: Unsilence Account
|
unsilence_account: Unsilence Account
|
||||||
unsuspend_account: Unsuspend Account
|
unsuspend_account: Unsuspend Account
|
||||||
update_announcement: Update Announcement
|
update_announcement: Update Announcement
|
||||||
|
@ -281,9 +286,11 @@ en:
|
||||||
reopen_report: "%{name} reopened report %{target}"
|
reopen_report: "%{name} reopened report %{target}"
|
||||||
reset_password_user: "%{name} reset password of user %{target}"
|
reset_password_user: "%{name} reset password of user %{target}"
|
||||||
resolve_report: "%{name} resolved report %{target}"
|
resolve_report: "%{name} resolved report %{target}"
|
||||||
|
sensitive_account: "%{name} marked %{target}'s media as sensitive"
|
||||||
silence_account: "%{name} silenced %{target}'s account"
|
silence_account: "%{name} silenced %{target}'s account"
|
||||||
suspend_account: "%{name} suspended %{target}'s account"
|
suspend_account: "%{name} suspended %{target}'s account"
|
||||||
unassigned_report: "%{name} unassigned report %{target}"
|
unassigned_report: "%{name} unassigned report %{target}"
|
||||||
|
unsensitive_account: "%{name} unmarked %{target}'s media as sensitive"
|
||||||
unsilence_account: "%{name} unsilenced %{target}'s account"
|
unsilence_account: "%{name} unsilenced %{target}'s account"
|
||||||
unsuspend_account: "%{name} unsuspended %{target}'s account"
|
unsuspend_account: "%{name} unsuspended %{target}'s account"
|
||||||
update_announcement: "%{name} updated announcement %{target}"
|
update_announcement: "%{name} updated announcement %{target}"
|
||||||
|
@ -1203,6 +1210,8 @@ en:
|
||||||
other: "%{count} votes"
|
other: "%{count} votes"
|
||||||
vote: Vote
|
vote: Vote
|
||||||
show_more: Show more
|
show_more: Show more
|
||||||
|
show_newer: Show newer
|
||||||
|
show_older: Show older
|
||||||
show_thread: Show thread
|
show_thread: Show thread
|
||||||
sign_in_to_participate: Sign in to participate in the conversation
|
sign_in_to_participate: Sign in to participate in the conversation
|
||||||
title: '%{name}: "%{quote}"'
|
title: '%{name}: "%{quote}"'
|
||||||
|
@ -1339,6 +1348,7 @@ en:
|
||||||
warning:
|
warning:
|
||||||
explanation:
|
explanation:
|
||||||
disable: You can no longer login to your account or use it in any other way, but your profile and other data remains intact.
|
disable: You can no longer login to your account or use it in any other way, but your profile and other data remains intact.
|
||||||
|
sensitive: Your uploaded media files and linked media will be treated as sensitive.
|
||||||
silence: You can still use your account but only people who are already following you will see your toots on this server, and you may be excluded from various public listings. However, others may still manually follow you.
|
silence: You can still use your account but only people who are already following you will see your toots on this server, and you may be excluded from various public listings. However, others may still manually follow you.
|
||||||
suspend: You can no longer use your account, and your profile and other data are no longer accessible. You can still login to request a backup of your data until the data is fully removed, but we will retain some data to prevent you from evading the suspension.
|
suspend: You can no longer use your account, and your profile and other data are no longer accessible. You can still login to request a backup of your data until the data is fully removed, but we will retain some data to prevent you from evading the suspension.
|
||||||
get_in_touch: You can reply to this e-mail to get in touch with the staff of %{instance}.
|
get_in_touch: You can reply to this e-mail to get in touch with the staff of %{instance}.
|
||||||
|
@ -1347,11 +1357,13 @@ en:
|
||||||
subject:
|
subject:
|
||||||
disable: Your account %{acct} has been frozen
|
disable: Your account %{acct} has been frozen
|
||||||
none: Warning for %{acct}
|
none: Warning for %{acct}
|
||||||
|
sensitive: Your account %{acct} posting media has been marked as sensitive
|
||||||
silence: Your account %{acct} has been limited
|
silence: Your account %{acct} has been limited
|
||||||
suspend: Your account %{acct} has been suspended
|
suspend: Your account %{acct} has been suspended
|
||||||
title:
|
title:
|
||||||
disable: Account frozen
|
disable: Account frozen
|
||||||
none: Warning
|
none: Warning
|
||||||
|
sensitive: Your media has been marked as sensitive
|
||||||
silence: Account limited
|
silence: Account limited
|
||||||
suspend: Account suspended
|
suspend: Account suspended
|
||||||
welcome:
|
welcome:
|
||||||
|
|
|
@ -172,6 +172,8 @@ ja:
|
||||||
search: 検索
|
search: 検索
|
||||||
search_same_email_domain: 同じドメインのメールアドレスを使用しているユーザー
|
search_same_email_domain: 同じドメインのメールアドレスを使用しているユーザー
|
||||||
search_same_ip: 同じ IP のユーザーを検索
|
search_same_ip: 同じ IP のユーザーを検索
|
||||||
|
sensitive: 閲覧注意
|
||||||
|
sensitized: 閲覧注意済み
|
||||||
shared_inbox_url: Shared inbox URL
|
shared_inbox_url: Shared inbox URL
|
||||||
show:
|
show:
|
||||||
created_reports: このアカウントで作られた通報
|
created_reports: このアカウントで作られた通報
|
||||||
|
@ -184,6 +186,7 @@ ja:
|
||||||
time_in_queue: "%{time} 待ち"
|
time_in_queue: "%{time} 待ち"
|
||||||
title: アカウント
|
title: アカウント
|
||||||
unconfirmed_email: 確認待ちのメールアドレス
|
unconfirmed_email: 確認待ちのメールアドレス
|
||||||
|
undo_sensitized: 閲覧注意から戻す
|
||||||
undo_silenced: サイレンスから戻す
|
undo_silenced: サイレンスから戻す
|
||||||
undo_suspension: 停止から戻す
|
undo_suspension: 停止から戻す
|
||||||
unsubscribe: 購読の解除
|
unsubscribe: 購読の解除
|
||||||
|
@ -220,9 +223,11 @@ ja:
|
||||||
reopen_report: 通報を再度開く
|
reopen_report: 通報を再度開く
|
||||||
reset_password_user: パスワードをリセット
|
reset_password_user: パスワードをリセット
|
||||||
resolve_report: 通報を解決済みにする
|
resolve_report: 通報を解決済みにする
|
||||||
|
sensitive_account: アカウントのメディアを閲覧注意にマーク
|
||||||
silence_account: アカウントをサイレンス
|
silence_account: アカウントをサイレンス
|
||||||
suspend_account: アカウントを停止
|
suspend_account: アカウントを停止
|
||||||
unassigned_report: 通報の担当を解除
|
unassigned_report: 通報の担当を解除
|
||||||
|
unsensitive_account: アカウントのメディアの閲覧注意マークを解除
|
||||||
unsilence_account: アカウントのサイレンスを解除
|
unsilence_account: アカウントのサイレンスを解除
|
||||||
unsuspend_account: アカウントの停止を解除
|
unsuspend_account: アカウントの停止を解除
|
||||||
update_announcement: お知らせを更新
|
update_announcement: お知らせを更新
|
||||||
|
@ -256,9 +261,11 @@ ja:
|
||||||
reopen_report: "%{name} さんが通報 %{target} を再び開きました"
|
reopen_report: "%{name} さんが通報 %{target} を再び開きました"
|
||||||
reset_password_user: "%{name} さんが %{target} さんのパスワードをリセットしました"
|
reset_password_user: "%{name} さんが %{target} さんのパスワードをリセットしました"
|
||||||
resolve_report: "%{name} さんが通報 %{target} を解決済みにしました"
|
resolve_report: "%{name} さんが通報 %{target} を解決済みにしました"
|
||||||
|
sensitive_account: "%{name} さんが %{target} さんのメディアを閲覧注意にマークしました"
|
||||||
silence_account: "%{name} さんが %{target} さんをサイレンスにしました"
|
silence_account: "%{name} さんが %{target} さんをサイレンスにしました"
|
||||||
suspend_account: "%{name} さんが %{target} さんを停止しました"
|
suspend_account: "%{name} さんが %{target} さんを停止しました"
|
||||||
unassigned_report: "%{name} さんが通報 %{target} の担当を外しました"
|
unassigned_report: "%{name} さんが通報 %{target} の担当を外しました"
|
||||||
|
unsensitive_account: "%{name} さんが %{target} さんのメディアの閲覧注意を解除しました"
|
||||||
unsilence_account: "%{name} さんが %{target} さんのサイレンスを解除しました"
|
unsilence_account: "%{name} さんが %{target} さんのサイレンスを解除しました"
|
||||||
unsuspend_account: "%{name} さんが %{target} さんの停止を解除しました"
|
unsuspend_account: "%{name} さんが %{target} さんの停止を解除しました"
|
||||||
update_announcement: "%{name} さんがお知らせ %{target} を更新しました"
|
update_announcement: "%{name} さんがお知らせ %{target} を更新しました"
|
||||||
|
@ -1271,6 +1278,7 @@ ja:
|
||||||
warning:
|
warning:
|
||||||
explanation:
|
explanation:
|
||||||
disable: アカウントが凍結されている間、データはそのまま残りますが、凍結が解除されるまでは何の操作もできません。
|
disable: アカウントが凍結されている間、データはそのまま残りますが、凍結が解除されるまでは何の操作もできません。
|
||||||
|
sensitive: あなたのアップロードしたメディアファイルとリンク先のメディアは、閲覧注意として扱われます。
|
||||||
silence: あなたのアカウントは制限されていますが、あなたをフォローしているユーザーのみ、このサーバー上の投稿を見ることができます。そしてあなたは様々な公開リストから除外されるかもしれません。ただし、他のユーザーは手動であなたをフォローすることができます。
|
silence: あなたのアカウントは制限されていますが、あなたをフォローしているユーザーのみ、このサーバー上の投稿を見ることができます。そしてあなたは様々な公開リストから除外されるかもしれません。ただし、他のユーザーは手動であなたをフォローすることができます。
|
||||||
suspend: あなたのアカウントは停止されています。あなたの投稿とアップロードされたメディアファイルは、このサーバーとあなたのフォロワーが参加していたサーバーから完全に削除されました。
|
suspend: あなたのアカウントは停止されています。あなたの投稿とアップロードされたメディアファイルは、このサーバーとあなたのフォロワーが参加していたサーバーから完全に削除されました。
|
||||||
get_in_touch: このメールに返信することで %{instance} のスタッフと連絡を取ることができます。
|
get_in_touch: このメールに返信することで %{instance} のスタッフと連絡を取ることができます。
|
||||||
|
@ -1279,11 +1287,13 @@ ja:
|
||||||
subject:
|
subject:
|
||||||
disable: あなたのアカウント %{acct} は凍結されました
|
disable: あなたのアカウント %{acct} は凍結されました
|
||||||
none: "%{acct} に対する警告"
|
none: "%{acct} に対する警告"
|
||||||
|
sensitive: あなたのアカウント %{acct} の投稿メディアは閲覧注意とマークされました
|
||||||
silence: あなたのアカウント %{acct} はサイレンスにされました
|
silence: あなたのアカウント %{acct} はサイレンスにされました
|
||||||
suspend: あなたのアカウント %{acct} は停止されました
|
suspend: あなたのアカウント %{acct} は停止されました
|
||||||
title:
|
title:
|
||||||
disable: アカウントが凍結されました
|
disable: アカウントが凍結されました
|
||||||
none: 警告
|
none: 警告
|
||||||
|
sensitive: あなたのメディアが閲覧注意とマークされました
|
||||||
silence: アカウントがサイレンスにされました
|
silence: アカウントがサイレンスにされました
|
||||||
suspend: アカウントが停止されました
|
suspend: アカウントが停止されました
|
||||||
welcome:
|
welcome:
|
||||||
|
|
|
@ -100,6 +100,7 @@ en:
|
||||||
types:
|
types:
|
||||||
disable: Freeze
|
disable: Freeze
|
||||||
none: Send a warning
|
none: Send a warning
|
||||||
|
sensitive: Sensitive
|
||||||
silence: Limit
|
silence: Limit
|
||||||
suspend: Suspend
|
suspend: Suspend
|
||||||
warning_preset_id: Use a warning preset
|
warning_preset_id: Use a warning preset
|
||||||
|
|
|
@ -91,6 +91,7 @@ ja:
|
||||||
types:
|
types:
|
||||||
disable: ログインを無効化
|
disable: ログインを無効化
|
||||||
none: 何もしない
|
none: 何もしない
|
||||||
|
sensitive: 閲覧注意
|
||||||
silence: サイレンス
|
silence: サイレンス
|
||||||
suspend: 停止しアカウントのデータを恒久的に削除する
|
suspend: 停止しアカウントのデータを恒久的に削除する
|
||||||
warning_preset_id: プリセット警告文を使用
|
warning_preset_id: プリセット警告文を使用
|
||||||
|
|
|
@ -238,6 +238,7 @@ Rails.application.routes.draw do
|
||||||
resources :accounts, only: [:index, :show, :destroy] do
|
resources :accounts, only: [:index, :show, :destroy] do
|
||||||
member do
|
member do
|
||||||
post :enable
|
post :enable
|
||||||
|
post :unsensitive
|
||||||
post :unsilence
|
post :unsilence
|
||||||
post :unsuspend
|
post :unsuspend
|
||||||
post :redownload
|
post :redownload
|
||||||
|
@ -480,6 +481,7 @@ Rails.application.routes.draw do
|
||||||
resources :accounts, only: [:index, :show, :destroy] do
|
resources :accounts, only: [:index, :show, :destroy] do
|
||||||
member do
|
member do
|
||||||
post :enable
|
post :enable
|
||||||
|
post :unsensitive
|
||||||
post :unsilence
|
post :unsilence
|
||||||
post :unsuspend
|
post :unsuspend
|
||||||
post :approve
|
post :approve
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Note: You must restart bin/webpack-dev-server for changes to take effect
|
// Note: You must restart bin/webpack-dev-server for changes to take effect
|
||||||
|
|
||||||
const merge = require('webpack-merge');
|
const { merge } = require('webpack-merge');
|
||||||
const sharedConfig = require('./shared');
|
const sharedConfig = require('./shared');
|
||||||
const { settings, output } = require('./configuration');
|
const { settings, output } = require('./configuration');
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { URL } = require('url');
|
const { URL } = require('url');
|
||||||
const merge = require('webpack-merge');
|
const { merge } = require('webpack-merge');
|
||||||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||||
const OfflinePlugin = require('offline-plugin');
|
const OfflinePlugin = require('offline-plugin');
|
||||||
const TerserPlugin = require('terser-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
|
|
|
@ -104,7 +104,8 @@ module.exports = {
|
||||||
chunkFilename: 'css/[name]-[contenthash:8].chunk.css',
|
chunkFilename: 'css/[name]-[contenthash:8].chunk.css',
|
||||||
}),
|
}),
|
||||||
new AssetsManifestPlugin({
|
new AssetsManifestPlugin({
|
||||||
integrity: false,
|
integrity: true,
|
||||||
|
integrityHashes: ['sha256'],
|
||||||
entrypoints: true,
|
entrypoints: true,
|
||||||
writeToDisk: true,
|
writeToDisk: true,
|
||||||
publicPath: true,
|
publicPath: true,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Note: You must restart bin/webpack-dev-server for changes to take effect
|
// Note: You must restart bin/webpack-dev-server for changes to take effect
|
||||||
|
|
||||||
const merge = require('webpack-merge');
|
const { merge } = require('webpack-merge');
|
||||||
const sharedConfig = require('./shared.js');
|
const sharedConfig = require('./shared.js');
|
||||||
|
|
||||||
module.exports = merge(sharedConfig, {
|
module.exports = merge(sharedConfig, {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddSensitizedToAccounts < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :accounts, :sensitized_at, :datetime
|
||||||
|
end
|
||||||
|
end
|
|
@ -189,6 +189,7 @@ ActiveRecord::Schema.define(version: 2020_10_08_220312) do
|
||||||
t.integer "avatar_storage_schema_version"
|
t.integer "avatar_storage_schema_version"
|
||||||
t.integer "header_storage_schema_version"
|
t.integer "header_storage_schema_version"
|
||||||
t.string "devices_url"
|
t.string "devices_url"
|
||||||
|
t.datetime "sensitized_at"
|
||||||
t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
|
t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
|
||||||
t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
|
t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
|
||||||
t.index ["moved_to_account_id"], name: "index_accounts_on_moved_to_account_id"
|
t.index ["moved_to_account_id"], name: "index_accounts_on_moved_to_account_id"
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Webpacker::HelperExtensions
|
||||||
|
def javascript_pack_tag(name, **options)
|
||||||
|
src, integrity = current_webpacker_instance.manifest.lookup!(name, type: :javascript, with_integrity: true)
|
||||||
|
javascript_include_tag(src, options.merge(integrity: integrity))
|
||||||
|
end
|
||||||
|
|
||||||
|
def stylesheet_pack_tag(name, **options)
|
||||||
|
src, integrity = current_webpacker_instance.manifest.lookup!(name, type: :stylesheet, with_integrity: true)
|
||||||
|
stylesheet_link_tag(src, options.merge(integrity: integrity))
|
||||||
|
end
|
||||||
|
|
||||||
|
def preload_pack_asset(name, **options)
|
||||||
|
src, integrity = current_webpacker_instance.manifest.lookup!(name, with_integrity: true)
|
||||||
|
preload_link_tag(src, options.merge(integrity: integrity))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Webpacker::Helper.prepend(Webpacker::HelperExtensions)
|
|
@ -0,0 +1,17 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Webpacker::ManifestExtensions
|
||||||
|
def lookup(name, pack_type = {})
|
||||||
|
asset = super
|
||||||
|
|
||||||
|
if pack_type[:with_integrity] && asset.respond_to?(:dig)
|
||||||
|
[asset.dig('src'), asset.dig('integrity')]
|
||||||
|
elsif asset.respond_to?(:dig)
|
||||||
|
asset.dig('src')
|
||||||
|
else
|
||||||
|
asset
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Webpacker::Manifest.prepend(Webpacker::ManifestExtensions)
|
20
package.json
20
package.json
|
@ -85,11 +85,11 @@
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"blurhash": "^1.1.3",
|
"blurhash": "^1.1.3",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"compression-webpack-plugin": "^6.0.3",
|
"compression-webpack-plugin": "^6.0.4",
|
||||||
"cross-env": "^7.0.2",
|
"cross-env": "^7.0.2",
|
||||||
"css-loader": "^5.0.0",
|
"css-loader": "^5.0.0",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"detect-passive-events": "^1.0.5",
|
"detect-passive-events": "^2.0.1",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"emoji-mart": "Gargron/emoji-mart#build",
|
"emoji-mart": "Gargron/emoji-mart#build",
|
||||||
"es6-symbol": "^3.1.3",
|
"es6-symbol": "^3.1.3",
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
"exif-js": "^2.3.0",
|
"exif-js": "^2.3.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"favico.js": "^0.3.10",
|
"favico.js": "^0.3.10",
|
||||||
"file-loader": "^6.1.1",
|
"file-loader": "^6.2.0",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"history": "^4.10.1",
|
"history": "^4.10.1",
|
||||||
|
@ -113,7 +113,7 @@
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
"mark-loader": "^0.1.6",
|
"mark-loader": "^0.1.6",
|
||||||
"marky": "^1.2.1",
|
"marky": "^1.2.1",
|
||||||
"mini-css-extract-plugin": "^1.2.0",
|
"mini-css-extract-plugin": "^1.2.1",
|
||||||
"mkdirp": "^1.0.4",
|
"mkdirp": "^1.0.4",
|
||||||
"npmlog": "^4.1.2",
|
"npmlog": "^4.1.2",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
|
@ -137,7 +137,7 @@
|
||||||
"react-motion": "^0.5.2",
|
"react-motion": "^0.5.2",
|
||||||
"react-notification": "^6.8.5",
|
"react-notification": "^6.8.5",
|
||||||
"react-overlays": "^0.9.2",
|
"react-overlays": "^0.9.2",
|
||||||
"react-redux": "^7.2.1",
|
"react-redux": "^7.2.2",
|
||||||
"react-redux-loading-bar": "^4.0.8",
|
"react-redux-loading-bar": "^4.0.8",
|
||||||
"react-router-dom": "^4.1.1",
|
"react-router-dom": "^4.1.1",
|
||||||
"react-router-scroll-4": "^1.0.0-beta.1",
|
"react-router-scroll-4": "^1.0.0-beta.1",
|
||||||
|
@ -155,7 +155,7 @@
|
||||||
"requestidlecallback": "^0.3.0",
|
"requestidlecallback": "^0.3.0",
|
||||||
"reselect": "^4.0.0",
|
"reselect": "^4.0.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sass": "^1.27.0",
|
"sass": "^1.28.0",
|
||||||
"sass-loader": "^10.0.4",
|
"sass-loader": "^10.0.4",
|
||||||
"stacktrace-js": "^2.0.2",
|
"stacktrace-js": "^2.0.2",
|
||||||
"stringz": "^2.1.0",
|
"stringz": "^2.1.0",
|
||||||
|
@ -169,17 +169,17 @@
|
||||||
"webpack-assets-manifest": "^3.1.1",
|
"webpack-assets-manifest": "^3.1.1",
|
||||||
"webpack-bundle-analyzer": "^3.9.0",
|
"webpack-bundle-analyzer": "^3.9.0",
|
||||||
"webpack-cli": "^3.3.12",
|
"webpack-cli": "^3.3.12",
|
||||||
"webpack-merge": "^4.2.1",
|
"webpack-merge": "^5.0.9",
|
||||||
"wicg-inert": "^3.0.3"
|
"wicg-inert": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@testing-library/jest-dom": "^5.11.5",
|
"@testing-library/jest-dom": "^5.11.5",
|
||||||
"@testing-library/react": "^11.1.0",
|
"@testing-library/react": "^11.1.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-jest": "^26.6.1",
|
"babel-jest": "^26.6.1",
|
||||||
"eslint": "^7.12.0",
|
"eslint": "^7.12.1",
|
||||||
"eslint-plugin-import": "~2.22.1",
|
"eslint-plugin-import": "~2.22.1",
|
||||||
"eslint-plugin-jsx-a11y": "~6.3.1",
|
"eslint-plugin-jsx-a11y": "~6.4.1",
|
||||||
"eslint-plugin-promise": "~4.2.1",
|
"eslint-plugin-promise": "~4.2.1",
|
||||||
"eslint-plugin-react": "~7.21.5",
|
"eslint-plugin-react": "~7.21.5",
|
||||||
"jest": "^26.6.1",
|
"jest": "^26.6.1",
|
||||||
|
|
|
@ -127,6 +127,24 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST #unsensitive' do
|
||||||
|
before do
|
||||||
|
account.touch(:sensitized_at)
|
||||||
|
post :unsensitive, params: { id: account.id }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write:statuses'
|
||||||
|
it_behaves_like 'forbidden for wrong role', 'user'
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unsensitives account' do
|
||||||
|
expect(account.reload.sensitized?).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'POST #unsilence' do
|
describe 'POST #unsilence' do
|
||||||
before do
|
before do
|
||||||
account.touch(:silenced_at)
|
account.touch(:silenced_at)
|
||||||
|
|
|
@ -115,16 +115,16 @@ RSpec.describe Admin::AccountAction, type: :model do
|
||||||
context 'account.local?' do
|
context 'account.local?' do
|
||||||
let(:account) { Fabricate(:account, domain: nil) }
|
let(:account) { Fabricate(:account, domain: nil) }
|
||||||
|
|
||||||
it 'returns ["none", "disable", "silence", "suspend"]' do
|
it 'returns ["none", "disable", "sensitive", "silence", "suspend"]' do
|
||||||
expect(subject).to eq %w(none disable silence suspend)
|
expect(subject).to eq %w(none disable sensitive silence suspend)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context '!account.local?' do
|
context '!account.local?' do
|
||||||
let(:account) { Fabricate(:account, domain: 'hoge.com') }
|
let(:account) { Fabricate(:account, domain: 'hoge.com') }
|
||||||
|
|
||||||
it 'returns ["silence", "suspend"]' do
|
it 'returns ["sensitive", "silence", "suspend"]' do
|
||||||
expect(subject).to eq %w(silence suspend)
|
expect(subject).to eq %w(sensitive silence suspend)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe AccountPolicy do
|
||||||
let(:admin) { Fabricate(:user, admin: true).account }
|
let(:admin) { Fabricate(:user, admin: true).account }
|
||||||
let(:john) { Fabricate(:user).account }
|
let(:john) { Fabricate(:user).account }
|
||||||
|
|
||||||
permissions :index?, :show?, :unsuspend?, :unsilence?, :remove_avatar?, :remove_header? do
|
permissions :index?, :show?, :unsuspend?, :unsensitive?, :unsilence?, :remove_avatar?, :remove_header? do
|
||||||
context 'staff' do
|
context 'staff' do
|
||||||
it 'permits' do
|
it 'permits' do
|
||||||
expect(subject).to permit(admin)
|
expect(subject).to permit(admin)
|
||||||
|
|
164
yarn.lock
164
yarn.lock
|
@ -1080,10 +1080,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc"
|
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc"
|
||||||
integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA==
|
integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA==
|
||||||
|
|
||||||
"@eslint/eslintrc@^0.2.0":
|
"@eslint/eslintrc@^0.2.1":
|
||||||
version "0.2.0"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.0.tgz#bc7e3c4304d4c8720968ccaee793087dfb5fe6b4"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c"
|
||||||
integrity sha512-+cIGPCBdLCzqxdtwppswP+zTsH9BOIGzAeKfBIbtb4gW/giMlfMwP0HUSFfhzh20f9u8uZ8hOp62+4GPquTbwQ==
|
integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^6.12.4"
|
ajv "^6.12.4"
|
||||||
debug "^4.1.1"
|
debug "^4.1.1"
|
||||||
|
@ -2100,10 +2100,10 @@ aws4@^1.8.0:
|
||||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428"
|
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428"
|
||||||
integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==
|
integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==
|
||||||
|
|
||||||
axe-core@^3.5.4:
|
axe-core@^4.0.2:
|
||||||
version "3.5.5"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.5.tgz#84315073b53fa3c0c51676c588d59da09a192227"
|
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.0.2.tgz#c7cf7378378a51fcd272d3c09668002a4990b1cb"
|
||||||
integrity sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q==
|
integrity sha512-arU1h31OGFu+LPrOLGZ7nB45v940NMDMEJeNmbutu57P+UFDVnkZg3e+J1I2HJRZ9hT7gO8J91dn/PMrAiKakA==
|
||||||
|
|
||||||
axios@^0.21.0:
|
axios@^0.21.0:
|
||||||
version "0.21.0"
|
version "0.21.0"
|
||||||
|
@ -2112,7 +2112,7 @@ axios@^0.21.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.10.0"
|
follow-redirects "^1.10.0"
|
||||||
|
|
||||||
axobject-query@^2.1.2:
|
axobject-query@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
||||||
integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
|
integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
|
||||||
|
@ -2894,6 +2894,15 @@ cliui@^7.0.2:
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
wrap-ansi "^7.0.0"
|
wrap-ansi "^7.0.0"
|
||||||
|
|
||||||
|
clone-deep@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
|
||||||
|
integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
|
||||||
|
dependencies:
|
||||||
|
is-plain-object "^2.0.4"
|
||||||
|
kind-of "^6.0.2"
|
||||||
|
shallow-clone "^3.0.0"
|
||||||
|
|
||||||
co@^4.6.0:
|
co@^4.6.0:
|
||||||
version "4.6.0"
|
version "4.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||||
|
@ -3000,10 +3009,10 @@ compressible@~2.0.16:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db ">= 1.43.0 < 2"
|
mime-db ">= 1.43.0 < 2"
|
||||||
|
|
||||||
compression-webpack-plugin@^6.0.3:
|
compression-webpack-plugin@^6.0.4:
|
||||||
version "6.0.3"
|
version "6.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-6.0.3.tgz#d0d3e913810e3bf67462e1cecd794b3109af89de"
|
resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-6.0.4.tgz#524699c0ad4e94cab0eb199c734e291f6ab685b9"
|
||||||
integrity sha512-xzSWiZWwBs+HHGhlYxw0oFaYL/0VYErEqDHCAJhJ3Mza5fmF5JJ4iaB6Ap2JT68C0UhhmoI4Mh37LVz/THv2Fw==
|
integrity sha512-PViPdrF5UmqZxsr9WNoE+R6lTre6/5tC9TmWotBfhOQtWlc7oj/SXCsrecbZJ9LDpwLjHH6llPCKmw+JGPGN+A==
|
||||||
dependencies:
|
dependencies:
|
||||||
cacache "^15.0.5"
|
cacache "^15.0.5"
|
||||||
find-cache-dir "^3.3.1"
|
find-cache-dir "^3.3.1"
|
||||||
|
@ -3644,10 +3653,10 @@ detect-node@^2.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
|
||||||
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
|
||||||
|
|
||||||
detect-passive-events@^1.0.5:
|
detect-passive-events@^2.0.1:
|
||||||
version "1.0.5"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/detect-passive-events/-/detect-passive-events-1.0.5.tgz#ce324db665123bef9e368b8059ff95d95217cc05"
|
resolved "https://registry.yarnpkg.com/detect-passive-events/-/detect-passive-events-2.0.1.tgz#fdbd6f6dd5e6ac10c6189a4cb26ab264d41c0835"
|
||||||
integrity sha512-foW7Q35wwOCxVzW0xLf5XeB5Fhe7oyRgvkBYdiP9IWgLMzjqUqTvsJv9ymuEWGjY6AoDXD3OC294+Z9iuOw0QA==
|
integrity sha512-7WbRn4mznO63FW0KSYa7S3HgCG94uZ6HGZO1TyVRtdZuMNGUeY/ScWrIx45XnUz1LWoLZVi13ULVHqKE07ZfKg==
|
||||||
|
|
||||||
diff-sequences@^25.2.6:
|
diff-sequences@^25.2.6:
|
||||||
version "25.2.6"
|
version "25.2.6"
|
||||||
|
@ -4107,21 +4116,21 @@ eslint-plugin-import@~2.22.1:
|
||||||
resolve "^1.17.0"
|
resolve "^1.17.0"
|
||||||
tsconfig-paths "^3.9.0"
|
tsconfig-paths "^3.9.0"
|
||||||
|
|
||||||
eslint-plugin-jsx-a11y@~6.3.1:
|
eslint-plugin-jsx-a11y@~6.4.1:
|
||||||
version "6.3.1"
|
version "6.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd"
|
||||||
integrity sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g==
|
integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.10.2"
|
"@babel/runtime" "^7.11.2"
|
||||||
aria-query "^4.2.2"
|
aria-query "^4.2.2"
|
||||||
array-includes "^3.1.1"
|
array-includes "^3.1.1"
|
||||||
ast-types-flow "^0.0.7"
|
ast-types-flow "^0.0.7"
|
||||||
axe-core "^3.5.4"
|
axe-core "^4.0.2"
|
||||||
axobject-query "^2.1.2"
|
axobject-query "^2.2.0"
|
||||||
damerau-levenshtein "^1.0.6"
|
damerau-levenshtein "^1.0.6"
|
||||||
emoji-regex "^9.0.0"
|
emoji-regex "^9.0.0"
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
jsx-ast-utils "^2.4.1"
|
jsx-ast-utils "^3.1.0"
|
||||||
language-tags "^1.0.5"
|
language-tags "^1.0.5"
|
||||||
|
|
||||||
eslint-plugin-promise@~4.2.1:
|
eslint-plugin-promise@~4.2.1:
|
||||||
|
@ -4218,13 +4227,13 @@ eslint@^2.7.0:
|
||||||
text-table "~0.2.0"
|
text-table "~0.2.0"
|
||||||
user-home "^2.0.0"
|
user-home "^2.0.0"
|
||||||
|
|
||||||
eslint@^7.12.0:
|
eslint@^7.12.1:
|
||||||
version "7.12.0"
|
version "7.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.12.0.tgz#7b6a85f87a9adc239e979bb721cde5ce0dc27da6"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.12.1.tgz#bd9a81fa67a6cfd51656cdb88812ce49ccec5801"
|
||||||
integrity sha512-n5pEU27DRxCSlOhJ2rO57GDLcNsxO0LPpAbpFdh7xmcDmjmlGUfoyrsB3I7yYdQXO5N3gkSTiDrPSPNFiiirXA==
|
integrity sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.0.0"
|
"@babel/code-frame" "^7.0.0"
|
||||||
"@eslint/eslintrc" "^0.2.0"
|
"@eslint/eslintrc" "^0.2.1"
|
||||||
ajv "^6.10.0"
|
ajv "^6.10.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
cross-spawn "^7.0.2"
|
cross-spawn "^7.0.2"
|
||||||
|
@ -4586,10 +4595,10 @@ file-entry-cache@^5.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
flat-cache "^2.0.1"
|
flat-cache "^2.0.1"
|
||||||
|
|
||||||
file-loader@^6.1.1:
|
file-loader@^6.2.0:
|
||||||
version "6.1.1"
|
version "6.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.1.1.tgz#a6f29dfb3f5933a1c350b2dbaa20ac5be0539baa"
|
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d"
|
||||||
integrity sha512-Klt8C4BjWSXYQAfhpYYkG4qHNTna4toMHEbWrI5IuVoxbU6uiDKeKAP99R8mmbJi3lvewn/jQBOgU4+NS3tDQw==
|
integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==
|
||||||
dependencies:
|
dependencies:
|
||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
schema-utils "^3.0.0"
|
schema-utils "^3.0.0"
|
||||||
|
@ -5196,10 +5205,10 @@ hoist-non-react-statics@^2.5.0:
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
|
||||||
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
|
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
|
||||||
|
|
||||||
hoist-non-react-statics@^3.3.0:
|
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
||||||
version "3.3.0"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||||
integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==
|
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||||
dependencies:
|
dependencies:
|
||||||
react-is "^16.7.0"
|
react-is "^16.7.0"
|
||||||
|
|
||||||
|
@ -6576,18 +6585,10 @@ jsprim@^1.2.2:
|
||||||
json-schema "0.2.3"
|
json-schema "0.2.3"
|
||||||
verror "1.10.0"
|
verror "1.10.0"
|
||||||
|
|
||||||
jsx-ast-utils@^2.4.1:
|
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0:
|
||||||
version "2.4.1"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e"
|
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz#642f1d7b88aa6d7eb9d8f2210e166478444fa891"
|
||||||
integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==
|
integrity sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA==
|
||||||
dependencies:
|
|
||||||
array-includes "^3.1.1"
|
|
||||||
object.assign "^4.1.0"
|
|
||||||
|
|
||||||
"jsx-ast-utils@^2.4.1 || ^3.0.0":
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.0.0.tgz#0f49d5093bafa4b45d3fe02147d8b40ffc6c7438"
|
|
||||||
integrity sha512-sPuicm6EPKYI/UnWpOatvg4pI50qaBo4dSOMGUPutmJ26ttedFKXr0It0XXPk4HKnQ/1X0st4eSS2w2jhFk9Ow==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes "^3.1.1"
|
array-includes "^3.1.1"
|
||||||
object.assign "^4.1.1"
|
object.assign "^4.1.1"
|
||||||
|
@ -7006,10 +7007,10 @@ min-indent@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
|
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
|
||||||
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
|
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
|
||||||
|
|
||||||
mini-css-extract-plugin@^1.2.0:
|
mini-css-extract-plugin@^1.2.1:
|
||||||
version "1.2.0"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.2.0.tgz#f1bdfa7bb6f6a238bc327f813f204283ea33ee36"
|
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.2.1.tgz#30ea7dee632b3002b0c77aeed447790408cb247e"
|
||||||
integrity sha512-iBZokjaIjHvI4N0AURx5aPBawcmxB/d2NYikxZ4J57Lg5sDShUPyWvuSWl1dueI5oCs7nz8V7qtOCaLjB7AYPw==
|
integrity sha512-G3yw7/TQaPfkuiR73MDcyiqhyP8SnbmLhUbpC76H+wtQxA6wfKhMCQOCb6wnPK0dQbjORAeOILQqEesg4/wF7A==
|
||||||
dependencies:
|
dependencies:
|
||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
schema-utils "^3.0.0"
|
schema-utils "^3.0.0"
|
||||||
|
@ -8679,7 +8680,7 @@ react-intl@^2.9.0:
|
||||||
intl-relativeformat "^2.1.0"
|
intl-relativeformat "^2.1.0"
|
||||||
invariant "^2.1.1"
|
invariant "^2.1.1"
|
||||||
|
|
||||||
react-is@^16.12.0, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0:
|
react-is@^16.12.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||||
|
@ -8739,16 +8740,16 @@ react-redux-loading-bar@^4.0.8:
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
react-lifecycles-compat "^3.0.2"
|
react-lifecycles-compat "^3.0.2"
|
||||||
|
|
||||||
react-redux@^7.2.1:
|
react-redux@^7.2.2:
|
||||||
version "7.2.1"
|
version "7.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985"
|
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736"
|
||||||
integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==
|
integrity sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.5.5"
|
"@babel/runtime" "^7.12.1"
|
||||||
hoist-non-react-statics "^3.3.0"
|
hoist-non-react-statics "^3.3.2"
|
||||||
loose-envify "^1.4.0"
|
loose-envify "^1.4.0"
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
react-is "^16.9.0"
|
react-is "^16.13.1"
|
||||||
|
|
||||||
react-router-dom@^4.1.1:
|
react-router-dom@^4.1.1:
|
||||||
version "4.3.1"
|
version "4.3.1"
|
||||||
|
@ -9424,10 +9425,10 @@ sass-loader@^10.0.4:
|
||||||
schema-utils "^3.0.0"
|
schema-utils "^3.0.0"
|
||||||
semver "^7.3.2"
|
semver "^7.3.2"
|
||||||
|
|
||||||
sass@^1.27.0:
|
sass@^1.28.0:
|
||||||
version "1.27.0"
|
version "1.28.0"
|
||||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.27.0.tgz#0657ff674206b95ec20dc638a93e179c78f6ada2"
|
resolved "https://registry.yarnpkg.com/sass/-/sass-1.28.0.tgz#546f1308ff74cc4ec2ad735fd35dc18bc3f51f72"
|
||||||
integrity sha512-0gcrER56OkzotK/GGwgg4fPrKuiFlPNitO7eUJ18Bs+/NBlofJfMxmxqpqJxjae9vu0Wq8TZzrSyxZal00WDig==
|
integrity sha512-9FWX/0wuE1KxwfiP02chZhHaPzu6adpx9+wGch7WMOuHy5npOo0UapRI3FNSHva2CczaYJu2yNUBN8cCSqHz/A==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar ">=2.0.0 <4.0.0"
|
chokidar ">=2.0.0 <4.0.0"
|
||||||
|
|
||||||
|
@ -9615,6 +9616,13 @@ sha.js@^2.4.0, sha.js@^2.4.8:
|
||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
shallow-clone@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
|
||||||
|
integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
|
||||||
|
dependencies:
|
||||||
|
kind-of "^6.0.2"
|
||||||
|
|
||||||
shallow-equal@^1.2.1:
|
shallow-equal@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
|
resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
|
||||||
|
@ -11048,12 +11056,13 @@ webpack-log@^2.0.0:
|
||||||
ansi-colors "^3.0.0"
|
ansi-colors "^3.0.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
webpack-merge@^4.2.1:
|
webpack-merge@^5.0.9:
|
||||||
version "4.2.2"
|
version "5.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d"
|
resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.0.9.tgz#d5e0e0ae564ae704836d747893bdd2741544bf31"
|
||||||
integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==
|
integrity sha512-P4teh6O26xIDPugOGX61wPxaeP918QOMjmzhu54zTVcLtOS28ffPWtnv+ilt3wscwBUCL2WNMnh97XkrKqt9Fw==
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.17.15"
|
clone-deep "^4.0.1"
|
||||||
|
wildcard "^2.0.0"
|
||||||
|
|
||||||
webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
|
webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
|
||||||
version "1.4.3"
|
version "1.4.3"
|
||||||
|
@ -11153,10 +11162,10 @@ which@^2.0.1, which@^2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
wicg-inert@^3.0.3:
|
wicg-inert@^3.1.0:
|
||||||
version "3.0.3"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/wicg-inert/-/wicg-inert-3.0.3.tgz#7d05eaed64176887ee4c66fc0c4d6fe4b38ccce5"
|
resolved "https://registry.yarnpkg.com/wicg-inert/-/wicg-inert-3.1.0.tgz#6525f12db188b83f0051bed2ddcf6c1aa5b17590"
|
||||||
integrity sha512-XwXf8K0NN4cpagjBlZ2/j/5Sjf6dW3HNbfywEy1y6Z8PJKvSHVGiuc5Id/9RZ6EmGq+GQCGTo7B2SK0Misbr6g==
|
integrity sha512-P0ZiWaN9SxOkJbYtF/PIwmIRO8UTqTJtyl33QTQlHfAb6h15T0Dp5m7WTJ8N6UWIoj+KU5M0a8EtfRZLlHiP0Q==
|
||||||
|
|
||||||
wide-align@^1.1.0:
|
wide-align@^1.1.0:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
|
@ -11165,6 +11174,11 @@ wide-align@^1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width "^1.0.2 || 2"
|
string-width "^1.0.2 || 2"
|
||||||
|
|
||||||
|
wildcard@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
|
||||||
|
integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
|
||||||
|
|
||||||
word-wrap@^1.2.3, word-wrap@~1.2.3:
|
word-wrap@^1.2.3, word-wrap@~1.2.3:
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||||
|
|
Loading…
Reference in New Issue