diff --git a/app/assets/javascripts/components/actions/follow.jsx b/app/assets/javascripts/components/actions/follow.jsx
deleted file mode 100644
index 8eb440789..000000000
--- a/app/assets/javascripts/components/actions/follow.jsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import api from '../api'
-
-export const FOLLOW_CHANGE = 'FOLLOW_CHANGE';
-export const FOLLOW_SUBMIT_REQUEST = 'FOLLOW_SUBMIT_REQUEST';
-export const FOLLOW_SUBMIT_SUCCESS = 'FOLLOW_SUBMIT_SUCCESS';
-export const FOLLOW_SUBMIT_FAIL = 'FOLLOW_SUBMIT_FAIL';
-
-export function changeFollow(text) {
- return {
- type: FOLLOW_CHANGE,
- text: text
- };
-};
-
-export function submitFollow(router) {
- return function (dispatch, getState) {
- dispatch(submitFollowRequest());
-
- api(getState).post('/api/v1/follows', {
- uri: getState().getIn(['follow', 'text'])
- }).then(function (response) {
- dispatch(submitFollowSuccess(response.data));
- router.push(`/accounts/${response.data.id}`);
- }).catch(function (error) {
- dispatch(submitFollowFail(error));
- });
- };
-};
-
-export function submitFollowRequest() {
- return {
- type: FOLLOW_SUBMIT_REQUEST
- };
-};
-
-export function submitFollowSuccess(account) {
- return {
- type: FOLLOW_SUBMIT_SUCCESS,
- account: account
- };
-};
-
-export function submitFollowFail(error) {
- return {
- type: FOLLOW_SUBMIT_FAIL,
- error: error
- };
-};
diff --git a/app/assets/javascripts/components/features/ui/components/character_counter.jsx b/app/assets/javascripts/components/features/compose/components/character_counter.jsx
similarity index 100%
rename from app/assets/javascripts/components/features/ui/components/character_counter.jsx
rename to app/assets/javascripts/components/features/compose/components/character_counter.jsx
diff --git a/app/assets/javascripts/components/features/ui/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx
similarity index 97%
rename from app/assets/javascripts/components/features/ui/components/compose_form.jsx
rename to app/assets/javascripts/components/features/compose/components/compose_form.jsx
index aef228d58..ead8e0008 100644
--- a/app/assets/javascripts/components/features/ui/components/compose_form.jsx
+++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx
@@ -7,6 +7,7 @@ import UploadButton from './upload_button';
import Autosuggest from 'react-autosuggest';
import AutosuggestAccountContainer from '../../compose/containers/autosuggest_account_container';
import { debounce } from 'react-decoration';
+import UploadButtonContainer from '../containers/upload_button_container';
const getTokenForSuggestions = (str, caretPosition) => {
let word;
@@ -168,6 +169,7 @@ const ComposeForm = React.createClass({
-
-
-
+
+
+
);
}
diff --git a/app/assets/javascripts/components/features/compose/components/upload_form.jsx b/app/assets/javascripts/components/features/compose/components/upload_form.jsx
new file mode 100644
index 000000000..751f76ab7
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/components/upload_form.jsx
@@ -0,0 +1,34 @@
+import PureRenderMixin from 'react-addons-pure-render-mixin';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import IconButton from '../../../components/icon_button';
+
+const UploadForm = React.createClass({
+
+ propTypes: {
+ media: ImmutablePropTypes.list.isRequired,
+ is_uploading: React.PropTypes.bool,
+ onSelectFile: React.PropTypes.func.isRequired,
+ onRemoveFile: React.PropTypes.func.isRequired
+ },
+
+ mixins: [PureRenderMixin],
+
+ render () {
+ const uploads = this.props.media.map(attachment => (
+
+ ));
+
+ return (
+
+ {uploads}
+
+ );
+ }
+
+});
+
+export default UploadForm;
diff --git a/app/assets/javascripts/components/features/ui/containers/compose_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
similarity index 100%
rename from app/assets/javascripts/components/features/ui/containers/compose_form_container.jsx
rename to app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
diff --git a/app/assets/javascripts/components/features/ui/containers/navigation_container.jsx b/app/assets/javascripts/components/features/compose/containers/navigation_container.jsx
similarity index 100%
rename from app/assets/javascripts/components/features/ui/containers/navigation_container.jsx
rename to app/assets/javascripts/components/features/compose/containers/navigation_container.jsx
diff --git a/app/assets/javascripts/components/features/compose/containers/upload_button_container.jsx b/app/assets/javascripts/components/features/compose/containers/upload_button_container.jsx
new file mode 100644
index 000000000..4154b0737
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/upload_button_container.jsx
@@ -0,0 +1,17 @@
+import { connect } from 'react-redux';
+import UploadButton from '../components/upload_button';
+import { uploadCompose } from '../../../actions/compose';
+
+const mapStateToProps = state => ({
+ disabled: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 3 || state.getIn(['compose', 'media_attachments']).some(m => m.get('type') === 'video')),
+});
+
+const mapDispatchToProps = dispatch => ({
+
+ onSelectFile (files) {
+ dispatch(uploadCompose(files));
+ }
+
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(UploadButton);
diff --git a/app/assets/javascripts/components/features/compose/containers/upload_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/upload_form_container.jsx
new file mode 100644
index 000000000..a6a202e17
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/upload_form_container.jsx
@@ -0,0 +1,17 @@
+import { connect } from 'react-redux';
+import UploadForm from '../components/upload_form';
+import { undoUploadCompose } from '../../../actions/compose';
+
+const mapStateToProps = (state, props) => ({
+ media: state.getIn(['compose', 'media_attachments']),
+});
+
+const mapDispatchToProps = dispatch => ({
+
+ onRemoveFile (media_id) {
+ dispatch(undoUploadCompose(media_id));
+ }
+
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(UploadForm);
diff --git a/app/assets/javascripts/components/features/compose/index.jsx b/app/assets/javascripts/components/features/compose/index.jsx
index 260f67034..a50118bef 100644
--- a/app/assets/javascripts/components/features/compose/index.jsx
+++ b/app/assets/javascripts/components/features/compose/index.jsx
@@ -1,8 +1,7 @@
-import Drawer from '../ui/components/drawer';
-import ComposeFormContainer from '../ui/containers/compose_form_container';
-import FollowFormContainer from '../ui/containers/follow_form_container';
-import UploadFormContainer from '../ui/containers/upload_form_container';
-import NavigationContainer from '../ui/containers/navigation_container';
+import Drawer from './components/drawer';
+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 SuggestionsContainer from './containers/suggestions_container';
import SearchContainer from './containers/search_container';
diff --git a/app/assets/javascripts/components/features/ui/components/follow_form.jsx b/app/assets/javascripts/components/features/ui/components/follow_form.jsx
deleted file mode 100644
index 4ba5dfc25..000000000
--- a/app/assets/javascripts/components/features/ui/components/follow_form.jsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import IconButton from '../../../components/icon_button';
-import PureRenderMixin from 'react-addons-pure-render-mixin';
-
-const FollowForm = React.createClass({
-
- contextTypes: {
- router: React.PropTypes.object
- },
-
- propTypes: {
- text: React.PropTypes.string.isRequired,
- is_submitting: React.PropTypes.bool,
- onChange: React.PropTypes.func.isRequired,
- onSubmit: React.PropTypes.func.isRequired
- },
-
- mixins: [PureRenderMixin],
-
- handleChange (e) {
- this.props.onChange(e.target.value);
- },
-
- handleKeyUp (e) {
- if (e.keyCode === 13) {
- this.handleSubmit();
- }
- },
-
- handleSubmit () {
- this.props.onSubmit(this.context.router);
- },
-
- render () {
- return (
-
- );
- }
-
-});
-
-export default FollowForm;
diff --git a/app/assets/javascripts/components/features/ui/components/upload_form.jsx b/app/assets/javascripts/components/features/ui/components/upload_form.jsx
deleted file mode 100644
index d584e9ab7..000000000
--- a/app/assets/javascripts/components/features/ui/components/upload_form.jsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import PureRenderMixin from 'react-addons-pure-render-mixin';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import UploadButton from './upload_button';
-import IconButton from '../../../components/icon_button';
-
-const UploadForm = React.createClass({
-
- propTypes: {
- media: ImmutablePropTypes.list.isRequired,
- is_uploading: React.PropTypes.bool,
- onSelectFile: React.PropTypes.func.isRequired,
- onRemoveFile: React.PropTypes.func.isRequired
- },
-
- mixins: [PureRenderMixin],
-
- render () {
- let uploads = this.props.media.map(function (attachment) {
- return (
-
-
- this.props.onRemoveFile(attachment.get('id'))} />
-
-
- );
- }.bind(this));
-
- const noMoreAllowed = (this.props.media.some(m => m.get('type') === 'video')) || (this.props.media.size > 3);
-
- return (
-
- );
- }
-
-});
-
-export default UploadForm;
diff --git a/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx b/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx
deleted file mode 100644
index 05cfb7c1d..000000000
--- a/app/assets/javascripts/components/features/ui/containers/follow_form_container.jsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { connect } from 'react-redux';
-import FollowForm from '../components/follow_form';
-import { changeFollow, submitFollow } from '../../../actions/follow';
-
-const mapStateToProps = function (state, props) {
- return {
- text: state.getIn(['follow', 'text']),
- is_submitting: state.getIn(['follow', 'is_submitting'])
- };
-};
-
-const mapDispatchToProps = function (dispatch) {
- return {
- onChange: function (text) {
- dispatch(changeFollow(text));
- },
-
- onSubmit: function (router) {
- dispatch(submitFollow(router));
- }
- }
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(FollowForm);
diff --git a/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx b/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx
deleted file mode 100644
index 6554f944f..000000000
--- a/app/assets/javascripts/components/features/ui/containers/upload_form_container.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { connect } from 'react-redux';
-import UploadForm from '../components/upload_form';
-import { uploadCompose, undoUploadCompose } from '../../../actions/compose';
-
-const mapStateToProps = function (state, props) {
- return {
- media: state.getIn(['compose', 'media_attachments']),
- progress: state.getIn(['compose', 'progress']),
- is_uploading: state.getIn(['compose', 'is_uploading'])
- };
-};
-
-const mapDispatchToProps = function (dispatch) {
- return {
- onSelectFile: function (files) {
- dispatch(uploadCompose(files));
- },
-
- onRemoveFile: function (media_id) {
- dispatch(undoUploadCompose(media_id));
- }
- }
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(UploadForm);
diff --git a/app/assets/javascripts/components/reducers/follow.jsx b/app/assets/javascripts/components/reducers/follow.jsx
deleted file mode 100644
index ed6e8e0ef..000000000
--- a/app/assets/javascripts/components/reducers/follow.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import {
- FOLLOW_CHANGE,
- FOLLOW_SUBMIT_REQUEST,
- FOLLOW_SUBMIT_SUCCESS,
- FOLLOW_SUBMIT_FAIL
-} from '../actions/follow';
-import Immutable from 'immutable';
-
-const initialState = Immutable.Map({
- text: '',
- is_submitting: false
-});
-
-export default function follow(state = initialState, action) {
- switch(action.type) {
- case FOLLOW_CHANGE:
- return state.set('text', action.text);
- case FOLLOW_SUBMIT_REQUEST:
- return state.set('is_submitting', true);
- case FOLLOW_SUBMIT_SUCCESS:
- return state.withMutations(map => {
- map.set('text', '').set('is_submitting', false);
- });
- case FOLLOW_SUBMIT_FAIL:
- return state.set('is_submitting', false);
- default:
- return state;
- }
-};
diff --git a/app/assets/javascripts/components/reducers/index.jsx b/app/assets/javascripts/components/reducers/index.jsx
index e2203cc1a..1e015cf74 100644
--- a/app/assets/javascripts/components/reducers/index.jsx
+++ b/app/assets/javascripts/components/reducers/index.jsx
@@ -2,7 +2,6 @@ import { combineReducers } from 'redux-immutable';
import timelines from './timelines';
import meta from './meta';
import compose from './compose';
-import follow from './follow';
import notifications from './notifications';
import { loadingBarReducer } from 'react-redux-loading-bar';
import modal from './modal';
@@ -16,7 +15,6 @@ export default combineReducers({
timelines,
meta,
compose,
- follow,
notifications,
loadingBar: loadingBarReducer,
modal,