Merge branch 'remove-unused' into 'develop'

Remove unused .js files, remove groups

See merge request soapbox-pub/soapbox!1862
merge-requests/1861/head^2
Alex Gleason 2022-11-04 14:38:05 +00:00
commit 645af3d1ed
28 zmienionych plików z 1 dodań i 2665 usunięć

Wyświetl plik

@ -1,143 +0,0 @@
import { isLoggedIn } from 'soapbox/utils/auth';
import api from '../api';
import type { AxiosError } from 'axios';
import type { History } from 'history';
import type { AppDispatch, RootState } from 'soapbox/store';
import type { APIEntity } from 'soapbox/types/entities';
const GROUP_CREATE_REQUEST = 'GROUP_CREATE_REQUEST';
const GROUP_CREATE_SUCCESS = 'GROUP_CREATE_SUCCESS';
const GROUP_CREATE_FAIL = 'GROUP_CREATE_FAIL';
const GROUP_UPDATE_REQUEST = 'GROUP_UPDATE_REQUEST';
const GROUP_UPDATE_SUCCESS = 'GROUP_UPDATE_SUCCESS';
const GROUP_UPDATE_FAIL = 'GROUP_UPDATE_FAIL';
const GROUP_EDITOR_VALUE_CHANGE = 'GROUP_EDITOR_VALUE_CHANGE';
const GROUP_EDITOR_RESET = 'GROUP_EDITOR_RESET';
const GROUP_EDITOR_SETUP = 'GROUP_EDITOR_SETUP';
const submit = (routerHistory: History) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const groupId = getState().group_editor.get('groupId') as string;
const title = getState().group_editor.get('title') as string;
const description = getState().group_editor.get('description') as string;
const coverImage = getState().group_editor.get('coverImage') as any;
if (groupId === null) {
dispatch(create(title, description, coverImage, routerHistory));
} else {
dispatch(update(groupId, title, description, coverImage, routerHistory));
}
};
const create = (title: string, description: string, coverImage: File, routerHistory: History) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(createRequest());
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
if (coverImage !== null) {
formData.append('cover_image', coverImage);
}
api(getState).post('/api/v1/groups', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(({ data }) => {
dispatch(createSuccess(data));
routerHistory.push(`/groups/${data.id}`);
}).catch(err => dispatch(createFail(err)));
};
const createRequest = (id?: string) => ({
type: GROUP_CREATE_REQUEST,
id,
});
const createSuccess = (group: APIEntity) => ({
type: GROUP_CREATE_SUCCESS,
group,
});
const createFail = (error: AxiosError) => ({
type: GROUP_CREATE_FAIL,
error,
});
const update = (groupId: string, title: string, description: string, coverImage: File, routerHistory: History) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(updateRequest(groupId));
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
if (coverImage !== null) {
formData.append('cover_image', coverImage);
}
api(getState).put(`/api/v1/groups/${groupId}`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(({ data }) => {
dispatch(updateSuccess(data));
routerHistory.push(`/groups/${data.id}`);
}).catch(err => dispatch(updateFail(err)));
};
const updateRequest = (id: string) => ({
type: GROUP_UPDATE_REQUEST,
id,
});
const updateSuccess = (group: APIEntity) => ({
type: GROUP_UPDATE_SUCCESS,
group,
});
const updateFail = (error: AxiosError) => ({
type: GROUP_UPDATE_FAIL,
error,
});
const changeValue = (field: string, value: string | File) => ({
type: GROUP_EDITOR_VALUE_CHANGE,
field,
value,
});
const reset = () => ({
type: GROUP_EDITOR_RESET,
});
const setUp = (group: string) => ({
type: GROUP_EDITOR_SETUP,
group,
});
export {
GROUP_CREATE_REQUEST,
GROUP_CREATE_SUCCESS,
GROUP_CREATE_FAIL,
GROUP_UPDATE_REQUEST,
GROUP_UPDATE_SUCCESS,
GROUP_UPDATE_FAIL,
GROUP_EDITOR_VALUE_CHANGE,
GROUP_EDITOR_RESET,
GROUP_EDITOR_SETUP,
submit,
create,
createRequest,
createSuccess,
createFail,
update,
updateRequest,
updateSuccess,
updateFail,
changeValue,
reset,
setUp,
};

Wyświetl plik

@ -1,550 +0,0 @@
import { AxiosError } from 'axios';
import { isLoggedIn } from 'soapbox/utils/auth';
import api, { getLinks } from '../api';
import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from './importer';
import type { AppDispatch, RootState } from 'soapbox/store';
import type { APIEntity } from 'soapbox/types/entities';
const GROUP_FETCH_REQUEST = 'GROUP_FETCH_REQUEST';
const GROUP_FETCH_SUCCESS = 'GROUP_FETCH_SUCCESS';
const GROUP_FETCH_FAIL = 'GROUP_FETCH_FAIL';
const GROUP_RELATIONSHIPS_FETCH_REQUEST = 'GROUP_RELATIONSHIPS_FETCH_REQUEST';
const GROUP_RELATIONSHIPS_FETCH_SUCCESS = 'GROUP_RELATIONSHIPS_FETCH_SUCCESS';
const GROUP_RELATIONSHIPS_FETCH_FAIL = 'GROUP_RELATIONSHIPS_FETCH_FAIL';
const GROUPS_FETCH_REQUEST = 'GROUPS_FETCH_REQUEST';
const GROUPS_FETCH_SUCCESS = 'GROUPS_FETCH_SUCCESS';
const GROUPS_FETCH_FAIL = 'GROUPS_FETCH_FAIL';
const GROUP_JOIN_REQUEST = 'GROUP_JOIN_REQUEST';
const GROUP_JOIN_SUCCESS = 'GROUP_JOIN_SUCCESS';
const GROUP_JOIN_FAIL = 'GROUP_JOIN_FAIL';
const GROUP_LEAVE_REQUEST = 'GROUP_LEAVE_REQUEST';
const GROUP_LEAVE_SUCCESS = 'GROUP_LEAVE_SUCCESS';
const GROUP_LEAVE_FAIL = 'GROUP_LEAVE_FAIL';
const GROUP_MEMBERS_FETCH_REQUEST = 'GROUP_MEMBERS_FETCH_REQUEST';
const GROUP_MEMBERS_FETCH_SUCCESS = 'GROUP_MEMBERS_FETCH_SUCCESS';
const GROUP_MEMBERS_FETCH_FAIL = 'GROUP_MEMBERS_FETCH_FAIL';
const GROUP_MEMBERS_EXPAND_REQUEST = 'GROUP_MEMBERS_EXPAND_REQUEST';
const GROUP_MEMBERS_EXPAND_SUCCESS = 'GROUP_MEMBERS_EXPAND_SUCCESS';
const GROUP_MEMBERS_EXPAND_FAIL = 'GROUP_MEMBERS_EXPAND_FAIL';
const GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST = 'GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST';
const GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS';
const GROUP_REMOVED_ACCOUNTS_FETCH_FAIL = 'GROUP_REMOVED_ACCOUNTS_FETCH_FAIL';
const GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST = 'GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST';
const GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS';
const GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL = 'GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL';
const GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST';
const GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS';
const GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL = 'GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL';
const GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST';
const GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS';
const GROUP_REMOVED_ACCOUNTS_CREATE_FAIL = 'GROUP_REMOVED_ACCOUNTS_CREATE_FAIL';
const GROUP_REMOVE_STATUS_REQUEST = 'GROUP_REMOVE_STATUS_REQUEST';
const GROUP_REMOVE_STATUS_SUCCESS = 'GROUP_REMOVE_STATUS_SUCCESS';
const GROUP_REMOVE_STATUS_FAIL = 'GROUP_REMOVE_STATUS_FAIL';
const fetchGroup = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(fetchGroupRelationships([id]));
if (getState().groups.get(id)) {
return;
}
dispatch(fetchGroupRequest(id));
api(getState).get(`/api/v1/groups/${id}`)
.then(({ data }) => dispatch(fetchGroupSuccess(data)))
.catch(err => dispatch(fetchGroupFail(id, err)));
};
const fetchGroupRequest = (id: string) => ({
type: GROUP_FETCH_REQUEST,
id,
});
const fetchGroupSuccess = (group: APIEntity) => ({
type: GROUP_FETCH_SUCCESS,
group,
});
const fetchGroupFail = (id: string, error: AxiosError) => ({
type: GROUP_FETCH_FAIL,
id,
error,
});
const fetchGroupRelationships = (groupIds: string[]) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
const loadedRelationships = getState().group_relationships;
const newGroupIds = groupIds.filter(id => loadedRelationships.get(id, null) === null);
if (newGroupIds.length === 0) {
return;
}
dispatch(fetchGroupRelationshipsRequest(newGroupIds));
api(getState).get(`/api/v1/groups/${newGroupIds[0]}/relationships?${newGroupIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
dispatch(fetchGroupRelationshipsSuccess(response.data));
}).catch(error => {
dispatch(fetchGroupRelationshipsFail(error));
});
};
const fetchGroupRelationshipsRequest = (ids: string[]) => ({
type: GROUP_RELATIONSHIPS_FETCH_REQUEST,
ids,
skipLoading: true,
});
const fetchGroupRelationshipsSuccess = (relationships: APIEntity[]) => ({
type: GROUP_RELATIONSHIPS_FETCH_SUCCESS,
relationships,
skipLoading: true,
});
const fetchGroupRelationshipsFail = (error: AxiosError) => ({
type: GROUP_RELATIONSHIPS_FETCH_FAIL,
error,
skipLoading: true,
});
const fetchGroups = (tab: string) => (dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(fetchGroupsRequest());
api(getState).get('/api/v1/groups?tab=' + tab)
.then(({ data }) => {
dispatch(fetchGroupsSuccess(data, tab));
dispatch(fetchGroupRelationships(data.map((item: APIEntity) => item.id)));
})
.catch(err => dispatch(fetchGroupsFail(err)));
};
const fetchGroupsRequest = () => ({
type: GROUPS_FETCH_REQUEST,
});
const fetchGroupsSuccess = (groups: APIEntity[], tab: string) => ({
type: GROUPS_FETCH_SUCCESS,
groups,
tab,
});
const fetchGroupsFail = (error: AxiosError) => ({
type: GROUPS_FETCH_FAIL,
error,
});
const joinGroup = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(joinGroupRequest(id));
api(getState).post(`/api/v1/groups/${id}/accounts`).then(response => {
dispatch(joinGroupSuccess(response.data));
}).catch(error => {
dispatch(joinGroupFail(id, error));
});
};
const leaveGroup = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(leaveGroupRequest(id));
api(getState).delete(`/api/v1/groups/${id}/accounts`).then(response => {
dispatch(leaveGroupSuccess(response.data));
}).catch(error => {
dispatch(leaveGroupFail(id, error));
});
};
const joinGroupRequest = (id: string) => ({
type: GROUP_JOIN_REQUEST,
id,
});
const joinGroupSuccess = (relationship: APIEntity) => ({
type: GROUP_JOIN_SUCCESS,
relationship,
});
const joinGroupFail = (id: string, error: AxiosError) => ({
type: GROUP_JOIN_FAIL,
id,
error,
});
const leaveGroupRequest = (id: string) => ({
type: GROUP_LEAVE_REQUEST,
id,
});
const leaveGroupSuccess = (relationship: APIEntity) => ({
type: GROUP_LEAVE_SUCCESS,
relationship,
});
const leaveGroupFail = (id: string, error: AxiosError) => ({
type: GROUP_LEAVE_FAIL,
id,
error,
});
const fetchMembers = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(fetchMembersRequest(id));
api(getState).get(`/api/v1/groups/${id}/accounts`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data));
dispatch(fetchMembersSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
}).catch(error => {
dispatch(fetchMembersFail(id, error));
});
};
const fetchMembersRequest = (id: string) => ({
type: GROUP_MEMBERS_FETCH_REQUEST,
id,
});
const fetchMembersSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
type: GROUP_MEMBERS_FETCH_SUCCESS,
id,
accounts,
next,
});
const fetchMembersFail = (id: string, error: AxiosError) => ({
type: GROUP_MEMBERS_FETCH_FAIL,
id,
error,
});
const expandMembers = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
const url = getState().user_lists.groups.get(id)!.next;
if (url === null) {
return;
}
dispatch(expandMembersRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data));
dispatch(expandMembersSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
}).catch(error => {
dispatch(expandMembersFail(id, error));
});
};
const expandMembersRequest = (id: string) => ({
type: GROUP_MEMBERS_EXPAND_REQUEST,
id,
});
const expandMembersSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
type: GROUP_MEMBERS_EXPAND_SUCCESS,
id,
accounts,
next,
});
const expandMembersFail = (id: string, error: AxiosError) => ({
type: GROUP_MEMBERS_EXPAND_FAIL,
id,
error,
});
const fetchRemovedAccounts = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(fetchRemovedAccountsRequest(id));
api(getState).get(`/api/v1/groups/${id}/removed_accounts`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data));
dispatch(fetchRemovedAccountsSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
}).catch(error => {
dispatch(fetchRemovedAccountsFail(id, error));
});
};
const fetchRemovedAccountsRequest = (id: string) => ({
type: GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST,
id,
});
const fetchRemovedAccountsSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
type: GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS,
id,
accounts,
next,
});
const fetchRemovedAccountsFail = (id: string, error: AxiosError) => ({
type: GROUP_REMOVED_ACCOUNTS_FETCH_FAIL,
id,
error,
});
const expandRemovedAccounts = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
const url = getState().user_lists.groups_removed_accounts.get(id)!.next;
if (url === null) {
return;
}
dispatch(expandRemovedAccountsRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(importFetchedAccounts(response.data));
dispatch(expandRemovedAccountsSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
}).catch(error => {
dispatch(expandRemovedAccountsFail(id, error));
});
};
const expandRemovedAccountsRequest = (id: string) => ({
type: GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST,
id,
});
const expandRemovedAccountsSuccess = (id: string, accounts: APIEntity[], next: string | null) => ({
type: GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS,
id,
accounts,
next,
});
const expandRemovedAccountsFail = (id: string, error: AxiosError) => ({
type: GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL,
id,
error,
});
const removeRemovedAccount = (groupId: string, id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(removeRemovedAccountRequest(groupId, id));
api(getState).delete(`/api/v1/groups/${groupId}/removed_accounts?account_id=${id}`).then(response => {
dispatch(removeRemovedAccountSuccess(groupId, id));
}).catch(error => {
dispatch(removeRemovedAccountFail(groupId, id, error));
});
};
const removeRemovedAccountRequest = (groupId: string, id: string) => ({
type: GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST,
groupId,
id,
});
const removeRemovedAccountSuccess = (groupId: string, id: string) => ({
type: GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS,
groupId,
id,
});
const removeRemovedAccountFail = (groupId: string, id: string, error: AxiosError) => ({
type: GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL,
groupId,
id,
error,
});
const createRemovedAccount = (groupId: string, id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(createRemovedAccountRequest(groupId, id));
api(getState).post(`/api/v1/groups/${groupId}/removed_accounts?account_id=${id}`).then(response => {
dispatch(createRemovedAccountSuccess(groupId, id));
}).catch(error => {
dispatch(createRemovedAccountFail(groupId, id, error));
});
};
const createRemovedAccountRequest = (groupId: string, id: string) => ({
type: GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST,
groupId,
id,
});
const createRemovedAccountSuccess = (groupId: string, id: string) => ({
type: GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
groupId,
id,
});
const createRemovedAccountFail = (groupId: string, id: string, error: AxiosError) => ({
type: GROUP_REMOVED_ACCOUNTS_CREATE_FAIL,
groupId,
id,
error,
});
const groupRemoveStatus = (groupId: string, id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
dispatch(groupRemoveStatusRequest(groupId, id));
api(getState).delete(`/api/v1/groups/${groupId}/statuses/${id}`).then(response => {
dispatch(groupRemoveStatusSuccess(groupId, id));
}).catch(error => {
dispatch(groupRemoveStatusFail(groupId, id, error));
});
};
const groupRemoveStatusRequest = (groupId: string, id: string) => ({
type: GROUP_REMOVE_STATUS_REQUEST,
groupId,
id,
});
const groupRemoveStatusSuccess = (groupId: string, id: string) => ({
type: GROUP_REMOVE_STATUS_SUCCESS,
groupId,
id,
});
const groupRemoveStatusFail = (groupId: string, id: string, error: AxiosError) => ({
type: GROUP_REMOVE_STATUS_FAIL,
groupId,
id,
error,
});
export {
GROUP_FETCH_REQUEST,
GROUP_FETCH_SUCCESS,
GROUP_FETCH_FAIL,
GROUP_RELATIONSHIPS_FETCH_REQUEST,
GROUP_RELATIONSHIPS_FETCH_SUCCESS,
GROUP_RELATIONSHIPS_FETCH_FAIL,
GROUPS_FETCH_REQUEST,
GROUPS_FETCH_SUCCESS,
GROUPS_FETCH_FAIL,
GROUP_JOIN_REQUEST,
GROUP_JOIN_SUCCESS,
GROUP_JOIN_FAIL,
GROUP_LEAVE_REQUEST,
GROUP_LEAVE_SUCCESS,
GROUP_LEAVE_FAIL,
GROUP_MEMBERS_FETCH_REQUEST,
GROUP_MEMBERS_FETCH_SUCCESS,
GROUP_MEMBERS_FETCH_FAIL,
GROUP_MEMBERS_EXPAND_REQUEST,
GROUP_MEMBERS_EXPAND_SUCCESS,
GROUP_MEMBERS_EXPAND_FAIL,
GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST,
GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS,
GROUP_REMOVED_ACCOUNTS_FETCH_FAIL,
GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST,
GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS,
GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL,
GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST,
GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS,
GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL,
GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST,
GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS,
GROUP_REMOVED_ACCOUNTS_CREATE_FAIL,
GROUP_REMOVE_STATUS_REQUEST,
GROUP_REMOVE_STATUS_SUCCESS,
GROUP_REMOVE_STATUS_FAIL,
fetchGroup,
fetchGroupRequest,
fetchGroupSuccess,
fetchGroupFail,
fetchGroupRelationships,
fetchGroupRelationshipsRequest,
fetchGroupRelationshipsSuccess,
fetchGroupRelationshipsFail,
fetchGroups,
fetchGroupsRequest,
fetchGroupsSuccess,
fetchGroupsFail,
joinGroup,
leaveGroup,
joinGroupRequest,
joinGroupSuccess,
joinGroupFail,
leaveGroupRequest,
leaveGroupSuccess,
leaveGroupFail,
fetchMembers,
fetchMembersRequest,
fetchMembersSuccess,
fetchMembersFail,
expandMembers,
expandMembersRequest,
expandMembersSuccess,
expandMembersFail,
fetchRemovedAccounts,
fetchRemovedAccountsRequest,
fetchRemovedAccountsSuccess,
fetchRemovedAccountsFail,
expandRemovedAccounts,
expandRemovedAccountsRequest,
expandRemovedAccountsSuccess,
expandRemovedAccountsFail,
removeRemovedAccount,
removeRemovedAccountRequest,
removeRemovedAccountSuccess,
removeRemovedAccountFail,
createRemovedAccount,
createRemovedAccountRequest,
createRemovedAccountSuccess,
createRemovedAccountFail,
groupRemoveStatus,
groupRemoveStatusRequest,
groupRemoveStatusSuccess,
groupRemoveStatusFail,
};

Wyświetl plik

@ -1,89 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import StillImage from 'soapbox/components/still_image';
export default class AvatarComposite extends React.PureComponent {
static propTypes = {
accounts: ImmutablePropTypes.list.isRequired,
size: PropTypes.number.isRequired,
};
renderItem(account, size, index) {
let width = 50;
let height = 100;
let top = 'auto';
let left = 'auto';
let bottom = 'auto';
let right = 'auto';
if (size === 1) {
width = 100;
}
if (size === 4 || (size === 3 && index > 0)) {
height = 50;
}
if (size === 2) {
if (index === 0) {
right = '2px';
} else {
left = '2px';
}
} else if (size === 3) {
if (index === 0) {
right = '2px';
} else if (index > 0) {
left = '2px';
}
if (index === 1) {
bottom = '2px';
} else if (index > 1) {
top = '2px';
}
} else if (size === 4) {
if (index === 0 || index === 2) {
right = '2px';
}
if (index === 1 || index === 3) {
left = '2px';
}
if (index < 2) {
bottom = '2px';
} else {
top = '2px';
}
}
const style = {
left: left,
top: top,
right: right,
bottom: bottom,
width: `${width}%`,
height: `${height}%`,
};
return (
<StillImage key={account.get('id')} src={account.get('avatar')} style={style} />
);
}
render() {
const { accounts, size } = this.props;
return (
<div className='account__avatar-composite' style={{ width: `${size}px`, height: `${size}px` }}>
{accounts.take(4).map((account, i) => this.renderItem(account, accounts.size, i))}
</div>
);
}
}

Wyświetl plik

@ -1,155 +0,0 @@
import classNames from 'clsx';
import debounce from 'lodash/debounce';
import PropTypes from 'prop-types';
import React from 'react';
import { withRouter } from 'react-router-dom';
export default @withRouter
class FilterBar extends React.PureComponent {
static propTypes = {
items: PropTypes.array.isRequired,
active: PropTypes.string,
className: PropTypes.string,
history: PropTypes.object,
};
state = {
mounted: false,
};
componentDidMount() {
this.node.addEventListener('keydown', this.handleKeyDown, false);
window.addEventListener('resize', this.handleResize, { passive: true });
const { left, width } = this.getActiveTabIndicationSize();
this.setState({ mounted: true, left, width });
}
componentWillUnmount() {
this.node.removeEventListener('keydown', this.handleKeyDown, false);
document.removeEventListener('resize', this.handleResize, false);
}
handleResize = debounce(() => {
this.setState(this.getActiveTabIndicationSize());
}, 300, {
trailing: true,
});
componentDidUpdate(prevProps) {
if (this.props.active !== prevProps.active) {
this.setState(this.getActiveTabIndicationSize());
}
}
setRef = c => {
this.node = c;
}
setFocusRef = c => {
this.focusedItem = c;
}
handleKeyDown = e => {
const items = Array.from(this.node.getElementsByTagName('a'));
const index = items.indexOf(document.activeElement);
let element = null;
switch (e.key) {
case 'ArrowRight':
element = items[index + 1] || items[0];
break;
case 'ArrowLeft':
element = items[index - 1] || items[items.length - 1];
break;
}
if (element) {
element.focus();
e.preventDefault();
e.stopPropagation();
}
}
handleItemKeyPress = e => {
if (e.key === 'Enter' || e.key === ' ') {
this.handleClick(e);
}
}
handleClick = e => {
const i = Number(e.currentTarget.getAttribute('data-index'));
const { action, to } = this.props.items[i];
if (typeof action === 'function') {
e.preventDefault();
action(e);
} else if (to) {
e.preventDefault();
this.props.history.push(to);
}
}
getActiveTabIndicationSize() {
const { active, items } = this.props;
if (!active || !this.node) return { width: null };
const index = items.findIndex(({ name }) => name === active);
const elements = Array.from(this.node.getElementsByTagName('a'));
const element = elements[index];
if (!element) return { width: null };
const left = element.offsetLeft;
const { width } = element.getBoundingClientRect();
return { left, width };
}
renderActiveTabIndicator() {
const { left, width } = this.state;
return (
<div className='filter-bar__active' style={{ left, width }} />
);
}
renderItem(option, i) {
if (option === null) {
return <li key={`sep-${i}`} className='dropdown-menu__separator' />;
}
const { name, text, href, to, title } = option;
return (
<a
key={name}
href={href || to || '#'}
role='button'
tabIndex='0'
ref={i === 0 ? this.setFocusRef : null}
onClick={this.handleClick}
onKeyPress={this.handleItemKeyPress}
data-index={i}
title={title}
>
{text}
</a>
);
}
render() {
const { className, items } = this.props;
const { mounted } = this.state;
return (
<div className={classNames('filter-bar', className)} ref={this.setRef}>
{mounted && this.renderActiveTabIndicator()}
{items.map((option, i) => this.renderItem(option, i))}
</div>
);
}
}

Wyświetl plik

@ -1,34 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
export default class SettingText extends React.PureComponent {
static propTypes = {
settings: ImmutablePropTypes.map.isRequired,
settingKey: PropTypes.array.isRequired,
label: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
};
handleChange = (e) => {
this.props.onChange(this.props.settingKey, e.target.value);
}
render() {
const { settings, settingKey, label } = this.props;
return (
<label>
<span style={{ display: 'none' }}>{label}</span>
<input
className='setting-text'
value={settings.getIn(settingKey)}
onChange={this.handleChange}
placeholder={label}
/>
</label>
);
}
}

Wyświetl plik

@ -1,55 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
import IconButton from 'soapbox/components/icon_button';
import SettingToggle from '../../notifications/components/setting_toggle';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
});
export default @injectIntl
class ColumnSettings extends React.PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};
render() {
const { intl, settings, onChange, onClose } = this.props;
return (
<div className='column-settings'>
<div className='column-settings__header'>
<h1 className='column-settings__title'>
<FormattedMessage id='home.column_settings.title' defaultMessage='Home settings' />
</h1>
<div className='column-settings__close'>
<IconButton title={intl.formatMessage(messages.close)} src={require('@tabler/icons/x.svg')} onClick={onClose} />
</div>
</div>
<div className='column-settings__content'>
<div className='column-settings__row'>
<SettingToggle prefix='home_timeline' settings={settings} settingPath={['shows', 'reblog']} onChange={onChange} label={<FormattedMessage id='home.column_settings.show_reblogs' defaultMessage='Show reposts' />} />
</div>
<div className='column-settings__row'>
<SettingToggle prefix='home_timeline' settings={settings} settingPath={['shows', 'reply']} onChange={onChange} label={<FormattedMessage id='home.column_settings.show_replies' defaultMessage='Show replies' />} />
</div>
<div className='column-settings__row'>
<SettingToggle prefix='home_timeline' settings={settings} settingPath={['shows', 'direct']} onChange={onChange} label={<FormattedMessage id='home.column_settings.show_direct' defaultMessage='Show direct messages' />} />
</div>
</div>
</div>
);
}
}

Wyświetl plik

@ -1,26 +0,0 @@
import { connect } from 'react-redux';
import {
getSettings,
changeSetting,
saveSettings,
} from '../../../actions/settings';
import ColumnSettings from '../components/column_settings';
const mapStateToProps = state => ({
settings: getSettings(state).get('home'),
});
const mapDispatchToProps = dispatch => ({
onChange(key, checked) {
dispatch(changeSetting(['home', ...key], checked));
},
onSave() {
dispatch(saveSettings());
},
});
export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings);

Wyświetl plik

@ -1,192 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
import IconButton from 'soapbox/components/icon_button';
import ClearColumnButton from './clear_column_button';
import MultiSettingToggle from './multi_setting_toggle';
import SettingToggle from './setting_toggle';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
});
export default @injectIntl
class ColumnSettings extends React.PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired,
pushSettings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onClear: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
supportsEmojiReacts: PropTypes.bool,
supportsBirthdays: PropTypes.bool,
};
onPushChange = (path, checked) => {
this.props.onChange(['push', ...path], checked);
}
onAllSoundsChange = (path, checked) => {
const soundSettings = [['sounds', 'follow'], ['sounds', 'favourite'], ['sounds', 'pleroma:emoji_reaction'], ['sounds', 'mention'], ['sounds', 'reblog'], ['sounds', 'poll'], ['sounds', 'move']];
for (let i = 0; i < soundSettings.length; i++) {
this.props.onChange(soundSettings[i], checked);
}
}
render() {
const { intl, settings, pushSettings, onChange, onClear, onClose, supportsEmojiReacts, supportsBirthdays } = this.props;
const filterShowStr = <FormattedMessage id='notifications.column_settings.filter_bar.show' defaultMessage='Show' />;
const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />;
const alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />;
const allSoundsStr = <FormattedMessage id='notifications.column_settings.sounds.all_sounds' defaultMessage='Play sound for all notifications' />;
const showStr = <FormattedMessage id='notifications.column_settings.show' defaultMessage='Show in column' />;
const soundStr = <FormattedMessage id='notifications.column_settings.sound' defaultMessage='Play sound' />;
const soundSettings = [['sounds', 'follow'], ['sounds', 'favourite'], ['sounds', 'pleroma:emoji_reaction'], ['sounds', 'mention'], ['sounds', 'reblog'], ['sounds', 'poll'], ['sounds', 'move']];
const showPushSettings = pushSettings.get('browserSupport') && pushSettings.get('isSubscribed');
const pushStr = showPushSettings && <FormattedMessage id='notifications.column_settings.push' defaultMessage='Push notifications' />;
const birthdaysStr = <FormattedMessage id='notifications.column_settings.birthdays.show' defaultMessage='Show birthday reminders' />;
return (
<div className='column-settings'>
<div className='column-settings__header'>
<h1 className='column-settings__title'>
<FormattedMessage id='notifications.column_settings.title' defaultMessage='Notification settings' />
</h1>
<div className='column-settings__close'>
<IconButton title={intl.formatMessage(messages.close)} src={require('@tabler/icons/x.svg')} onClick={onClose} />
</div>
</div>
<div className='column-settings__content'>
<div className='column-settings__row'>
<ClearColumnButton onClick={onClear} />
</div>
<div role='group' aria-labelledby='notifications-all_sounds'>
<span id='notifications-filter-bar' className='column-settings__section'>
<FormattedMessage id='notifications.column_settings.sounds' defaultMessage='Sounds' />
</span>
<MultiSettingToggle prefix='notifications_all_sounds' settings={settings} settingPaths={soundSettings} onChange={this.onAllSoundsChange} label={allSoundsStr} />
</div>
<div role='group' aria-labelledby='notifications-filter-bar'>
<span id='notifications-filter-bar' className='column-settings__section'>
<FormattedMessage id='notifications.column_settings.filter_bar.category' defaultMessage='Quick filter bar' />
</span>
<div className='column-settings__row'>
<SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'show']} onChange={onChange} label={filterShowStr} />
<SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'advanced']} onChange={onChange} label={filterAdvancedStr} />
</div>
</div>
{supportsBirthdays &&
<div role='group' aria-labelledby='notifications-filter-bar'>
<span id='notifications-filter-bar' className='column-settings__section'>
<FormattedMessage id='notifications.column_settings.birthdays.category' defaultMessage='Birthdays' />
</span>
<div className='column-settings__row'>
<SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['birthdays', 'show']} onChange={onChange} label={birthdaysStr} />
</div>
</div>
}
<div role='group' aria-labelledby='notifications-follow'>
<span id='notifications-follow' className='column-settings__section'><FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'follow']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'follow']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow']} onChange={onChange} label={soundStr} />
</div>
</div>
<div role='group' aria-labelledby='notifications-follow-request'>
<span id='notifications-follow-request' className='column-settings__section'><FormattedMessage id='notifications.column_settings.follow_request' defaultMessage='New follow requests:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow_request']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'follow_request']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'follow_request']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow_request']} onChange={onChange} label={soundStr} />
</div>
</div>
<div role='group' aria-labelledby='notifications-favourite'>
<span id='notifications-favourite' className='column-settings__section'><FormattedMessage id='notifications.column_settings.favourite' defaultMessage='Likes:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favourite']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'favourite']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'favourite']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'favourite']} onChange={onChange} label={soundStr} />
</div>
</div>
{supportsEmojiReacts && <div role='group' aria-labelledby='notifications-emoji-react'>
<span id='notifications-favourite' className='column-settings__section'><FormattedMessage id='notifications.column_settings.emoji_react' defaultMessage='Emoji reacts:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'pleroma:emoji_reaction']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'pleroma:emoji_reaction']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'pleroma:emoji_reaction']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'pleroma:emoji_reaction']} onChange={onChange} label={soundStr} />
</div>
</div>}
<div role='group' aria-labelledby='notifications-mention'>
<span id='notifications-mention' className='column-settings__section'><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'mention']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'mention']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'mention']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'mention']} onChange={onChange} label={soundStr} />
</div>
</div>
<div role='group' aria-labelledby='notifications-reblog'>
<span id='notifications-reblog' className='column-settings__section'><FormattedMessage id='notifications.column_settings.reblog' defaultMessage='Reposts:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'reblog']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'reblog']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'reblog']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'reblog']} onChange={onChange} label={soundStr} />
</div>
</div>
<div role='group' aria-labelledby='notifications-poll'>
<span id='notifications-poll' className='column-settings__section'><FormattedMessage id='notifications.column_settings.poll' defaultMessage='Poll results:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'poll']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'poll']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'poll']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'poll']} onChange={onChange} label={soundStr} />
</div>
</div>
<div role='group' aria-labelledby='notifications-move'>
<span id='notifications-move' className='column-settings__section'><FormattedMessage id='notifications.column_settings.move' defaultMessage='Moves:' /></span>
<div className='column-settings__row'>
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'move']} onChange={onChange} label={alertStr} />
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'move']} onChange={this.onPushChange} label={pushStr} />}
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'move']} onChange={onChange} label={showStr} />
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'move']} onChange={onChange} label={soundStr} />
</div>
</div>
</div>
</div>
);
}
}

Wyświetl plik

@ -1,60 +0,0 @@
import PropTypes from 'prop-types';
import React, { Fragment } from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { defineMessages, injectIntl } from 'react-intl';
import Avatar from 'soapbox/components/avatar';
import DisplayName from 'soapbox/components/display-name';
import IconButton from 'soapbox/components/icon_button';
import Permalink from 'soapbox/components/permalink';
const messages = defineMessages({
authorize: { id: 'follow_request.authorize', defaultMessage: 'Authorize' },
reject: { id: 'follow_request.reject', defaultMessage: 'Reject' },
});
export default @injectIntl
class FollowRequest extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.record.isRequired,
onAuthorize: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
render() {
const { intl, hidden, account, onAuthorize, onReject } = this.props;
if (!account) {
return <div />;
}
if (hidden) {
return (
<Fragment>
{account.get('display_name')}
{account.get('username')}
</Fragment>
);
}
return (
<div className='account'>
<div className='account__wrapper'>
<Permalink key={account.get('id')} className='account__display-name' title={account.get('acct')} href={account.get('url')} to={`/@${account.get('acct')}`}>
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
<DisplayName account={account} />
</Permalink>
<div className='account__relationship'>
<IconButton title={intl.formatMessage(messages.authorize)} src={require('@tabler/icons/check.svg')} onClick={onAuthorize} />
<IconButton title={intl.formatMessage(messages.reject)} src={require('@tabler/icons/x.svg')} onClick={onReject} />
</div>
</div>
</div>
);
}
}

Wyświetl plik

@ -1,39 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Toggle from 'react-toggle';
export default class MultiSettingToggle extends React.PureComponent {
static propTypes = {
prefix: PropTypes.string,
settings: ImmutablePropTypes.map.isRequired,
settingPaths: PropTypes.array.isRequired,
label: PropTypes.node,
onChange: PropTypes.func.isRequired,
ariaLabel: PropTypes.string,
}
onChange = ({ target }) => {
for (let i = 0; i < this.props.settingPaths.length; i++) {
this.props.onChange(this.props.settingPaths[i], target.checked);
}
}
areTrue = (settingPath) => {
return this.props.settings.getIn(settingPath) === true;
}
render() {
const { prefix, settingPaths, label, ariaLabel } = this.props;
const id = ['setting-toggle', prefix].filter(Boolean).join('-');
return (
<div className='setting-toggle' aria-label={ariaLabel}>
<Toggle id={id} checked={settingPaths.every(this.areTrue)} onChange={this.onChange} onKeyDown={this.onKeyDown} />
{label && (<label htmlFor={id} className='setting-toggle__label'>{label}</label>)}
</div>
);
}
}

Wyświetl plik

@ -1,55 +0,0 @@
import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { openModal } from 'soapbox/actions/modals';
import { clearNotifications, setFilter } from 'soapbox/actions/notifications';
import { changeAlerts as changePushNotifications } from 'soapbox/actions/push_notifications';
import { getSettings, changeSetting } from 'soapbox/actions/settings';
import { getFeatures } from 'soapbox/utils/features';
import ColumnSettings from '../components/column_settings';
const messages = defineMessages({
clearHeading: { id: 'notifications.clear_heading', defaultMessage: 'Clear notifications' },
clearMessage: { id: 'notifications.clear_confirmation', defaultMessage: 'Are you sure you want to permanently clear all your notifications?' },
clearConfirm: { id: 'notifications.clear', defaultMessage: 'Clear notifications' },
});
const mapStateToProps = state => {
const instance = state.get('instance');
const features = getFeatures(instance);
return {
settings: getSettings(state).get('notifications'),
pushSettings: state.get('push_notifications'),
supportsEmojiReacts: features.emojiReacts,
supportsBirthdays: features.birthdays,
};
};
const mapDispatchToProps = (dispatch, { intl }) => ({
onChange(path, checked) {
if (path[0] === 'push') {
dispatch(changePushNotifications(path.slice(1), checked));
} else if (path[0] === 'quickFilter') {
dispatch(changeSetting(['notifications', ...path], checked));
dispatch(setFilter('all'));
} else {
dispatch(changeSetting(['notifications', ...path], checked));
}
},
onClear() {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/eraser.svg'),
heading: intl.formatMessage(messages.clearHeading),
message: intl.formatMessage(messages.clearMessage),
confirm: intl.formatMessage(messages.clearConfirm),
onConfirm: () => dispatch(clearNotifications()),
}));
},
});
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ColumnSettings));

Wyświetl plik

@ -1,28 +0,0 @@
import { connect } from 'react-redux';
import { authorizeFollowRequest, rejectFollowRequest } from 'soapbox/actions/accounts';
import { makeGetAccount } from 'soapbox/selectors';
import FollowRequest from '../components/follow_request';
const makeMapStateToProps = () => {
const getAccount = makeGetAccount();
const mapStateToProps = (state, props) => ({
account: getAccount(state, props.id),
});
return mapStateToProps;
};
const mapDispatchToProps = (dispatch, { id }) => ({
onAuthorize() {
dispatch(authorizeFollowRequest(id));
},
onReject() {
dispatch(rejectFollowRequest(id));
},
});
export default connect(makeMapStateToProps, mapDispatchToProps)(FollowRequest);

Wyświetl plik

@ -1,57 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { Link } from 'react-router-dom';
import Icon from 'soapbox/components/icon';
import AccountContainer from 'soapbox/containers/account_container';
export default class AccountListPanel extends ImmutablePureComponent {
static propTypes = {
title: PropTypes.node.isRequired,
accountIds: ImmutablePropTypes.orderedSet.isRequired,
icon: PropTypes.string.isRequired,
limit: PropTypes.number,
total: PropTypes.number,
expandMessage: PropTypes.string,
expandRoute: PropTypes.string,
};
static defaultProps = {
limit: Infinity,
}
render() {
const { title, icon, accountIds, limit, total, expandMessage, expandRoute, ...props } = this.props;
if (!accountIds || accountIds.isEmpty()) {
return null;
}
const canExpand = expandMessage && expandRoute && (accountIds.size < total);
return (
<div className='wtf-panel'>
<div className='wtf-panel-header'>
<Icon src={icon} className='wtf-panel-header__icon' />
<span className='wtf-panel-header__label'>
{title}
</span>
</div>
<div className='wtf-panel__content'>
<div className='wtf-panel__list'>
{accountIds.take(limit).map(accountId => (
<AccountContainer key={accountId} id={accountId} {...props} />
))}
</div>
</div>
{canExpand && <Link className='wtf-panel__expand-btn' to={expandRoute}>
{expandMessage}
</Link>}
</div>
);
}
}

Wyświetl plik

@ -1,16 +0,0 @@
import { Map as ImmutableMap } from 'immutable';
import reducer from '../group_editor';
describe('group_editor reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {} as any)).toEqual(ImmutableMap({
groupId: null,
isSubmitting: false,
isChanged: false,
title: '',
description: '',
coverImage: null,
}));
});
});

Wyświetl plik

@ -1,13 +0,0 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import reducer from '../group_lists';
describe('group_lists reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {} as any)).toEqual(ImmutableMap({
featured: ImmutableList(),
member: ImmutableList(),
admin: ImmutableList(),
}));
});
});

Wyświetl plik

@ -1,9 +0,0 @@
import { Map as ImmutableMap } from 'immutable';
import reducer from '../group_relationships';
describe('group_relationships reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {} as any)).toEqual(ImmutableMap());
});
});

Wyświetl plik

@ -1,9 +0,0 @@
import { Map as ImmutableMap } from 'immutable';
import reducer from '../groups';
describe('groups reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {} as any)).toEqual(ImmutableMap());
});
});

Wyświetl plik

@ -1,153 +0,0 @@
import { Map as ImmutableMap, List as ImmutableList, Record as ImmutableRecord } from 'immutable';
import * as actions from 'soapbox/actions/lists';
import reducer from '../list_editor';
describe('list_editor reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {})).toMatchObject({
listId: null,
isSubmitting: false,
isChanged: false,
title: '',
accounts: {
items: ImmutableList(),
loaded: false,
isLoading: false,
},
suggestions: {
value: '',
items: ImmutableList(),
},
});
});
it('should handle LIST_EDITOR_RESET', () => {
const state = ImmutableRecord({
listId: null,
isSubmitting: false,
isChanged: false,
title: '',
accounts: ImmutableRecord({
items: ImmutableList(),
loaded: false,
isLoading: false,
})(),
suggestions: ImmutableRecord({
value: '',
items: ImmutableList(),
})(),
})();
const action = {
type: actions.LIST_EDITOR_RESET,
};
expect(reducer(state, action)).toMatchObject({
listId: null,
isSubmitting: false,
isChanged: false,
title: '',
accounts: {
items: ImmutableList(),
loaded: false,
isLoading: false,
},
suggestions: {
value: '',
items: ImmutableList(),
},
});
});
it('should handle LIST_EDITOR_SETUP', () => {
const state = ImmutableRecord({
listId: null,
isSubmitting: false,
isChanged: false,
title: '',
accounts: ImmutableRecord({
items: ImmutableList(),
loaded: false,
isLoading: false,
})(),
suggestions: ImmutableRecord({
value: '',
items: ImmutableList(),
})(),
})();
const action = {
type: actions.LIST_EDITOR_SETUP,
list: ImmutableMap({
id: '22',
title: 'list 1',
}),
};
expect(reducer(state, action)).toMatchObject({
listId: '22',
isSubmitting: false,
isChanged: false,
title: 'list 1',
accounts: {
items: ImmutableList(),
loaded: false,
isLoading: false,
},
suggestions: {
value: '',
items: ImmutableList(),
},
});
});
it('should handle LIST_EDITOR_TITLE_CHANGE', () => {
const state = ImmutableMap({
title: 'list 1',
isChanged: false,
});
const action = {
type: actions.LIST_EDITOR_TITLE_CHANGE,
value: 'list 1 edited',
};
expect(reducer(state, action).toJS()).toMatchObject({
isChanged: true,
title: 'list 1 edited',
});
});
it('should handle LIST_UPDATE_REQUEST', () => {
const state = ImmutableMap({
isSubmitting: false,
isChanged: true,
});
const action = {
type: actions.LIST_UPDATE_REQUEST,
};
expect(reducer(state, action).toJS()).toMatchObject({
isSubmitting: true,
isChanged: false,
});
});
it('should handle LIST_UPDATE_FAIL', () => {
const state = ImmutableMap({
isSubmitting: true,
});
const action = {
type: actions.LIST_UPDATE_FAIL,
};
expect(reducer(state, action).toJS()).toMatchObject({
isSubmitting: false,
});
});
});

Wyświetl plik

@ -1,673 +0,0 @@
import {
Map as ImmutableMap,
OrderedMap as ImmutableOrderedMap,
Record as ImmutableRecord,
} from 'immutable';
import take from 'lodash/take';
import intlMessages from 'soapbox/__fixtures__/intlMessages.json';
import notification from 'soapbox/__fixtures__/notification.json';
import notifications from 'soapbox/__fixtures__/notifications.json';
import relationship from 'soapbox/__fixtures__/relationship.json';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'soapbox/actions/accounts';
import {
MARKER_FETCH_SUCCESS,
MARKER_SAVE_REQUEST,
MARKER_SAVE_SUCCESS,
} from 'soapbox/actions/markers';
import {
NOTIFICATIONS_EXPAND_SUCCESS,
NOTIFICATIONS_EXPAND_REQUEST,
NOTIFICATIONS_EXPAND_FAIL,
NOTIFICATIONS_FILTER_SET,
NOTIFICATIONS_SCROLL_TOP,
NOTIFICATIONS_UPDATE,
NOTIFICATIONS_UPDATE_QUEUE,
NOTIFICATIONS_DEQUEUE,
NOTIFICATIONS_CLEAR,
NOTIFICATIONS_MARK_READ_REQUEST,
} from 'soapbox/actions/notifications';
import { TIMELINE_DELETE } from 'soapbox/actions/timelines';
import { applyActions } from 'soapbox/jest/test-helpers';
import reducer from '../notifications';
const initialState = reducer(undefined, {});
describe('notifications reducer', () => {
it('should return the initial state', () => {
const expected = {
items: {},
hasMore: true,
top: false,
unread: 0,
isLoading: false,
queuedNotifications: {},
totalQueuedNotificationsCount: 0,
lastRead: -1,
};
expect(ImmutableRecord.isRecord(initialState)).toBe(true);
expect(initialState.toJS()).toMatchObject(expected);
});
describe('NOTIFICATIONS_EXPAND_SUCCESS', () => {
it('imports the notifications', () => {
const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: take(notifications, 3),
next: null,
skipLoading: true,
};
const result = reducer(undefined, action);
// The items are parsed as records
expect(ImmutableOrderedMap.isOrderedMap(result.items)).toBe(true);
expect(ImmutableRecord.isRecord(result.items.get('10743'))).toBe(true);
// We can get an item
expect(result.items.get('10744').emoji).toEqual('😢');
// hasMore is set to false because `next` is null
expect(result.hasMore).toBe(false);
});
it('drops invalid notifications', () => {
const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: [
{ id: '1', type: 'mention', status: null, account: { id: '10' } },
{ id: '2', type: 'reblog', status: null, account: { id: '9' } },
{ id: '3', type: 'favourite', status: null, account: { id: '8' } },
{ id: '4', type: 'mention', status: { id: 'a' }, account: { id: '7' } },
{ id: '5', type: 'reblog', status: { id: 'b' }, account: null },
],
next: null,
skipLoading: true,
};
const result = reducer(undefined, action);
// Only '4' is valid
expect(result.items.size).toEqual(1);
expect(result.items.get('4').id).toEqual('4');
});
it('imports move notification', () => {
const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: [
require('soapbox/__fixtures__/pleroma-notification-move.json'),
],
next: null,
skipLoading: true,
};
const result = reducer(undefined, action).items.get('406814');
expect(result.account).toEqual('AFmHQ18XZ7Lco68MW8');
expect(result.target).toEqual('A5c5LK7EJTFR0u26Pg');
});
});
describe('NOTIFICATIONS_EXPAND_REQUEST', () => {
it('sets isLoading to true', () => {
const state = initialState.set('isLoading', false);
const action = { type: NOTIFICATIONS_EXPAND_REQUEST };
expect(reducer(state, action).isLoading).toBe(true);
});
});
describe('NOTIFICATIONS_EXPAND_FAIL', () => {
it('sets isLoading to false', () => {
const state = initialState.set('isLoading', true);
const action = { type: NOTIFICATIONS_EXPAND_FAIL };
expect(reducer(state, action).isLoading).toBe(false);
});
});
describe('NOTIFICATIONS_FILTER_SET', () => {
it('clears the items', () => {
const actions = [{
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: [
{ id: '1', type: 'mention', status: { id: '4' }, account: { id: '7' } },
{ id: '2', type: 'mention', status: { id: '5' }, account: { id: '8' } },
{ id: '3', type: 'mention', status: { id: '6' }, account: { id: '9' } },
],
next: null,
skipLoading: true,
}, {
type: NOTIFICATIONS_FILTER_SET,
}];
// Setup by expanding, then calling `NOTIFICATIONS_FILTER_SET`
const result = applyActions(initialState, actions, reducer);
// Setting the filter wipes notifications
expect(result.items.isEmpty()).toBe(true);
});
it('sets hasMore to true', () => {
const state = initialState.set('hasMore', false);
const action = { type: NOTIFICATIONS_FILTER_SET };
const result = reducer(state, action);
expect(result.hasMore).toBe(true);
});
});
describe('NOTIFICATIONS_SCROLL_TOP', () => {
it('resets `unread` counter to 0 when top is true (ie, scrolled to the top)', () => {
const state = initialState.set('unread', 1);
const action = { type: NOTIFICATIONS_SCROLL_TOP, top: true };
const result = reducer(state, action);
expect(result.unread).toEqual(0);
expect(result.top).toBe(true);
});
it('leaves `unread` alone when top is false (ie, not scrolled to top)', () => {
const state = initialState.set('unread', 3);
const action = { type: NOTIFICATIONS_SCROLL_TOP, top: false };
const result = reducer(state, action);
expect(result.unread).toEqual(3);
expect(result.top).toBe(false);
});
});
describe('NOTIFICATIONS_UPDATE', () => {
it('imports the notification', () => {
const action = { type: NOTIFICATIONS_UPDATE, notification };
const result = reducer(initialState, action);
expect(result.items.get('10743').type).toEqual('favourite');
});
it('imports follow_request notification', () => {
const action = {
type: NOTIFICATIONS_UPDATE,
notification: require('soapbox/__fixtures__/notification-follow_request.json'),
};
const result = reducer(initialState, action);
expect(result.items.get('87967').type).toEqual('follow_request');
});
it('increments `unread` counter when top is false', () => {
const action = { type: NOTIFICATIONS_UPDATE, notification };
const result = reducer(initialState, action);
expect(result.unread).toEqual(1);
});
});
describe('NOTIFICATIONS_UPDATE_QUEUE', () => {
it('adds the notification to the queue (and increases the counter)', () => {
const action = {
type: NOTIFICATIONS_UPDATE_QUEUE,
notification,
intlMessages,
intlLocale: 'en',
};
const result = reducer(initialState, action);
// Doesn't add it as a regular item
expect(result.items.isEmpty()).toBe(true);
// Adds it to the queued items
expect(result.queuedNotifications.size).toEqual(1);
expect(result.totalQueuedNotificationsCount).toEqual(1);
expect(result.queuedNotifications.getIn(['10743', 'notification', 'type'])).toEqual('favourite');
});
});
describe('NOTIFICATIONS_DEQUEUE', () => {
it('resets the queued counter to 0', () => {
const state = initialState.set('totalQueuedNotificationsCount', 1);
const action = { type: NOTIFICATIONS_DEQUEUE };
const result = reducer(state, action);
expect(result.totalQueuedNotificationsCount).toEqual(0);
});
});
describe('NOTIFICATIONS_EXPAND_SUCCESS', () => {
it('with non-empty items and next set true', () => {
const state = ImmutableMap({
items: ImmutableOrderedMap([
['10734', ImmutableMap({
id: '10734',
type: 'pleroma:emoji_reaction',
account: '9vMAje101ngtjlMj7w',
target: null,
created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢',
chat_message: null,
})],
]),
unread: 1,
hasMore: true,
isLoading: false,
});
const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: take(notifications, 3),
next: true,
};
const expected = ImmutableMap({
items: ImmutableOrderedMap([
['10744', ImmutableMap({
id: '10744',
type: 'pleroma:emoji_reaction',
account: '9vMAje101ngtjlMj7w',
target: null,
created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢',
chat_message: null,
total_count: null,
})],
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
total_count: null,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
total_count: null,
})],
['10734', ImmutableMap({
id: '10734',
type: 'pleroma:emoji_reaction',
account: '9vMAje101ngtjlMj7w',
target: null,
created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢',
chat_message: null,
})],
]),
unread: 1,
hasMore: true,
isLoading: false,
});
expect(reducer(state, action).toJS()).toEqual(expected.toJS());
});
it('with empty items and next set true', () => {
const state = ImmutableMap({
items: ImmutableOrderedMap(),
unread: 1,
hasMore: true,
isLoading: false,
});
const action = {
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: take(notifications, 3),
next: true,
};
const expected = ImmutableMap({
items: ImmutableOrderedMap([
['10744', ImmutableMap({
id: '10744',
type: 'pleroma:emoji_reaction',
account: '9vMAje101ngtjlMj7w',
target: null,
created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢',
chat_message: null,
total_count: null,
})],
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
total_count: null,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
total_count: null,
})],
]),
unread: 1,
hasMore: true,
isLoading: false,
});
expect(reducer(state, action).toJS()).toEqual(expected.toJS());
});
});
describe('ACCOUNT_BLOCK_SUCCESS', () => {
it('should handle', () => {
const state = ImmutableMap({
items: ImmutableOrderedMap([
['10744', ImmutableMap({
id: '10744',
type: 'pleroma:emoji_reaction',
account: '9vMAje101ngtjlMj7w',
target: null,
created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢',
chat_message: null,
})],
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
]),
});
const action = {
type: ACCOUNT_BLOCK_SUCCESS,
relationship,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap([
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
]),
}));
});
});
describe('ACCOUNT_MUTE_SUCCESS', () => {
it('should handle', () => {
const state = ImmutableMap({
items: ImmutableOrderedMap([
['10744', ImmutableMap({
id: '10744',
type: 'pleroma:emoji_reaction',
account: '9vMAje101ngtjlMj7w',
target: null,
created_at: '2020-06-10T02:54:39.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: '😢',
chat_message: null,
})],
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
]),
});
const action = {
type: ACCOUNT_MUTE_SUCCESS,
relationship: relationship,
};
expect(reducer(state, action)).toEqual(ImmutableMap({
items: ImmutableOrderedMap([
['10743', ImmutableMap({
id: '10743',
type: 'favourite',
account: '9v5c6xSEgAi3Zu1Lv6',
target: null,
created_at: '2020-06-10T02:51:05.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
['10741', ImmutableMap({
id: '10741',
type: 'favourite',
account: '9v5cKMOPGqPcgfcWp6',
target: null,
created_at: '2020-06-10T02:05:06.000Z',
status: '9vvNxoo5EFbbnfdXQu',
emoji: null,
chat_message: null,
})],
]),
}));
});
});
describe('NOTIFICATIONS_CLEAR', () => {
it('clears the items', () => {
const state = initialState.set('items', ImmutableOrderedMap([['1', {}], ['2', {}]]));
const action = { type: NOTIFICATIONS_CLEAR };
const result = reducer(state, action);
expect(result.items.isEmpty()).toBe(true);
});
});
describe('NOTIFICATIONS_MARK_READ_REQUEST', () => {
it('sets lastRead to the one in the action', () => {
const action = { type: NOTIFICATIONS_MARK_READ_REQUEST, lastRead: '1234' };
const result = reducer(undefined, action);
expect(result.lastRead).toEqual('1234');
});
});
describe('TIMELINE_DELETE', () => {
it('deletes notifications corresponding to the status ID', () => {
const actions = [{
type: NOTIFICATIONS_EXPAND_SUCCESS,
notifications: [
{ id: '1', type: 'mention', status: { id: '4' }, account: { id: '7' } },
{ id: '2', type: 'mention', status: { id: '5' }, account: { id: '8' } },
{ id: '3', type: 'mention', status: { id: '6' }, account: { id: '9' } },
{ id: '4', type: 'mention', status: { id: '5' }, account: { id: '7' } },
],
next: null,
skipLoading: true,
}, {
type: TIMELINE_DELETE,
id: '5',
}];
// Setup by expanding, then calling `NOTIFICATIONS_FILTER_SET`
const result = applyActions(initialState, actions, reducer);
expect(result.items.size).toEqual(2);
expect(result.items.get('5')).toBe(undefined);
});
});
describe('MARKER_FETCH_SUCCESS', () => {
it('sets lastRead', () => {
const action = {
type: MARKER_FETCH_SUCCESS,
timeline: ['notifications'],
marker: {
notifications: {
last_read_id: '1234',
},
},
};
expect(reducer(undefined, action).get('lastRead')).toEqual('1234');
});
it('updates the unread count', () => {
const action = {
type: MARKER_FETCH_SUCCESS,
timeline: ['notifications'],
marker: {
notifications: {
last_read_id: '5678',
},
},
};
const state = ImmutableMap({
items: ImmutableOrderedMap({
'9012': ImmutableMap({ id: '9012' }),
'5678': ImmutableMap({ id: '5678' }),
'1234': ImmutableMap({ id: '1234' }),
}),
unread: 3,
});
expect(reducer(state, action).get('unread')).toEqual(1);
});
});
describe('MARKER_SAVE_REQUEST', () => {
it('sets lastRead', () => {
const action = {
type: MARKER_SAVE_REQUEST,
timeline: ['notifications'],
marker: {
notifications: {
last_read_id: '1234',
},
},
};
expect(reducer(undefined, action).get('lastRead')).toEqual('1234');
});
it('updates the unread count', () => {
const action = {
type: MARKER_SAVE_REQUEST,
timeline: ['notifications'],
marker: {
notifications: {
last_read_id: '5678',
},
},
};
const state = ImmutableMap({
items: ImmutableOrderedMap({
'9012': ImmutableMap({ id: '9012' }),
'5678': ImmutableMap({ id: '5678' }),
'1234': ImmutableMap({ id: '1234' }),
}),
unread: 3,
});
expect(reducer(state, action).get('unread')).toEqual(1);
});
});
describe('MARKER_SAVE_SUCCESS', () => {
it('sets lastRead', () => {
const action = {
type: MARKER_SAVE_SUCCESS,
timeline: ['notifications'],
marker: {
notifications: {
last_read_id: '5678',
},
},
};
expect(reducer(undefined, action).get('lastRead')).toEqual('5678');
});
it('updates the unread count', () => {
const action = {
type: MARKER_SAVE_SUCCESS,
timeline: ['notifications'],
marker: {
notifications: {
last_read_id: '9012',
},
},
};
const state = ImmutableMap({
items: ImmutableOrderedMap({
'9012': ImmutableMap({ id: '9012' }),
'5678': ImmutableMap({ id: '5678' }),
'1234': ImmutableMap({ id: '1234' }),
}),
unread: 3,
});
expect(reducer(state, action).get('unread')).toEqual(0);
});
});
});

Wyświetl plik

@ -1,131 +0,0 @@
import { Map as ImmutableMap, List as ImmutableList, Record as ImmutableRecord } from 'immutable';
import {
SEARCH_CHANGE,
SEARCH_CLEAR,
SEARCH_EXPAND_SUCCESS,
} from 'soapbox/actions/search';
import reducer from '../search';
describe('search reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {}).toJS()).toEqual({
value: '',
submitted: false,
submittedValue: '',
hidden: false,
results: {
accounts: [],
statuses: [],
hashtags: [],
accountsHasMore: false,
statusesHasMore: false,
hashtagsHasMore: false,
accountsLoaded: false,
statusesLoaded: false,
hashtagsLoaded: false,
},
filter: 'accounts',
accountId: null,
});
});
describe('SEARCH_CHANGE', () => {
it('sets the value', () => {
const state = ImmutableMap({ value: 'hell' });
const action = { type: SEARCH_CHANGE, value: 'hello' };
expect(reducer(state, action).get('value')).toEqual('hello');
});
});
describe('SEARCH_CLEAR', () => {
it('resets the state', () => {
const state = ImmutableRecord({
value: 'hello world',
submitted: true,
submittedValue: 'hello world',
hidden: false,
results: ImmutableRecord({})(),
filter: 'statuses',
})();
const action = { type: SEARCH_CLEAR };
const expected = {
value: '',
submitted: false,
submittedValue: '',
hidden: false,
results: {
accounts: [],
statuses: [],
hashtags: [],
accountsHasMore: false,
statusesHasMore: false,
hashtagsHasMore: false,
accountsLoaded: false,
statusesLoaded: false,
hashtagsLoaded: false,
},
filter: 'accounts',
accountId: null,
};
expect(reducer(state, action).toJS()).toEqual(expected);
});
});
describe(SEARCH_EXPAND_SUCCESS, () => {
it('imports hashtags as maps', () => {
const state = ImmutableRecord({
value: 'artist',
submitted: true,
submittedValue: 'artist',
hidden: false,
results: ImmutableRecord({
hashtags: ImmutableList(),
hashtagsHasMore: false,
hashtagsLoaded: true,
})(),
filter: 'hashtags',
})();
const action = {
type: SEARCH_EXPAND_SUCCESS,
results: {
accounts: [],
statuses: [],
hashtags: [{
name: 'artist',
url: 'https://gleasonator.com/tags/artist',
history: [],
}],
},
searchTerm: 'artist',
searchType: 'hashtags',
};
const expected = {
value: 'artist',
submitted: true,
submittedValue: 'artist',
hidden: false,
results: {
hashtags: [
{
name: 'artist',
url: 'https://gleasonator.com/tags/artist',
history: [],
},
],
hashtagsHasMore: false,
hashtagsLoaded: true,
},
filter: 'hashtags',
};
expect(reducer(state, action).toJS()).toEqual(expected);
});
});
});

Wyświetl plik

@ -14,8 +14,6 @@ describe('user_lists reducer', () => {
blocks: { next: null, items: ImmutableOrderedSet(), isLoading: false },
mutes: { next: null, items: ImmutableOrderedSet(), isLoading: false },
directory: { next: null, items: ImmutableOrderedSet(), isLoading: true },
groups: {},
groups_removed_accounts: {},
pinned: {},
birthday_reminders: {},
familiar_followers: {},

Wyświetl plik

@ -1,58 +0,0 @@
import { Map as ImmutableMap } from 'immutable';
import {
GROUP_CREATE_REQUEST,
GROUP_CREATE_FAIL,
GROUP_CREATE_SUCCESS,
GROUP_UPDATE_REQUEST,
GROUP_UPDATE_FAIL,
GROUP_UPDATE_SUCCESS,
GROUP_EDITOR_RESET,
GROUP_EDITOR_SETUP,
GROUP_EDITOR_VALUE_CHANGE,
} from '../actions/group_editor';
const initialState = ImmutableMap({
groupId: null,
isSubmitting: false,
isChanged: false,
title: '',
description: '',
coverImage: null,
});
export default function groupEditorReducer(state = initialState, action) {
switch (action.type) {
case GROUP_EDITOR_RESET:
return initialState;
case GROUP_EDITOR_SETUP:
return state.withMutations(map => {
map.set('groupId', action.group.get('id'));
map.set('title', action.group.get('title'));
map.set('description', action.group.get('description'));
map.set('isSubmitting', false);
});
case GROUP_EDITOR_VALUE_CHANGE:
return state.withMutations(map => {
map.set(action.field, action.value);
map.set('isChanged', true);
});
case GROUP_CREATE_REQUEST:
case GROUP_UPDATE_REQUEST:
return state.withMutations(map => {
map.set('isSubmitting', true);
map.set('isChanged', false);
});
case GROUP_CREATE_FAIL:
case GROUP_UPDATE_FAIL:
return state.set('isSubmitting', false);
case GROUP_CREATE_SUCCESS:
case GROUP_UPDATE_SUCCESS:
return state.withMutations(map => {
map.set('isSubmitting', false);
map.set('groupId', action.group.id);
});
default:
return state;
}
}

Wyświetl plik

@ -1,22 +0,0 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { GROUPS_FETCH_SUCCESS } from '../actions/groups';
const initialState = ImmutableMap({
featured: ImmutableList(),
member: ImmutableList(),
admin: ImmutableList(),
});
const normalizeList = (state, type, id, groups) => {
return state.set(type, ImmutableList(groups.map(item => item.id)));
};
export default function groupLists(state = initialState, action) {
switch (action.type) {
case GROUPS_FETCH_SUCCESS:
return normalizeList(state, action.tab, action.id, action.groups);
default:
return state;
}
}

Wyświetl plik

@ -1,27 +0,0 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { GROUP_RELATIONSHIPS_FETCH_SUCCESS, GROUP_JOIN_SUCCESS, GROUP_LEAVE_SUCCESS } from '../actions/groups';
const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship));
const normalizeRelationships = (state, relationships) => {
relationships.forEach(relationship => {
state = normalizeRelationship(state, relationship);
});
return state;
};
const initialState = ImmutableMap();
export default function group_relationships(state = initialState, action) {
switch (action.type) {
case GROUP_JOIN_SUCCESS:
case GROUP_LEAVE_SUCCESS:
return normalizeRelationship(state, action.relationship);
case GROUP_RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);
default:
return state;
}
}

Wyświetl plik

@ -1,34 +0,0 @@
import { Map as ImmutableMap, fromJS } from 'immutable';
import { GROUP_UPDATE_SUCCESS } from '../actions/group_editor';
import {
GROUP_FETCH_SUCCESS,
GROUP_FETCH_FAIL,
GROUPS_FETCH_SUCCESS,
} from '../actions/groups';
const initialState = ImmutableMap();
const normalizeGroup = (state, group) => state.set(group.id, fromJS(group));
const normalizeGroups = (state, groups) => {
groups.forEach(group => {
state = normalizeGroup(state, group);
});
return state;
};
export default function groups(state = initialState, action) {
switch (action.type) {
case GROUP_FETCH_SUCCESS:
case GROUP_UPDATE_SUCCESS:
return normalizeGroup(state, action.group);
case GROUPS_FETCH_SUCCESS:
return normalizeGroups(state, action.groups);
case GROUP_FETCH_FAIL:
return state.set(action.id, false);
default:
return state;
}
}

Wyświetl plik

@ -25,10 +25,6 @@ import custom_emojis from './custom_emojis';
import domain_lists from './domain_lists';
import dropdown_menu from './dropdown_menu';
import filters from './filters';
import group_editor from './group_editor';
import group_lists from './group_lists';
import group_relationships from './group_relationships';
import groups from './groups';
import history from './history';
import instance from './instance';
import listAdder from './list_adder';
@ -95,10 +91,6 @@ const reducers = {
suggestions,
polls,
trends,
groups,
group_relationships,
group_lists,
group_editor,
sidebar,
patron,
soapbox,

Wyświetl plik

@ -12,7 +12,6 @@ import {
ACCOUNT_MUTE_SUCCESS,
ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
import { GROUP_REMOVE_STATUS_SUCCESS } from '../actions/groups';
import {
STATUS_CREATE_REQUEST,
STATUS_CREATE_SUCCESS,
@ -210,10 +209,6 @@ const filterTimelines = (state: State, relationship: APIEntity, statuses: Immuta
});
};
const removeStatusFromGroup = (state: State, groupId: string, statusId: string) => {
return state.updateIn([`group:${groupId}`, 'items'], ImmutableOrderedSet(), ids => (ids as ImmutableOrderedSet<string>).delete(statusId));
};
const timelineDequeue = (state: State, timelineId: string) => {
const top = state.getIn([timelineId, 'top']);
@ -348,8 +343,6 @@ export default function timelines(state: State = initialState, action: AnyAction
return timelineConnect(state, action.timeline);
case TIMELINE_DISCONNECT:
return timelineDisconnect(state, action.timeline);
case GROUP_REMOVE_STATUS_SUCCESS:
return removeStatusFromGroup(state, action.groupId, action.id);
case TIMELINE_REPLACE:
return state
.update('home', TimelineRecord(), timeline => timeline.withMutations(timeline => {

Wyświetl plik

@ -32,13 +32,6 @@ import {
import {
FAMILIAR_FOLLOWERS_FETCH_SUCCESS,
} from '../actions/familiar_followers';
import {
GROUP_MEMBERS_FETCH_SUCCESS,
GROUP_MEMBERS_EXPAND_SUCCESS,
GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS,
GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS,
GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS,
} from '../actions/groups';
import {
REBLOGS_FETCH_SUCCESS,
FAVOURITES_FETCH_SUCCESS,
@ -82,8 +75,6 @@ export const ReducerRecord = ImmutableRecord({
blocks: ListRecord(),
mutes: ListRecord(),
directory: ListRecord({ isLoading: true }),
groups: ImmutableMap<string, List>(),
groups_removed_accounts: ImmutableMap<string, List>(),
pinned: ImmutableMap<string, List>(),
birthday_reminders: ImmutableMap<string, List>(),
familiar_followers: ImmutableMap<string, List>(),
@ -94,7 +85,7 @@ export type List = ReturnType<typeof ListRecord>;
type Reaction = ReturnType<typeof ReactionRecord>;
type ReactionList = ReturnType<typeof ReactionListRecord>;
type Items = ImmutableOrderedSet<string>;
type NestedListPath = ['followers' | 'following' | 'reblogged_by' | 'favourited_by' | 'reactions' | 'groups' | 'groups_removed_accounts' | 'pinned' | 'birthday_reminders' | 'familiar_followers', string];
type NestedListPath = ['followers' | 'following' | 'reblogged_by' | 'favourited_by' | 'reactions' | 'pinned' | 'birthday_reminders' | 'familiar_followers', string];
type ListPath = ['follow_requests' | 'blocks' | 'mutes' | 'directory'];
const normalizeList = (state: State, path: NestedListPath | ListPath, accounts: APIEntity[], next?: string | null) => {
@ -170,16 +161,6 @@ export default function userLists(state = ReducerRecord(), action: AnyAction) {
case DIRECTORY_FETCH_FAIL:
case DIRECTORY_EXPAND_FAIL:
return state.setIn(['directory', 'isLoading'], false);
case GROUP_MEMBERS_FETCH_SUCCESS:
return normalizeList(state, ['groups', action.id], action.accounts, action.next);
case GROUP_MEMBERS_EXPAND_SUCCESS:
return appendToList(state, ['groups', action.id], action.accounts, action.next);
case GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS:
return normalizeList(state, ['groups_removed_accounts', action.id], action.accounts, action.next);
case GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS:
return appendToList(state, ['groups_removed_accounts', action.id], action.accounts, action.next);
case GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS:
return removeFromList(state, ['groups_removed_accounts', action.groupId], action.id);
case PINNED_ACCOUNTS_FETCH_SUCCESS:
return normalizeList(state, ['pinned', action.id], action.accounts, action.next);
case BIRTHDAY_REMINDERS_FETCH_SUCCESS: