0
0
Fork 0

Remove deprecated features at React v15.5 (#1905)

* Remove deprecated features at React v15.5

- [x] React.PropTypes
- [x] react-addons-pure-render-mixin
- [x] react-addons-test-utils

* Uncommented out & Add browserify_rails options

* re-add react-addons-shallow

* Fix syntax error from resolve conflicts

* follow up 59a77923b3
This commit is contained in:
Yamagishi Kazutoshi 2017-04-22 03:05:35 +09:00 committed by Eugen
parent 27ea2a88c1
commit 1948f9e767
83 changed files with 1441 additions and 1291 deletions

View file

@ -1,20 +1,13 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import PropTypes from 'prop-types';
const CharacterCounter = React.createClass({
propTypes: {
text: React.PropTypes.string.isRequired,
max: React.PropTypes.number.isRequired
},
mixins: [PureRenderMixin],
class CharacterCounter extends React.PureComponent {
checkRemainingText (diff) {
if (diff <= 0) {
return <span style={{ fontSize: '16px', cursor: 'default', color: '#ff5050' }}>{diff}</span>;
}
return <span style={{ fontSize: '16px', cursor: 'default' }}>{diff}</span>;
},
}
render () {
const diff = this.props.max - this.props.text.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "_").length;
@ -22,6 +15,11 @@ const CharacterCounter = React.createClass({
return this.checkRemainingText(diff);
}
});
}
CharacterCounter.propTypes = {
text: PropTypes.string.isRequired,
max: PropTypes.number.isRequired
}
export default CharacterCounter;

View file

@ -1,7 +1,7 @@
import CharacterCounter from './character_counter';
import Button from '../../../components/button';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import ReplyIndicatorContainer from '../containers/reply_indicator_container';
import AutosuggestTextarea from '../../../components/autosuggest_textarea';
import { debounce } from 'react-decoration';
@ -22,67 +22,53 @@ const messages = defineMessages({
publish: { id: 'compose_form.publish', defaultMessage: 'Toot' }
});
const ComposeForm = React.createClass({
class ComposeForm extends React.PureComponent {
propTypes: {
intl: React.PropTypes.object.isRequired,
text: React.PropTypes.string.isRequired,
suggestion_token: React.PropTypes.string,
suggestions: ImmutablePropTypes.list,
spoiler: React.PropTypes.bool,
privacy: React.PropTypes.string,
spoiler_text: React.PropTypes.string,
focusDate: React.PropTypes.instanceOf(Date),
preselectDate: React.PropTypes.instanceOf(Date),
is_submitting: React.PropTypes.bool,
is_uploading: React.PropTypes.bool,
me: React.PropTypes.number,
needsPrivacyWarning: React.PropTypes.bool,
mentionedDomains: React.PropTypes.array.isRequired,
onChange: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired,
onClearSuggestions: React.PropTypes.func.isRequired,
onFetchSuggestions: React.PropTypes.func.isRequired,
onSuggestionSelected: React.PropTypes.func.isRequired,
onChangeSpoilerText: React.PropTypes.func.isRequired,
onPaste: React.PropTypes.func.isRequired,
onPickEmoji: React.PropTypes.func.isRequired
},
mixins: [PureRenderMixin],
constructor (props, context) {
super(props, context);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.onSuggestionsClearRequested = this.onSuggestionsClearRequested.bind(this);
this.onSuggestionsFetchRequested = this.onSuggestionsFetchRequested.bind(this);
this.onSuggestionSelected = this.onSuggestionSelected.bind(this);
this.handleChangeSpoilerText = this.handleChangeSpoilerText.bind(this);
this.setAutosuggestTextarea = this.setAutosuggestTextarea.bind(this);
this.handleEmojiPick = this.handleEmojiPick.bind(this);
}
handleChange (e) {
this.props.onChange(e.target.value);
},
}
handleKeyDown (e) {
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
this.props.onSubmit();
}
},
}
handleSubmit () {
this.autosuggestTextarea.textarea.style.height = "auto";
this.props.onSubmit();
},
}
onSuggestionsClearRequested () {
this.props.onClearSuggestions();
},
}
@debounce(500)
onSuggestionsFetchRequested (token) {
this.props.onFetchSuggestions(token);
},
}
onSuggestionSelected (tokenStart, token, value) {
this._restoreCaret = null;
this.props.onSuggestionSelected(tokenStart, token, value);
},
}
handleChangeSpoilerText (e) {
this.props.onChangeSpoilerText(e.target.value);
},
}
componentWillReceiveProps (nextProps) {
// If this is the update where we've finished uploading,
@ -90,7 +76,7 @@ const ComposeForm = React.createClass({
if (!nextProps.is_uploading && this.props.is_uploading) {
this._restoreCaret = this.autosuggestTextarea.textarea.selectionStart;
}
},
}
componentDidUpdate (prevProps) {
// This statement does several things:
@ -117,17 +103,17 @@ const ComposeForm = React.createClass({
this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd);
this.autosuggestTextarea.textarea.focus();
}
},
}
setAutosuggestTextarea (c) {
this.autosuggestTextarea = c;
},
}
handleEmojiPick (data) {
const position = this.autosuggestTextarea.textarea.selectionStart;
this._restoreCaret = position + data.shortname.length + 1;
this.props.onPickEmoji(position, data);
},
}
render () {
const { intl, needsPrivacyWarning, mentionedDomains, onPaste } = this.props;
@ -207,6 +193,31 @@ const ComposeForm = React.createClass({
);
}
});
}
ComposeForm.propTypes = {
intl: PropTypes.object.isRequired,
text: PropTypes.string.isRequired,
suggestion_token: PropTypes.string,
suggestions: ImmutablePropTypes.list,
spoiler: PropTypes.bool,
privacy: PropTypes.string,
spoiler_text: PropTypes.string,
focusDate: PropTypes.instanceOf(Date),
preselectDate: PropTypes.instanceOf(Date),
is_submitting: PropTypes.bool,
is_uploading: PropTypes.bool,
me: PropTypes.number,
needsPrivacyWarning: PropTypes.bool,
mentionedDomains: PropTypes.array.isRequired,
onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
onClearSuggestions: PropTypes.func.isRequired,
onFetchSuggestions: PropTypes.func.isRequired,
onSuggestionSelected: PropTypes.func.isRequired,
onChangeSpoilerText: PropTypes.func.isRequired,
onPaste: PropTypes.func.isRequired,
onPickEmoji: PropTypes.func.isRequired
};
export default injectIntl(ComposeForm);

View file

@ -1,6 +1,6 @@
import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown';
import EmojiPicker from 'emojione-picker';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
const messages = defineMessages({
@ -19,23 +19,22 @@ const style = {
top: '5px'
};
const EmojiPickerDropdown = React.createClass({
class EmojiPickerDropdown extends React.PureComponent {
propTypes: {
intl: React.PropTypes.object.isRequired,
onPickEmoji: React.PropTypes.func.isRequired
},
mixins: [PureRenderMixin],
constructor (props, context) {
super(props, context);
this.setRef = this.setRef.bind(this);
this.handleChange = this.handleChange.bind(this);
}
setRef (c) {
this.dropdown = c;
},
}
handleChange (data) {
this.dropdown.hide();
this.props.onPickEmoji(data);
},
}
render () {
const { intl } = this.props;
@ -53,6 +52,11 @@ const EmojiPickerDropdown = React.createClass({
);
}
});
}
EmojiPickerDropdown.propTypes = {
intl: PropTypes.object.isRequired,
onPickEmoji: PropTypes.func.isRequired
};
export default injectIntl(EmojiPickerDropdown);

View file

@ -1,4 +1,3 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Avatar from '../../../components/avatar';
import IconButton from '../../../components/icon_button';
@ -7,12 +6,7 @@ import Permalink from '../../../components/permalink';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
const NavigationBar = React.createClass({
propTypes: {
account: ImmutablePropTypes.map.isRequired
},
mixins: [PureRenderMixin],
class NavigationBar extends React.PureComponent {
render () {
return (
@ -27,6 +21,10 @@ const NavigationBar = React.createClass({
);
}
});
}
NavigationBar.propTypes = {
account: ImmutablePropTypes.map.isRequired
};
export default NavigationBar;

View file

@ -1,4 +1,4 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import PropTypes from 'prop-types';
import { injectIntl, defineMessages } from 'react-intl';
import IconButton from '../../../components/icon_button';
@ -19,51 +19,48 @@ const iconStyle = {
height: null
};
const PrivacyDropdown = React.createClass({
class PrivacyDropdown extends React.PureComponent {
propTypes: {
value: React.PropTypes.string.isRequired,
onChange: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired
},
getInitialState () {
return {
constructor (props, context) {
super(props, context);
this.state = {
open: false
};
},
mixins: [PureRenderMixin],
this.handleToggle = this.handleToggle.bind(this);
this.handleClick = this.handleClick.bind(this);
this.onGlobalClick = this.onGlobalClick.bind(this);
this.setRef = this.setRef.bind(this);
}
handleToggle () {
this.setState({ open: !this.state.open });
},
}
handleClick (value, e) {
e.preventDefault();
this.setState({ open: false });
this.props.onChange(value);
},
}
onGlobalClick (e) {
if (e.target !== this.node && !this.node.contains(e.target) && this.state.open) {
this.setState({ open: false });
}
},
}
componentDidMount () {
window.addEventListener('click', this.onGlobalClick);
window.addEventListener('touchstart', this.onGlobalClick);
},
}
componentWillUnmount () {
window.removeEventListener('click', this.onGlobalClick);
window.removeEventListener('touchstart', this.onGlobalClick);
},
}
setRef (c) {
this.node = c;
},
}
render () {
const { value, onChange, intl } = this.props;
@ -96,6 +93,12 @@ const PrivacyDropdown = React.createClass({
);
}
});
}
PrivacyDropdown.propTypes = {
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired
};
export default injectIntl(PrivacyDropdown);

View file

@ -1,5 +1,5 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import Avatar from '../../../components/avatar';
import IconButton from '../../../components/icon_button';
import DisplayName from '../../../components/display_name';
@ -10,30 +10,24 @@ const messages = defineMessages({
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' }
});
const ReplyIndicator = React.createClass({
class ReplyIndicator extends React.PureComponent {
contextTypes: {
router: React.PropTypes.object
},
propTypes: {
status: ImmutablePropTypes.map,
onCancel: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired
},
mixins: [PureRenderMixin],
constructor (props, context) {
super(props, context);
this.handleClick = this.handleClick.bind(this);
this.handleAccountClick = this.handleAccountClick.bind(this);
}
handleClick () {
this.props.onCancel();
},
}
handleAccountClick (e) {
if (e.button === 0) {
e.preventDefault();
this.context.router.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`);
}
},
}
render () {
const { status, intl } = this.props;
@ -60,6 +54,16 @@ const ReplyIndicator = React.createClass({
);
}
});
}
ReplyIndicator.contextTypes = {
router: PropTypes.object
};
ReplyIndicator.propTypes = {
status: ImmutablePropTypes.map,
onCancel: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired
};
export default injectIntl(ReplyIndicator);

View file

@ -1,48 +1,43 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
const messages = defineMessages({
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }
});
const Search = React.createClass({
class Search extends React.PureComponent {
propTypes: {
value: React.PropTypes.string.isRequired,
submitted: React.PropTypes.bool,
onChange: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired,
onClear: React.PropTypes.func.isRequired,
onShow: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired
},
mixins: [PureRenderMixin],
constructor (props, context) {
super(props, context);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleFocus = this.handleFocus.bind(this);
}
handleChange (e) {
this.props.onChange(e.target.value);
},
}
handleClear (e) {
e.preventDefault();
this.props.onClear();
},
}
handleKeyDown (e) {
if (e.key === 'Enter') {
e.preventDefault();
this.props.onSubmit();
}
},
}
noop () {
},
}
handleFocus () {
this.props.onShow();
},
}
render () {
const { intl, value, submitted } = this.props;
@ -68,6 +63,16 @@ const Search = React.createClass({
);
}
});
}
Search.propTypes = {
value: PropTypes.string.isRequired,
submitted: PropTypes.bool,
onChange: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
onClear: PropTypes.func.isRequired,
onShow: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired
};
export default injectIntl(Search);

View file

@ -1,17 +1,10 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import AccountContainer from '../../../containers/account_container';
import StatusContainer from '../../../containers/status_container';
import { Link } from 'react-router';
const SearchResults = React.createClass({
propTypes: {
results: ImmutablePropTypes.map.isRequired
},
mixins: [PureRenderMixin],
class SearchResults extends React.PureComponent {
render () {
const { results } = this.props;
@ -63,6 +56,10 @@ const SearchResults = React.createClass({
);
}
});
}
SearchResults.propTypes = {
results: ImmutablePropTypes.map.isRequired
};
export default SearchResults;

View file

@ -1,20 +1,16 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import PropTypes from 'prop-types';
const TextIconButton = React.createClass({
class TextIconButton extends React.PureComponent {
propTypes: {
label: React.PropTypes.string.isRequired,
title: React.PropTypes.string,
active: React.PropTypes.bool,
onClick: React.PropTypes.func.isRequired
},
mixins: [PureRenderMixin],
constructor (props, context) {
super(props, context);
this.handleClick = this.handleClick.bind(this);
}
handleClick (e) {
e.preventDefault();
this.props.onClick();
},
}
render () {
const { label, title, active } = this.props;
@ -26,6 +22,13 @@ const TextIconButton = React.createClass({
);
}
});
}
TextIconButton.propTypes = {
label: PropTypes.string.isRequired,
title: PropTypes.string,
active: PropTypes.bool,
onClick: PropTypes.func.isRequired
};
export default TextIconButton;

View file

@ -1,5 +1,5 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import IconButton from '../../../components/icon_button';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl } from 'react-intl';
const messages = defineMessages({
@ -11,31 +11,28 @@ const iconStyle = {
height: null
};
const UploadButton = React.createClass({
class UploadButton extends React.PureComponent {
propTypes: {
disabled: React.PropTypes.bool,
onSelectFile: React.PropTypes.func.isRequired,
style: React.PropTypes.object,
resetFileKey: React.PropTypes.number,
intl: React.PropTypes.object.isRequired
},
mixins: [PureRenderMixin],
constructor (props, context) {
super(props, context);
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
this.setRef = this.setRef.bind(this);
}
handleChange (e) {
if (e.target.files.length > 0) {
this.props.onSelectFile(e.target.files);
}
},
}
handleClick () {
this.fileElement.click();
},
}
setRef (c) {
this.fileElement = c;
},
}
render () {
const { intl, resetFileKey, disabled } = this.props;
@ -48,6 +45,14 @@ const UploadButton = React.createClass({
);
}
});
}
UploadButton.propTypes = {
disabled: PropTypes.bool,
onSelectFile: PropTypes.func.isRequired,
style: PropTypes.object,
resetFileKey: PropTypes.number,
intl: PropTypes.object.isRequired
};
export default injectIntl(UploadButton);

View file

@ -1,5 +1,5 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import IconButton from '../../../components/icon_button';
import { defineMessages, injectIntl } from 'react-intl';
import UploadProgressContainer from '../containers/upload_progress_container';
@ -9,15 +9,7 @@ const messages = defineMessages({
undo: { id: 'upload_form.undo', defaultMessage: 'Undo' }
});
const UploadForm = React.createClass({
propTypes: {
media: ImmutablePropTypes.list.isRequired,
onRemoveFile: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired
},
mixins: [PureRenderMixin],
class UploadForm extends React.PureComponent {
render () {
const { intl, media } = this.props;
@ -42,6 +34,12 @@ const UploadForm = React.createClass({
);
}
});
}
UploadForm.propTypes = {
media: ImmutablePropTypes.list.isRequired,
onRemoveFile: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired
};
export default injectIntl(UploadForm);

View file

@ -1,15 +1,8 @@
import PureRenderMixin from 'react-addons-pure-render-mixin';
import PropTypes from 'prop-types';
import { Motion, spring } from 'react-motion';
import { FormattedMessage } from 'react-intl';
const UploadProgress = React.createClass({
propTypes: {
active: React.PropTypes.bool,
progress: React.PropTypes.number
},
mixins: [PureRenderMixin],
class UploadProgress extends React.PureComponent {
render () {
const { active, progress } = this.props;
@ -39,6 +32,11 @@ const UploadProgress = React.createClass({
);
}
});
}
UploadProgress.propTypes = {
active: PropTypes.bool,
progress: PropTypes.number
};
export default UploadProgress;

View file

@ -1,4 +1,5 @@
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import TextIconButton from '../components/text_icon_button';
import { changeComposeSensitivity } from '../../../actions/compose';
import { Motion, spring } from 'react-motion';
@ -21,14 +22,7 @@ const mapDispatchToProps = dispatch => ({
});
const SensitiveButton = React.createClass({
propTypes: {
visible: React.PropTypes.bool,
active: React.PropTypes.bool,
onClick: React.PropTypes.func.isRequired,
intl: React.PropTypes.object.isRequired
},
class SensitiveButton extends React.PureComponent {
render () {
const { visible, active, onClick, intl } = this.props;
@ -44,6 +38,13 @@ const SensitiveButton = React.createClass({
);
}
});
}
SensitiveButton.propTypes = {
visible: PropTypes.bool,
active: PropTypes.bool,
onClick: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired
};
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(SensitiveButton));

View file

@ -1,7 +1,7 @@
import ComposeFormContainer from './containers/compose_form_container';
import UploadFormContainer from './containers/upload_form_container';
import NavigationContainer from './containers/navigation_container';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { mountCompose, unmountCompose } from '../../actions/compose';
import { Link } from 'react-router';
@ -22,24 +22,15 @@ const mapStateToProps = state => ({
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden'])
});
const Compose = React.createClass({
propTypes: {
dispatch: React.PropTypes.func.isRequired,
withHeader: React.PropTypes.bool,
showSearch: React.PropTypes.bool,
intl: React.PropTypes.object.isRequired
},
mixins: [PureRenderMixin],
class Compose extends React.PureComponent {
componentDidMount () {
this.props.dispatch(mountCompose());
},
}
componentWillUnmount () {
this.props.dispatch(unmountCompose());
},
}
render () {
const { withHeader, showSearch, intl } = this.props;
@ -82,6 +73,13 @@ const Compose = React.createClass({
);
}
});
}
Compose.propTypes = {
dispatch: PropTypes.func.isRequired,
withHeader: PropTypes.bool,
showSearch: PropTypes.bool,
intl: PropTypes.object.isRequired
};
export default connect(mapStateToProps)(injectIntl(Compose));