kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge remote-tracking branch 'soapbox/develop' into ts
commit
ee5453c18f
|
@ -3,12 +3,13 @@ image: node:18
|
||||||
variables:
|
variables:
|
||||||
NODE_ENV: test
|
NODE_ENV: test
|
||||||
|
|
||||||
cache:
|
cache: &cache
|
||||||
key:
|
key:
|
||||||
files:
|
files:
|
||||||
- yarn.lock
|
- yarn.lock
|
||||||
paths:
|
paths:
|
||||||
- node_modules/
|
- node_modules/
|
||||||
|
policy: pull
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- deps
|
- deps
|
||||||
|
@ -21,6 +22,16 @@ deps:
|
||||||
only:
|
only:
|
||||||
changes:
|
changes:
|
||||||
- yarn.lock
|
- yarn.lock
|
||||||
|
cache:
|
||||||
|
<<: *cache
|
||||||
|
policy: push
|
||||||
|
|
||||||
|
danger:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
# https://github.com/danger/danger-js/issues/1029#issuecomment-998915436
|
||||||
|
- export CI_MERGE_REQUEST_IID=${CI_OPEN_MERGE_REQUESTS#*!}
|
||||||
|
- npx danger ci
|
||||||
|
|
||||||
lint-js:
|
lint-js:
|
||||||
stage: test
|
stage: test
|
||||||
|
|
|
@ -435,10 +435,14 @@ describe('followAccount()', () => {
|
||||||
skipLoading: true,
|
skipLoading: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
await store.dispatch(followAccount(id));
|
|
||||||
const actions = store.getActions();
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
await store.dispatch(followAccount(id));
|
||||||
|
} catch (e) {
|
||||||
|
const actions = store.getActions();
|
||||||
expect(actions).toEqual(expectedActions);
|
expect(actions).toEqual(expectedActions);
|
||||||
|
expect(e).toEqual(new Error('Network Error'));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -240,7 +240,10 @@ export function followAccount(id, options = { reblogs: true }) {
|
||||||
return api(getState)
|
return api(getState)
|
||||||
.post(`/api/v1/accounts/${id}/follow`, options)
|
.post(`/api/v1/accounts/${id}/follow`, options)
|
||||||
.then(response => dispatch(followAccountSuccess(response.data, alreadyFollowing)))
|
.then(response => dispatch(followAccountSuccess(response.data, alreadyFollowing)))
|
||||||
.catch(error => dispatch(followAccountFail(error, locked)));
|
.catch(error => {
|
||||||
|
dispatch(followAccountFail(error, locked));
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { CancelToken, isCancel } from 'axios';
|
import { CancelToken, isCancel } from 'axios';
|
||||||
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||||
import { throttle } from 'lodash';
|
import throttle from 'lodash/throttle';
|
||||||
import { defineMessages } from 'react-intl';
|
import { defineMessages } from 'react-intl';
|
||||||
|
|
||||||
import snackbar from 'soapbox/actions/snackbar';
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
import { get } from 'lodash';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import KVStore from 'soapbox/storage/kv_store';
|
import KVStore from 'soapbox/storage/kv_store';
|
||||||
import { RootState } from 'soapbox/store';
|
import { RootState } from 'soapbox/store';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { mapValues } from 'lodash';
|
import mapValues from 'lodash/mapValues';
|
||||||
|
|
||||||
import { verifyCredentials } from './auth';
|
import { verifyCredentials } from './auth';
|
||||||
import { importFetchedAccounts } from './importer';
|
import { importFetchedAccounts } from './importer';
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
* @module soapbox/build_config
|
* @module soapbox/build_config
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { trim, trimEnd } = require('lodash');
|
const trim = require('lodash/trim');
|
||||||
|
const trimEnd = require('lodash/trimEnd');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
NODE_ENV,
|
NODE_ENV,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||||
import { throttle } from 'lodash';
|
import throttle from 'lodash/throttle';
|
||||||
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
import { accountSearch } from 'soapbox/actions/accounts';
|
import { accountSearch } from 'soapbox/actions/accounts';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { throttle } from 'lodash';
|
import throttle from 'lodash/throttle';
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { useIntl, MessageDescriptor } from 'react-intl';
|
import { useIntl, MessageDescriptor } from 'react-intl';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useEffect, useRef, useMemo, useCallback } from 'react';
|
import React, { useEffect, useRef, useMemo, useCallback } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { Virtuoso, Components, VirtuosoProps, VirtuosoHandle, ListRange, IndexLocationWithAlign } from 'react-virtuoso';
|
import { Virtuoso, Components, VirtuosoProps, VirtuosoHandle, ListRange, IndexLocationWithAlign } from 'react-virtuoso';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useRef, useCallback } from 'react';
|
import React, { useRef, useCallback } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { throttle } from 'lodash';
|
import throttle from 'lodash/throttle';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { injectIntl, defineMessages } from 'react-intl';
|
import { injectIntl, defineMessages } from 'react-intl';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
@ -17,6 +17,7 @@ import StillImage from 'soapbox/components/still_image';
|
||||||
import { HStack, IconButton, Menu, MenuButton, MenuItem, MenuList, MenuLink, MenuDivider } from 'soapbox/components/ui';
|
import { HStack, IconButton, Menu, MenuButton, MenuItem, MenuList, MenuLink, MenuDivider } from 'soapbox/components/ui';
|
||||||
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
||||||
import ActionButton from 'soapbox/features/ui/components/action-button';
|
import ActionButton from 'soapbox/features/ui/components/action-button';
|
||||||
|
import SubscriptionButton from 'soapbox/features/ui/components/subscription-button';
|
||||||
import {
|
import {
|
||||||
isLocal,
|
isLocal,
|
||||||
isRemote,
|
isRemote,
|
||||||
|
@ -61,8 +62,6 @@ const messages = defineMessages({
|
||||||
promoteToModerator: { id: 'admin.users.actions.promote_to_moderator', defaultMessage: 'Promote @{name} to a moderator' },
|
promoteToModerator: { id: 'admin.users.actions.promote_to_moderator', defaultMessage: 'Promote @{name} to a moderator' },
|
||||||
demoteToModerator: { id: 'admin.users.actions.demote_to_moderator', defaultMessage: 'Demote @{name} to a moderator' },
|
demoteToModerator: { id: 'admin.users.actions.demote_to_moderator', defaultMessage: 'Demote @{name} to a moderator' },
|
||||||
demoteToUser: { id: 'admin.users.actions.demote_to_user', defaultMessage: 'Demote @{name} to a regular user' },
|
demoteToUser: { id: 'admin.users.actions.demote_to_user', defaultMessage: 'Demote @{name} to a regular user' },
|
||||||
subscribe: { id: 'account.subscribe', defaultMessage: 'Subscribe to notifications from @{name}' },
|
|
||||||
unsubscribe: { id: 'account.unsubscribe', defaultMessage: 'Unsubscribe to notifications from @{name}' },
|
|
||||||
suggestUser: { id: 'admin.users.actions.suggest_user', defaultMessage: 'Suggest @{name}' },
|
suggestUser: { id: 'admin.users.actions.suggest_user', defaultMessage: 'Suggest @{name}' },
|
||||||
unsuggestUser: { id: 'admin.users.actions.unsuggest_user', defaultMessage: 'Unsuggest @{name}' },
|
unsuggestUser: { id: 'admin.users.actions.unsuggest_user', defaultMessage: 'Unsuggest @{name}' },
|
||||||
});
|
});
|
||||||
|
@ -250,22 +249,6 @@ class Header extends ImmutablePureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (features.accountSubscriptions) {
|
|
||||||
if (account.relationship?.subscribing) {
|
|
||||||
menu.push({
|
|
||||||
text: intl.formatMessage(messages.unsubscribe, { name: account.get('username') }),
|
|
||||||
action: this.props.onSubscriptionToggle,
|
|
||||||
icon: require('@tabler/icons/icons/bell.svg'),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
menu.push({
|
|
||||||
text: intl.formatMessage(messages.subscribe, { name: account.get('username') }),
|
|
||||||
action: this.props.onSubscriptionToggle,
|
|
||||||
icon: require('@tabler/icons/icons/bell-off.svg'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (features.lists) {
|
if (features.lists) {
|
||||||
menu.push({
|
menu.push({
|
||||||
text: intl.formatMessage(messages.add_or_remove_from_list),
|
text: intl.formatMessage(messages.add_or_remove_from_list),
|
||||||
|
@ -578,11 +561,6 @@ class Header extends ImmutablePureComponent {
|
||||||
const menu = this.makeMenu();
|
const menu = this.makeMenu();
|
||||||
const header = account.get('header', '');
|
const header = account.get('header', '');
|
||||||
|
|
||||||
// NOTE: Removing Subscription element
|
|
||||||
// {features.accountSubscriptions && <div className='account__header__subscribe'>
|
|
||||||
// <SubscriptionButton account={account} />
|
|
||||||
// </div>}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='-mt-4 -mx-4'>
|
<div className='-mt-4 -mx-4'>
|
||||||
<div>
|
<div>
|
||||||
|
@ -618,6 +596,8 @@ class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
<div className='mt-6 flex justify-end w-full sm:pb-1'>
|
<div className='mt-6 flex justify-end w-full sm:pb-1'>
|
||||||
<div className='mt-10 flex flex-row space-y-0 space-x-2'>
|
<div className='mt-10 flex flex-row space-y-0 space-x-2'>
|
||||||
|
<SubscriptionButton account={account} />
|
||||||
|
|
||||||
{me && (
|
{me && (
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuButton
|
<MenuButton
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Set as ImmutableSet, OrderedSet as ImmutableOrderedSet, is } from 'immutable';
|
import { Set as ImmutableSet, OrderedSet as ImmutableOrderedSet, is } from 'immutable';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -61,7 +61,7 @@ class UserIndex extends ImmutablePureComponent {
|
||||||
nextLink: next,
|
nextLink: next,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { debounce, throttle } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useState, useRef, useCallback } from 'react';
|
import React, { useState, useRef, useCallback } from 'react';
|
||||||
import { useIntl, FormattedMessage, defineMessages } from 'react-intl';
|
import { useIntl, FormattedMessage, defineMessages } from 'react-intl';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
import { escape, throttle } from 'lodash';
|
import escape from 'lodash/escape';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { get } from 'lodash';
|
import get from 'lodash/get';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { emojiIndex } from 'emoji-mart';
|
import { emojiIndex } from 'emoji-mart';
|
||||||
import { pick } from 'lodash';
|
import pick from 'lodash/pick';
|
||||||
|
|
||||||
import { search } from '../emoji_mart_search_light';
|
import { search } from '../emoji_mart_search_light';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { isEqual } from 'lodash';
|
import isEqual from 'lodash/isEqual';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
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 ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
// import { Map as ImmutableMap } from 'immutable';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { render, screen } from '../../../../jest/test-helpers';
|
||||||
|
import { normalizeAccount, normalizeRelationship } from '../../../../normalizers';
|
||||||
|
import SubscribeButton from '../subscription-button';
|
||||||
|
|
||||||
|
let account = {
|
||||||
|
id: '1',
|
||||||
|
acct: 'justin-username',
|
||||||
|
display_name: 'Justin L',
|
||||||
|
avatar: 'test.jpg',
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('<SubscribeButton />', () => {
|
||||||
|
let store;
|
||||||
|
|
||||||
|
describe('with "accountNotifies" disabled', () => {
|
||||||
|
it('renders nothing', () => {
|
||||||
|
account = normalizeAccount({ ...account, relationship: normalizeRelationship({ following: true }) });
|
||||||
|
|
||||||
|
render(<SubscribeButton account={account} />, null, store);
|
||||||
|
expect(screen.queryAllByTestId('icon-button')).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// describe('with "accountNotifies" enabled', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// instance: normalizeInstance({
|
||||||
|
// version: '3.4.1 (compatible; TruthSocial 1.0.0)',
|
||||||
|
// software: 'TRUTHSOCIAL',
|
||||||
|
// pleroma: ImmutableMap({}),
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('when the relationship is requested', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// account = normalizeAccount({ ...account, relationship: normalizeRelationship({ requested: true }) });
|
||||||
|
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// accounts: ImmutableMap({
|
||||||
|
// '1': account,
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('renders the button', () => {
|
||||||
|
// render(<SubscribeButton account={account} />, null, store);
|
||||||
|
// expect(screen.getByTestId('icon-button')).toBeInTheDocument();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('when the user "isSubscribed"', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// account = normalizeAccount({
|
||||||
|
// ...account,
|
||||||
|
// relationship: normalizeRelationship({ requested: true, notifying: true }),
|
||||||
|
// });
|
||||||
|
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// accounts: ImmutableMap({
|
||||||
|
// '1': account,
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('renders the unsubscribe button', () => {
|
||||||
|
// render(<SubscribeButton account={account} />, null, store);
|
||||||
|
// expect(screen.getByTestId('icon-button').title).toEqual(`Unsubscribe to notifications from @${account.acct}`);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('when the user is not "isSubscribed"', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// account = normalizeAccount({
|
||||||
|
// ...account,
|
||||||
|
// relationship: normalizeRelationship({ requested: true, notifying: false }),
|
||||||
|
// });
|
||||||
|
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// accounts: ImmutableMap({
|
||||||
|
// '1': account,
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('renders the unsubscribe button', () => {
|
||||||
|
// render(<SubscribeButton account={account} />, null, store);
|
||||||
|
// expect(screen.getByTestId('icon-button').title).toEqual(`Subscribe to notifications from @${account.acct}`);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('when the user is not following the account', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// account = normalizeAccount({ ...account, relationship: normalizeRelationship({ following: false }) });
|
||||||
|
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// accounts: ImmutableMap({
|
||||||
|
// '1': account,
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('renders nothing', () => {
|
||||||
|
// render(<SubscribeButton account={account} />, null, store);
|
||||||
|
// expect(screen.queryAllByTestId('icon-button')).toHaveLength(0);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('when the user is following the account', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// account = normalizeAccount({ ...account, relationship: normalizeRelationship({ following: true }) });
|
||||||
|
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// accounts: ImmutableMap({
|
||||||
|
// '1': account,
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('renders the button', () => {
|
||||||
|
// render(<SubscribeButton account={account} />, null, store);
|
||||||
|
// expect(screen.getByTestId('icon-button')).toBeInTheDocument();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('when the user "isSubscribed"', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// account = normalizeAccount({
|
||||||
|
// ...account,
|
||||||
|
// relationship: normalizeRelationship({ requested: true, notifying: true }),
|
||||||
|
// });
|
||||||
|
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// accounts: ImmutableMap({
|
||||||
|
// '1': account,
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('renders the unsubscribe button', () => {
|
||||||
|
// render(<SubscribeButton account={account} />, null, store);
|
||||||
|
// expect(screen.getByTestId('icon-button').title).toEqual(`Unsubscribe to notifications from @${account.acct}`);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// describe('when the user is not "isSubscribed"', () => {
|
||||||
|
// beforeEach(() => {
|
||||||
|
// account = normalizeAccount({
|
||||||
|
// ...account,
|
||||||
|
// relationship: normalizeRelationship({ requested: true, notifying: false }),
|
||||||
|
// });
|
||||||
|
|
||||||
|
// store = {
|
||||||
|
// ...store,
|
||||||
|
// accounts: ImmutableMap({
|
||||||
|
// '1': account,
|
||||||
|
// }),
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('renders the unsubscribe button', () => {
|
||||||
|
// render(<SubscribeButton account={account} />, null, store);
|
||||||
|
// expect(screen.getByTestId('icon-button').title).toEqual(`Subscribe to notifications from @${account.acct}`);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,105 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import {
|
||||||
|
followAccount,
|
||||||
|
subscribeAccount,
|
||||||
|
unsubscribeAccount,
|
||||||
|
} from 'soapbox/actions/accounts';
|
||||||
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
import { IconButton } from 'soapbox/components/ui';
|
||||||
|
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
import type { Account as AccountEntity } from 'soapbox/types/entities';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
subscribe: { id: 'account.subscribe', defaultMessage: 'Subscribe to notifications from @{name}' },
|
||||||
|
unsubscribe: { id: 'account.unsubscribe', defaultMessage: 'Unsubscribe to notifications from @{name}' },
|
||||||
|
subscribeSuccess: { id: 'account.subscribe.success', defaultMessage: 'You have subscribed to this account.' },
|
||||||
|
unsubscribeSuccess: { id: 'account.unsubscribe.success', defaultMessage: 'You have unsubscribed from this account.' },
|
||||||
|
subscribeFailure: { id: 'account.subscribe.failure', defaultMessage: 'An error occurred trying to subscribed to this account.' },
|
||||||
|
unsubscribeFailure: { id: 'account.unsubscribe.failure', defaultMessage: 'An error occurred trying to unsubscribed to this account.' },
|
||||||
|
});
|
||||||
|
|
||||||
|
interface ISubscriptionButton {
|
||||||
|
account: AccountEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
const SubscriptionButton = ({ account }: ISubscriptionButton) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const features = useFeatures();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const isFollowing = account.relationship?.following;
|
||||||
|
const isRequested = account.relationship?.requested;
|
||||||
|
const isSubscribed = features.accountNotifies ?
|
||||||
|
account.relationship?.notifying :
|
||||||
|
account.relationship?.subscribing;
|
||||||
|
const title = isSubscribed ?
|
||||||
|
intl.formatMessage(messages.unsubscribe, { name: account.get('username') }) :
|
||||||
|
intl.formatMessage(messages.subscribe, { name: account.get('username') });
|
||||||
|
|
||||||
|
const onSubscribeSuccess = () =>
|
||||||
|
dispatch(snackbar.success(intl.formatMessage(messages.subscribeSuccess)));
|
||||||
|
|
||||||
|
const onSubscribeFailure = () =>
|
||||||
|
dispatch(snackbar.error(intl.formatMessage(messages.subscribeFailure)));
|
||||||
|
|
||||||
|
const onUnsubscribeSuccess = () =>
|
||||||
|
dispatch(snackbar.success(intl.formatMessage(messages.unsubscribeSuccess)));
|
||||||
|
|
||||||
|
const onUnsubscribeFailure = () =>
|
||||||
|
dispatch(snackbar.error(intl.formatMessage(messages.unsubscribeFailure)));
|
||||||
|
|
||||||
|
const onNotifyToggle = () => {
|
||||||
|
if (account.relationship?.notifying) {
|
||||||
|
dispatch(followAccount(account.get('id'), { notify: false } as any))
|
||||||
|
?.then(() => onUnsubscribeSuccess())
|
||||||
|
.catch(() => onUnsubscribeFailure());
|
||||||
|
} else {
|
||||||
|
dispatch(followAccount(account.get('id'), { notify: true } as any))
|
||||||
|
?.then(() => onSubscribeSuccess())
|
||||||
|
.catch(() => onSubscribeFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubscriptionToggle = () => {
|
||||||
|
if (account.relationship?.subscribing) {
|
||||||
|
dispatch(unsubscribeAccount(account.get('id')))
|
||||||
|
?.then(() => onUnsubscribeSuccess())
|
||||||
|
.catch(() => onUnsubscribeFailure());
|
||||||
|
} else {
|
||||||
|
dispatch(subscribeAccount(account.get('id')))
|
||||||
|
?.then(() => onSubscribeSuccess())
|
||||||
|
.catch(() => onSubscribeFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleToggle = () => {
|
||||||
|
if (features.accountNotifies) {
|
||||||
|
onNotifyToggle();
|
||||||
|
} else {
|
||||||
|
onSubscriptionToggle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!features.accountSubscriptions && !features.accountNotifies) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRequested || isFollowing) {
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
src={isSubscribed ? require('@tabler/icons/icons/bell-ringing.svg') : require('@tabler/icons/icons/bell.svg')}
|
||||||
|
onClick={handleToggle}
|
||||||
|
title={title}
|
||||||
|
className='text-primary-700 bg-primary-100 dark:!bg-slate-700 dark:!text-white hover:bg-primary-200 p-2'
|
||||||
|
iconClassName='w-5 h-5'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SubscriptionButton;
|
|
@ -1,83 +0,0 @@
|
||||||
import classNames from 'classnames';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import {
|
|
||||||
followAccount,
|
|
||||||
subscribeAccount,
|
|
||||||
unsubscribeAccount,
|
|
||||||
} from 'soapbox/actions/accounts';
|
|
||||||
import Icon from 'soapbox/components/icon';
|
|
||||||
import { Button } from 'soapbox/components/ui';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
subscribe: { id: 'account.subscribe', defaultMessage: 'Subscribe to notifications from @{name}' },
|
|
||||||
unsubscribe: { id: 'account.unsubscribe', defaultMessage: 'Unsubscribe to notifications from @{name}' },
|
|
||||||
subscribed: { id: 'account.subscribed', defaultMessage: 'Subscribed' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
const me = state.get('me');
|
|
||||||
return {
|
|
||||||
me,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
onSubscriptionToggle(account) {
|
|
||||||
if (account.relationship?.subscribing) {
|
|
||||||
dispatch(unsubscribeAccount(account.get('id')));
|
|
||||||
} else {
|
|
||||||
dispatch(subscribeAccount(account.get('id')));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onNotifyToggle(account) {
|
|
||||||
if (account.relationship?.notifying) {
|
|
||||||
dispatch(followAccount(account.get('id'), { notify: false }));
|
|
||||||
} else {
|
|
||||||
dispatch(followAccount(account.get('id'), { notify: true }));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps, mapDispatchToProps)
|
|
||||||
@injectIntl
|
|
||||||
class SubscriptionButton extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
account: ImmutablePropTypes.record,
|
|
||||||
features: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSubscriptionToggle = () => {
|
|
||||||
if (this.props.features.accountNotifies) this.props.onNotifyToggle(this.props.account);
|
|
||||||
else this.props.onSubscriptionToggle(this.props.account);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { account, intl, features } = this.props;
|
|
||||||
const subscribing = features.accountNotifies ? account.relationship?.notifying : account.relationship?.subscribing;
|
|
||||||
const following = account.relationship?.following;
|
|
||||||
const requested = account.relationship?.requested;
|
|
||||||
|
|
||||||
if (requested || following) {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
className={classNames('subscription-button', subscribing && 'button-active')}
|
|
||||||
title={intl.formatMessage(subscribing ? messages.unsubscribe : messages.subscribe, { name: account.get('username') })}
|
|
||||||
onClick={this.handleSubscriptionToggle}
|
|
||||||
>
|
|
||||||
<Icon src={subscribing ? require('@tabler/icons/icons/bell-ringing.svg') : require('@tabler/icons/icons/bell.svg')} />
|
|
||||||
{subscribing && intl.formatMessage(messages.subscribed)}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { defineMessages } from 'react-intl';
|
import { defineMessages } from 'react-intl';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { HotKeys } from 'react-hotkeys';
|
import { HotKeys } from 'react-hotkeys';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
@ -609,7 +609,12 @@ const UI: React.FC = ({ children }) => {
|
||||||
|
|
||||||
const isProfileOrStatusPage = !!matchPath(
|
const isProfileOrStatusPage = !!matchPath(
|
||||||
history.location.pathname,
|
history.location.pathname,
|
||||||
['/@:username', '/@:username/posts/:statusId'],
|
[
|
||||||
|
'/@:username',
|
||||||
|
'/@:username/posts/:statusId',
|
||||||
|
'/users/:username',
|
||||||
|
'/users/:username/statuses/:statusId',
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Require login if Guest Experience is disabled and we're not trying
|
// Require login if Guest Experience is disabled and we're not trying
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { fromJS, is } from 'immutable';
|
import { fromJS, is } from 'immutable';
|
||||||
import { throttle, debounce } from 'lodash';
|
import debounce from 'lodash/debounce';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
fromJS,
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
import { trimStart } from 'lodash';
|
import trimStart from 'lodash/trimStart';
|
||||||
|
|
||||||
import { toTailwind } from 'soapbox/utils/tailwind';
|
import { toTailwind } from 'soapbox/utils/tailwind';
|
||||||
import { generateAccent } from 'soapbox/utils/theme';
|
import { generateAccent } from 'soapbox/utils/theme';
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {
|
||||||
OrderedMap as ImmutableOrderedMap,
|
OrderedMap as ImmutableOrderedMap,
|
||||||
Record as ImmutableRecord,
|
Record as ImmutableRecord,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
import { take } from 'lodash';
|
import take from 'lodash/take';
|
||||||
|
|
||||||
import intlMessages from 'soapbox/__fixtures__/intlMessages.json';
|
import intlMessages from 'soapbox/__fixtures__/intlMessages.json';
|
||||||
import notification from 'soapbox/__fixtures__/notification.json';
|
import notification from 'soapbox/__fixtures__/notification.json';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
|
||||||
import { trim } from 'lodash';
|
import trim from 'lodash/trim';
|
||||||
|
|
||||||
import { MASTODON_PRELOAD_IMPORT } from 'soapbox/actions/preload';
|
import { MASTODON_PRELOAD_IMPORT } from 'soapbox/actions/preload';
|
||||||
import { FE_SUBDIRECTORY } from 'soapbox/build_config';
|
import { FE_SUBDIRECTORY } from 'soapbox/build_config';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||||
import { get } from 'lodash';
|
import get from 'lodash/get';
|
||||||
|
|
||||||
import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming';
|
import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming';
|
||||||
import { normalizeRelationship } from 'soapbox/normalizers/relationship';
|
import { normalizeRelationship } from 'soapbox/normalizers/relationship';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import IntlMessageFormat from 'intl-messageformat';
|
import IntlMessageFormat from 'intl-messageformat';
|
||||||
import 'intl-pluralrules';
|
import 'intl-pluralrules';
|
||||||
import { unescape } from 'lodash';
|
import unescape from 'lodash/unescape';
|
||||||
|
|
||||||
import locales from './web_push_locales';
|
import locales from './web_push_locales';
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
Set as ImmutableSet,
|
Set as ImmutableSet,
|
||||||
fromJS,
|
fromJS,
|
||||||
} from 'immutable';
|
} from 'immutable';
|
||||||
import { trimStart } from 'lodash';
|
import trimStart from 'lodash/trimStart';
|
||||||
|
|
||||||
export type Config = ImmutableMap<string, any>;
|
export type Config = ImmutableMap<string, any>;
|
||||||
export type Policy = ImmutableMap<string, any>;
|
export type Policy = ImmutableMap<string, any>;
|
||||||
|
|
|
@ -126,6 +126,7 @@ const getInstanceFeatures = (instance: Instance) => {
|
||||||
accountNotifies: any([
|
accountNotifies: any([
|
||||||
v.software === MASTODON && gte(v.compatVersion, '3.3.0'),
|
v.software === MASTODON && gte(v.compatVersion, '3.3.0'),
|
||||||
v.software === PLEROMA && gte(v.version, '2.4.50'),
|
v.software === PLEROMA && gte(v.version, '2.4.50'),
|
||||||
|
// v.software === TRUTHSOCIAL,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { danger, warn, message } from 'danger';
|
||||||
|
|
||||||
|
const docs = danger.git.fileMatch('docs/**/*.md');
|
||||||
|
const app = danger.git.fileMatch('app/**/*.(js|ts|tsx)');
|
||||||
|
const tests = danger.git.fileMatch('*/__tests__/*');
|
||||||
|
|
||||||
|
if (docs.edited) {
|
||||||
|
message('Thanks - We :heart: our [documentarians](http://www.writethedocs.org/)!');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app.modified && !tests.modified) {
|
||||||
|
warn('You have app changes without tests.');
|
||||||
|
}
|
|
@ -209,6 +209,7 @@
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-jest": "^28.1.0",
|
"babel-jest": "^28.1.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
"danger": "^11.0.7",
|
||||||
"eslint": "^7.0.0",
|
"eslint": "^7.0.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-jsdoc": "^39.2.9",
|
"eslint-plugin-jsdoc": "^39.2.9",
|
||||||
|
|
Ładowanie…
Reference in New Issue