Merge remote-tracking branch 'upstream/main' into develop

This commit is contained in:
Jeremy Kescher 2023-05-07 21:40:37 +02:00
commit 48cfb27b7c
No known key found for this signature in database
GPG key ID: 80A419A7A613DFA4
54 changed files with 177 additions and 201 deletions

View file

@ -225,6 +225,8 @@ Lint/Void:
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize: Metrics/AbcSize:
Max: 150 Max: 150
Exclude:
- 'app/serializers/initial_state_serializer.rb'
# Configuration parameters: CountBlocks, Max. # Configuration parameters: CountBlocks, Max.
Metrics/BlockNesting: Metrics/BlockNesting:
@ -247,6 +249,7 @@ Metrics/ModuleLength:
- 'app/helpers/jsonld_helper.rb' - 'app/helpers/jsonld_helper.rb'
- 'app/models/concerns/account_interactions.rb' - 'app/models/concerns/account_interactions.rb'
- 'app/models/concerns/has_user_settings.rb' - 'app/models/concerns/has_user_settings.rb'
- 'lib/sanitize_ext/sanitize_config.rb'
# Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. # Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters.
Metrics/ParameterLists: Metrics/ParameterLists:

View file

@ -11,6 +11,7 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
import classNames from 'classnames';
const messages = defineMessages({ const messages = defineMessages({
btnAll : { id: 'notification_purge.btn_all', defaultMessage: 'Select\nall' }, btnAll : { id: 'notification_purge.btn_all', defaultMessage: 'Select\nall' },
@ -36,19 +37,19 @@ class NotificationPurgeButtons extends ImmutablePureComponent {
//className='active' //className='active'
return ( return (
<div className='column-header__notif-cleaning-buttons'> <div className='column-header__notif-cleaning-buttons'>
<button onClick={this.props.onMarkAll} className={markNewForDelete ? 'active' : ''}> <button onClick={this.props.onMarkAll} className={classNames('column-header__button', { active: markNewForDelete })}>
<b></b><br />{intl.formatMessage(messages.btnAll)} <b></b><br />{intl.formatMessage(messages.btnAll)}
</button> </button>
<button onClick={this.props.onMarkNone} className={!markNewForDelete ? 'active' : ''}> <button onClick={this.props.onMarkNone} className={classNames('column-header__button', { active: !markNewForDelete })}>
<b></b><br />{intl.formatMessage(messages.btnNone)} <b></b><br />{intl.formatMessage(messages.btnNone)}
</button> </button>
<button onClick={this.props.onInvert}> <button onClick={this.props.onInvert} className='column-header__button'>
<b>¬</b><br />{intl.formatMessage(messages.btnInvert)} <b>¬</b><br />{intl.formatMessage(messages.btnInvert)}
</button> </button>
<button onClick={this.props.onDeleteMarked}> <button onClick={this.props.onDeleteMarked} className='column-header__button'>
<Icon id='trash' /><br />{intl.formatMessage(messages.btnApply)} <Icon id='trash' /><br />{intl.formatMessage(messages.btnApply)}
</button> </button>
</div> </div>

View file

@ -90,15 +90,19 @@ class ScrollableList extends PureComponent {
lastScrollWasSynthetic = false; lastScrollWasSynthetic = false;
scrollToTopOnMouseIdle = false; scrollToTopOnMouseIdle = false;
_getScrollingElement = () => {
if (this.props.bindToDocument) {
return (document.scrollingElement || document.body);
} else {
return this.node;
}
};
setScrollTop = newScrollTop => { setScrollTop = newScrollTop => {
if (this.getScrollTop() !== newScrollTop) { if (this.getScrollTop() !== newScrollTop) {
this.lastScrollWasSynthetic = true; this.lastScrollWasSynthetic = true;
if (this.props.bindToDocument) { this._getScrollingElement().scrollTop = newScrollTop;
document.scrollingElement.scrollTop = newScrollTop;
} else {
this.node.scrollTop = newScrollTop;
}
} }
}; };
@ -106,6 +110,7 @@ class ScrollableList extends PureComponent {
if (this.mouseIdleTimer === null) { if (this.mouseIdleTimer === null) {
return; return;
} }
clearTimeout(this.mouseIdleTimer); clearTimeout(this.mouseIdleTimer);
this.mouseIdleTimer = null; this.mouseIdleTimer = null;
}; };
@ -113,13 +118,13 @@ class ScrollableList extends PureComponent {
handleMouseMove = throttle(() => { handleMouseMove = throttle(() => {
// As long as the mouse keeps moving, clear and restart the idle timer. // As long as the mouse keeps moving, clear and restart the idle timer.
this.clearMouseIdleTimer(); this.clearMouseIdleTimer();
this.mouseIdleTimer = this.mouseIdleTimer = setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY);
setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY);
if (!this.mouseMovedRecently && this.getScrollTop() === 0) { if (!this.mouseMovedRecently && this.getScrollTop() === 0) {
// Only set if we just started moving and are scrolled to the top. // Only set if we just started moving and are scrolled to the top.
this.scrollToTopOnMouseIdle = true; this.scrollToTopOnMouseIdle = true;
} }
// Save setting this flag for last, so we can do the comparison above. // Save setting this flag for last, so we can do the comparison above.
this.mouseMovedRecently = true; this.mouseMovedRecently = true;
}, MOUSE_IDLE_DELAY / 2); }, MOUSE_IDLE_DELAY / 2);
@ -134,6 +139,7 @@ class ScrollableList extends PureComponent {
if (this.scrollToTopOnMouseIdle && !this.props.preventScroll) { if (this.scrollToTopOnMouseIdle && !this.props.preventScroll) {
this.setScrollTop(0); this.setScrollTop(0);
} }
this.mouseMovedRecently = false; this.mouseMovedRecently = false;
this.scrollToTopOnMouseIdle = false; this.scrollToTopOnMouseIdle = false;
}; };
@ -141,6 +147,7 @@ class ScrollableList extends PureComponent {
componentDidMount () { componentDidMount () {
this.attachScrollListener(); this.attachScrollListener();
this.attachIntersectionObserver(); this.attachIntersectionObserver();
attachFullscreenListener(this.onFullScreenChange); attachFullscreenListener(this.onFullScreenChange);
// Handle initial scroll position // Handle initial scroll position
@ -156,15 +163,15 @@ class ScrollableList extends PureComponent {
}; };
getScrollTop = () => { getScrollTop = () => {
return this.props.bindToDocument ? document.scrollingElement.scrollTop : this.node.scrollTop; return this._getScrollingElement().scrollTop;
}; };
getScrollHeight = () => { getScrollHeight = () => {
return this.props.bindToDocument ? document.scrollingElement.scrollHeight : this.node.scrollHeight; return this._getScrollingElement().scrollHeight;
}; };
getClientHeight = () => { getClientHeight = () => {
return this.props.bindToDocument ? document.scrollingElement.clientHeight : this.node.clientHeight; return this._getScrollingElement().clientHeight;
}; };
updateScrollBottom = (snapshot) => { updateScrollBottom = (snapshot) => {
@ -173,11 +180,7 @@ class ScrollableList extends PureComponent {
this.setScrollTop(newScrollTop); this.setScrollTop(newScrollTop);
}; };
cacheMediaWidth = (width) => { getSnapshotBeforeUpdate (prevProps) {
if (width && this.state.cachedMediaWidth != width) this.setState({ cachedMediaWidth: width });
};
getSnapshotBeforeUpdate (prevProps, prevState) {
const someItemInserted = React.Children.count(prevProps.children) > 0 && const someItemInserted = React.Children.count(prevProps.children) > 0 &&
React.Children.count(prevProps.children) < React.Children.count(this.props.children) && React.Children.count(prevProps.children) < React.Children.count(this.props.children) &&
this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props); this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props);
@ -198,10 +201,17 @@ class ScrollableList extends PureComponent {
} }
} }
cacheMediaWidth = (width) => {
if (width && this.state.cachedMediaWidth !== width) {
this.setState({ cachedMediaWidth: width });
}
};
componentWillUnmount () { componentWillUnmount () {
this.clearMouseIdleTimer(); this.clearMouseIdleTimer();
this.detachScrollListener(); this.detachScrollListener();
this.detachIntersectionObserver(); this.detachIntersectionObserver();
detachFullscreenListener(this.onFullScreenChange); detachFullscreenListener(this.onFullScreenChange);
} }
@ -210,10 +220,13 @@ class ScrollableList extends PureComponent {
}; };
attachIntersectionObserver () { attachIntersectionObserver () {
this.intersectionObserverWrapper.connect({ let nodeOptions = {
root: this.node, root: this.node,
rootMargin: '300% 0px', rootMargin: '300% 0px',
}); };
this.intersectionObserverWrapper
.connect(this.props.bindToDocument ? {} : nodeOptions);
} }
detachIntersectionObserver () { detachIntersectionObserver () {

View file

@ -138,6 +138,9 @@ class Status extends ImmutablePureComponent {
'expanded', 'expanded',
'unread', 'unread',
'pictureInPicture', 'pictureInPicture',
'previousId',
'nextInReplyToId',
'rootId',
]; ];
updateOnStates = [ updateOnStates = [

View file

@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import spring from 'react-motion/lib/spring';
import Toggle from 'react-toggle'; import Toggle from 'react-toggle';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
@ -16,7 +15,6 @@ import LanguageDropdown from '../containers/language_dropdown_container';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
// Utils. // Utils.
import Motion from '../../ui/util/optional_motion';
import { pollLimits } from 'flavours/glitch/initial_state'; import { pollLimits } from 'flavours/glitch/initial_state';
// Messages. // Messages.
@ -125,7 +123,6 @@ class ComposerOptions extends ImmutablePureComponent {
advancedOptions: ImmutablePropTypes.map, advancedOptions: ImmutablePropTypes.map,
disabled: PropTypes.bool, disabled: PropTypes.bool,
allowMedia: PropTypes.bool, allowMedia: PropTypes.bool,
hasMedia: PropTypes.bool,
allowPoll: PropTypes.bool, allowPoll: PropTypes.bool,
hasPoll: PropTypes.bool, hasPoll: PropTypes.bool,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
@ -190,7 +187,6 @@ class ComposerOptions extends ImmutablePureComponent {
contentType, contentType,
disabled, disabled,
allowMedia, allowMedia,
hasMedia,
allowPoll, allowPoll,
hasPoll, hasPoll,
onChangeAdvancedOption, onChangeAdvancedOption,

View file

@ -9,7 +9,6 @@ import {
import { openModal } from 'flavours/glitch/actions/modal'; import { openModal } from 'flavours/glitch/actions/modal';
function mapStateToProps (state) { function mapStateToProps (state) {
const spoilersAlwaysOn = state.getIn(['local_settings', 'always_show_spoilers_field']);
const poll = state.getIn(['compose', 'poll']); const poll = state.getIn(['compose', 'poll']);
const media = state.getIn(['compose', 'media_attachments']); const media = state.getIn(['compose', 'media_attachments']);
const pending_media = state.getIn(['compose', 'pending_media_attachments']); const pending_media = state.getIn(['compose', 'pending_media_attachments']);
@ -18,7 +17,6 @@ function mapStateToProps (state) {
resetFileKey: state.getIn(['compose', 'resetFileKey']), resetFileKey: state.getIn(['compose', 'resetFileKey']),
hasPoll: !!poll, hasPoll: !!poll,
allowMedia: !poll && (media ? media.size + pending_media < 4 && !media.some(item => ['video', 'audio'].includes(item.get('type'))) : pending_media < 4), allowMedia: !poll && (media ? media.size + pending_media < 4 && !media.some(item => ['video', 'audio'].includes(item.get('type'))) : pending_media < 4),
hasMedia: media && !!media.size,
allowPoll: !(media && !!media.size), allowPoll: !(media && !!media.size),
showContentTypeChoice: state.getIn(['local_settings', 'show_content_type_choice']), showContentTypeChoice: state.getIn(['local_settings', 'show_content_type_choice']),
contentType: state.getIn(['compose', 'content_type']), contentType: state.getIn(['compose', 'content_type']),

View file

@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import Immutable from 'immutable'; import Immutable from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import punycode from 'punycode';
import classnames from 'classnames'; import classnames from 'classnames';
import { decode as decodeIDNA } from 'flavours/glitch/utils/idna'; import { decode as decodeIDNA } from 'flavours/glitch/utils/idna';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
@ -164,7 +163,7 @@ export default class Card extends React.PureComponent {
} }
render () { render () {
const { card, compact, defaultWidth } = this.props; const { card, compact } = this.props;
const { width, embedded, revealed } = this.state; const { width, embedded, revealed } = this.state;
if (card === null) { if (card === null) {

View file

@ -126,9 +126,8 @@ class DetailedStatus extends ImmutablePureComponent {
render () { render () {
const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status; const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status;
const { expanded, onToggleHidden, settings, pictureInPicture, intl } = this.props;
const outerStyle = { boxSizing: 'border-box' }; const outerStyle = { boxSizing: 'border-box' };
const { compact } = this.props; const { compact, pictureInPicture, expanded, onToggleHidden, settings } = this.props;
if (!status) { if (!status) {
return null; return null;

View file

@ -18,8 +18,6 @@ import {
muteStatus, muteStatus,
unmuteStatus, unmuteStatus,
deleteStatus, deleteStatus,
hideStatus,
revealStatus,
} from 'flavours/glitch/actions/statuses'; } from 'flavours/glitch/actions/statuses';
import { initMuteModal } from 'flavours/glitch/actions/mutes'; import { initMuteModal } from 'flavours/glitch/actions/mutes';
import { initBlockModal } from 'flavours/glitch/actions/blocks'; import { initBlockModal } from 'flavours/glitch/actions/blocks';

View file

@ -50,7 +50,6 @@ export default class ColumnsArea extends ImmutablePureComponent {
columns: ImmutablePropTypes.list.isRequired, columns: ImmutablePropTypes.list.isRequired,
singleColumn: PropTypes.bool, singleColumn: PropTypes.bool,
children: PropTypes.node, children: PropTypes.node,
navbarUnder: PropTypes.bool,
openSettings: PropTypes.func, openSettings: PropTypes.func,
}; };
@ -136,7 +135,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
}; };
render () { render () {
const { columns, children, singleColumn, navbarUnder, openSettings } = this.props; const { columns, children, singleColumn, openSettings } = this.props;
const { renderComposePanel } = this.state; const { renderComposePanel } = this.state;
if (singleColumn) { if (singleColumn) {

View file

@ -64,7 +64,7 @@ class DeprecatedSettingsModal extends React.PureComponent {
<div className='deprecated-settings-info'> <div className='deprecated-settings-info'>
<ul> <ul>
{ settings.map((setting_name) => ( { settings.map((setting_name) => (
<li> <li key={setting_name}>
<a href={preferenceLink(setting_name)}><FormattedMessage {...messages[setting_name]} /></a> <a href={preferenceLink(setting_name)}><FormattedMessage {...messages[setting_name]} /></a>
</li> </li>
)) } )) }

View file

@ -1,15 +1,14 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import { timelinePreview, showTrends } from 'flavours/glitch/initial_state'; import { timelinePreview, showTrends } from 'flavours/glitch/initial_state';
import ColumnLink from 'flavours/glitch/features/ui/components/column_link'; import ColumnLink from './column_link';
import DisabledAccountBanner from './disabled_account_banner'; import DisabledAccountBanner from './disabled_account_banner';
import FollowRequestsColumnLink from './follow_requests_column_link'; import FollowRequestsColumnLink from './follow_requests_column_link';
import ListPanel from './list_panel'; import ListPanel from './list_panel';
import NotificationsCounterIcon from './notifications_counter_icon'; import NotificationsCounterIcon from './notifications_counter_icon';
import SignInBanner from './sign_in_banner'; import SignInBanner from './sign_in_banner';
import { preferencesLink, relationshipsLink } from 'flavours/glitch/utils/backend_links'; import { preferencesLink } from 'flavours/glitch/utils/backend_links';
import NavigationPortal from 'flavours/glitch/components/navigation_portal'; import NavigationPortal from 'flavours/glitch/components/navigation_portal';
const messages = defineMessages({ const messages = defineMessages({
@ -37,6 +36,7 @@ class NavigationPanel extends React.Component {
}; };
static propTypes = { static propTypes = {
intl: PropTypes.object.isRequired,
onOpenSettings: PropTypes.func, onOpenSettings: PropTypes.func,
}; };

View file

@ -40,7 +40,7 @@ PageOne.propTypes = {
domain: PropTypes.string.isRequired, domain: PropTypes.string.isRequired,
}; };
const PageTwo = ({ intl, myAccount }) => ( const PageTwo = ({ myAccount }) => (
<div className='onboarding-modal__page onboarding-modal__page-two'> <div className='onboarding-modal__page onboarding-modal__page-two'>
<div className='figure non-interactive'> <div className='figure non-interactive'>
<div className='pseudo-drawer'> <div className='pseudo-drawer'>
@ -63,7 +63,7 @@ PageTwo.propTypes = {
myAccount: ImmutablePropTypes.map.isRequired, myAccount: ImmutablePropTypes.map.isRequired,
}; };
const PageThree = ({ intl, myAccount }) => ( const PageThree = ({ myAccount }) => (
<div className='onboarding-modal__page onboarding-modal__page-three'> <div className='onboarding-modal__page onboarding-modal__page-three'>
<div className='figure non-interactive'> <div className='figure non-interactive'>
<Search <Search
@ -188,11 +188,11 @@ class OnboardingModal extends React.PureComponent {
componentWillMount() { componentWillMount() {
const { myAccount, admin, domain, intl } = this.props; const { myAccount, admin, domain, intl } = this.props;
this.pages = [ this.pages = [
<PageOne acct={myAccount.get('acct')} domain={domain} />, <PageOne key='1' acct={myAccount.get('acct')} domain={domain} />,
<PageTwo myAccount={myAccount} intl={intl} />, <PageTwo key='2' myAccount={myAccount} intl={intl} />,
<PageThree myAccount={myAccount} intl={intl} />, <PageThree key='3' myAccount={myAccount} intl={intl} />,
<PageFour domain={domain} intl={intl} />, <PageFour key='4' domain={domain} intl={intl} />,
<PageSix admin={admin} domain={domain} />, <PageSix key='6' admin={admin} domain={domain} />,
]; ];
} }

View file

@ -13,10 +13,6 @@ const mapStateToProps = (state, { statusId }) => ({
class VideoModal extends ImmutablePureComponent { class VideoModal extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = { static propTypes = {
media: ImmutablePropTypes.map.isRequired, media: ImmutablePropTypes.map.isRequired,
statusId: PropTypes.string, statusId: PropTypes.string,
@ -31,7 +27,7 @@ class VideoModal extends ImmutablePureComponent {
}; };
componentDidMount () { componentDidMount () {
const { media, onChangeBackgroundColor, onClose } = this.props; const { media, onChangeBackgroundColor } = this.props;
const backgroundColor = getAverageFromBlurhash(media.get('blurhash')); const backgroundColor = getAverageFromBlurhash(media.get('blurhash'));

View file

@ -60,7 +60,6 @@ import { HotKeys } from 'react-hotkeys';
import initialState, { me, owner, singleUserMode, showTrends, trendsAsLanding, timelinePreview } from '../../initial_state'; import initialState, { me, owner, singleUserMode, showTrends, trendsAsLanding, timelinePreview } from '../../initial_state';
import { closeOnboarding, INTRODUCTION_VERSION } from 'flavours/glitch/actions/onboarding'; import { closeOnboarding, INTRODUCTION_VERSION } from 'flavours/glitch/actions/onboarding';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { Helmet } from 'react-helmet';
import Header from './components/header'; import Header from './components/header';
// Dummy import, to make sure that <Status /> ends up in the application bundle. // Dummy import, to make sure that <Status /> ends up in the application bundle.
@ -78,7 +77,6 @@ const mapStateToProps = state => ({
canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < 4, canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < 4,
layout_local_setting: state.getIn(['local_settings', 'layout']), layout_local_setting: state.getIn(['local_settings', 'layout']),
isWide: state.getIn(['local_settings', 'stretch']), isWide: state.getIn(['local_settings', 'stretch']),
navbarUnder: state.getIn(['local_settings', 'navbar_under']),
dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null, dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null,
unreadNotifications: state.getIn(['notifications', 'unread']), unreadNotifications: state.getIn(['notifications', 'unread']),
showFaviconBadge: state.getIn(['local_settings', 'notifications', 'favicon_badge']), showFaviconBadge: state.getIn(['local_settings', 'notifications', 'favicon_badge']),
@ -132,7 +130,6 @@ class SwitchingColumnsArea extends React.PureComponent {
static propTypes = { static propTypes = {
children: PropTypes.node, children: PropTypes.node,
location: PropTypes.object, location: PropTypes.object,
navbarUnder: PropTypes.bool,
mobile: PropTypes.bool, mobile: PropTypes.bool,
}; };
@ -164,7 +161,7 @@ class SwitchingColumnsArea extends React.PureComponent {
}; };
render () { render () {
const { children, mobile, navbarUnder } = this.props; const { children, mobile } = this.props;
const { signedIn } = this.context.identity; const { signedIn } = this.context.identity;
let redirect; let redirect;
@ -184,7 +181,7 @@ class SwitchingColumnsArea extends React.PureComponent {
} }
return ( return (
<ColumnsAreaContainer ref={this.setRef} singleColumn={mobile} navbarUnder={navbarUnder}> <ColumnsAreaContainer ref={this.setRef} singleColumn={mobile}>
<WrappedSwitch> <WrappedSwitch>
{redirect} {redirect}
@ -255,7 +252,6 @@ class UI extends React.Component {
layout_local_setting: PropTypes.string, layout_local_setting: PropTypes.string,
isWide: PropTypes.bool, isWide: PropTypes.bool,
systemFontUi: PropTypes.bool, systemFontUi: PropTypes.bool,
navbarUnder: PropTypes.bool,
isComposing: PropTypes.bool, isComposing: PropTypes.bool,
hasComposingText: PropTypes.bool, hasComposingText: PropTypes.bool,
hasMediaAttachments: PropTypes.bool, hasMediaAttachments: PropTypes.bool,
@ -267,6 +263,7 @@ class UI extends React.Component {
dropdownMenuIsOpen: PropTypes.bool, dropdownMenuIsOpen: PropTypes.bool,
unreadNotifications: PropTypes.number, unreadNotifications: PropTypes.number,
showFaviconBadge: PropTypes.bool, showFaviconBadge: PropTypes.bool,
hicolorPrivacyIcons: PropTypes.bool,
moved: PropTypes.map, moved: PropTypes.map,
layout: PropTypes.string.isRequired, layout: PropTypes.string.isRequired,
firstLaunch: PropTypes.bool, firstLaunch: PropTypes.bool,
@ -455,8 +452,8 @@ class UI extends React.Component {
} }
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
if (this.props.unreadNotifications != prevProps.unreadNotifications || if (this.props.unreadNotifications !== prevProps.unreadNotifications ||
this.props.showFaviconBadge != prevProps.showFaviconBadge) { this.props.showFaviconBadge !== prevProps.showFaviconBadge) {
if (this.favicon) { if (this.favicon) {
try { try {
this.favicon.badge(this.props.showFaviconBadge ? this.props.unreadNotifications : 0); this.favicon.badge(this.props.showFaviconBadge ? this.props.unreadNotifications : 0);
@ -605,7 +602,7 @@ class UI extends React.Component {
render () { render () {
const { draggingOver } = this.state; const { draggingOver } = this.state;
const { children, isWide, navbarUnder, location, dropdownMenuIsOpen, layout, moved } = this.props; const { children, isWide, location, dropdownMenuIsOpen, layout, moved } = this.props;
const columnsClass = layout => { const columnsClass = layout => {
switch (layout) { switch (layout) {
@ -621,7 +618,6 @@ class UI extends React.Component {
const className = classNames('ui', columnsClass(layout), { const className = classNames('ui', columnsClass(layout), {
'wide': isWide, 'wide': isWide,
'system-font': this.props.systemFontUi, 'system-font': this.props.systemFontUi,
'navbar-under': navbarUnder,
'hicolor-privacy-icons': this.props.hicolorPrivacyIcons, 'hicolor-privacy-icons': this.props.hicolorPrivacyIcons,
}); });
@ -664,7 +660,7 @@ class UI extends React.Component {
<Header /> <Header />
<SwitchingColumnsArea location={location} mobile={layout === 'mobile' || layout === 'single-column'} navbarUnder={navbarUnder}> <SwitchingColumnsArea location={location} mobile={layout === 'mobile' || layout === 'single-column'}>
{children} {children}
</SwitchingColumnsArea> </SwitchingColumnsArea>

View file

@ -29,6 +29,7 @@ export const formatTime = secondsNum => {
if (hours < 10) hours = '0' + hours; if (hours < 10) hours = '0' + hours;
if (minutes < 10) minutes = '0' + minutes; if (minutes < 10) minutes = '0' + minutes;
if (seconds < 10) seconds = '0' + seconds; if (seconds < 10) seconds = '0' + seconds;
return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`; return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
}; };
@ -107,18 +108,18 @@ class Video extends React.PureComponent {
currentTime: PropTypes.number, currentTime: PropTypes.number,
onOpenVideo: PropTypes.func, onOpenVideo: PropTypes.func,
onCloseVideo: PropTypes.func, onCloseVideo: PropTypes.func,
letterbox: PropTypes.bool,
fullwidth: PropTypes.bool,
detailed: PropTypes.bool, detailed: PropTypes.bool,
inline: PropTypes.bool, inline: PropTypes.bool,
editable: PropTypes.bool, editable: PropTypes.bool,
alwaysVisible: PropTypes.bool, alwaysVisible: PropTypes.bool,
cacheWidth: PropTypes.func, cacheWidth: PropTypes.func,
intl: PropTypes.object.isRequired,
visible: PropTypes.bool, visible: PropTypes.bool,
letterbox: PropTypes.bool,
fullwidth: PropTypes.bool,
preventPlayback: PropTypes.bool,
onToggleVisibility: PropTypes.func, onToggleVisibility: PropTypes.func,
deployPictureInPicture: PropTypes.func, deployPictureInPicture: PropTypes.func,
preventPlayback: PropTypes.bool, intl: PropTypes.object.isRequired,
blurhash: PropTypes.string, blurhash: PropTypes.string,
autoPlay: PropTypes.bool, autoPlay: PropTypes.bool,
volume: PropTypes.number, volume: PropTypes.number,
@ -161,7 +162,7 @@ class Video extends React.PureComponent {
_setDimensions () { _setDimensions () {
const width = this.player.offsetWidth; const width = this.player.offsetWidth;
if (width && width != this.state.containerWidth) { if (width && width !== this.state.containerWidth) {
if (this.props.cacheWidth) { if (this.props.cacheWidth) {
this.props.cacheWidth(width); this.props.cacheWidth(width);
} }
@ -403,7 +404,7 @@ class Video extends React.PureComponent {
} }
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
if (this.player && this.player.offsetWidth && this.player.offsetWidth != this.state.containerWidth && !this.state.fullscreen) { if (this.player && this.player.offsetWidth && this.player.offsetWidth !== this.state.containerWidth && !this.state.fullscreen) {
if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth); if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth);
this.setState({ this.setState({
containerWidth: this.player.offsetWidth, containerWidth: this.player.offsetWidth,
@ -534,7 +535,7 @@ class Video extends React.PureComponent {
return this.props.frameRate.split('/').reduce((p, c) => p / c); return this.props.frameRate.split('/').reduce((p, c) => p / c);
} }
return this.props.frameRate || 25; return this.props.frameRate;
} }
render () { render () {
@ -576,6 +577,7 @@ class Video extends React.PureComponent {
return ( return (
<div <div
role='menuitem'
className={computedClass} className={computedClass}
style={playerStyle} style={playerStyle}
ref={this.setPlayerRef} ref={this.setPlayerRef}
@ -598,7 +600,6 @@ class Video extends React.PureComponent {
src={src} src={src}
poster={preview} poster={preview}
preload={preload} preload={preload}
loop
role='button' role='button'
tabIndex={0} tabIndex={0}
aria-label={alt} aria-label={alt}

View file

@ -1,4 +1,6 @@
{ {
"about.fork_disclaimer": "Glitch-soc - это бесплатное программное обеспечение с открытым исходным кодом, обращенное от Mastodon.",
"account.add_account_note": "Добавить заметку для @{name}",
"empty_column.follow_recommendations": "Похоже, у нас нет предложений для вас. Вы можете попробовать поискать людей, которых уже знаете, или изучить актуальные хэштеги.", "empty_column.follow_recommendations": "Похоже, у нас нет предложений для вас. Вы можете попробовать поискать людей, которых уже знаете, или изучить актуальные хэштеги.",
"follow_recommendations.done": "Готово", "follow_recommendations.done": "Готово",
"follow_recommendations.heading": "Подпишитесь на людей, чьи посты вы бы хотели видеть. Вот несколько предложений.", "follow_recommendations.heading": "Подпишитесь на людей, чьи посты вы бы хотели видеть. Вот несколько предложений.",

View file

@ -447,6 +447,7 @@ export default function compose(state = initialState, action) {
}); });
case COMPOSE_REPLY_CANCEL: case COMPOSE_REPLY_CANCEL:
state = state.setIn(['advanced_options', 'threaded_mode'], false); state = state.setIn(['advanced_options', 'threaded_mode'], false);
// eslint-disable-next-line no-fallthrough -- fall-through to `COMPOSE_RESET` is intended
case COMPOSE_RESET: case COMPOSE_RESET:
return state.withMutations(map => { return state.withMutations(map => {
map.set('in_reply_to', null); map.set('in_reply_to', null);
@ -457,6 +458,7 @@ export default function compose(state = initialState, action) {
map.set('privacy', state.get('default_privacy')); map.set('privacy', state.get('default_privacy'));
map.set('id', null); map.set('id', null);
map.set('poll', null); map.set('poll', null);
map.set('language', state.get('default_language'));
map.update( map.update(
'advanced_options', 'advanced_options',
map => map.mergeWith(overwrite, state.get('default_advanced_options')), map => map.mergeWith(overwrite, state.get('default_advanced_options')),

View file

@ -8,7 +8,6 @@ import { LOCAL_SETTING_CHANGE, LOCAL_SETTING_DELETE } from 'flavours/glitch/acti
const initialState = ImmutableMap({ const initialState = ImmutableMap({
layout : 'auto', layout : 'auto',
stretch : true, stretch : true,
navbar_under : false,
side_arm : 'none', side_arm : 'none',
side_arm_reply_mode : 'keep', side_arm_reply_mode : 'keep',
show_reply_count : false, show_reply_count : false,

View file

@ -1,6 +1,5 @@
import escapeTextContentForBrowser from 'escape-html';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { List as ImmutableList, Map as ImmutableMap, is } from 'immutable'; import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
import { toServerSideType } from 'flavours/glitch/utils/filters'; import { toServerSideType } from 'flavours/glitch/utils/filters';
import { me } from 'flavours/glitch/initial_state'; import { me } from 'flavours/glitch/initial_state';

View file

@ -24,9 +24,11 @@ $emojis-requiring-inversion: 'back' 'copyright' 'curly_loop' 'currency_exchange'
position: absolute; position: absolute;
content: '\F00C'; content: '\F00C';
font-size: 50%; font-size: 50%;
font-family: FontAwesome;
inset-inline-end: -0.55em; inset-inline-end: -0.55em;
top: -0.44em; top: -0.44em;
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword -- this is an icon font, this can't use a generic font */
font-family: FontAwesome;
} }
} }

View file

@ -33,7 +33,7 @@
border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0;
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
height: 200px; height: 200px;
} }
} }
@ -162,7 +162,7 @@
color: lighten($inverted-text-color, 10%); color: lighten($inverted-text-color, 10%);
} }
@media screen and (max-width: 700px) { @media screen and (width <= 700px) {
padding: 30px 20px; padding: 30px 20px;
.page { .page {

View file

@ -1377,7 +1377,7 @@ a.sparkline {
} }
} }
@media screen and (max-width: 930px) { @media screen and (width <= 930px) {
grid-template-columns: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr);
} }
} }
@ -1663,7 +1663,7 @@ a.sparkline {
} }
} }
@media screen and (max-width: 800px) { @media screen and (width <= 800px) {
border: 0; border: 0;
&__item { &__item {

View file

@ -136,7 +136,7 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
display: block; display: block;
h4 { h4 {

View file

@ -281,7 +281,7 @@
.notification__message { .notification__message {
margin-inline-start: 42px; margin-inline-start: 42px;
padding-top:8px; padding-top: 8px;
padding-inline-start: 26px; padding-inline-start: 26px;
cursor: default; cursor: default;
color: $darker-text-color; color: $darker-text-color;

View file

@ -79,7 +79,7 @@ $ui-header-height: 55px;
display: none; display: none;
} }
@media screen and (min-width: 320px) { @media screen and (width >= 320px) {
.logo--wordmark { .logo--wordmark {
display: block; display: block;
} }
@ -205,7 +205,7 @@ $ui-header-height: 55px;
&:last-child { &:last-child {
padding: 0; padding: 0;
padding-inline-end: 15px;; padding-inline-end: 15px;
} }
} }
@ -441,9 +441,7 @@ $ui-header-height: 55px;
align-items: stretch; align-items: stretch;
justify-content: space-around; justify-content: space-around;
button { .column-header__button {
@extend .column-header__button;
background: transparent; background: transparent;
text-align: center; text-align: center;
padding: 10px 5px; padding: 10px 5px;
@ -713,31 +711,6 @@ $ui-header-height: 55px;
} }
} }
// more fixes for the navbar-under mode
@mixin fix-margins-for-navbar-under {
.tabs-bar {
margin-top: 0 !important;
margin-bottom: -6px !important;
}
}
.single-column.navbar-under {
@include fix-margins-for-navbar-under;
}
.auto-columns.navbar-under {
@media screen and (max-width: $no-gap-breakpoint) {
@include fix-margins-for-navbar-under;
}
}
.auto-columns.navbar-under .react-swipeable-view-container .columns-area,
.single-column.navbar-under .react-swipeable-view-container .columns-area {
@media screen and (max-width: $no-gap-breakpoint) {
height: 100% !important;
}
}
.column-inline-form { .column-inline-form {
padding: 7px 15px; padding: 7px 15px;
padding-inline-end: 5px; padding-inline-end: 5px;
@ -809,7 +782,7 @@ $ui-header-height: 55px;
background: lighten($ui-base-color, 4%); background: lighten($ui-base-color, 4%);
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
font-size: 16px; font-size: 16px;
} }
} }

View file

@ -1,8 +1,6 @@
$doodle-background: #d9e1e8; $doodle-background: #d9e1e8;
.doodle-modal { .doodle-modal {
@extend .boost-modal;
width: unset; width: unset;
} }
@ -16,8 +14,6 @@ $doodle-background: #d9e1e8;
} }
.doodle-modal__action-bar { .doodle-modal__action-bar {
@extend .boost-modal__action-bar;
.filler { .filler {
flex-grow: 1; flex-grow: 1;
margin: 0; margin: 0;

View file

@ -229,7 +229,7 @@
cursor: inherit; cursor: inherit;
} }
@media screen and (min-height: 640px) { @media screen and (height >= 640px) {
display: block; display: block;
} }
} }

View file

@ -6,7 +6,7 @@
width: 380px; width: 380px;
overflow: hidden; overflow: hidden;
@media screen and (max-width: 420px) { @media screen and (width <= 420px) {
width: 90%; width: 90%;
} }
@ -60,7 +60,7 @@
width: 380px; width: 380px;
overflow: hidden; overflow: hidden;
@media screen and (max-width: 420px) { @media screen and (width <= 420px) {
width: 90%; width: 90%;
} }

View file

@ -125,7 +125,7 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
@media screen and (max-width: 630px) { @media screen and (width <= 630px) {
.glitch.local-settings__navigation { .glitch.local-settings__navigation {
width: 40px; width: 40px;
flex-shrink: 0; flex-shrink: 0;

View file

@ -827,7 +827,7 @@ body > [data-popper-placement] {
overflow: hidden; overflow: hidden;
} }
@media screen and (min-width: 631px) { @media screen and (width >= 631px) {
.columns-area { .columns-area {
padding: 0; padding: 0;
} }
@ -1134,19 +1134,19 @@ body > [data-popper-placement] {
} }
} }
@media screen and (max-height: 810px) { @media screen and (height <= 810px) {
.trends__item:nth-of-type(3) { .trends__item:nth-of-type(3) {
display: none; display: none;
} }
} }
@media screen and (max-height: 720px) { @media screen and (height <= 720px) {
.trends__item:nth-of-type(2) { .trends__item:nth-of-type(2) {
display: none; display: none;
} }
} }
@media screen and (max-height: 670px) { @media screen and (height <= 670px) {
display: none; display: none;
} }

View file

@ -115,7 +115,7 @@
text-align: center; text-align: center;
} }
@media screen and (max-width: 550px) { @media screen and (width <= 550px) {
.onboarding-modal { .onboarding-modal {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -382,7 +382,7 @@
} }
} }
@media screen and (max-width: 320px) and (max-height: 600px) { @media screen and (width <= 320px) and (height <= 600px) {
.onboarding-modal__page p { .onboarding-modal__page p {
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
@ -413,6 +413,7 @@
margin-inline-start: 10px; margin-inline-start: 10px;
} }
.doodle-modal,
.boost-modal, .boost-modal,
.confirmation-modal, .confirmation-modal,
.report-modal, .report-modal,
@ -485,6 +486,7 @@
} }
} }
.doodle-modal__action-bar,
.boost-modal__action-bar, .boost-modal__action-bar,
.confirmation-modal__action-bar, .confirmation-modal__action-bar,
.mute-modal__action-bar, .mute-modal__action-bar,
@ -560,7 +562,7 @@
font-weight: 700; font-weight: 700;
margin-bottom: 15px; margin-bottom: 15px;
@media screen and (max-height: 800px) { @media screen and (height <= 800px) {
font-size: 22px; font-size: 22px;
} }
} }
@ -747,7 +749,7 @@
display: flex; display: flex;
border-top: 1px solid $ui-secondary-color; border-top: 1px solid $ui-secondary-color;
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
flex-wrap: wrap; flex-wrap: wrap;
overflow-y: auto; overflow-y: auto;
} }
@ -758,7 +760,7 @@
box-sizing: border-box; box-sizing: border-box;
width: 50%; width: 50%;
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
width: 100%; width: 100%;
} }
} }
@ -775,13 +777,13 @@
color: $highlight-text-color; color: $highlight-text-color;
} }
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
max-height: 10vh; max-height: 10vh;
} }
} }
.focal-point-modal__content { .focal-point-modal__content {
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
max-height: 40vh; max-height: 40vh;
} }
} }
@ -877,7 +879,7 @@
} }
} }
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
padding: 10px; padding: 10px;
max-width: 100%; max-width: 100%;
order: 2; order: 2;
@ -1152,7 +1154,7 @@
background: lighten($ui-base-color, 4%); background: lighten($ui-base-color, 4%);
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
font-size: 16px; font-size: 16px;
} }
} }
@ -1233,7 +1235,7 @@
} }
} }
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
img, img,
video { video {
max-height: 100%; max-height: 100%;

View file

@ -94,7 +94,7 @@
} }
} }
@media screen and (min-width: 600px) { @media screen and (width >= 600px) {
.tabs-bar__link { .tabs-bar__link {
span { span {
display: inline; display: inline;

View file

@ -2,7 +2,7 @@
width: 700px; width: 700px;
margin: 0 auto; margin: 0 auto;
@media screen and (max-width: 740px) { @media screen and (width <= 740px) {
width: 100%; width: 100%;
margin: 0; margin: 0;
} }
@ -44,7 +44,7 @@
margin-top: 40px; margin-top: 40px;
box-sizing: border-box; box-sizing: border-box;
@media screen and (max-width: 400px) { @media screen and (width <= 400px) {
width: 100%; width: 100%;
margin-top: 0; margin-top: 0;
padding: 20px; padding: 20px;
@ -64,7 +64,7 @@
margin-bottom: 10px; margin-bottom: 10px;
border-bottom: 1px solid $ui-base-color; border-bottom: 1px solid $ui-base-color;
@media screen and (max-width: 440px) { @media screen and (width <= 440px) {
width: 100%; width: 100%;
margin: 0; margin: 0;
padding: 20px; padding: 20px;

View file

@ -59,7 +59,7 @@
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
grid-gap: 10px; grid-gap: 10px;
@media screen and (max-width: 1350px) { @media screen and (width <= 1350px) {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
} }

View file

@ -723,7 +723,7 @@ code {
} }
} }
@media screen and (max-width: 740px) and (min-width: 441px) { @media screen and (width <= 740px) and (width >= 441px) {
margin-top: 40px; margin-top: 40px;
} }

View file

@ -30,7 +30,7 @@
} }
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
.account-header { .account-header {
margin-top: 0; margin-top: 0;
} }

View file

@ -59,7 +59,7 @@
} }
} }
@media screen and (max-width: 740px) { @media screen and (width <= 740px) {
.detailed-status, .detailed-status,
.status, .status,
.load-more { .load-more {

View file

@ -357,7 +357,7 @@ a.table-action-link {
} }
} }
@media screen and (max-width: 870px) { @media screen and (width <= 870px) {
.accounts-table tbody td.optional { .accounts-table tbody td.optional {
display: none; display: none;
} }

View file

@ -3,8 +3,7 @@
src: local('Roboto Mono'), src: local('Roboto Mono'),
url('~fonts/roboto-mono/robotomono-regular-webfont.woff2') format('woff2'), url('~fonts/roboto-mono/robotomono-regular-webfont.woff2') format('woff2'),
url('~fonts/roboto-mono/robotomono-regular-webfont.woff') format('woff'), url('~fonts/roboto-mono/robotomono-regular-webfont.woff') format('woff'),
url('~fonts/roboto-mono/robotomono-regular-webfont.ttf') url('~fonts/roboto-mono/robotomono-regular-webfont.ttf') format('truetype'),
format('truetype'),
url('~fonts/roboto-mono/robotomono-regular-webfont.svg#roboto_monoregular') url('~fonts/roboto-mono/robotomono-regular-webfont.svg#roboto_monoregular')
format('svg'); format('svg');
font-weight: 400; font-weight: 400;

View file

@ -547,7 +547,7 @@ ul.rules-list {
} }
} }
@media (max-width: 697px) { @media (width <= 697px) {
.email-container, .email-container,
.col-1, .col-1,
.col-2, .col-2,

View file

@ -33,7 +33,7 @@
border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0;
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
height: 200px; height: 200px;
} }
} }
@ -158,7 +158,7 @@
color: lighten($inverted-text-color, 10%); color: lighten($inverted-text-color, 10%);
} }
@media screen and (max-width: 700px) { @media screen and (width <= 700px) {
padding: 30px 20px; padding: 30px 20px;
.page { .page {

View file

@ -1371,7 +1371,7 @@ a.sparkline {
} }
} }
@media screen and (max-width: 930px) { @media screen and (width <= 930px) {
grid-template-columns: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr);
} }
} }
@ -1657,7 +1657,7 @@ a.sparkline {
} }
} }
@media screen and (max-width: 800px) { @media screen and (width <= 800px) {
border: 0; border: 0;
&__item { &__item {

View file

@ -514,7 +514,7 @@ body > [data-popper-placement] {
outline: 0; outline: 0;
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
font-size: 16px; font-size: 16px;
} }
} }
@ -535,7 +535,7 @@ body > [data-popper-placement] {
all: unset; all: unset;
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
height: 100px !important; // Prevent auto-resize textarea height: 100px !important; // Prevent auto-resize textarea
resize: vertical; resize: vertical;
} }
@ -1151,12 +1151,12 @@ body > [data-popper-placement] {
.status__content, .status__content,
.status__action-bar, .status__action-bar,
.reactions-bar,
.media-gallery, .media-gallery,
.video-player, .video-player,
.audio-player, .audio-player,
.attachment-list, .attachment-list,
.status-card, .status-card {
.reactions-bar {
margin-inline-start: 46px + 10px; margin-inline-start: 46px + 10px;
width: calc(100% - (46px + 10px)); width: calc(100% - (46px + 10px));
} }
@ -2428,7 +2428,7 @@ $ui-header-height: 55px;
display: none; display: none;
} }
@media screen and (min-width: 320px) { @media screen and (width >= 320px) {
.logo--wordmark { .logo--wordmark {
display: block; display: block;
} }
@ -2540,7 +2540,7 @@ $ui-header-height: 55px;
overflow: hidden; overflow: hidden;
} }
@media screen and (min-width: 631px) { @media screen and (width >= 631px) {
.columns-area { .columns-area {
padding: 0; padding: 0;
} }
@ -2600,7 +2600,7 @@ $ui-header-height: 55px;
&:hover, &:hover,
&:focus, &:focus,
&:active { &:active {
@media screen and (min-width: 631px) { @media screen and (width >= 631px) {
background: lighten($ui-base-color, 14%); background: lighten($ui-base-color, 14%);
border-bottom-color: lighten($ui-base-color, 14%); border-bottom-color: lighten($ui-base-color, 14%);
} }
@ -2617,7 +2617,7 @@ $ui-header-height: 55px;
} }
} }
@media screen and (min-width: 600px) { @media screen and (width >= 600px) {
.tabs-bar__link { .tabs-bar__link {
span { span {
display: inline; display: inline;
@ -2840,7 +2840,7 @@ $ui-header-height: 55px;
color: $darker-text-color; color: $darker-text-color;
} }
@media screen and (min-width: 600px) { @media screen and (width >= 600px) {
padding: 40px; padding: 40px;
} }
} }
@ -2950,7 +2950,7 @@ $ui-header-height: 55px;
height: 36px; height: 36px;
color: $dark-text-color; color: $dark-text-color;
@media screen and (min-width: 600px) { @media screen and (width >= 600px) {
display: flex; display: flex;
} }
} }
@ -3002,7 +3002,7 @@ $ui-header-height: 55px;
position: sticky; position: sticky;
background: $ui-base-color; background: $ui-base-color;
@media screen and (min-width: 600) { @media screen and (width >= 600) {
padding: 0 40px; padding: 0 40px;
} }
@ -3270,7 +3270,7 @@ $ui-header-height: 55px;
user-select: none; user-select: none;
} }
@media screen and (min-height: 640px) { @media screen and (height >= 640px) {
display: block; display: block;
} }
} }
@ -3619,19 +3619,19 @@ $ui-header-height: 55px;
} }
} }
@media screen and (max-height: 810px) { @media screen and (height <= 810px) {
.trends__item:nth-of-type(3) { .trends__item:nth-of-type(3) {
display: none; display: none;
} }
} }
@media screen and (max-height: 720px) { @media screen and (height <= 720px) {
.trends__item:nth-of-type(2) { .trends__item:nth-of-type(2) {
display: none; display: none;
} }
} }
@media screen and (max-height: 670px) { @media screen and (height <= 670px) {
display: none; display: none;
} }
@ -3715,7 +3715,7 @@ $ui-header-height: 55px;
margin-bottom: 20px; margin-bottom: 20px;
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
font-size: 16px; font-size: 16px;
} }
} }
@ -4515,7 +4515,7 @@ a.status-card.compact:hover {
background: lighten($ui-base-color, 4%); background: lighten($ui-base-color, 4%);
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
font-size: 16px; font-size: 16px;
} }
} }
@ -5850,7 +5850,7 @@ a.status-card.compact:hover {
font-weight: 700; font-weight: 700;
margin-bottom: 15px; margin-bottom: 15px;
@media screen and (max-height: 800px) { @media screen and (height <= 800px) {
font-size: 22px; font-size: 22px;
} }
} }
@ -6037,7 +6037,7 @@ a.status-card.compact:hover {
display: flex; display: flex;
border-top: 1px solid $ui-secondary-color; border-top: 1px solid $ui-secondary-color;
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
flex-wrap: wrap; flex-wrap: wrap;
overflow-y: auto; overflow-y: auto;
} }
@ -6048,7 +6048,7 @@ a.status-card.compact:hover {
box-sizing: border-box; box-sizing: border-box;
width: 50%; width: 50%;
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
width: 100%; width: 100%;
} }
} }
@ -6070,13 +6070,13 @@ a.status-card.compact:hover {
color: $inverted-text-color; color: $inverted-text-color;
} }
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
max-height: 10vh; max-height: 10vh;
} }
} }
.focal-point-modal__content { .focal-point-modal__content {
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
max-height: 40vh; max-height: 40vh;
} }
} }
@ -6127,7 +6127,7 @@ a.status-card.compact:hover {
} }
} }
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
padding: 10px; padding: 10px;
max-width: 100%; max-width: 100%;
order: 2; order: 2;
@ -7155,7 +7155,7 @@ noscript {
} }
} }
@media screen and (max-width: 630px) and (max-height: 400px) { @media screen and (width <= 630px) and (height <= 400px) {
$duration: 400ms; $duration: 400ms;
$delay: 100ms; $delay: 100ms;
@ -7285,7 +7285,7 @@ noscript {
background: lighten($ui-base-color, 4%); background: lighten($ui-base-color, 4%);
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
font-size: 16px; font-size: 16px;
} }
} }
@ -7376,7 +7376,7 @@ noscript {
width: 380px; width: 380px;
overflow: hidden; overflow: hidden;
@media screen and (max-width: 420px) { @media screen and (width <= 420px) {
width: 90%; width: 90%;
} }
@ -7431,7 +7431,7 @@ noscript {
width: 380px; width: 380px;
overflow: hidden; overflow: hidden;
@media screen and (max-width: 420px) { @media screen and (width <= 420px) {
width: 90%; width: 90%;
} }
@ -7530,7 +7530,7 @@ noscript {
} }
} }
@media screen and (max-width: 480px) { @media screen and (width <= 480px) {
img, img,
video { video {
max-height: 100%; max-height: 100%;
@ -9087,7 +9087,7 @@ noscript {
margin-bottom: 20px; margin-bottom: 20px;
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
display: block; display: block;
h4 { h4 {

View file

@ -2,7 +2,7 @@
width: 700px; width: 700px;
margin: 0 auto; margin: 0 auto;
@media screen and (max-width: 740px) { @media screen and (width <= 740px) {
width: 100%; width: 100%;
margin: 0; margin: 0;
} }
@ -44,7 +44,7 @@
margin-top: 40px; margin-top: 40px;
box-sizing: border-box; box-sizing: border-box;
@media screen and (max-width: 400px) { @media screen and (width <= 400px) {
width: 100%; width: 100%;
margin-top: 0; margin-top: 0;
padding: 20px; padding: 20px;
@ -64,7 +64,7 @@
margin-bottom: 10px; margin-bottom: 10px;
border-bottom: 1px solid $ui-base-color; border-bottom: 1px solid $ui-base-color;
@media screen and (max-width: 440px) { @media screen and (width <= 440px) {
width: 100%; width: 100%;
margin: 0; margin: 0;
padding: 20px; padding: 20px;

View file

@ -59,7 +59,7 @@
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
grid-gap: 10px; grid-gap: 10px;
@media screen and (max-width: 1350px) { @media screen and (width <= 1350px) {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
} }

View file

@ -722,7 +722,7 @@ code {
} }
} }
@media screen and (max-width: 740px) and (min-width: 441px) { @media screen and (width <= 740px) and (width >= 441px) {
margin-top: 40px; margin-top: 40px;
} }

View file

@ -30,7 +30,7 @@
} }
} }
@media screen and (max-width: 600px) { @media screen and (width <= 600px) {
.account-header { .account-header {
margin-top: 0; margin-top: 0;
} }

View file

@ -63,7 +63,7 @@
} }
} }
@media screen and (max-width: 740px) { @media screen and (width <= 740px) {
.detailed-status, .detailed-status,
.status, .status,
.load-more { .load-more {

View file

@ -361,7 +361,7 @@ a.table-action-link {
} }
} }
@media screen and (max-width: 870px) { @media screen and (width <= 870px) {
.accounts-table tbody td.optional { .accounts-table tbody td.optional {
display: none; display: none;
} }

View file

@ -64,14 +64,16 @@ class PostStatusService < BaseService
def fill_blank_text! def fill_blank_text!
return unless @text.blank? && @options[:spoiler_text].present? return unless @text.blank? && @options[:spoiler_text].present?
if @media&.any?(&:video?) || @media&.any?(&:gifv?) @text = begin
@text = '📹' if @media&.any?(&:video?) || @media&.any?(&:gifv?)
elsif @media&.any?(&:audio?) '📹'
@text = '🎵' elsif @media&.any?(&:audio?)
elsif @media&.any?(&:image?) '🎵'
@text = '🖼' elsif @media&.any?(&:image?)
else '🖼'
@text = '.' else
'.'
end
end end
end end

View file

@ -1,11 +1,10 @@
// 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 webpack = require('webpack'); const webpack = require('webpack');
const { basename, dirname, join, relative, resolve } = require('path'); const { resolve } = require('path');
const { sync } = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const AssetsManifestPlugin = require('webpack-assets-manifest'); const AssetsManifestPlugin = require('webpack-assets-manifest');
const { env, settings, core, flavours, output } = require('./configuration.js'); const { env, settings, core, flavours, output } = require('./configuration');
const rules = require('./rules'); const rules = require('./rules');
const localePacks = require('./generateLocalePacks'); const localePacks = require('./generateLocalePacks');
@ -50,7 +49,7 @@ const entries = Object.assign(
{ locales: resolve('app', 'javascript', 'locales') }, { locales: resolve('app', 'javascript', 'locales') },
localePacks, localePacks,
reducePacks(core), reducePacks(core),
Object.values(flavours).reduce((map, data) => reducePacks(data, map), {}) Object.values(flavours).reduce((map, data) => reducePacks(data, map), {}),
); );

View file

@ -95,7 +95,7 @@ const provideExtractedMessages = () => {
originalExtractedMessages.forEach(file => { originalExtractedMessages.forEach(file => {
file.descriptors.forEach(descriptor => { file.descriptors.forEach(descriptor => {
originalKeys.add(descriptor.id) originalKeys.add(descriptor.id);
}); });
}); });

View file

@ -373,7 +373,6 @@ const startServer = async () => {
const channelNameFromPath = req => { const channelNameFromPath = req => {
const { path, query } = req; const { path, query } = req;
const onlyMedia = isTruthy(query.only_media); const onlyMedia = isTruthy(query.only_media);
const allowLocalOnly = isTruthy(query.allow_local_only);
switch (path) { switch (path) {
case '/api/v1/streaming/user': case '/api/v1/streaming/user':
@ -990,7 +989,7 @@ const startServer = async () => {
case 'public:media': case 'public:media':
resolve({ resolve({
channelIds: ['timeline:public:media'], channelIds: ['timeline:public:media'],
options: { needsFiltering: true, allowLocalOnly: isTruthy(query.allow_local_only) }, options: { needsFiltering: true, allowLocalOnly: isTruthy(params.allow_local_only) },
}); });
break; break;