diff --git a/app/soapbox/actions/chats.js b/app/soapbox/actions/chats.js index e69de29bb..1f864ef80 100644 --- a/app/soapbox/actions/chats.js +++ b/app/soapbox/actions/chats.js @@ -0,0 +1,16 @@ +import api from '../api'; + +export const CHATS_FETCH_REQUEST = 'CHATS_FETCH_REQUEST'; +export const CHATS_FETCH_SUCCESS = 'CHATS_FETCH_SUCCESS'; +export const CHATS_FETCH_FAIL = 'CHATS_FETCH_FAIL'; + +export function fetchChats() { + return (dispatch, getState) => { + dispatch({ type: CHATS_FETCH_REQUEST }); + return api(getState).get('/api/v1/pleroma/chats').then(({ data }) => { + dispatch({ type: CHATS_FETCH_SUCCESS, data }); + }).catch(error => { + dispatch({ type: CHATS_FETCH_FAIL, error }); + }); + }; +} diff --git a/app/soapbox/features/chats/components/chat_list.js b/app/soapbox/features/chats/components/chat_list.js new file mode 100644 index 000000000..e2446e07f --- /dev/null +++ b/app/soapbox/features/chats/components/chat_list.js @@ -0,0 +1,44 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { injectIntl, FormattedMessage } from 'react-intl'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { fetchChats } from 'soapbox/actions/chats'; + +const mapStateToProps = state => ({ + chats: state.get('chats'), +}); + +export default @connect(mapStateToProps) +@injectIntl +class ChatList extends ImmutablePureComponent { + + static propTypes = { + dispatch: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + componentDidMount() { + this.props.dispatch(fetchChats()); + } + + render() { + const { chats } = this.props; + + return ( +
+
+ +
+
+ {chats.toList().map(chat => ( +
+ {chat.getIn(['account', 'acct'])} +
+ ))} +
+
+ ); + } + +} diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index cdac3a3d8..15b9ced5f 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -36,6 +36,7 @@ import { connectUserStream } from '../../actions/streaming'; import { Redirect } from 'react-router-dom'; import Icon from 'soapbox/components/icon'; import { isStaff } from 'soapbox/utils/accounts'; +import ChatList from 'soapbox/features/chats/components/chat_list'; import { Status, @@ -604,6 +605,7 @@ class UI extends React.PureComponent { {me && } + {me && } ); diff --git a/app/soapbox/reducers/chats.js b/app/soapbox/reducers/chats.js new file mode 100644 index 000000000..feb44c97a --- /dev/null +++ b/app/soapbox/reducers/chats.js @@ -0,0 +1,15 @@ +import { CHATS_FETCH_SUCCESS } from '../actions/chats'; +import { Map as ImmutableMap, fromJS } from 'immutable'; + +const initialState = ImmutableMap(); + +export default function admin(state = initialState, action) { + switch(action.type) { + case CHATS_FETCH_SUCCESS: + return state.merge(fromJS(action.data).reduce((acc, curr) => ( + acc.set(curr.get('id'), curr) + ), ImmutableMap())); + default: + return state; + } +}; diff --git a/app/soapbox/reducers/index.js b/app/soapbox/reducers/index.js index 7a8219522..90cd6af62 100644 --- a/app/soapbox/reducers/index.js +++ b/app/soapbox/reducers/index.js @@ -43,6 +43,7 @@ import instance from './instance'; import me from './me'; import auth from './auth'; import admin from './admin'; +import chats from './chats'; const reducers = { dropdown_menu, @@ -89,6 +90,7 @@ const reducers = { me, auth, admin, + chats, }; export default combineReducers(reducers); diff --git a/app/styles/application.scss b/app/styles/application.scss index 2b4c52a83..96eb4dcf4 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -28,6 +28,7 @@ @import 'demetricator'; @import 'pro'; @import 'overflow_hacks'; +@import 'chats'; // COMPONENTS @import 'components/buttons'; diff --git a/app/styles/chats.scss b/app/styles/chats.scss new file mode 100644 index 000000000..60d1355e2 --- /dev/null +++ b/app/styles/chats.scss @@ -0,0 +1,24 @@ +.chat-list { + position: fixed; + bottom: 0; + right: 20px; + width: 265px; + + &__header { + background: var(--brand-color); + color: #fff; + padding: 6px 10px; + font-size: 18px; + font-weight: bold; + border-radius: 6px 6px 0 0; + } + + &__content { + background: var(--foreground-color); + padding: 10px; + } + + &__actions { + background: var(--foreground-color); + } +}