Fix some more Javascript linting issues and discrepancies with upstream (#2209)

* Fix typo in flavours/glitch/features/video/index.js

* Fix various linting issues and discrepancies with upstream
lolsob-rspec
Claire 2023-05-07 21:43:25 +02:00 committed by GitHub
parent 43c40b5df8
commit 12e8bcac9d
39 changed files with 87 additions and 200 deletions

View File

@ -1,10 +1,8 @@
// This file will be loaded on public pages, regardless of theme. // This file will be loaded on public pages, regardless of theme.
import 'packs/public-path'; import 'packs/public-path';
import ready from '../mastodon/ready';
const { delegate } = require('@rails/ujs'); const { delegate } = require('@rails/ujs');
const { length } = require('stringz');
const getProfileAvatarAnimationHandler = (swapTo) => { const getProfileAvatarAnimationHandler = (swapTo) => {
//animate avatar gifs on the profile page when moused over //animate avatar gifs on the profile page when moused over

View File

@ -1,5 +1,5 @@
import api, { getLinks } from '../api'; import api, { getLinks } from '../api';
import { importAccount, importFetchedAccount, importFetchedAccounts } from './importer'; import { importFetchedAccount, importFetchedAccounts } from './importer';
export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST'; export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS'; export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS';

View File

@ -3,7 +3,7 @@ import { submitMarkers } from './markers';
import api, { getLinks } from 'flavours/glitch/api'; import api, { getLinks } from 'flavours/glitch/api';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import compareId from 'flavours/glitch/compare_id'; import compareId from 'flavours/glitch/compare_id';
import { me, usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state'; import { usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state';
import { toServerSideType } from 'flavours/glitch/utils/filters'; import { toServerSideType } from 'flavours/glitch/utils/filters';
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE'; export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
@ -121,7 +121,6 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
api(getState).get(path, { params }).then(response => { api(getState).get(path, { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next'); const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedStatuses(response.data)); dispatch(importFetchedStatuses(response.data));
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems)); dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems));
@ -163,10 +162,10 @@ export const expandListTimeline = (id, { maxId } = {}, done = noOp) =
export const expandHashtagTimeline = (hashtag, { maxId, tags, local } = {}, done = noOp) => { export const expandHashtagTimeline = (hashtag, { maxId, tags, local } = {}, done = noOp) => {
return expandTimeline(`hashtag:${hashtag}${local ? ':local' : ''}`, `/api/v1/timelines/tag/${hashtag}`, { return expandTimeline(`hashtag:${hashtag}${local ? ':local' : ''}`, `/api/v1/timelines/tag/${hashtag}`, {
max_id: maxId, max_id: maxId,
any: parseTags(tags, 'any'), any: parseTags(tags, 'any'),
all: parseTags(tags, 'all'), all: parseTags(tags, 'all'),
none: parseTags(tags, 'none'), none: parseTags(tags, 'none'),
local: local, local: local,
}, done); }, done);
}; };

View File

@ -9,6 +9,7 @@ export default class AvatarComposite extends React.PureComponent {
accounts: ImmutablePropTypes.list.isRequired, accounts: ImmutablePropTypes.list.isRequired,
animate: PropTypes.bool, animate: PropTypes.bool,
size: PropTypes.number.isRequired, size: PropTypes.number.isRequired,
onAccountClick: PropTypes.func.isRequired,
}; };
static defaultProps = { static defaultProps = {

View File

@ -14,6 +14,7 @@ export default class DisplayName extends React.PureComponent {
localDomain: PropTypes.string, localDomain: PropTypes.string,
others: ImmutablePropTypes.list, others: ImmutablePropTypes.list,
handleClick: PropTypes.func, handleClick: PropTypes.func,
onAccountClick: PropTypes.func,
}; };
handleMouseEnter = ({ currentTarget }) => { handleMouseEnter = ({ currentTarget }) => {
@ -61,6 +62,7 @@ export default class DisplayName extends React.PureComponent {
if (others && others.size > 0) { if (others && others.size > 0) {
displayName = others.take(2).map(a => ( displayName = others.take(2).map(a => (
<a <a
key={a.get('id')}
href={a.get('url')} href={a.get('url')}
target='_blank' target='_blank'
onClick={(e) => onAccountClick(a.get('acct'), e)} onClick={(e) => onAccountClick(a.get('acct'), e)}

View File

@ -1,6 +1,4 @@
import React from 'react'; import React from 'react';
import Motion from '../features/ui/util/optional_motion';
import spring from 'react-motion/lib/spring';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
@ -25,7 +23,7 @@ export default class IconButton extends React.PureComponent {
inverted: PropTypes.bool, inverted: PropTypes.bool,
animate: PropTypes.bool, animate: PropTypes.bool,
overlay: PropTypes.bool, overlay: PropTypes.bool,
tabIndex: PropTypes.string, tabIndex: PropTypes.number,
label: PropTypes.string, label: PropTypes.string,
counter: PropTypes.number, counter: PropTypes.number,
obfuscateCount: PropTypes.bool, obfuscateCount: PropTypes.bool,
@ -39,7 +37,7 @@ export default class IconButton extends React.PureComponent {
disabled: false, disabled: false,
animate: false, animate: false,
overlay: false, overlay: false,
tabIndex: '0', tabIndex: 0,
ariaHidden: false, ariaHidden: false,
}; };
@ -156,6 +154,7 @@ export default class IconButton extends React.PureComponent {
return ( return (
<button <button
type='button'
aria-label={title} aria-label={title}
aria-expanded={expanded} aria-expanded={expanded}
aria-hidden={ariaHidden} aria-hidden={ariaHidden}

View File

@ -289,7 +289,7 @@ class MediaGallery extends React.PureComponent {
} }
} }
componentDidUpdate (prevProps) { componentDidUpdate () {
if (this.node) { if (this.node) {
this.handleResize(); this.handleResize();
} }
@ -327,7 +327,7 @@ class MediaGallery extends React.PureComponent {
_setDimensions () { _setDimensions () {
const width = this.node.offsetWidth; const width = this.node.offsetWidth;
if (width && width != this.state.width) { if (width && width !== this.state.width) {
// offsetWidth triggers a layout, so only calculate when we need to // offsetWidth triggers a layout, so only calculate when we need to
if (this.props.cacheWidth) { if (this.props.cacheWidth) {
this.props.cacheWidth(width); this.props.cacheWidth(width);

View File

@ -1,52 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
export default
class Spoilers extends React.PureComponent {
static propTypes = {
spoilerText: PropTypes.string,
children: PropTypes.node,
};
state = {
hidden: true,
};
handleSpoilerClick = () => {
this.setState({ hidden: !this.state.hidden });
};
render () {
const { spoilerText, children } = this.props;
const { hidden } = this.state;
const toggleText = hidden ?
(<FormattedMessage
id='status.show_more'
defaultMessage='Show more'
key='0'
/>) :
(<FormattedMessage
id='status.show_less'
defaultMessage='Show less'
key='0'
/>);
return ([
<p className='spoiler__text'>
{spoilerText}
{' '}
<button tabIndex={0} className='status__content__spoiler-link' onClick={this.handleSpoilerClick}>
{toggleText}
</button>
</p>,
<div className={`status__content__spoiler ${!hidden ? 'status__content__spoiler--visible' : ''}`}>
{children}
</div>,
]);
}
}

View File

@ -282,7 +282,7 @@ class Status extends ImmutablePureComponent {
// Hack to fix timeline jumps on second rendering when auto-collapsing // Hack to fix timeline jumps on second rendering when auto-collapsing
// or on subsequent rendering when a preview card has been fetched // or on subsequent rendering when a preview card has been fetched
getSnapshotBeforeUpdate (prevProps, prevState) { getSnapshotBeforeUpdate() {
if (!this.props.getScrollPosition) return null; if (!this.props.getScrollPosition) return null;
const { muted, hidden, status, settings } = this.props; const { muted, hidden, status, settings } = this.props;
@ -297,7 +297,7 @@ class Status extends ImmutablePureComponent {
} }
} }
componentDidUpdate (prevProps, prevState, snapshot) { componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null && this.props.updateScrollBottom && this.node.offsetTop < snapshot.top) { if (snapshot !== null && this.props.updateScrollBottom && this.node.offsetTop < snapshot.top) {
this.props.updateScrollBottom(snapshot.height - snapshot.top); this.props.updateScrollBottom(snapshot.height - snapshot.top);
} }
@ -461,7 +461,7 @@ class Status extends ImmutablePureComponent {
this.props.onMoveDown(this.props.containerId || this.props.id, e.target.getAttribute('data-featured')); this.props.onMoveDown(this.props.containerId || this.props.id, e.target.getAttribute('data-featured'));
}; };
handleHotkeyCollapse = e => { handleHotkeyCollapse = () => {
if (!this.props.settings.getIn(['collapsed', 'enabled'])) if (!this.props.settings.getIn(['collapsed', 'enabled']))
return; return;
@ -505,7 +505,6 @@ class Status extends ImmutablePureComponent {
const { const {
handleRef, handleRef,
parseClick, parseClick,
setExpansion,
setCollapsed, setCollapsed,
} = this; } = this;
const { router } = this.context; const { router } = this.context;
@ -529,7 +528,7 @@ class Status extends ImmutablePureComponent {
rootId, rootId,
...other ...other
} = this.props; } = this.props;
const { isCollapsed, forceFilter } = this.state; const { isCollapsed } = this.state;
let background = null; let background = null;
let attachments = null; let attachments = null;

View File

@ -6,7 +6,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
// Mastodon imports. // Mastodon imports.
import Avatar from './avatar'; import Avatar from './avatar';
import AvatarOverlay from './avatar_overlay'; import AvatarOverlay from './avatar_overlay';
import AvatarComposite from './avatar_composite';
import DisplayName from './display_name'; import DisplayName from './display_name';
export default class StatusHeader extends React.PureComponent { export default class StatusHeader extends React.PureComponent {

View File

@ -64,18 +64,15 @@ class StatusIcons extends React.PureComponent {
mediaIconTitleText (mediaIcon) { mediaIconTitleText (mediaIcon) {
const { intl } = this.props; const { intl } = this.props;
switch (mediaIcon) { const message = {
case 'link': 'link': messages.previewCard,
return intl.formatMessage(messages.previewCard); 'picture-o': messages.pictures,
case 'picture-o': 'tasks': messages.poll,
return intl.formatMessage(messages.pictures); 'video-camera': messages.video,
case 'tasks': 'music': messages.audio,
return intl.formatMessage(messages.poll); }[mediaIcon];
case 'video-camera':
return intl.formatMessage(messages.video); return message && intl.formatMessage(message);
case 'music':
return intl.formatMessage(messages.audio);
}
} }
renderIcon (mediaIcon) { renderIcon (mediaIcon) {

View File

@ -10,8 +10,7 @@ const messages = defineMessages({
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {
const mapStateToProps = (state, { }) => ({ const mapStateToProps = () => ({});
});
return mapStateToProps; return mapStateToProps;
}; };

View File

@ -1,6 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import Status from 'flavours/glitch/components/status'; import Status from 'flavours/glitch/components/status';
import { List as ImmutableList } from 'immutable';
import { makeGetStatus, makeGetPictureInPicture } from 'flavours/glitch/selectors'; import { makeGetStatus, makeGetPictureInPicture } from 'flavours/glitch/selectors';
import { import {
replyCompose, replyCompose,
@ -37,13 +36,9 @@ import { initBoostModal } from 'flavours/glitch/actions/boosts';
import { openModal } from 'flavours/glitch/actions/modal'; import { openModal } from 'flavours/glitch/actions/modal';
import { deployPictureInPicture } from 'flavours/glitch/actions/picture_in_picture'; import { deployPictureInPicture } from 'flavours/glitch/actions/picture_in_picture';
import { changeLocalSetting } from 'flavours/glitch/actions/local_settings'; import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/initial_state'; import { boostModal, favouriteModal, deleteModal } from 'flavours/glitch/initial_state';
import { filterEditLink } from 'flavours/glitch/utils/backend_links';
import { showAlertForError } from '../actions/alerts'; import { showAlertForError } from '../actions/alerts';
import AccountContainer from 'flavours/glitch/containers/account_container';
import Spoilers from '../components/spoilers';
import Icon from 'flavours/glitch/components/icon';
const messages = defineMessages({ const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },

View File

@ -1,18 +1,13 @@
import React from 'react'; import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
import { NavLink } from 'react-router-dom'; import { NavLink } from 'react-router-dom';
import { injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; import { FormattedMessage, FormattedNumber } from 'react-intl';
import { me, isStaff } from 'flavours/glitch/initial_state';
import { profileLink, accountAdminLink } from 'flavours/glitch/utils/backend_links';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
class ActionBar extends React.PureComponent { class ActionBar extends React.PureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map.isRequired, account: ImmutablePropTypes.map.isRequired,
intl: PropTypes.object.isRequired,
}; };
isStatusesPageActive = (match, location) => { isStatusesPageActive = (match, location) => {
@ -23,7 +18,7 @@ class ActionBar extends React.PureComponent {
}; };
render () { render () {
const { account, intl } = this.props; const { account } = this.props;
if (account.get('suspended')) { if (account.get('suspended')) {
return ( return (
@ -83,4 +78,4 @@ class ActionBar extends React.PureComponent {
} }
export default injectIntl(ActionBar); export default ActionBar;

View File

@ -14,6 +14,7 @@ import HeaderContainer from 'flavours/glitch/features/account_timeline/container
import ScrollContainer from 'flavours/glitch/containers/scroll_container'; import ScrollContainer from 'flavours/glitch/containers/scroll_container';
import LoadMore from 'flavours/glitch/components/load_more'; import LoadMore from 'flavours/glitch/components/load_more';
import { openModal } from 'flavours/glitch/actions/modal'; import { openModal } from 'flavours/glitch/actions/modal';
import { FormattedMessage } from 'react-intl';
import { normalizeForLookup } from 'flavours/glitch/reducers/accounts_map'; import { normalizeForLookup } from 'flavours/glitch/reducers/accounts_map';
import BundleColumnError from 'flavours/glitch/features/ui/components/bundle_column_error'; import BundleColumnError from 'flavours/glitch/features/ui/components/bundle_column_error';
@ -71,8 +72,8 @@ class AccountGallery extends ImmutablePureComponent {
isLoading: PropTypes.bool, isLoading: PropTypes.bool,
hasMore: PropTypes.bool, hasMore: PropTypes.bool,
isAccount: PropTypes.bool, isAccount: PropTypes.bool,
multiColumn: PropTypes.bool,
suspended: PropTypes.bool, suspended: PropTypes.bool,
multiColumn: PropTypes.bool,
}; };
state = { state = {

View File

@ -93,10 +93,6 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(directCompose(account, router)); dispatch(directCompose(account, router));
}, },
onDirect (account, router) {
dispatch(directCompose(account, router));
},
onReblogToggle (account) { onReblogToggle (account) {
if (account.getIn(['relationship', 'showing_reblogs'])) { if (account.getIn(['relationship', 'showing_reblogs'])) {
dispatch(followAccount(account.get('id'), { reblogs: false })); dispatch(followAccount(account.get('id'), { reblogs: false }));

View File

@ -9,7 +9,6 @@ import LoadingIndicator from '../../components/loading_indicator';
import Column from '../ui/components/column'; import Column from '../ui/components/column';
import ProfileColumnHeader from 'flavours/glitch/features/account/components/profile_column_header'; import ProfileColumnHeader from 'flavours/glitch/features/account/components/profile_column_header';
import HeaderContainer from './containers/header_container'; import HeaderContainer from './containers/header_container';
import ColumnBackButton from 'flavours/glitch/components/column_back_button';
import { List as ImmutableList } from 'immutable'; import { List as ImmutableList } from 'immutable';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';

View File

@ -94,7 +94,7 @@ class Audio extends React.PureComponent {
const width = this.player.offsetWidth; const width = this.player.offsetWidth;
const height = this.props.fullscreen ? this.player.offsetHeight : (width / (16/9)); const height = this.props.fullscreen ? this.player.offsetHeight : (width / (16/9));
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);
} }

View File

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import CharacterCounter from './character_counter';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ReplyIndicatorContainer from '../containers/reply_indicator_container'; import ReplyIndicatorContainer from '../containers/reply_indicator_container';
@ -11,13 +12,12 @@ import UploadFormContainer from '../containers/upload_form_container';
import WarningContainer from '../containers/warning_container'; import WarningContainer from '../containers/warning_container';
import { isMobile } from 'flavours/glitch/is_mobile'; import { isMobile } from 'flavours/glitch/is_mobile';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { length } from 'stringz';
import { countableText } from '../util/counter'; import { countableText } from '../util/counter';
import { maxChars } from 'flavours/glitch/initial_state';
import OptionsContainer from '../containers/options_container'; import OptionsContainer from '../containers/options_container';
import Publisher from './publisher'; import Publisher from './publisher';
import TextareaIcons from './textarea_icons'; import TextareaIcons from './textarea_icons';
import { maxChars } from 'flavours/glitch/initial_state';
import CharacterCounter from './character_counter';
import { length } from 'stringz';
const messages = defineMessages({ const messages = defineMessages({
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' }, placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
@ -76,7 +76,6 @@ class ComposeForm extends ImmutablePureComponent {
preselectOnReply: PropTypes.bool, preselectOnReply: PropTypes.bool,
onChangeSpoilerness: PropTypes.func, onChangeSpoilerness: PropTypes.func,
onChangeVisibility: PropTypes.func, onChangeVisibility: PropTypes.func,
onPaste: PropTypes.func,
onMediaDescriptionConfirm: PropTypes.func, onMediaDescriptionConfirm: PropTypes.func,
}; };
@ -164,11 +163,11 @@ class ComposeForm extends ImmutablePureComponent {
}; };
// Selects a suggestion from the autofill. // Selects a suggestion from the autofill.
onSuggestionSelected = (tokenStart, token, value) => { handleSuggestionSelected = (tokenStart, token, value) => {
this.props.onSuggestionSelected(tokenStart, token, value, ['text']); this.props.onSuggestionSelected(tokenStart, token, value, ['text']);
}; };
onSpoilerSuggestionSelected = (tokenStart, token, value) => { handleSpoilerSuggestionSelected = (tokenStart, token, value) => {
this.props.onSuggestionSelected(tokenStart, token, value, ['spoiler_text']); this.props.onSuggestionSelected(tokenStart, token, value, ['spoiler_text']);
}; };
@ -177,7 +176,7 @@ class ComposeForm extends ImmutablePureComponent {
this.handleSubmit(); this.handleSubmit();
} }
if (e.keyCode == 13 && e.altKey) { if (e.keyCode === 13 && e.altKey) {
this.handleSecondarySubmit(); this.handleSecondarySubmit();
} }
}; };
@ -281,9 +280,7 @@ class ComposeForm extends ImmutablePureComponent {
const { const {
handleEmojiPick, handleEmojiPick,
handleSecondarySubmit, handleSecondarySubmit,
handleSelect,
handleSubmit, handleSubmit,
handleRefTextarea,
} = this; } = this;
const { const {
advancedOptions, advancedOptions,
@ -291,7 +288,6 @@ class ComposeForm extends ImmutablePureComponent {
isSubmitting, isSubmitting,
layout, layout,
onChangeSpoilerness, onChangeSpoilerness,
onChangeVisibility,
onClearSuggestions, onClearSuggestions,
onFetchSuggestions, onFetchSuggestions,
onPaste, onPaste,
@ -322,10 +318,10 @@ class ComposeForm extends ImmutablePureComponent {
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
disabled={!spoiler} disabled={!spoiler}
ref={this.handleRefSpoilerText} ref={this.handleRefSpoilerText}
suggestions={this.props.suggestions} suggestions={suggestions}
onSuggestionsFetchRequested={onFetchSuggestions} onSuggestionsFetchRequested={onFetchSuggestions}
onSuggestionsClearRequested={onClearSuggestions} onSuggestionsClearRequested={onClearSuggestions}
onSuggestionSelected={this.onSpoilerSuggestionSelected} onSuggestionSelected={this.handleSpoilerSuggestionSelected}
searchTokens={[':']} searchTokens={[':']}
id='glitch.composer.spoiler.input' id='glitch.composer.spoiler.input'
className='spoiler-input__input' className='spoiler-input__input'
@ -342,11 +338,11 @@ class ComposeForm extends ImmutablePureComponent {
value={this.props.text} value={this.props.text}
onChange={this.handleChange} onChange={this.handleChange}
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
suggestions={this.props.suggestions} suggestions={suggestions}
onFocus={this.handleFocus} onFocus={this.handleFocus}
onSuggestionsFetchRequested={onFetchSuggestions} onSuggestionsFetchRequested={onFetchSuggestions}
onSuggestionsClearRequested={onClearSuggestions} onSuggestionsClearRequested={onClearSuggestions}
onSuggestionSelected={this.onSuggestionSelected} onSuggestionSelected={this.handleSuggestionSelected}
onPaste={onPaste} onPaste={onPaste}
autoFocus={!showSearch && !isMobile(window.innerWidth, layout)} autoFocus={!showSearch && !isMobile(window.innerWidth, layout)}
lang={this.props.lang} lang={this.props.lang}

View File

@ -8,9 +8,6 @@ import Overlay from 'react-overlays/Overlay';
import IconButton from 'flavours/glitch/components/icon_button'; import IconButton from 'flavours/glitch/components/icon_button';
import DropdownMenu from './dropdown_menu'; import DropdownMenu from './dropdown_menu';
// Utils.
import { assignHandlers } from 'flavours/glitch/utils/react_helpers';
// The component. // The component.
export default class ComposerOptionsDropdown extends React.PureComponent { export default class ComposerOptionsDropdown extends React.PureComponent {
@ -50,7 +47,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
const { open } = this.state; const { open } = this.state;
if (this.props.isUserTouching && this.props.isUserTouching()) { if (this.props.isUserTouching && this.props.isUserTouching()) {
if (this.state.open) { if (open) {
this.props.onModalClose(); this.props.onModalClose();
} else { } else {
const modal = this.handleMakeModal(); const modal = this.handleMakeModal();
@ -59,10 +56,10 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
} }
} }
} else { } else {
if (this.state.open && this.activeElement) { if (open && this.activeElement) {
this.activeElement.focus({ preventScroll: true }); this.activeElement.focus({ preventScroll: true });
} }
this.setState({ open: !this.state.open, openedViaKeyboard: type !== 'click' }); this.setState({ open: !open, openedViaKeyboard: type !== 'click' });
} }
}; };

View File

@ -1,7 +1,6 @@
// Package imports. // Package imports.
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import classNames from 'classnames'; import classNames from 'classnames';
// Components. // Components.
@ -9,7 +8,6 @@ import Icon from 'flavours/glitch/components/icon';
// Utils. // Utils.
import { withPassive } from 'flavours/glitch/utils/dom_helpers'; import { withPassive } from 'flavours/glitch/utils/dom_helpers';
import { assignHandlers } from 'flavours/glitch/utils/react_helpers';
// The component. // The component.
export default class ComposerOptionsDropdownContent extends React.PureComponent { export default class ComposerOptionsDropdownContent extends React.PureComponent {
@ -78,7 +76,8 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
items, items,
} = this.props; } = this.props;
const { name } = this.props.items[i]; const { name } = items[i];
e.preventDefault(); // Prevents change in focus on click e.preventDefault(); // Prevents change in focus on click
if (closeOnChange) { if (closeOnChange) {
onClose(); onClose();
@ -131,7 +130,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
if (element) { if (element) {
element.focus(); element.focus();
this.handleChange(this.props.items[Number(element.getAttribute('data-index'))].name); this.handleChange(items[Number(element.getAttribute('data-index'))].name);
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
@ -169,6 +168,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
onClick={this.handleClick} onClick={this.handleClick}
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
role='option' role='option'
aria-selected={active}
tabIndex={0} tabIndex={0}
key={name} key={name}
data-index={i} data-index={i}
@ -183,8 +183,6 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
render () { render () {
const { const {
items, items,
onChange,
onClose,
style, style,
} = this.props; } = this.props;

View File

@ -145,6 +145,7 @@ class PollForm extends ImmutablePureComponent {
</ul> </ul>
<div className='poll__footer'> <div className='poll__footer'>
{/* eslint-disable-next-line jsx-a11y/no-onchange */}
<select value={isMultiple ? 'true' : 'false'} onChange={this.handleSelectMultiple}> <select value={isMultiple ? 'true' : 'false'} onChange={this.handleSelectMultiple}>
<option value='false'>{intl.formatMessage(messages.single_choice)}</option> <option value='false'>{intl.formatMessage(messages.single_choice)}</option>
<option value='true'>{intl.formatMessage(messages.multiple_choices)}</option> <option value='true'>{intl.formatMessage(messages.multiple_choices)}</option>

View File

@ -1,6 +1,5 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import Dropdown from './dropdown'; import Dropdown from './dropdown';

View File

@ -1,8 +1,6 @@
// Package imports. // Package imports.
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import PropTypes from 'prop-types';
import { import {
injectIntl, injectIntl,
FormattedMessage, FormattedMessage,

View File

@ -6,7 +6,6 @@ import spring from 'react-motion/lib/spring';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
import { isUserTouching } from 'flavours/glitch/is_mobile';
export default class Upload extends ImmutablePureComponent { export default class Upload extends ImmutablePureComponent {

View File

@ -2,7 +2,6 @@ import React from 'react';
import ComposeFormContainer from './containers/compose_form_container'; import ComposeFormContainer from './containers/compose_form_container';
import NavigationContainer from './containers/navigation_container'; import NavigationContainer from './containers/navigation_container';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { mountCompose, unmountCompose, cycleElefriendCompose } from 'flavours/glitch/actions/compose'; import { mountCompose, unmountCompose, cycleElefriendCompose } from 'flavours/glitch/actions/compose';
import { injectIntl, defineMessages } from 'react-intl'; import { injectIntl, defineMessages } from 'react-intl';
@ -11,7 +10,7 @@ import SearchContainer from './containers/search_container';
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 SearchResultsContainer from './containers/search_results_container'; import SearchResultsContainer from './containers/search_results_container';
import { me, mascot } from 'flavours/glitch/initial_state'; import { mascot } from 'flavours/glitch/initial_state';
import HeaderContainer from './containers/header_container'; import HeaderContainer from './containers/header_container';
import Column from 'flavours/glitch/components/column'; import Column from 'flavours/glitch/components/column';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
@ -25,7 +24,7 @@ const mapStateToProps = (state, ownProps) => ({
showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : false, showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : false,
}); });
const mapDispatchToProps = (dispatch, { intl }) => ({ const mapDispatchToProps = (dispatch) => ({
onClickElefriend () { onClickElefriend () {
dispatch(cycleElefriendCompose()); dispatch(cycleElefriendCompose());
}, },

View File

@ -2,7 +2,7 @@ import React from 'react';
import Column from 'flavours/glitch/features/ui/components/column'; import Column from 'flavours/glitch/features/ui/components/column';
import ColumnLink from 'flavours/glitch/features/ui/components/column_link'; import ColumnLink from 'flavours/glitch/features/ui/components/column_link';
import ColumnSubheading from 'flavours/glitch/features/ui/components/column_subheading'; import ColumnSubheading from 'flavours/glitch/features/ui/components/column_subheading';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { openModal } from 'flavours/glitch/actions/modal'; import { openModal } from 'flavours/glitch/actions/modal';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -35,7 +35,6 @@ const messages = defineMessages({
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' }, lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
keyboard_shortcuts: { id: 'navigation_bar.keyboard_shortcuts', defaultMessage: 'Keyboard shortcuts' }, keyboard_shortcuts: { id: 'navigation_bar.keyboard_shortcuts', defaultMessage: 'Keyboard shortcuts' },
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
lists_subheading: { id: 'column_subheading.lists', defaultMessage: 'Lists' }, lists_subheading: { id: 'column_subheading.lists', defaultMessage: 'Lists' },
misc: { id: 'navigation_bar.misc', defaultMessage: 'Misc' }, misc: { id: 'navigation_bar.misc', defaultMessage: 'Misc' },
menu: { id: 'getting_started.heading', defaultMessage: 'Getting started' }, menu: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
@ -77,8 +76,6 @@ const badgeDisplay = (number, limit) => {
} }
}; };
const NAVIGATION_PANEL_BREAKPOINT = 600 + (285 * 2) + (10 * 2);
class GettingStarted extends ImmutablePureComponent { class GettingStarted extends ImmutablePureComponent {
static contextTypes = { static contextTypes = {
@ -189,7 +186,7 @@ class GettingStarted extends ImmutablePureComponent {
<LinkFooter /> <LinkFooter />
</div> </div>
{multiColumn && showTrends && <TrendsContainer />} {(multiColumn && showTrends) && <TrendsContainer />}
<Helmet> <Helmet>
<title>{intl.formatMessage(messages.menu)}</title> <title>{intl.formatMessage(messages.menu)}</title>

View File

@ -34,11 +34,11 @@ class GettingStartedMisc extends ImmutablePureComponent {
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
}; };
openOnboardingModal = (e) => { openOnboardingModal = () => {
this.props.dispatch(openModal('ONBOARDING')); this.props.dispatch(openModal('ONBOARDING'));
}; };
openFeaturedAccountsModal = (e) => { openFeaturedAccountsModal = () => {
this.props.dispatch(openModal('PINNED_ACCOUNTS_EDITOR')); this.props.dispatch(openModal('PINNED_ACCOUNTS_EDITOR'));
}; };

View File

@ -1,4 +1,3 @@
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeGetAccount } from 'flavours/glitch/selectors'; import { makeGetAccount } from 'flavours/glitch/selectors';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';

View File

@ -1,4 +1,3 @@
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';
import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists'; import { fetchListSuggestions, clearListSuggestions, changeListSuggestions } from '../../../actions/lists';

View File

@ -133,9 +133,9 @@ class ListTimeline extends React.PureComponent {
}; };
handleRepliesPolicyChange = ({ target }) => { handleRepliesPolicyChange = ({ target }) => {
const { dispatch, list } = this.props; const { dispatch } = this.props;
const { id } = this.props.params; const { id } = this.props.params;
this.props.dispatch(updateList(id, undefined, false, target.value)); dispatch(updateList(id, undefined, false, target.value));
}; };
render () { render () {
@ -172,11 +172,11 @@ class ListTimeline extends React.PureComponent {
multiColumn={multiColumn} multiColumn={multiColumn}
> >
<div className='column-settings__row column-header__links'> <div className='column-settings__row column-header__links'>
<button className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleEditClick}> <button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleEditClick}>
<Icon id='pencil' /> <FormattedMessage id='lists.edit' defaultMessage='Edit list' /> <Icon id='pencil' /> <FormattedMessage id='lists.edit' defaultMessage='Edit list' />
</button> </button>
<button className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleDeleteClick}> <button type='button' className='text-btn column-header__setting-btn' tabIndex={0} onClick={this.handleDeleteClick}>
<Icon id='trash' /> <FormattedMessage id='lists.delete' defaultMessage='Delete list' /> <Icon id='trash' /> <FormattedMessage id='lists.delete' defaultMessage='Delete list' />
</button> </button>
</div> </div>
@ -202,7 +202,7 @@ class ListTimeline extends React.PureComponent {
scrollKey={`list_timeline-${columnId}`} scrollKey={`list_timeline-${columnId}`}
timelineId={`list:${id}`} timelineId={`list:${id}`}
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}
emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet.' />} emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' />}
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
/> />

View File

@ -26,7 +26,7 @@ export default class LocalSettingsPageItem extends React.PureComponent {
const optionElems = options && options.length > 0 && options.map((opt) => { const optionElems = options && options.length > 0 && options.map((opt) => {
let optionId = `${id}--${opt.value}`; let optionId = `${id}--${opt.value}`;
return ( return (
<label htmlFor={optionId}> <label key={id} htmlFor={optionId}>
<input <input
type='radio' type='radio'
name={id} name={id}

View File

@ -54,12 +54,11 @@ export default class LocalSettingsPageItem extends React.PureComponent {
const optionElems = options && options.length > 0 && options.map((opt) => { const optionElems = options && options.length > 0 && options.map((opt) => {
let optionId = `${id}--${opt.value}`; let optionId = `${id}--${opt.value}`;
return ( return (
<label htmlFor={optionId}> <label key={optionId} htmlFor={optionId}>
<input <input
type='radio' type='radio'
name={id} name={id}
id={optionId} id={optionId}
key={optionId}
value={opt.value} value={opt.value}
onBlur={handleChange} onBlur={handleChange}
onChange={handleChange} onChange={handleChange}
@ -93,7 +92,7 @@ export default class LocalSettingsPageItem extends React.PureComponent {
placeholder={placeholder} placeholder={placeholder}
onChange={handleChange} onChange={handleChange}
disabled={!enabled} disabled={!enabled}
{...inputProps} {...inputProps}
/> />
</p> </p>
</label> </label>

View File

@ -2,22 +2,17 @@
import React from 'react'; import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { HotKeys } from 'react-hotkeys'; import { HotKeys } from 'react-hotkeys';
import classNames from 'classnames'; import classNames from 'classnames';
// Our imports. // Our imports.
import Permalink from 'flavours/glitch/components/permalink'; import Permalink from 'flavours/glitch/components/permalink';
import AccountContainer from 'flavours/glitch/containers/account_container';
import NotificationOverlayContainer from '../containers/overlay_container'; import NotificationOverlayContainer from '../containers/overlay_container';
import Icon from 'flavours/glitch/components/icon'; import Icon from 'flavours/glitch/components/icon';
import Report from './report'; import Report from './report';
const messages = defineMessages({
adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' },
});
export default class AdminReport extends ImmutablePureComponent { export default class AdminReport extends ImmutablePureComponent {
static propTypes = { static propTypes = {
@ -67,7 +62,7 @@ export default class AdminReport extends ImmutablePureComponent {
} }
render () { render () {
const { intl, account, notification, unread, report } = this.props; const { account, notification, unread, report } = this.props;
if (!report) { if (!report) {
return null; return null;

View File

@ -1,5 +1,4 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeGetAccount } from 'flavours/glitch/selectors';
import FollowRequest from '../components/follow_request'; import FollowRequest from '../components/follow_request';
import { authorizeFollowRequest, rejectFollowRequest } from 'flavours/glitch/actions/accounts'; import { authorizeFollowRequest, rejectFollowRequest } from 'flavours/glitch/actions/accounts';

View File

@ -9,9 +9,9 @@ import {
enterNotificationClearingMode, enterNotificationClearingMode,
expandNotifications, expandNotifications,
scrollTopNotifications, scrollTopNotifications,
loadPending,
mountNotifications, mountNotifications,
unmountNotifications, unmountNotifications,
loadPending,
markNotificationsAsRead, markNotificationsAsRead,
} from 'flavours/glitch/actions/notifications'; } from 'flavours/glitch/actions/notifications';
import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns'; import { addColumn, removeColumn, moveColumn } from 'flavours/glitch/actions/columns';
@ -79,16 +79,6 @@ const mapDispatchToProps = dispatch => ({
onEnterCleaningMode(yes) { onEnterCleaningMode(yes) {
dispatch(enterNotificationClearingMode(yes)); dispatch(enterNotificationClearingMode(yes));
}, },
onMarkAsRead() {
dispatch(markNotificationsAsRead());
dispatch(submitMarkers({ immediate: true }));
},
onMount() {
dispatch(mountNotifications());
},
onUnmount() {
dispatch(unmountNotifications());
},
dispatch, dispatch,
}); });
@ -112,8 +102,6 @@ class Notifications extends React.PureComponent {
localSettings: ImmutablePropTypes.map, localSettings: ImmutablePropTypes.map,
notifCleaningActive: PropTypes.bool, notifCleaningActive: PropTypes.bool,
onEnterCleaningMode: PropTypes.func, onEnterCleaningMode: PropTypes.func,
onMount: PropTypes.func,
onUnmount: PropTypes.func,
lastReadId: PropTypes.string, lastReadId: PropTypes.string,
canMarkAsRead: PropTypes.bool, canMarkAsRead: PropTypes.bool,
needsNotificationPermission: PropTypes.bool, needsNotificationPermission: PropTypes.bool,
@ -127,6 +115,18 @@ class Notifications extends React.PureComponent {
animatingNCD: false, animatingNCD: false,
}; };
componentDidMount() {
this.props.dispatch(mountNotifications());
}
componentWillUnmount () {
this.handleLoadOlder.cancel();
this.handleScrollToTop.cancel();
this.handleScroll.cancel();
// this.props.dispatch(scrollTopNotifications(false));
this.props.dispatch(unmountNotifications());
}
handleLoadGap = (maxId) => { handleLoadGap = (maxId) => {
this.props.dispatch(expandNotifications({ maxId })); this.props.dispatch(expandNotifications({ maxId }));
}; };
@ -195,20 +195,6 @@ class Notifications extends React.PureComponent {
} }
} }
componentDidMount () {
const { onMount } = this.props;
if (onMount) {
onMount();
}
}
componentWillUnmount () {
const { onUnmount } = this.props;
if (onUnmount) {
onUnmount();
}
}
handleTransitionEndNCD = () => { handleTransitionEndNCD = () => {
this.setState({ animatingNCD: false }); this.setState({ animatingNCD: false });
}; };
@ -219,12 +205,13 @@ class Notifications extends React.PureComponent {
}; };
handleMarkAsRead = () => { handleMarkAsRead = () => {
this.props.onMarkAsRead(); this.props.dispatch(markNotificationsAsRead());
this.props.dispatch(submitMarkers({ immediate: true }));
}; };
render () { render () {
const { intl, notifications, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar, lastReadId, canMarkAsRead, needsNotificationPermission } = this.props; const { intl, notifications, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar, lastReadId, canMarkAsRead, needsNotificationPermission } = this.props;
const { notifCleaning, notifCleaningActive } = this.props; const { notifCleaningActive } = this.props;
const { animatingNCD } = this.state; const { animatingNCD } = this.state;
const pinned = !!columnId; const pinned = !!columnId;
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. When other people interact with you, you will see it here." />; const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. When other people interact with you, you will see it here." />;

View File

@ -1,4 +1,3 @@
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeGetAccount } from 'flavours/glitch/selectors'; import { makeGetAccount } from 'flavours/glitch/selectors';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';

View File

@ -1,4 +1,3 @@
import React from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';
import { import {

View File

@ -554,7 +554,7 @@ class Video extends React.PureComponent {
playerStyle.height = height; playerStyle.height = height;
} else if (inline) { } else if (inline) {
return (<div className={computedClass} ref={this.setPlayerRef} tabindex={0} />); return (<div className={computedClass} ref={this.setPlayerRef} tabIndex={0} />);
} }
let preload; let preload;