diff --git a/app/soapbox/actions/emoji_reacts.js b/app/soapbox/actions/emoji_reacts.js
index c3e6b63f4..8ed43b8ed 100644
--- a/app/soapbox/actions/emoji_reacts.js
+++ b/app/soapbox/actions/emoji_reacts.js
@@ -2,6 +2,7 @@ import api from '../api';
import { importFetchedAccounts, importFetchedStatus } from './importer';
import { favourite, unfavourite } from './interactions';
import { isLoggedIn } from 'soapbox/utils/auth';
+import { List as ImmutableList } from 'immutable';
export const EMOJI_REACT_REQUEST = 'EMOJI_REACT_REQUEST';
export const EMOJI_REACT_SUCCESS = 'EMOJI_REACT_SUCCESS';
@@ -19,7 +20,7 @@ const noOp = () => () => new Promise(f => f());
export const simpleEmojiReact = (status, emoji) => {
return (dispatch, getState) => {
- const emojiReacts = status.getIn(['pleroma', 'emoji_reactions']);
+ const emojiReacts = status.getIn(['pleroma', 'emoji_reactions'], ImmutableList());
if (emoji === '👍' && status.get('favourited')) return dispatch(unfavourite(status));
diff --git a/app/soapbox/components/status_action_bar.js b/app/soapbox/components/status_action_bar.js
index fa4fd993e..b7ee34aae 100644
--- a/app/soapbox/components/status_action_bar.js
+++ b/app/soapbox/components/status_action_bar.js
@@ -14,6 +14,7 @@ import EmojiSelector from 'soapbox/components/emoji_selector';
import { getReactForStatus, reduceEmoji } from 'soapbox/utils/emoji_reacts';
import { simpleEmojiReact } from 'soapbox/actions/emoji_reacts';
import { List as ImmutableList } from 'immutable';
+import { getFeatures } from 'soapbox/utils/features';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
@@ -93,6 +94,7 @@ class StatusActionBar extends ImmutablePureComponent {
allowedEmoji: ImmutablePropTypes.list,
emojiSelectorFocused: PropTypes.bool,
handleEmojiSelectorUnfocus: PropTypes.func.isRequired,
+ features: PropTypes.object.isRequired,
};
static defaultProps = {
@@ -132,16 +134,26 @@ class StatusActionBar extends ImmutablePureComponent {
isMobile = () => window.matchMedia('only screen and (max-width: 895px)').matches;
handleLikeButtonHover = e => {
- if (!this.isMobile()) this.setState({ emojiSelectorVisible: true });
+ const { features } = this.props;
+
+ if (features.emojiReacts && !this.isMobile()) {
+ this.setState({ emojiSelectorVisible: true });
+ }
}
handleLikeButtonLeave = e => {
- if (!this.isMobile()) this.setState({ emojiSelectorVisible: false });
+ const { features } = this.props;
+
+ if (features.emojiReacts && !this.isMobile()) {
+ this.setState({ emojiSelectorVisible: false });
+ }
}
handleLikeButtonClick = e => {
+ const { features } = this.props;
const meEmojiReact = getReactForStatus(this.props.status, this.props.allowedEmoji) || '👍';
- if (this.isMobile()) {
+
+ if (features.emojiReacts && this.isMobile()) {
if (this.state.emojiSelectorVisible) {
this.handleReactClick(meEmojiReact)();
} else {
@@ -362,7 +374,7 @@ class StatusActionBar extends ImmutablePureComponent {
}
render() {
- const { status, intl, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorUnfocus } = this.props;
+ const { status, intl, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorUnfocus, features } = this.props;
const { emojiSelectorVisible } = this.state;
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
@@ -427,7 +439,7 @@ class StatusActionBar extends ImmutablePureComponent {
>
@@ -456,11 +468,13 @@ class StatusActionBar extends ImmutablePureComponent {
const mapStateToProps = state => {
const me = state.get('me');
const account = state.getIn(['accounts', me]);
+ const instance = state.get('instance');
return {
me,
isStaff: account ? isStaff(account) : false,
isAdmin: account ? isAdmin(account) : false,
+ features: getFeatures(instance),
};
};
diff --git a/app/soapbox/features/status/components/action_bar.js b/app/soapbox/features/status/components/action_bar.js
index b435c77a4..332108133 100644
--- a/app/soapbox/features/status/components/action_bar.js
+++ b/app/soapbox/features/status/components/action_bar.js
@@ -11,6 +11,7 @@ import { isStaff, isAdmin } from 'soapbox/utils/accounts';
import { isUserTouching } from 'soapbox/is_mobile';
import EmojiSelector from 'soapbox/components/emoji_selector';
import { getReactForStatus } from 'soapbox/utils/emoji_reacts';
+import { getFeatures } from 'soapbox/utils/features';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
@@ -54,11 +55,13 @@ const messages = defineMessages({
const mapStateToProps = state => {
const me = state.get('me');
const account = state.getIn(['accounts', me]);
+ const instance = state.get('instance');
return {
me,
isStaff: account ? isStaff(account) : false,
isAdmin: account ? isAdmin(account) : false,
+ features: getFeatures(instance),
};
};
@@ -103,6 +106,7 @@ class ActionBar extends React.PureComponent {
emojiSelectorFocused: PropTypes.bool,
handleEmojiSelectorExpand: PropTypes.func.isRequired,
handleEmojiSelectorUnfocus: PropTypes.func.isRequired,
+ features: PropTypes.object.isRequired,
};
static defaultProps = {
@@ -146,16 +150,26 @@ class ActionBar extends React.PureComponent {
}
handleLikeButtonHover = e => {
- if (!isUserTouching()) this.setState({ emojiSelectorVisible: true });
+ const { features } = this.props;
+
+ if (features.emojiReacts && !isUserTouching()) {
+ this.setState({ emojiSelectorVisible: true });
+ }
}
handleLikeButtonLeave = e => {
- if (!isUserTouching()) this.setState({ emojiSelectorVisible: false });
+ const { features } = this.props;
+
+ if (features.emojiReacts && !isUserTouching()) {
+ this.setState({ emojiSelectorVisible: false });
+ }
}
handleLikeButtonClick = e => {
+ const { features } = this.props;
const meEmojiReact = getReactForStatus(this.props.status, this.props.allowedEmoji) || '👍';
- if (isUserTouching()) {
+
+ if (features.emojiReacts && isUserTouching()) {
if (this.state.emojiSelectorVisible) {
this.handleReactClick(meEmojiReact)();
} else {
@@ -278,7 +292,7 @@ class ActionBar extends React.PureComponent {
}
render() {
- const { status, intl, me, isStaff, isAdmin, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorExpand, handleEmojiSelectorUnfocus } = this.props;
+ const { status, intl, me, isStaff, isAdmin, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorExpand, handleEmojiSelectorUnfocus, features } = this.props;
const { emojiSelectorVisible } = this.state;
const ownAccount = status.getIn(['account', 'id']) === me;
@@ -391,7 +405,7 @@ class ActionBar extends React.PureComponent {
>
diff --git a/app/soapbox/features/ui/components/tabs_bar.js b/app/soapbox/features/ui/components/tabs_bar.js
index fda0e19cc..9bb512057 100644
--- a/app/soapbox/features/ui/components/tabs_bar.js
+++ b/app/soapbox/features/ui/components/tabs_bar.js
@@ -15,6 +15,7 @@ import Icon from '../../../components/icon';
import ThemeToggle from '../../ui/components/theme_toggle_container';
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
import { isStaff } from 'soapbox/utils/accounts';
+import { getFeatures } from 'soapbox/utils/features';
const messages = defineMessages({
post: { id: 'tabs_bar.post', defaultMessage: 'Post' },
@@ -32,6 +33,7 @@ class TabsBar extends React.PureComponent {
dashboardCount: PropTypes.number,
notificationCount: PropTypes.number,
chatsCount: PropTypes.number,
+ features: PropTypes.object.isRequired,
}
state = {
@@ -52,7 +54,7 @@ class TabsBar extends React.PureComponent {
}
getNavLinks() {
- const { intl: { formatMessage }, logo, account, dashboardCount, notificationCount, chatsCount } = this.props;
+ const { intl: { formatMessage }, logo, account, dashboardCount, notificationCount, chatsCount, features } = this.props;
const links = [];
if (logo) {
links.push(
@@ -73,7 +75,7 @@ class TabsBar extends React.PureComponent {
);
}
- if (account) {
+ if (features.chats && account) {
links.push(
@@ -155,12 +157,15 @@ const mapStateToProps = state => {
const me = state.get('me');
const reportsCount = state.getIn(['admin', 'openReports']).count();
const approvalCount = state.getIn(['admin', 'awaitingApproval']).count();
+ const instance = state.get('instance');
+
return {
account: state.getIn(['accounts', me]),
logo: getSoapboxConfig(state).get('logo'),
notificationCount: state.getIn(['notifications', 'unread']),
chatsCount: state.get('chats').reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0),
dashboardCount: reportsCount + approvalCount,
+ features: getFeatures(instance),
};
};
diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js
index bc963e028..45d77a466 100644
--- a/app/soapbox/features/ui/index.js
+++ b/app/soapbox/features/ui/index.js
@@ -42,6 +42,7 @@ import Icon from 'soapbox/components/icon';
import { isStaff, isAdmin } from 'soapbox/utils/accounts';
import ProfileHoverCard from 'soapbox/components/profile_hover_card';
import { getAccessToken } from 'soapbox/utils/auth';
+import { getFeatures } from 'soapbox/utils/features';
import {
Status,
@@ -115,6 +116,7 @@ const messages = defineMessages({
const mapStateToProps = state => {
const me = state.get('me');
const account = state.getIn(['accounts', me]);
+ const instance = state.get('instance');
return {
dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null,
@@ -122,6 +124,7 @@ const mapStateToProps = state => {
streamingUrl: state.getIn(['instance', 'urls', 'streaming_api']),
me,
account,
+ features: getFeatures(instance),
};
};
@@ -302,6 +305,7 @@ class UI extends React.PureComponent {
me: SoapboxPropTypes.me,
streamingUrl: PropTypes.string,
account: PropTypes.object,
+ features: PropTypes.object.isRequired,
};
state = {
@@ -411,7 +415,7 @@ class UI extends React.PureComponent {
});
componentDidMount() {
- const { account } = this.props;
+ const { account, features } = this.props;
if (!account) return;
window.addEventListener('resize', this.handleResize, { passive: true });
@@ -432,7 +436,10 @@ class UI extends React.PureComponent {
if (account) {
this.props.dispatch(expandHomeTimeline());
this.props.dispatch(expandNotifications());
- this.props.dispatch(fetchChats());
+
+ if (features.chats) {
+ this.props.dispatch(fetchChats());
+ }
if (isStaff(account)) {
this.props.dispatch(fetchReports({ state: 'open' }));
@@ -577,7 +584,7 @@ class UI extends React.PureComponent {
}
render() {
- const { streamingUrl } = this.props;
+ const { streamingUrl, features } = this.props;
const { draggingOver, mobile } = this.state;
const { intl, children, location, dropdownMenuIsOpen, me } = this.props;
@@ -635,7 +642,7 @@ class UI extends React.PureComponent {
{me && }
- {me && !mobile && (
+ {me && features.chats && !mobile && (
{Component => }
diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js
index f89652219..9b520c78c 100644
--- a/app/soapbox/utils/features.js
+++ b/app/soapbox/utils/features.js
@@ -16,6 +16,7 @@ export const getFeatures = createSelector([
focalPoint: v.software === 'Mastodon' && gte(v.compatVersion, '2.3.0'),
importMutes: v.software === 'Pleroma' && gte(v.version, '2.2.0'),
emailList: f.includes('email_list'),
+ chats: v.software === 'Pleroma' && gte(v.version, '2.1.0'),
};
});