diff --git a/src/__fixtures__/realDonaldTrump.json b/src/__fixtures__/realDonaldTrump.json
deleted file mode 100644
index c9cf20076..000000000
--- a/src/__fixtures__/realDonaldTrump.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "id": "107780257626128497",
- "username": "realDonaldTrump",
- "acct": "realDonaldTrump",
- "display_name": "Donald J. Trump",
- "locked": false,
- "bot": false,
- "discoverable": null,
- "group": false,
- "created_at": "2022-02-11T00:00:00.000Z",
- "note": "
45th President of the United States of America
",
- "url": "https://truthsocial.com/@realDonaldTrump",
- "avatar": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/avatars/107/780/257/626/128/497/original/573cf5cc8281e7e9.jpeg",
- "avatar_static": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/avatars/107/780/257/626/128/497/original/573cf5cc8281e7e9.jpeg",
- "header": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/headers/107/780/257/626/128/497/original/3c1acf607b065ded.jpeg",
- "header_static": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/headers/107/780/257/626/128/497/original/3c1acf607b065ded.jpeg",
- "followers_count": 51507,
- "following_count": 1,
- "statuses_count": 1,
- "last_status_at": "2022-02-14",
- "verified": true,
- "location": "",
- "website": "",
- "emojis": [],
- "fields": []
-}
diff --git a/src/__fixtures__/rules.json b/src/__fixtures__/rules.json
index c1c7a1f7d..b26807ce8 100644
--- a/src/__fixtures__/rules.json
+++ b/src/__fixtures__/rules.json
@@ -3,12 +3,10 @@
"id": "1",
"text": "Illegal activity and behavior",
"subtext": "Content that depicts illegal or criminal acts, threats of violence.",
- "rule_type": "content"
},
{
"id": "2",
"text": "Intellectual property infringement",
"subtext": "Impersonating another account or business, infringing on intellectual property rights.",
- "rule_type": "content"
}
]
diff --git a/src/__fixtures__/truthsocial-account.json b/src/__fixtures__/truthsocial-account.json
deleted file mode 100644
index 6b451ca8b..000000000
--- a/src/__fixtures__/truthsocial-account.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "id": "107759994408336377",
- "username": "alex",
- "acct": "alex",
- "display_name": "Alex G.",
- "locked": false,
- "bot": false,
- "discoverable": null,
- "group": false,
- "created_at": "2022-02-08T00:00:00.000Z",
- "note": "Launching Truth Social
",
- "url": "https://truthsocial.com/@alex",
- "avatar": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/avatars/107/759/994/408/336/377/original/119cb0dd1fa615b7.png",
- "avatar_static": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/avatars/107/759/994/408/336/377/original/119cb0dd1fa615b7.png",
- "header": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/headers/107/759/994/408/336/377/original/31f62b0453ccf554.png",
- "header_static": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/headers/107/759/994/408/336/377/original/31f62b0453ccf554.png",
- "followers_count": 966,
- "following_count": 39,
- "statuses_count": 4,
- "last_status_at": "2022-02-20",
- "verified": true,
- "location": "Texas",
- "website": "https://soapbox.pub",
- "emojis": [],
- "fields": []
-}
diff --git a/src/__fixtures__/truthsocial-status-in-moderation.json b/src/__fixtures__/truthsocial-status-in-moderation.json
deleted file mode 100644
index 7613ebd93..000000000
--- a/src/__fixtures__/truthsocial-status-in-moderation.json
+++ /dev/null
@@ -1,85 +0,0 @@
-{
- "id": "108046224464672537",
- "created_at": "2022-03-30T15:40:53.287Z",
- "in_reply_to_id": null,
- "in_reply_to_account_id": null,
- "sensitive": false,
- "spoiler_text": "",
- "visibility": "self",
- "language": null,
- "uri": "https://truthsocial.com/users/alex/statuses/108046244464677537",
- "url": "https://truthsocial.com/@alex/108046244464677537",
- "replies_count": 0,
- "reblogs_count": 0,
- "favourites_count": 0,
- "favourited": false,
- "reblogged": false,
- "muted": false,
- "bookmarked": false,
- "pinned": false,
- "content": "A federal agent inspects a 'lumber' truck after smelling alcohol during the prohibition period. Los Angeles, 1926 (during the Prohibition era).
",
- "reblog": null,
- "application": {
- "name": "Soapbox FE",
- "website": "https://soapbox.pub/"
- },
- "account": {
- "id": "107759994408336377",
- "username": "alex",
- "acct": "alex",
- "display_name": "Alex Gleason",
- "locked": false,
- "bot": false,
- "discoverable": null,
- "group": false,
- "created_at": "2022-02-08T00:00:00.000Z",
- "note": "Launching Truth Social
",
- "url": "https://truthsocial.com/@alex",
- "avatar": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/avatars/107/759/994/408/336/377/original/119cb0dd1fa615b7.png",
- "avatar_static": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/avatars/107/759/994/408/336/377/original/119cb0dd1fa615b7.png",
- "header": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/headers/107/759/994/408/336/377/original/31f62b0453ccf554.png",
- "header_static": "https://static-assets.truthsocial.com/tmtg:prime-truth-social-assets/accounts/headers/107/759/994/408/336/377/original/31f62b0453ccf554.png",
- "followers_count": 4713,
- "following_count": 43,
- "statuses_count": 7,
- "last_status_at": "2022-03-30",
- "verified": true,
- "location": "Texas",
- "website": "https://soapbox.pub/",
- "emojis": [],
- "fields": []
- },
- "media_attachments": [
- {
- "id": "108635651287436632",
- "type": "image",
- "url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/files/108/635/651/487/436/632/original/7873bda5a7ab45d3.jpeg",
- "preview_url": "https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/files/108/635/651/487/436/632/small/7873bda5a7ab45d3.jpeg",
- "external_video_id": null,
- "remote_url": null,
- "preview_remote_url": null,
- "text_url": "https://truthsocial.com/media/_Kc-2w2Pe7knhYJV-CM",
- "meta": {
- "original": {
- "width": 1080,
- "height": 841,
- "size": "1080x841",
- "aspect": 1.2841854934601664
- },
- "small": {
- "width": 907,
- "height": 706,
- "size": "907x706",
- "aspect": 1.2847025495750708
- }
- },
- "description": null,
- "blurhash": "UIIY5?4n~q9FIUIUD%WB?bt7M{t7of%MofIU"
- }
- ],
- "mentions": [],
- "tags": [],
- "emojis": [],
- "card": null,
- "poll": null
-}
\ No newline at end of file
diff --git a/src/actions/compose.ts b/src/actions/compose.ts
index 99f84298e..57327b157 100644
--- a/src/actions/compose.ts
+++ b/src/actions/compose.ts
@@ -50,7 +50,6 @@ const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL' as const;
const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS' as const;
const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO' as const;
const COMPOSE_GROUP_POST = 'COMPOSE_GROUP_POST' as const;
-const COMPOSE_SET_GROUP_TIMELINE_VISIBLE = 'COMPOSE_SET_GROUP_TIMELINE_VISIBLE' as const;
const COMPOSE_SUGGESTIONS_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR' as const;
const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY' as const;
@@ -366,7 +365,6 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}) =>
if (compose.privacy === 'group') {
params.group_id = compose.group_id;
- params.group_timeline_visible = compose.group_timeline_visible; // Truth Social
}
return dispatch(createStatus(params, idempotencyKey, statusId)).then(function(data) {
@@ -506,12 +504,6 @@ const groupCompose = (composeId: string, groupId: string) => ({
group_id: groupId,
});
-const setGroupTimelineVisible = (composeId: string, groupTimelineVisible: boolean) => ({
- type: COMPOSE_SET_GROUP_TIMELINE_VISIBLE,
- id: composeId,
- groupTimelineVisible,
-});
-
const clearComposeSuggestions = (composeId: string) => {
if (cancelFetchComposeSuggestions) {
cancelFetchComposeSuggestions();
@@ -882,7 +874,6 @@ type ComposeAction =
| ReturnType
| ReturnType
| ReturnType
- | ReturnType
| ReturnType
| ComposeSuggestionsReadyAction
| ComposeSuggestionSelectAction
@@ -954,7 +945,6 @@ export {
COMPOSE_REMOVE_FROM_MENTIONS,
COMPOSE_SET_STATUS,
COMPOSE_EDITOR_STATE_SET,
- COMPOSE_SET_GROUP_TIMELINE_VISIBLE,
COMPOSE_CHANGE_MEDIA_ORDER,
setComposeToStatus,
changeCompose,
@@ -984,7 +974,6 @@ export {
undoUploadCompose,
groupCompose,
groupComposeModal,
- setGroupTimelineVisible,
clearComposeSuggestions,
fetchComposeSuggestions,
readyComposeSuggestionsEmojis,
diff --git a/src/actions/notifications.ts b/src/actions/notifications.ts
index c6ce8043a..fb70a717b 100644
--- a/src/actions/notifications.ts
+++ b/src/actions/notifications.ts
@@ -89,7 +89,6 @@ const updateNotificationsQueue = (notification: APIEntity, intlMessages: Record<
(dispatch: AppDispatch, getState: () => RootState) => {
if (!notification.type) return; // drop invalid notifications
if (notification.type === 'pleroma:chat_mention') return; // Drop chat notifications, handle them per-chat
- if (notification.type === 'chat') return; // Drop Truth Social chat notifications.
const showAlert = getSettings(getState()).getIn(['notifications', 'alerts', notification.type]);
const filters = getFilters(getState(), { contextType: 'notifications' });
diff --git a/src/actions/reports.ts b/src/actions/reports.ts
index 662b24b3d..6911a97b2 100644
--- a/src/actions/reports.ts
+++ b/src/actions/reports.ts
@@ -22,8 +22,6 @@ const REPORT_RULE_CHANGE = 'REPORT_RULE_CHANGE';
enum ReportableEntities {
ACCOUNT = 'ACCOUNT',
- CHAT_MESSAGE = 'CHAT_MESSAGE',
- GROUP = 'GROUP',
STATUS = 'STATUS'
}
diff --git a/src/actions/security.ts b/src/actions/security.ts
index 4448104b7..6c2121b0e 100644
--- a/src/actions/security.ts
+++ b/src/actions/security.ts
@@ -6,7 +6,6 @@
import toast from 'soapbox/toast';
import { getLoggedInAccount } from 'soapbox/utils/auth';
-import { parseVersion, TRUTHSOCIAL } from 'soapbox/utils/features';
import { normalizeUsername } from 'soapbox/utils/input';
import api from '../api';
@@ -86,8 +85,6 @@ const changePassword = (oldPassword: string, newPassword: string, confirmation:
const resetPassword = (usernameOrEmail: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const input = normalizeUsername(usernameOrEmail);
- const state = getState();
- const v = parseVersion(state.instance.version);
dispatch({ type: RESET_PASSWORD_REQUEST });
@@ -96,12 +93,7 @@ const resetPassword = (usernameOrEmail: string) =>
? { email: input }
: { nickname: input, username: input };
- const endpoint =
- v.software === TRUTHSOCIAL
- ? '/api/v1/truth/password_reset/request'
- : '/auth/password';
-
- return api(getState).post(endpoint, params).then(() => {
+ return api(getState).post('/auth/password', params).then(() => {
dispatch({ type: RESET_PASSWORD_SUCCESS });
}).catch(error => {
dispatch({ type: RESET_PASSWORD_FAIL, error });
@@ -109,19 +101,6 @@ const resetPassword = (usernameOrEmail: string) =>
});
};
-const resetPasswordConfirm = (password: string, token: string) =>
- (dispatch: AppDispatch, getState: () => RootState) => {
- const params = { password, reset_password_token: token };
- dispatch({ type: RESET_PASSWORD_CONFIRM_REQUEST });
-
- return api(getState).post('/api/v1/truth/password_reset/confirm', params).then(() => {
- dispatch({ type: RESET_PASSWORD_CONFIRM_SUCCESS });
- }).catch(error => {
- dispatch({ type: RESET_PASSWORD_CONFIRM_FAIL, error });
- throw error;
- });
- };
-
const changeEmail = (email: string, password: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch({ type: CHANGE_EMAIL_REQUEST, email });
@@ -137,10 +116,6 @@ const changeEmail = (email: string, password: string) =>
});
};
-const confirmChangedEmail = (token: string) =>
- (_dispatch: AppDispatch, getState: () => RootState) =>
- api(getState).get(`/api/v1/truth/email/confirm?confirmation_token=${token}`);
-
const deleteAccount = (password: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const account = getLoggedInAccount(getState());
@@ -203,9 +178,7 @@ export {
revokeOAuthTokenById,
changePassword,
resetPassword,
- resetPasswordConfirm,
changeEmail,
- confirmChangedEmail,
deleteAccount,
moveAccount,
};
diff --git a/src/actions/statuses.ts b/src/actions/statuses.ts
index ab6a855ee..e5ec19032 100644
--- a/src/actions/statuses.ts
+++ b/src/actions/statuses.ts
@@ -1,8 +1,7 @@
import { isLoggedIn } from 'soapbox/utils/auth';
-import { getFeatures } from 'soapbox/utils/features';
import { shouldHaveCard } from 'soapbox/utils/status';
-import api, { getNextLink } from '../api';
+import api from '../api';
import { setComposeToStatus } from './compose';
import { fetchGroupRelationships } from './groups';
@@ -195,62 +194,13 @@ const fetchContext = (id: string) =>
});
};
-const fetchNext = (statusId: string, next: string) =>
- async(dispatch: AppDispatch, getState: () => RootState) => {
- const response = await api(getState).get(next);
- dispatch(importFetchedStatuses(response.data));
-
- dispatch({
- type: CONTEXT_FETCH_SUCCESS,
- id: statusId,
- ancestors: [],
- descendants: response.data,
- });
-
- return { next: getNextLink(response) };
- };
-
-const fetchAncestors = (id: string) =>
- async(dispatch: AppDispatch, getState: () => RootState) => {
- const response = await api(getState).get(`/api/v1/statuses/${id}/context/ancestors`);
- dispatch(importFetchedStatuses(response.data));
- return response;
- };
-
-const fetchDescendants = (id: string) =>
- async(dispatch: AppDispatch, getState: () => RootState) => {
- const response = await api(getState).get(`/api/v1/statuses/${id}/context/descendants`);
- dispatch(importFetchedStatuses(response.data));
- return response;
- };
-
const fetchStatusWithContext = (id: string) =>
async(dispatch: AppDispatch, getState: () => RootState) => {
- const features = getFeatures(getState().instance);
-
- if (features.paginatedContext) {
- await dispatch(fetchStatus(id));
- const responses = await Promise.all([
- dispatch(fetchAncestors(id)),
- dispatch(fetchDescendants(id)),
- ]);
-
- dispatch({
- type: CONTEXT_FETCH_SUCCESS,
- id,
- ancestors: responses[0].data,
- descendants: responses[1].data,
- });
-
- const next = getNextLink(responses[1]);
- return { next };
- } else {
- await Promise.all([
- dispatch(fetchContext(id)),
- dispatch(fetchStatus(id)),
- ]);
- return { next: undefined };
- }
+ await Promise.all([
+ dispatch(fetchContext(id)),
+ dispatch(fetchStatus(id)),
+ ]);
+ return { next: undefined };
};
const muteStatus = (id: string) =>
@@ -381,9 +331,6 @@ export {
deleteStatus,
updateStatus,
fetchContext,
- fetchNext,
- fetchAncestors,
- fetchDescendants,
fetchStatusWithContext,
muteStatus,
unmuteStatus,
diff --git a/src/actions/streaming.ts b/src/actions/streaming.ts
index 925832265..eb369fcb9 100644
--- a/src/actions/streaming.ts
+++ b/src/actions/streaming.ts
@@ -4,11 +4,9 @@ import { importEntities } from 'soapbox/entity-store/actions';
import { Entities } from 'soapbox/entity-store/entities';
import { selectEntity } from 'soapbox/entity-store/selectors';
import messages from 'soapbox/messages';
-import { ChatKeys, IChat, isLastMessage } from 'soapbox/queries/chats';
import { queryClient } from 'soapbox/queries/client';
import { announcementSchema, type Announcement, type Relationship } from 'soapbox/schemas';
-import { getUnreadChatsCount, updateChatListItem, updateChatMessage } from 'soapbox/utils/chats';
-import { removePageItem } from 'soapbox/utils/queries';
+import { getUnreadChatsCount, updateChatListItem } from 'soapbox/utils/chats';
import { play, soundCache } from 'soapbox/utils/sounds';
import { connectStream } from '../stream';
@@ -27,41 +25,10 @@ import {
import type { IStatContext } from 'soapbox/contexts/stat-context';
import type { AppDispatch, RootState } from 'soapbox/store';
-import type { APIEntity, Chat } from 'soapbox/types/entities';
+import type { APIEntity } from 'soapbox/types/entities';
const STREAMING_CHAT_UPDATE = 'STREAMING_CHAT_UPDATE';
-const removeChatMessage = (payload: string) => {
- const data = JSON.parse(payload);
- const chatId = data.chat_id;
- const chatMessageId = data.deleted_message_id;
-
- // If the user just deleted the "last_message", then let's invalidate
- // the Chat Search query so the Chat List will show the new "last_message".
- if (isLastMessage(chatMessageId)) {
- queryClient.invalidateQueries({
- queryKey: ChatKeys.chatSearch(),
- });
- }
-
- removePageItem(ChatKeys.chatMessages(chatId), chatMessageId, (o: any, n: any) => String(o.id) === String(n));
-};
-
-// Update the specific Chat query data.
-const updateChatQuery = (chat: IChat) => {
- const cachedChat = queryClient.getQueryData(ChatKeys.chat(chat.id));
- if (!cachedChat) {
- return;
- }
-
- const newChat = {
- ...cachedChat,
- latest_read_message_by_account: chat.latest_read_message_by_account,
- latest_read_message_created_at: chat.latest_read_message_created_at,
- };
- queryClient.setQueryData(ChatKeys.chat(chat.id), newChat as any);
-};
-
const updateAnnouncementReactions = ({ announcement_id: id, name, count }: APIEntity) => {
queryClient.setQueryData(['announcements'], (prevResult: Announcement[]) =>
prevResult.map(value => {
@@ -149,7 +116,6 @@ const connectTimelineStream = (
dispatch(fetchFilters());
break;
case 'pleroma:chat_update':
- case 'chat_message.created': // TruthSocial
dispatch((_dispatch: AppDispatch, getState: () => RootState) => {
const chat = JSON.parse(data.payload);
const me = getState().me;
@@ -169,22 +135,6 @@ const connectTimelineStream = (
}
});
break;
- case 'chat_message.deleted': // TruthSocial
- removeChatMessage(data.payload);
- break;
- case 'chat_message.read': // TruthSocial
- dispatch((_dispatch: AppDispatch, getState: () => RootState) => {
- const chat = JSON.parse(data.payload);
- const me = getState().me;
- const isFromOtherUser = chat.account.id !== me;
- if (isFromOtherUser) {
- updateChatQuery(JSON.parse(data.payload));
- }
- });
- break;
- case 'chat_message.reaction': // TruthSocial
- updateChatMessage(JSON.parse(data.payload));
- break;
case 'pleroma:follow_relationships_update':
dispatch(updateFollowRelationships(JSON.parse(data.payload)));
break;
diff --git a/src/actions/timelines.ts b/src/actions/timelines.ts
index 35f0f5638..6713e78b4 100644
--- a/src/actions/timelines.ts
+++ b/src/actions/timelines.ts
@@ -243,9 +243,6 @@ const expandGroupTimeline = (id: string, { maxId }: Record = {}, do
const expandGroupFeaturedTimeline = (id: string) =>
expandTimeline(`group:${id}:pinned`, `/api/v1/timelines/group/${id}`, { pinned: true });
-const expandGroupTimelineFromTag = (id: string, tagName: string, { maxId }: Record = {}, done = noOp) =>
- expandTimeline(`group:tags:${id}:${tagName}`, `/api/v1/timelines/group/${id}/tags/${tagName}`, { max_id: maxId }, done);
-
const expandGroupMediaTimeline = (id: string | number, { maxId }: Record = {}) =>
expandTimeline(`group:${id}:media`, `/api/v1/timelines/group/${id}`, { max_id: maxId, only_media: true, limit: 40, with_muted: true });
@@ -345,7 +342,6 @@ export {
expandListTimeline,
expandGroupTimeline,
expandGroupFeaturedTimeline,
- expandGroupTimelineFromTag,
expandGroupMediaTimeline,
expandHashtagTimeline,
expandTimelineRequest,
diff --git a/src/api/hooks/groups/useGroupLookup.test.ts b/src/api/hooks/groups/useGroupLookup.test.ts
deleted file mode 100644
index ce3903ae3..000000000
--- a/src/api/hooks/groups/useGroupLookup.test.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { __stub } from 'soapbox/api';
-import { buildGroup } from 'soapbox/jest/factory';
-import { renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers';
-
-import { useGroupLookup } from './useGroupLookup';
-
-const group = buildGroup({ id: '1', slug: 'soapbox' });
-const state = rootState.setIn(['instance', 'version'], '3.4.1 (compatible; TruthSocial 1.0.0)');
-
-describe('useGroupLookup hook', () => {
- describe('with a successful request', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet(`/api/v1/groups/lookup?name=${group.slug}`).reply(200, group);
- });
- });
-
- it('is successful', async () => {
- const { result } = renderHook(() => useGroupLookup(group.slug), undefined, state);
-
- await waitFor(() => expect(result.current.isFetching).toBe(false));
-
- expect(result.current.entity?.id).toBe(group.id);
- });
- });
-
- describe('with an unsuccessful query', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet(`/api/v1/groups/lookup?name=${group.slug}`).networkError();
- });
- });
-
- it('is has error state', async() => {
- const { result } = renderHook(() => useGroupLookup(group.slug), undefined, state);
-
- await waitFor(() => expect(result.current.isFetching).toBe(false));
-
- expect(result.current.entity).toBeUndefined();
- });
- });
-});
\ No newline at end of file
diff --git a/src/api/hooks/groups/useGroupLookup.ts b/src/api/hooks/groups/useGroupLookup.ts
deleted file mode 100644
index 8e161af78..000000000
--- a/src/api/hooks/groups/useGroupLookup.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { useEffect } from 'react';
-import { useHistory } from 'react-router-dom';
-
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntityLookup } from 'soapbox/entity-store/hooks';
-import { useApi } from 'soapbox/hooks/useApi';
-import { useFeatures } from 'soapbox/hooks/useFeatures';
-import { groupSchema } from 'soapbox/schemas';
-
-import { useGroupRelationship } from './useGroupRelationship';
-
-function useGroupLookup(slug: string) {
- const api = useApi();
- const features = useFeatures();
- const history = useHistory();
-
- const { entity: group, isUnauthorized, ...result } = useEntityLookup(
- Entities.GROUPS,
- (group) => group.slug.toLowerCase() === slug.toLowerCase(),
- () => api.get(`/api/v1/groups/lookup?name=${slug}`),
- { schema: groupSchema, enabled: features.groups && !!slug },
- );
-
- const { groupRelationship: relationship } = useGroupRelationship(group?.id);
-
- useEffect(() => {
- if (isUnauthorized) {
- history.push('/login');
- }
- }, [isUnauthorized]);
-
- return {
- ...result,
- isUnauthorized,
- entity: group ? { ...group, relationship: relationship || null } : undefined,
- };
-}
-
-export { useGroupLookup };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useGroupMutes.ts b/src/api/hooks/groups/useGroupMutes.ts
deleted file mode 100644
index 67eca0772..000000000
--- a/src/api/hooks/groups/useGroupMutes.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { useFeatures } from 'soapbox/hooks';
-import { useApi } from 'soapbox/hooks/useApi';
-import { groupSchema } from 'soapbox/schemas';
-
-import type { Group } from 'soapbox/schemas';
-
-function useGroupMutes() {
- const api = useApi();
- const features = useFeatures();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUP_MUTES],
- () => api.get('/api/v1/groups/mutes'),
- { schema: groupSchema, enabled: features.groupsMuting },
- );
-
- return {
- ...result,
- mutes: entities,
- };
-}
-
-export { useGroupMutes };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useGroupSearch.ts b/src/api/hooks/groups/useGroupSearch.ts
deleted file mode 100644
index 295d63933..000000000
--- a/src/api/hooks/groups/useGroupSearch.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { useApi, useFeatures } from 'soapbox/hooks';
-import { groupSchema } from 'soapbox/schemas';
-
-import { useGroupRelationships } from './useGroupRelationships';
-
-import type { Group } from 'soapbox/schemas';
-
-function useGroupSearch(search: string) {
- const api = useApi();
- const features = useFeatures();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUPS, 'discover', 'search', search],
- () => api.get('/api/v1/groups/search', {
- params: {
- q: search,
- },
- }),
- { enabled: features.groupsDiscovery && !!search, schema: groupSchema },
- );
-
- const { relationships } = useGroupRelationships(
- ['discover', 'search', search],
- entities.map(entity => entity.id),
- );
-
- const groups = entities.map((group) => ({
- ...group,
- relationship: relationships[group.id] || null,
- }));
-
- return {
- ...result,
- groups,
- };
-}
-
-export { useGroupSearch };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useGroupTag.ts b/src/api/hooks/groups/useGroupTag.ts
deleted file mode 100644
index d0e63d74d..000000000
--- a/src/api/hooks/groups/useGroupTag.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntity } from 'soapbox/entity-store/hooks';
-import { useApi } from 'soapbox/hooks';
-import { type GroupTag, groupTagSchema } from 'soapbox/schemas';
-
-function useGroupTag(tagId: string) {
- const api = useApi();
-
- const { entity: tag, ...result } = useEntity(
- [Entities.GROUP_TAGS, tagId],
- () => api.get(`/api/v1/tags/${tagId }`),
- { schema: groupTagSchema },
- );
-
- return {
- ...result,
- tag,
- };
-}
-
-export { useGroupTag };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useGroupTags.ts b/src/api/hooks/groups/useGroupTags.ts
deleted file mode 100644
index b2c29aa3c..000000000
--- a/src/api/hooks/groups/useGroupTags.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { useApi } from 'soapbox/hooks/useApi';
-import { groupTagSchema } from 'soapbox/schemas';
-
-import type { GroupTag } from 'soapbox/schemas';
-
-function useGroupTags(groupId: string) {
- const api = useApi();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUP_TAGS, groupId],
- () => api.get(`/api/v1/truth/trends/groups/${groupId}/tags`),
- { schema: groupTagSchema },
- );
-
- return {
- ...result,
- tags: entities,
- };
-}
-
-export { useGroupTags };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useGroupValidation.ts b/src/api/hooks/groups/useGroupValidation.ts
deleted file mode 100644
index 470be22a5..000000000
--- a/src/api/hooks/groups/useGroupValidation.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { useQuery } from '@tanstack/react-query';
-
-import { useApi } from 'soapbox/hooks/useApi';
-import { useFeatures } from 'soapbox/hooks/useFeatures';
-
-type Validation = {
- error: string;
- message: string;
-}
-
-const ValidationKeys = {
- validation: (name: string) => ['group', 'validation', name] as const,
-};
-
-function useGroupValidation(name: string = '') {
- const api = useApi();
- const features = useFeatures();
-
- const getValidation = async() => {
- const { data } = await api.get('/api/v1/groups/validate', {
- params: { name },
- })
- .catch((error) => {
- if (error.response.status === 422) {
- return { data: error.response.data };
- }
-
- throw error;
- });
-
- return data;
- };
-
- const queryInfo = useQuery({
- queryKey: ValidationKeys.validation(name),
- queryFn: getValidation,
- enabled: features.groupsValidation && !!name,
- });
-
- return {
- ...queryInfo,
- data: {
- ...queryInfo.data,
- isValid: !queryInfo.data?.error,
- },
- };
-}
-
-export { useGroupValidation };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useGroups.ts b/src/api/hooks/groups/useGroups.ts
index f5450bd73..a5384e136 100644
--- a/src/api/hooks/groups/useGroups.ts
+++ b/src/api/hooks/groups/useGroups.ts
@@ -6,17 +6,17 @@ import { groupSchema, type Group } from 'soapbox/schemas/group';
import { useGroupRelationships } from './useGroupRelationships';
-function useGroups(q: string = '') {
+function useGroups() {
const api = useApi();
const features = useFeatures();
const { entities, ...result } = useEntities(
- [Entities.GROUPS, 'search', q],
- () => api.get('/api/v1/groups', { params: { q } }),
+ [Entities.GROUPS, 'search', ''],
+ () => api.get('/api/v1/groups'),
{ enabled: features.groups, schema: groupSchema },
);
const { relationships } = useGroupRelationships(
- ['search', q],
+ ['search', ''],
entities.map(entity => entity.id),
);
diff --git a/src/api/hooks/groups/useGroupsFromTag.ts b/src/api/hooks/groups/useGroupsFromTag.ts
deleted file mode 100644
index 6c2b88bb1..000000000
--- a/src/api/hooks/groups/useGroupsFromTag.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { useApi, useFeatures } from 'soapbox/hooks';
-import { groupSchema } from 'soapbox/schemas';
-
-import { useGroupRelationships } from './useGroupRelationships';
-
-import type { Group } from 'soapbox/schemas';
-
-function useGroupsFromTag(tagId: string) {
- const api = useApi();
- const features = useFeatures();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUPS, 'tags', tagId],
- () => api.get(`/api/v1/tags/${tagId}/groups`),
- {
- schema: groupSchema,
- enabled: features.groupsDiscovery,
- },
- );
- const { relationships } = useGroupRelationships(
- ['tags', tagId],
- entities.map(entity => entity.id),
- );
-
- const groups = entities.map((group) => ({
- ...group,
- relationship: relationships[group.id] || null,
- }));
-
- return {
- ...result,
- groups,
- };
-}
-
-export { useGroupsFromTag };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useMuteGroup.ts b/src/api/hooks/groups/useMuteGroup.ts
deleted file mode 100644
index e31c7f4d1..000000000
--- a/src/api/hooks/groups/useMuteGroup.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntityActions } from 'soapbox/entity-store/hooks';
-import { type Group, groupRelationshipSchema } from 'soapbox/schemas';
-
-function useMuteGroup(group?: Group) {
- const { createEntity, isSubmitting } = useEntityActions(
- [Entities.GROUP_RELATIONSHIPS, group?.id as string],
- { post: `/api/v1/groups/${group?.id}/mute` },
- { schema: groupRelationshipSchema },
- );
-
- return {
- mutate: createEntity,
- isSubmitting,
- };
-}
-
-export { useMuteGroup };
\ No newline at end of file
diff --git a/src/api/hooks/groups/usePendingGroups.test.ts b/src/api/hooks/groups/usePendingGroups.test.ts
deleted file mode 100644
index 33190ae0b..000000000
--- a/src/api/hooks/groups/usePendingGroups.test.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { __stub } from 'soapbox/api';
-import { Entities } from 'soapbox/entity-store/entities';
-import { buildAccount, buildGroup } from 'soapbox/jest/factory';
-import { renderHook, waitFor } from 'soapbox/jest/test-helpers';
-import { instanceSchema } from 'soapbox/schemas';
-
-import { usePendingGroups } from './usePendingGroups';
-
-const id = '1';
-const group = buildGroup({ id, display_name: 'soapbox' });
-const store = {
- instance: instanceSchema.parse({
- version: '3.4.1 (compatible; TruthSocial 1.0.0+unreleased)',
- }),
- me: '1',
- entities: {
- [Entities.ACCOUNTS]: {
- store: {
- [id]: buildAccount({
- id,
- acct: 'tiger',
- display_name: 'Tiger',
- avatar: 'test.jpg',
- verified: true,
- }),
- },
- lists: {},
- },
- },
-};
-
-describe('usePendingGroups hook', () => {
- describe('with a successful request', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet('/api/v1/groups').reply(200, [group]);
- });
- });
-
- it('is successful', async () => {
- const { result } = renderHook(usePendingGroups, undefined, store);
-
- await waitFor(() => expect(result.current.isFetching).toBe(false));
-
- expect(result.current.groups).toHaveLength(1);
- });
- });
-
- describe('with an unsuccessful query', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet('/api/v1/groups').networkError();
- });
- });
-
- it('is has error state', async() => {
- const { result } = renderHook(usePendingGroups, undefined, store);
-
- await waitFor(() => expect(result.current.isFetching).toBe(false));
-
- expect(result.current.groups).toHaveLength(0);
- });
- });
-});
\ No newline at end of file
diff --git a/src/api/hooks/groups/usePendingGroups.ts b/src/api/hooks/groups/usePendingGroups.ts
deleted file mode 100644
index f4ea16a43..000000000
--- a/src/api/hooks/groups/usePendingGroups.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { useApi, useFeatures, useOwnAccount } from 'soapbox/hooks';
-import { Group, groupSchema } from 'soapbox/schemas';
-
-function usePendingGroups() {
- const api = useApi();
- const { account } = useOwnAccount();
- const features = useFeatures();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUPS, account?.id!, 'pending'],
- () => api.get('/api/v1/groups', {
- params: {
- pending: true,
- },
- }),
- {
- schema: groupSchema,
- enabled: !!account && features.groupsPending,
- },
- );
-
- return {
- ...result,
- groups: entities,
- };
-}
-
-export { usePendingGroups };
\ No newline at end of file
diff --git a/src/api/hooks/groups/usePopularGroups.ts b/src/api/hooks/groups/usePopularGroups.ts
deleted file mode 100644
index 69b04e32f..000000000
--- a/src/api/hooks/groups/usePopularGroups.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { Group, groupSchema } from 'soapbox/schemas';
-
-import { useApi } from '../../../hooks/useApi';
-import { useFeatures } from '../../../hooks/useFeatures';
-
-import { useGroupRelationships } from './useGroupRelationships';
-
-function usePopularGroups() {
- const api = useApi();
- const features = useFeatures();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUPS, 'popular'],
- () => api.get('/api/v1/truth/trends/groups'),
- {
- schema: groupSchema,
- enabled: features.groupsDiscovery,
- },
- );
-
- const { relationships } = useGroupRelationships(['popular'], entities.map(entity => entity.id));
-
- const groups = entities.map((group) => ({
- ...group,
- relationship: relationships[group.id] || null,
- }));
-
- return {
- ...result,
- groups,
- };
-}
-
-export { usePopularGroups };
\ No newline at end of file
diff --git a/src/api/hooks/groups/usePopularTags.ts b/src/api/hooks/groups/usePopularTags.ts
deleted file mode 100644
index e0ec2c550..000000000
--- a/src/api/hooks/groups/usePopularTags.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { useApi, useFeatures } from 'soapbox/hooks';
-import { type GroupTag, groupTagSchema } from 'soapbox/schemas';
-
-function usePopularTags() {
- const api = useApi();
- const features = useFeatures();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUP_TAGS],
- () => api.get('/api/v1/groups/tags'),
- {
- schema: groupTagSchema,
- enabled: features.groupsDiscovery,
- },
- );
-
- return {
- ...result,
- tags: entities,
- };
-}
-
-export { usePopularTags };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useSuggestedGroups.ts b/src/api/hooks/groups/useSuggestedGroups.ts
deleted file mode 100644
index 69fb71065..000000000
--- a/src/api/hooks/groups/useSuggestedGroups.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntities } from 'soapbox/entity-store/hooks';
-import { useApi, useFeatures } from 'soapbox/hooks';
-import { type Group, groupSchema } from 'soapbox/schemas';
-
-import { useGroupRelationships } from './useGroupRelationships';
-
-function useSuggestedGroups() {
- const api = useApi();
- const features = useFeatures();
-
- const { entities, ...result } = useEntities(
- [Entities.GROUPS, 'suggested'],
- () => api.get('/api/v1/truth/suggestions/groups'),
- {
- schema: groupSchema,
- enabled: features.groupsDiscovery,
- },
- );
-
- const { relationships } = useGroupRelationships(['suggested'], entities.map(entity => entity.id));
-
- const groups = entities.map((group) => ({
- ...group,
- relationship: relationships[group.id] || null,
- }));
-
- return {
- ...result,
- groups,
- };
-}
-
-export { useSuggestedGroups };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useUnmuteGroup.ts b/src/api/hooks/groups/useUnmuteGroup.ts
deleted file mode 100644
index 6c8768d25..000000000
--- a/src/api/hooks/groups/useUnmuteGroup.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntityActions } from 'soapbox/entity-store/hooks';
-import { type Group, groupRelationshipSchema } from 'soapbox/schemas';
-
-function useUnmuteGroup(group?: Group) {
- const { createEntity, isSubmitting } = useEntityActions(
- [Entities.GROUP_RELATIONSHIPS, group?.id as string],
- { post: `/api/v1/groups/${group?.id}/unmute` },
- { schema: groupRelationshipSchema },
- );
-
- return {
- mutate: createEntity,
- isSubmitting,
- };
-}
-
-export { useUnmuteGroup };
\ No newline at end of file
diff --git a/src/api/hooks/groups/useUpdateGroup.ts b/src/api/hooks/groups/useUpdateGroup.ts
index 129849514..02f61d224 100644
--- a/src/api/hooks/groups/useUpdateGroup.ts
+++ b/src/api/hooks/groups/useUpdateGroup.ts
@@ -10,7 +10,6 @@ interface UpdateGroupParams {
header?: File | '';
group_visibility?: string;
discoverable?: boolean;
- tags?: string[];
}
function useUpdateGroup(groupId: string) {
diff --git a/src/api/hooks/groups/useUpdateGroupTag.ts b/src/api/hooks/groups/useUpdateGroupTag.ts
deleted file mode 100644
index 1c68c714d..000000000
--- a/src/api/hooks/groups/useUpdateGroupTag.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Entities } from 'soapbox/entity-store/entities';
-import { useEntityActions } from 'soapbox/entity-store/hooks';
-
-import type { GroupTag } from 'soapbox/schemas';
-
-function useUpdateGroupTag(groupId: string, tagId: string) {
- const { updateEntity, ...rest } = useEntityActions(
- [Entities.GROUP_TAGS, groupId, tagId],
- { patch: `/api/v1/groups/${groupId}/tags/${tagId}` },
- );
-
- return {
- updateGroupTag: updateEntity,
- ...rest,
- };
-}
-
-export { useUpdateGroupTag };
\ No newline at end of file
diff --git a/src/api/hooks/index.ts b/src/api/hooks/index.ts
index f085f3c4b..bccb87cb2 100644
--- a/src/api/hooks/index.ts
+++ b/src/api/hooks/index.ts
@@ -19,30 +19,16 @@ export { useCreateGroup, type CreateGroupParams } from './groups/useCreateGroup'
export { useDeleteGroup } from './groups/useDeleteGroup';
export { useDemoteGroupMember } from './groups/useDemoteGroupMember';
export { useGroup } from './groups/useGroup';
-export { useGroupLookup } from './groups/useGroupLookup';
export { useGroupMedia } from './groups/useGroupMedia';
export { useGroupMembers } from './groups/useGroupMembers';
export { useGroupMembershipRequests } from './groups/useGroupMembershipRequests';
-export { useGroupMutes } from './groups/useGroupMutes';
export { useGroupRelationship } from './groups/useGroupRelationship';
export { useGroupRelationships } from './groups/useGroupRelationships';
-export { useGroupSearch } from './groups/useGroupSearch';
-export { useGroupTag } from './groups/useGroupTag';
-export { useGroupTags } from './groups/useGroupTags';
-export { useGroupValidation } from './groups/useGroupValidation';
export { useGroups } from './groups/useGroups';
-export { useGroupsFromTag } from './groups/useGroupsFromTag';
export { useJoinGroup } from './groups/useJoinGroup';
-export { useMuteGroup } from './groups/useMuteGroup';
export { useLeaveGroup } from './groups/useLeaveGroup';
-export { usePendingGroups } from './groups/usePendingGroups';
-export { usePopularGroups } from './groups/usePopularGroups';
-export { usePopularTags } from './groups/usePopularTags';
export { usePromoteGroupMember } from './groups/usePromoteGroupMember';
-export { useSuggestedGroups } from './groups/useSuggestedGroups';
-export { useUnmuteGroup } from './groups/useUnmuteGroup';
export { useUpdateGroup } from './groups/useUpdateGroup';
-export { useUpdateGroupTag } from './groups/useUpdateGroupTag';
// Statuses
export { useBookmarkFolders } from './statuses/useBookmarkFolders';
diff --git a/src/components/groups/popover/group-popover.tsx b/src/components/groups/popover/group-popover.tsx
index 44d1d5244..4e079f430 100644
--- a/src/components/groups/popover/group-popover.tsx
+++ b/src/components/groups/popover/group-popover.tsx
@@ -30,7 +30,7 @@ const GroupPopover = (props: IGroupPopoverContainer) => {
const path = history.location.pathname;
const shouldHideAction = matchPath(path, {
- path: ['/group/:groupSlug'],
+ path: ['/group/:groupId'],
exact: true,
});
@@ -88,7 +88,7 @@ const GroupPopover = (props: IGroupPopoverContainer) => {
{!shouldHideAction && (
-
+
diff --git a/src/components/sidebar-menu.tsx b/src/components/sidebar-menu.tsx
index f8d091b20..17ca4fc81 100644
--- a/src/components/sidebar-menu.tsx
+++ b/src/components/sidebar-menu.tsx
@@ -11,7 +11,7 @@ import { useAccount } from 'soapbox/api/hooks';
import Account from 'soapbox/components/account';
import { Stack, Divider, HStack, Icon, IconButton, Text } from 'soapbox/components/ui';
import ProfileStats from 'soapbox/features/ui/components/profile-stats';
-import { useAppDispatch, useAppSelector, useGroupsPath, useFeatures } from 'soapbox/hooks';
+import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
import { makeGetOtherAccounts } from 'soapbox/selectors';
import type { List as ImmutableList } from 'immutable';
@@ -88,7 +88,6 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
const sidebarOpen = useAppSelector((state) => state.sidebar.sidebarOpen);
const settings = useAppSelector((state) => getSettings(state));
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
- const groupsPath = useGroupsPath();
const closeButtonRef = React.useRef(null);
@@ -209,7 +208,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => {
{features.groups && (
{
const features = useFeatures();
const { isDeveloper } = useSettings();
const { account } = useOwnAccount();
- const groupsPath = useGroupsPath();
const notificationCount = useAppSelector((state) => state.notifications.unread);
const followRequestsCount = useAppSelector((state) => state.user_lists.follow_requests.items.count());
@@ -142,7 +141,7 @@ const SidebarNavigation = () => {
{features.groups && (
}
diff --git a/src/components/status-action-bar.tsx b/src/components/status-action-bar.tsx
index 61242fee0..f4cad0d0b 100644
--- a/src/components/status-action-bar.tsx
+++ b/src/components/status-action-bar.tsx
@@ -13,7 +13,7 @@ import { initMuteModal } from 'soapbox/actions/mutes';
import { initReport, ReportableEntities } from 'soapbox/actions/reports';
import { deleteStatus, editStatus, toggleMuteStatus } from 'soapbox/actions/statuses';
import { deleteFromTimelines } from 'soapbox/actions/timelines';
-import { useBlockGroupMember, useGroup, useGroupRelationship, useMuteGroup, useUnmuteGroup } from 'soapbox/api/hooks';
+import { useBlockGroupMember, useGroup, useGroupRelationship } from 'soapbox/api/hooks';
import { useDeleteGroupStatus } from 'soapbox/api/hooks/groups/useDeleteGroupStatus';
import DropdownMenu from 'soapbox/components/dropdown-menu';
import StatusActionButton from 'soapbox/components/status-action-button';
@@ -69,12 +69,7 @@ const messages = defineMessages({
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
more: { id: 'status.more', defaultMessage: 'More' },
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
- muteConfirm: { id: 'confirmations.mute_group.confirm', defaultMessage: 'Mute' },
muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute Conversation' },
- muteGroup: { id: 'group.mute.long_label', defaultMessage: 'Mute Group' },
- muteHeading: { id: 'confirmations.mute_group.heading', defaultMessage: 'Mute Group' },
- muteMessage: { id: 'confirmations.mute_group.message', defaultMessage: 'You are about to mute the group. Do you want to continue?' },
- muteSuccess: { id: 'group.mute.success', defaultMessage: 'Muted the group' },
open: { id: 'status.open', defaultMessage: 'Show Post Details' },
pin: { id: 'status.pin', defaultMessage: 'Pin on profile' },
pinToGroup: { id: 'status.pin_to_group', defaultMessage: 'Pin to Group' },
@@ -101,8 +96,6 @@ const messages = defineMessages({
share: { id: 'status.share', defaultMessage: 'Share' },
unbookmark: { id: 'status.unbookmark', defaultMessage: 'Remove bookmark' },
unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute Conversation' },
- unmuteGroup: { id: 'group.unmute.long_label', defaultMessage: 'Unmute Group' },
- unmuteSuccess: { id: 'group.unmute.success', defaultMessage: 'Unmuted the group' },
unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' },
unpinFromGroup: { id: 'status.unpin_to_group', defaultMessage: 'Unpin from Group' },
zap: { id: 'status.zap', defaultMessage: 'Zap' },
@@ -128,12 +121,9 @@ const StatusActionBar: React.FC = ({
const intl = useIntl();
const history = useHistory();
const dispatch = useAppDispatch();
- const match = useRouteMatch<{ groupSlug: string }>('/group/:groupSlug');
+ const match = useRouteMatch<{ groupId: string }>('/group/:groupId');
const { group } = useGroup((status.group as Group)?.id as string);
- const muteGroup = useMuteGroup(group as Group);
- const unmuteGroup = useUnmuteGroup(group as Group);
- const isMutingGroup = !!group?.relationship?.muting;
const deleteGroupStatus = useDeleteGroupStatus(group as Group, status.id);
const blockGroupMember = useBlockGroupMember(group as Group, status.account);
@@ -294,27 +284,6 @@ const StatusActionBar: React.FC = ({
dispatch(initMuteModal(status.account));
};
- const handleMuteGroupClick: React.EventHandler = () =>
- dispatch(openModal('CONFIRM', {
- heading: intl.formatMessage(messages.muteHeading),
- message: intl.formatMessage(messages.muteMessage),
- confirm: intl.formatMessage(messages.muteConfirm),
- confirmationTheme: 'primary',
- onConfirm: () => muteGroup.mutate(undefined, {
- onSuccess() {
- toast.success(intl.formatMessage(messages.muteSuccess));
- },
- }),
- }));
-
- const handleUnmuteGroupClick: React.EventHandler = () => {
- unmuteGroup.mutate(undefined, {
- onSuccess() {
- toast.success(intl.formatMessage(messages.unmuteSuccess));
- },
- });
- };
-
const handleBlockClick: React.EventHandler = (e) => {
const account = status.account;
@@ -542,14 +511,6 @@ const StatusActionBar: React.FC = ({
}
menu.push(null);
- if (features.groupsMuting && status.group) {
- menu.push({
- text: isMutingGroup ? intl.formatMessage(messages.unmuteGroup) : intl.formatMessage(messages.muteGroup),
- icon: require('@tabler/icons/outline/volume-3.svg'),
- action: isMutingGroup ? handleUnmuteGroupClick : handleMuteGroupClick,
- });
- menu.push(null);
- }
menu.push({
text: intl.formatMessage(messages.mute, { name: username }),
diff --git a/src/components/status-media.tsx b/src/components/status-media.tsx
index 2c96c0078..77be4b031 100644
--- a/src/components/status-media.tsx
+++ b/src/components/status-media.tsx
@@ -3,7 +3,6 @@ import React, { Suspense } from 'react';
import { openModal } from 'soapbox/actions/modals';
import AttachmentThumbs from 'soapbox/components/attachment-thumbs';
import PreviewCard from 'soapbox/components/preview-card';
-import { GroupLinkPreview } from 'soapbox/features/groups/components/group-link-preview';
import PlaceholderCard from 'soapbox/features/placeholder/components/placeholder-card';
import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components';
import { useAppDispatch } from 'soapbox/hooks';
@@ -112,10 +111,6 @@ const StatusMedia: React.FC = ({
);
}
- } else if (status.spoiler_text.length === 0 && !status.quote && status.card?.group) {
- media = (
-
- );
} else if (status.spoiler_text.length === 0 && !status.quote && status.card) {
media = (
= (props) => {
),
group: (
-
+
= (props) => {
defaultMessage='Posted in {group}'
values={{
group: (
-
+
diff --git a/src/components/thumb-navigation.tsx b/src/components/thumb-navigation.tsx
index 1aee06594..275bb5a6a 100644
--- a/src/components/thumb-navigation.tsx
+++ b/src/components/thumb-navigation.tsx
@@ -3,12 +3,11 @@ import { FormattedMessage } from 'react-intl';
import ThumbNavigationLink from 'soapbox/components/thumb-navigation-link';
import { useStatContext } from 'soapbox/contexts/stat-context';
-import { useAppSelector, useFeatures, useGroupsPath, useOwnAccount } from 'soapbox/hooks';
+import { useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
const ThumbNavigation: React.FC = (): JSX.Element => {
const { account } = useOwnAccount();
const features = useFeatures();
- const groupsPath = useGroupsPath();
const { unreadChatsCount } = useStatContext();
@@ -60,7 +59,7 @@ const ThumbNavigation: React.FC = (): JSX.Element => {
src={require('@tabler/icons/outline/circles.svg')}
activeSrc={require('@tabler/icons/filled/circles.svg')}
text={}
- to={groupsPath}
+ to='/groups'
exact
/>
)}
diff --git a/src/contexts/chat-context.tsx b/src/contexts/chat-context.tsx
index 14354549e..f1afe4b8b 100644
--- a/src/contexts/chat-context.tsx
+++ b/src/contexts/chat-context.tsx
@@ -2,12 +2,11 @@ import React, { createContext, useContext, useEffect, useMemo, useState } from '
import { useHistory, useParams } from 'react-router-dom';
import { toggleMainWindow } from 'soapbox/actions/chats';
-import { useAppDispatch, useOwnAccount, useSettings } from 'soapbox/hooks';
+import { useAppDispatch, useSettings } from 'soapbox/hooks';
import { IChat, useChat } from 'soapbox/queries/chats';
const ChatContext = createContext({
isOpen: false,
- needsAcceptance: false,
});
enum ChatWidgetScreens {
@@ -25,7 +24,6 @@ const ChatProvider: React.FC = ({ children }) => {
const history = useHistory();
const dispatch = useAppDispatch();
const { chats } = useSettings();
- const { account } = useOwnAccount();
const path = history.location.pathname;
const isUsingMainChatPage = Boolean(path.match(/^\/chats/));
@@ -36,7 +34,6 @@ const ChatProvider: React.FC = ({ children }) => {
const { data: chat } = useChat(currentChatId as string);
- const needsAcceptance = !chat?.accepted && chat?.created_by_account !== account?.id;
const isOpen = chats.mainWindow === 'open';
const changeScreen = (screen: ChatWidgetScreens, currentChatId?: string | null) => {
@@ -48,14 +45,13 @@ const ChatProvider: React.FC = ({ children }) => {
const value = useMemo(() => ({
chat,
- needsAcceptance,
isOpen,
isUsingMainChatPage,
toggleChatPane,
screen,
changeScreen,
currentChatId,
- }), [chat, currentChatId, needsAcceptance, isUsingMainChatPage, isOpen, screen, changeScreen]);
+ }), [chat, currentChatId, isUsingMainChatPage, isOpen, screen, changeScreen]);
useEffect(() => {
if (chatId) {
@@ -76,7 +72,6 @@ interface IChatContext {
chat: IChat | null;
isOpen: boolean;
isUsingMainChatPage?: boolean;
- needsAcceptance: boolean;
toggleChatPane(): void;
screen: ChatWidgetScreens;
currentChatId: string | null;
diff --git a/src/entity-store/entities.ts b/src/entity-store/entities.ts
index 13cdf4eaa..2b6f00c8f 100644
--- a/src/entity-store/entities.ts
+++ b/src/entity-store/entities.ts
@@ -8,7 +8,6 @@ enum Entities {
GROUP_MEMBERSHIPS = 'GroupMemberships',
GROUP_MUTES = 'GroupMutes',
GROUP_RELATIONSHIPS = 'GroupRelationships',
- GROUP_TAGS = 'GroupTags',
PATRON_USERS = 'PatronUsers',
RELATIONSHIPS = 'Relationships',
RELAYS = 'Relays',
@@ -23,7 +22,6 @@ interface EntityTypes {
[Entities.GROUPS]: Schemas.Group;
[Entities.GROUP_MEMBERSHIPS]: Schemas.GroupMember;
[Entities.GROUP_RELATIONSHIPS]: Schemas.GroupRelationship;
- [Entities.GROUP_TAGS]: Schemas.GroupTag;
[Entities.PATRON_USERS]: Schemas.PatronUser;
[Entities.RELATIONSHIPS]: Schemas.Relationship;
[Entities.RELAYS]: Schemas.Relay;
diff --git a/src/features/account/components/header.tsx b/src/features/account/components/header.tsx
index 392ecd834..4489c133c 100644
--- a/src/features/account/components/header.tsx
+++ b/src/features/account/components/header.tsx
@@ -24,7 +24,7 @@ import ActionButton from 'soapbox/features/ui/components/action-button';
import SubscriptionButton from 'soapbox/features/ui/components/subscription-button';
import { useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
import { normalizeAttachment } from 'soapbox/normalizers';
-import { ChatKeys, useChats } from 'soapbox/queries/chats';
+import { useChats } from 'soapbox/queries/chats';
import { queryClient } from 'soapbox/queries/client';
import { Account } from 'soapbox/schemas';
import toast from 'soapbox/toast';
@@ -101,7 +101,7 @@ const Header: React.FC = ({ account }) => {
onSuccess: (response) => {
history.push(`/chats/${response.data.id}`);
queryClient.invalidateQueries({
- queryKey: ChatKeys.chatSearch(),
+ queryKey: ['chats', 'search'],
});
},
});
@@ -555,24 +555,7 @@ const Header: React.FC = ({ account }) => {
return null;
}
- if (features.chatsWithFollowers) { // Truth Social
- const canChat = account.relationship?.followed_by;
- if (!canChat) {
- return null;
- }
-
- return (
- createAndNavigateToChat.mutate(account.id)}
- title={intl.formatMessage(messages.chat, { name: account.username })}
- theme='outlined'
- className='px-2'
- iconClassName='h-4 w-4'
- disabled={createAndNavigateToChat.isPending}
- />
- );
- } else if (account.pleroma?.accepts_chat_messages) {
+ if (account.pleroma?.accepts_chat_messages) {
return (
(
-
-
- Homepage
-
-);
-
-describe('', () => {
- it('handles successful responses from the API', async() => {
- __stub(mock => {
- mock.onPost('/api/v1/truth/password_reset/confirm')
- .reply(200, {});
- });
-
- render(
- ,
- {},
- null,
- { initialEntries: ['/edit'] },
- );
-
- fireEvent.submit(
- screen.getByTestId('form'), {
- preventDefault: () => {},
- },
- );
-
- await waitFor(() => {
- expect(screen.getByTestId('home')).toHaveTextContent('Homepage');
- expect(screen.queryByTestId('form-group-error')).not.toBeInTheDocument();
- });
- });
-
- it('handles failed responses from the API', async() => {
- __stub(mock => {
- mock.onPost('/api/v1/truth/password_reset/confirm')
- .reply(403, {});
- });
-
- render(
- ,
- {},
- null,
- { initialEntries: ['/edit'] },
- );
-
- await fireEvent.submit(
- screen.getByTestId('form'), {
- preventDefault: () => {},
- },
- );
-
- await waitFor(() => {
- expect(screen.queryByTestId('home')).not.toBeInTheDocument();
- expect(screen.queryByTestId('form-group-error')).toBeInTheDocument();
- });
- });
-});
diff --git a/src/features/auth-login/components/password-reset-confirm.tsx b/src/features/auth-login/components/password-reset-confirm.tsx
deleted file mode 100644
index c079b418d..000000000
--- a/src/features/auth-login/components/password-reset-confirm.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import React from 'react';
-import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import { Redirect } from 'react-router-dom';
-
-import { resetPasswordConfirm } from 'soapbox/actions/security';
-import { BigCard } from 'soapbox/components/big-card';
-import { Button, Form, FormActions, FormGroup, Input } from 'soapbox/components/ui';
-import { useAppDispatch } from 'soapbox/hooks';
-
-const token = new URLSearchParams(window.location.search).get('reset_password_token');
-
-const messages = defineMessages({
- resetPasswordFail: { id: 'reset_password.fail', defaultMessage: 'Expired token, please try again.' },
- passwordPlaceholder: { id: 'reset_password.password.placeholder', defaultMessage: 'Placeholder' },
-});
-
-const Statuses = {
- IDLE: 'IDLE',
- LOADING: 'LOADING',
- SUCCESS: 'SUCCESS',
- FAIL: 'FAIL',
-};
-
-const PasswordResetConfirm = () => {
- const intl = useIntl();
- const dispatch = useAppDispatch();
-
- const [password, setPassword] = React.useState('');
- const [status, setStatus] = React.useState(Statuses.IDLE);
-
- const isLoading = status === Statuses.LOADING;
-
- const handleSubmit: React.FormEventHandler = React.useCallback((event) => {
- event.preventDefault();
-
- setStatus(Statuses.LOADING);
- dispatch(resetPasswordConfirm(password, token as string))
- .then(() => setStatus(Statuses.SUCCESS))
- .catch(() => setStatus(Statuses.FAIL));
- }, [password]);
-
- const onChange: React.ChangeEventHandler = React.useCallback((event) => {
- setPassword(event.target.value);
- }, []);
-
- const renderErrors = () => {
- if (status === Statuses.FAIL) {
- return [intl.formatMessage(messages.resetPasswordFail)];
- }
-
- return [];
- };
-
- if (status === Statuses.SUCCESS) {
- return ;
- }
-
- return (
- }>
-
-
- );
-};
-
-export default PasswordResetConfirm;
diff --git a/src/features/chats/components/chat-list-item.test.tsx b/src/features/chats/components/chat-list-item.test.tsx
index cd6ad0421..294456dc3 100644
--- a/src/features/chats/components/chat-list-item.test.tsx
+++ b/src/features/chats/components/chat-list-item.test.tsx
@@ -8,20 +8,17 @@ import ChatListItem from './chat-list-item';
const chat: any = {
id: '1',
unread: 5,
- created_by_account: '2',
last_message: {
account_id: '2',
chat_id: '1',
content: 'hello world',
created_at: '2022-09-09T16:02:26.186Z',
- discarded_at: null,
id: '12332423234',
unread: true,
},
created_at: '2022-09-09T16:02:26.186Z',
updated_at: '2022-09-09T16:02:26.186Z',
accepted: true,
- discarded_at: null,
account: {
acct: 'username',
display_name: 'johnnie',
diff --git a/src/features/chats/components/chat-list.tsx b/src/features/chats/components/chat-list.tsx
index 0c353e940..f896f027b 100644
--- a/src/features/chats/components/chat-list.tsx
+++ b/src/features/chats/components/chat-list.tsx
@@ -14,15 +14,14 @@ import ChatListItem from './chat-list-item';
interface IChatList {
onClickChat: (chat: any) => void;
useWindowScroll?: boolean;
- searchValue?: string;
}
-const ChatList: React.FC = ({ onClickChat, useWindowScroll = false, searchValue }) => {
+const ChatList: React.FC = ({ onClickChat, useWindowScroll = false }) => {
const dispatch = useAppDispatch();
const chatListRef = useRef(null);
- const { chatsQuery: { data: chats, isFetching, hasNextPage, fetchNextPage } } = useChats(searchValue);
+ const { chatsQuery: { data: chats, isFetching, hasNextPage, fetchNextPage } } = useChats();
const [isNearBottom, setNearBottom] = useState(false);
const [isNearTop, setNearTop] = useState(true);
diff --git a/src/features/chats/components/chat-message-list-intro.tsx b/src/features/chats/components/chat-message-list-intro.tsx
deleted file mode 100644
index d41c55240..000000000
--- a/src/features/chats/components/chat-message-list-intro.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import clsx from 'clsx';
-import React from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-import { useHistory } from 'react-router-dom';
-
-import { openModal } from 'soapbox/actions/modals';
-import Link from 'soapbox/components/link';
-import { Avatar, Button, HStack, Icon, Stack, Text } from 'soapbox/components/ui';
-import { useChatContext } from 'soapbox/contexts/chat-context';
-import { useAppDispatch, useFeatures } from 'soapbox/hooks';
-import { useChatActions } from 'soapbox/queries/chats';
-import { secondsToDays } from 'soapbox/utils/numbers';
-
-const messages = defineMessages({
- leaveChatHeading: { id: 'chat_message_list_intro.leave_chat.heading', defaultMessage: 'Leave Chat' },
- leaveChatMessage: { id: 'chat_message_list_intro.leave_chat.message', defaultMessage: 'Are you sure you want to leave this chat? Messages will be deleted for you and this chat will be removed from your inbox.' },
- leaveChatConfirm: { id: 'chat_message_list_intro.leave_chat.confirm', defaultMessage: 'Leave Chat' },
- intro: { id: 'chat_message_list_intro.intro', defaultMessage: 'wants to start a chat with you' },
- accept: { id: 'chat_message_list_intro.actions.accept', defaultMessage: 'Accept' },
- leaveChat: { id: 'chat_message_list_intro.actions.leave_chat', defaultMessage: 'Leave chat' },
- report: { id: 'chat_message_list_intro.actions.report', defaultMessage: 'Report' },
- messageLifespan: { id: 'chat_message_list_intro.actions.message_lifespan', defaultMessage: 'Messages older than {day, plural, one {# day} other {# days}} are deleted.' },
-});
-
-const ChatMessageListIntro = () => {
- const dispatch = useAppDispatch();
- const intl = useIntl();
- const features = useFeatures();
- const history = useHistory();
-
- const { chat, isUsingMainChatPage, needsAcceptance } = useChatContext();
- const { acceptChat, deleteChat } = useChatActions(chat?.id as string);
-
- const handleLeaveChat = () => {
- dispatch(openModal('CONFIRM', {
- heading: intl.formatMessage(messages.leaveChatHeading),
- message: intl.formatMessage(messages.leaveChatMessage),
- confirm: intl.formatMessage(messages.leaveChatConfirm),
- confirmationTheme: 'primary',
- onConfirm: () => {
- deleteChat.mutate(undefined, {
- onSuccess() {
- if (isUsingMainChatPage) {
- history.push('/chats');
- }
- },
- });
- },
- }));
- };
-
- if (!chat || !features.chatAcceptance) {
- return null;
- }
-
- return (
-
-
-
-
-
-
-
- {needsAcceptance ? (
- <>
- @{chat.account.acct}
- {' '}
- {intl.formatMessage(messages.intro)}
- >
- ) : (
-
- @{chat.account.acct}
-
- )}
-
-
-
- {needsAcceptance ? (
-
-
-
-
-
- ) : (
-
-
- {chat.message_expiration && (
-
- {intl.formatMessage(messages.messageLifespan, { day: secondsToDays(chat.message_expiration) })}
-
- )}
-
- )}
-
- );
-};
-
-export default ChatMessageListIntro;
diff --git a/src/features/chats/components/chat-message-list.test.tsx b/src/features/chats/components/chat-message-list.test.tsx
index 23c522e81..c62805799 100644
--- a/src/features/chats/components/chat-message-list.test.tsx
+++ b/src/features/chats/components/chat-message-list.test.tsx
@@ -13,7 +13,6 @@ import { ChatMessage } from 'soapbox/types/entities';
import ChatMessageList from './chat-message-list';
const chat: IChat = {
- accepted: true,
account: buildAccount({
username: 'username',
verified: true,
@@ -23,15 +22,9 @@ const chat: IChat = {
avatar_static: 'avatar',
display_name: 'my name',
}),
- chat_type: 'direct',
created_at: '2020-06-10T02:05:06.000Z',
- created_by_account: '2',
- discarded_at: null,
id: '14',
last_message: null,
- latest_read_message_by_account: [],
- latest_read_message_created_at: null,
- message_expiration: 1209600,
unread: 5,
};
@@ -41,8 +34,6 @@ const chatMessages: ChatMessage[] = [
chat_id: '14',
content: 'this is the first chat',
created_at: '2022-09-09T16:02:26.186Z',
- emoji_reactions: null,
- expiration: 1209600,
id: '1',
unread: false,
pending: false,
@@ -52,8 +43,6 @@ const chatMessages: ChatMessage[] = [
chat_id: '14',
content: 'this is the second chat',
created_at: '2022-09-09T16:04:26.186Z',
- emoji_reactions: null,
- expiration: 1209600,
id: '2',
unread: true,
pending: false,
diff --git a/src/features/chats/components/chat-message-list.tsx b/src/features/chats/components/chat-message-list.tsx
index 0d8272cd0..84c9de270 100644
--- a/src/features/chats/components/chat-message-list.tsx
+++ b/src/features/chats/components/chat-message-list.tsx
@@ -4,11 +4,10 @@ import { Components, Virtuoso, VirtuosoHandle } from 'react-virtuoso';
import { Avatar, Button, Divider, Spinner, Stack, Text } from 'soapbox/components/ui';
import PlaceholderChatMessage from 'soapbox/features/placeholder/components/placeholder-chat-message';
-import { useAppSelector, useOwnAccount } from 'soapbox/hooks';
+import { useAppSelector } from 'soapbox/hooks';
import { IChat, useChatActions, useChatMessages } from 'soapbox/queries/chats';
import ChatMessage from './chat-message';
-import ChatMessageListIntro from './chat-message-list-intro';
import type { ChatMessage as ChatMessageEntity } from 'soapbox/types/entities';
@@ -69,10 +68,6 @@ interface IChatMessageList {
/** Scrollable list of chat messages. */
const ChatMessageList: React.FC = ({ chat }) => {
const intl = useIntl();
- const { account } = useOwnAccount();
-
- const myLastReadMessageDateString = chat.latest_read_message_by_account?.find((latest) => latest.id === account?.id)?.date;
- const myLastReadMessageTimestamp = myLastReadMessageDateString ? new Date(myLastReadMessageDateString) : null;
const node = useRef(null);
const [firstItemIndex, setFirstItemIndex] = useState(START_INDEX - 20);
@@ -174,14 +169,13 @@ const ChatMessageList: React.FC = ({ chat }) => {
const lastMessageId = lastMessage.id;
const isMessagePending = lastMessage.pending;
- const isAlreadyRead = myLastReadMessageTimestamp ? myLastReadMessageTimestamp >= new Date(lastMessage.created_at) : false;
/**
* Only "mark the message as read" if..
* 1) it is not pending and
* 2) it has not already been read
*/
- if (!isMessagePending && !isAlreadyRead) {
+ if (!isMessagePending) {
markChatAsRead(lastMessageId);
}
}, [formattedChatMessages.length]);
@@ -265,10 +259,6 @@ const ChatMessageList: React.FC = ({ chat }) => {
return ;
}
- if (!hasNextPage && !isLoading) {
- return ;
- }
-
return null;
},
}}
diff --git a/src/features/chats/components/chat-message-reaction-wrapper/chat-message-reaction-wrapper.tsx b/src/features/chats/components/chat-message-reaction-wrapper/chat-message-reaction-wrapper.tsx
deleted file mode 100644
index 6e604ff09..000000000
--- a/src/features/chats/components/chat-message-reaction-wrapper/chat-message-reaction-wrapper.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import React, { useState, useEffect } from 'react';
-
-import { Portal } from 'soapbox/components/ui';
-import EmojiSelector from 'soapbox/components/ui/emoji-selector/emoji-selector';
-
-interface IChatMessageReactionWrapper {
- onOpen(isOpen: boolean): void;
- onSelect(emoji: string): void;
- children: JSX.Element;
-}
-
-/**
- * Emoji Reaction Selector
- */
-function ChatMessageReactionWrapper(props: IChatMessageReactionWrapper) {
- const { onOpen, onSelect, children } = props;
-
- const [isOpen, setIsOpen] = useState(false);
-
- const [referenceElement, setReferenceElement] = useState(null);
-
- const handleSelect = (emoji: string) => {
- onSelect(emoji);
- setIsOpen(false);
- };
-
- const onToggleVisibility = () => setIsOpen((prevValue) => !prevValue);
-
- useEffect(() => {
- onOpen(isOpen);
- }, [isOpen]);
-
- return (
-
- {React.cloneElement(children, {
- ref: setReferenceElement,
- onClick: onToggleVisibility,
- })}
-
- {isOpen && (
-
- setIsOpen(false)}
- offsetOptions={{ mainAxis: 12, crossAxis: -10 }}
- all={false}
- />
-
- )}
-
- );
-}
-
-export default ChatMessageReactionWrapper;
\ No newline at end of file
diff --git a/src/features/chats/components/chat-message-reaction.test.tsx b/src/features/chats/components/chat-message-reaction.test.tsx
deleted file mode 100644
index 88f102711..000000000
--- a/src/features/chats/components/chat-message-reaction.test.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import userEvent from '@testing-library/user-event';
-import React from 'react';
-
-import { render, screen } from 'soapbox/jest/test-helpers';
-
-import ChatMessageReaction from './chat-message-reaction';
-
-const emojiReaction = ({
- name: '👍',
- count: 1,
- me: false,
-});
-
-describe('', () => {
- it('renders properly', () => {
- render(
- ,
- );
-
- expect(screen.getByRole('img').getAttribute('alt')).toEqual(emojiReaction.name);
- expect(screen.getByRole('button')).toHaveTextContent(String(emojiReaction.count));
- });
-
- it('triggers the "onAddReaction" function', async () => {
- const onAddFn = vi.fn();
- const onRemoveFn = vi.fn();
- const user = userEvent.setup();
-
- render(
- ,
- );
-
- expect(onAddFn).not.toBeCalled();
- expect(onRemoveFn).not.toBeCalled();
-
- await user.click(screen.getByRole('button'));
-
- // add function triggered
- expect(onAddFn).toBeCalled();
- expect(onRemoveFn).not.toBeCalled();
- });
-
- it('triggers the "onRemoveReaction" function', async () => {
- const onAddFn = vi.fn();
- const onRemoveFn = vi.fn();
- const user = userEvent.setup();
-
- render(
- ,
- );
-
- expect(onAddFn).not.toBeCalled();
- expect(onRemoveFn).not.toBeCalled();
-
- await user.click(screen.getByRole('button'));
-
- // remove function triggered
- expect(onAddFn).not.toBeCalled();
- expect(onRemoveFn).toBeCalled();
- });
-});
\ No newline at end of file
diff --git a/src/features/chats/components/chat-message-reaction.tsx b/src/features/chats/components/chat-message-reaction.tsx
deleted file mode 100644
index 3b054bd50..000000000
--- a/src/features/chats/components/chat-message-reaction.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import clsx from 'clsx';
-import React from 'react';
-
-import { Text } from 'soapbox/components/ui';
-import emojify from 'soapbox/features/emoji';
-import { EmojiReaction } from 'soapbox/types/entities';
-
-interface IChatMessageReaction {
- emojiReaction: EmojiReaction;
- onRemoveReaction(emoji: string): void;
- onAddReaction(emoji: string): void;
-}
-
-const ChatMessageReaction = (props: IChatMessageReaction) => {
- const { emojiReaction, onAddReaction, onRemoveReaction } = props;
-
- const isAlreadyReacted = emojiReaction.me;
-
- const handleClick = () => {
- if (isAlreadyReacted) {
- onRemoveReaction(emojiReaction.name);
- } else {
- onAddReaction(emojiReaction.name);
- }
- };
-
- return (
-
- );
-};
-
-export default ChatMessageReaction;
diff --git a/src/features/chats/components/chat-message.tsx b/src/features/chats/components/chat-message.tsx
index 3498ecddf..5921149ca 100644
--- a/src/features/chats/components/chat-message.tsx
+++ b/src/features/chats/components/chat-message.tsx
@@ -6,20 +6,16 @@ import React, { useMemo, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { openModal } from 'soapbox/actions/modals';
-import { initReport, ReportableEntities } from 'soapbox/actions/reports';
import DropdownMenu from 'soapbox/components/dropdown-menu';
import { HStack, Icon, Stack, Text } from 'soapbox/components/ui';
import emojify from 'soapbox/features/emoji';
import { MediaGallery } from 'soapbox/features/ui/util/async-components';
-import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
+import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { ChatKeys, IChat, useChatActions } from 'soapbox/queries/chats';
import { queryClient } from 'soapbox/queries/client';
import { stripHTML } from 'soapbox/utils/html';
import { onlyEmoji } from 'soapbox/utils/rich-content';
-import ChatMessageReaction from './chat-message-reaction';
-import ChatMessageReactionWrapper from './chat-message-reaction-wrapper/chat-message-reaction-wrapper';
-
import type { Menu as IMenu } from 'soapbox/components/dropdown-menu';
import type { ChatMessage as ChatMessageEntity } from 'soapbox/types/entities';
@@ -59,13 +55,11 @@ const ChatMessage = (props: IChatMessage) => {
const { chat, chatMessage } = props;
const dispatch = useAppDispatch();
- const features = useFeatures();
const intl = useIntl();
const me = useAppSelector((state) => state.me);
- const { createReaction, deleteChatMessage, deleteReaction } = useChatActions(chat.id);
+ const { deleteChatMessage } = useChatActions(chat.id);
- const [isReactionSelectorOpen, setIsReactionSelectorOpen] = useState(false);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const handleDeleteMessage = useMutation({
@@ -78,32 +72,14 @@ const ChatMessage = (props: IChatMessage) => {
});
const content = parseContent(chatMessage);
- const lastReadMessageDateString = chat.latest_read_message_by_account?.find((latest) => latest.id === chat.account.id)?.date;
- const lastReadMessageTimestamp = lastReadMessageDateString ? new Date(lastReadMessageDateString) : null;
const isMyMessage = chatMessage.account_id === me;
- // did this occur before this time?
- const isRead = isMyMessage
- && lastReadMessageTimestamp
- && lastReadMessageTimestamp >= new Date(chatMessage.created_at);
-
const isOnlyEmoji = useMemo(() => {
const hiddenEl = document.createElement('div');
hiddenEl.innerHTML = content;
return onlyEmoji(hiddenEl, BIG_EMOJI_LIMIT, false);
}, []);
- const emojiReactionRows = useMemo(() => {
- if (!chatMessage.emoji_reactions) {
- return [];
- }
-
- return chatMessage.emoji_reactions.reduce((rows: any, key: any, index) => {
- return (index % 4 === 0 ? rows.push([key])
- : rows[rows.length - 1].push(key)) && rows;
- }, []);
- }, [chatMessage.emoji_reactions]);
-
const onOpenMedia = (media: any, index: number) => {
dispatch(openModal('MEDIA', { media, index }));
};
@@ -171,13 +147,6 @@ const ChatMessage = (props: IChatMessage) => {
destructive: true,
});
} else {
- if (features.reportChats) {
- menu.push({
- text: intl.formatMessage(messages.report),
- action: () => dispatch(initReport(ReportableEntities.CHAT_MESSAGE, chat.account, { chatMessage })),
- icon: require('@tabler/icons/outline/flag.svg'),
- });
- }
menu.push({
text: intl.formatMessage(messages.deleteForMe),
action: () => handleDeleteMessage.mutate(chatMessage.id),
@@ -194,7 +163,7 @@ const ChatMessage = (props: IChatMessage) => {
className={
clsx({
'group relative px-4 py-2 hover:bg-gray-200/40 dark:hover:bg-gray-800/40': true,
- 'bg-gray-200/40 dark:bg-gray-800/40': isMenuOpen || isReactionSelectorOpen,
+ 'bg-gray-200/40 dark:bg-gray-800/40': isMenuOpen,
})
}
data-testid='chat-message'
@@ -205,29 +174,10 @@ const ChatMessage = (props: IChatMessage) => {
'p-1 flex items-center space-x-0.5 z-10 absolute opacity-0 transition-opacity group-hover:opacity-100 focus:opacity-100 rounded-md shadow-lg bg-white dark:bg-gray-900 dark:ring-2 dark:ring-primary-700': true,
'top-2 right-2': !isMyMessage,
'top-2 left-2': isMyMessage,
- '!opacity-100': isMenuOpen || isReactionSelectorOpen,
+ '!opacity-100': isMenuOpen,
})
}
>
- {features.chatEmojiReactions && (
- createReaction.mutate({ emoji, messageId: chatMessage.id, chatMessage })}
- >
-
-
- )}
{menu.length > 0 && (
{
- {(chatMessage.emoji_reactions?.length) ? (
-
- {emojiReactionRows?.map((emojiReactionRow: any, idx: number) => (
-
- {emojiReactionRow.map((emojiReaction: any, idx: number) => (
- createReaction.mutate({ emoji, messageId: chatMessage.id, chatMessage })}
- onRemoveReaction={(emoji) => deleteReaction.mutate({ emoji, messageId: chatMessage.id })}
- />
- ))}
-
- ))}
-
- ) : null}
-
{
{intl.formatTime(chatMessage.created_at)}
-
- {(isMyMessage && features.chatsReadReceipts) ? (
- <>
- {isRead ? (
-
-
-
- ) : (
-
-
-
- )}
- >
- ) : null}
diff --git a/src/features/chats/components/chat-page/chat-page.tsx b/src/features/chats/components/chat-page/chat-page.tsx
index 8384c8744..178607898 100644
--- a/src/features/chats/components/chat-page/chat-page.tsx
+++ b/src/features/chats/components/chat-page/chat-page.tsx
@@ -3,24 +3,19 @@ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { matchPath, Route, Switch, useHistory } from 'react-router-dom';
import { Stack } from 'soapbox/components/ui';
-import { useOwnAccount } from 'soapbox/hooks';
import ChatPageMain from './components/chat-page-main';
import ChatPageNew from './components/chat-page-new';
import ChatPageSettings from './components/chat-page-settings';
import ChatPageSidebar from './components/chat-page-sidebar';
-import Welcome from './components/welcome';
interface IChatPage {
chatId?: string;
}
const ChatPage: React.FC = ({ chatId }) => {
- const { account } = useOwnAccount();
const history = useHistory();
- const isOnboarded = account?.source?.chats_onboarded ?? true;
-
const path = history.location.pathname;
const isSidebarHidden = matchPath(path, {
path: ['/chats/settings', '/chats/new', '/chats/:chatId'],
@@ -62,40 +57,36 @@ const ChatPage: React.FC = ({ chatId }) => {
style={{ height }}
className='h-screen overflow-hidden bg-white text-gray-900 shadow-lg black:bg-transparent sm:rounded-t-xl dark:bg-primary-900 dark:text-gray-100 dark:shadow-none'
>
- {isOnboarded ? (
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ) : (
-
- )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/features/chats/components/chat-page/components/chat-page-main.tsx b/src/features/chats/components/chat-page/components/chat-page-main.tsx
index 15178e0c7..df3a0f4f7 100644
--- a/src/features/chats/components/chat-page/components/chat-page-main.tsx
+++ b/src/features/chats/components/chat-page/components/chat-page-main.tsx
@@ -4,13 +4,11 @@ import { Link, useHistory, useParams } from 'react-router-dom';
import { blockAccount, unblockAccount } from 'soapbox/actions/accounts';
import { openModal } from 'soapbox/actions/modals';
-import List, { ListItem } from 'soapbox/components/list';
-import { Avatar, HStack, Icon, IconButton, Menu, MenuButton, MenuItem, MenuList, Stack, Text, Tooltip } from 'soapbox/components/ui';
+import { Avatar, HStack, Icon, IconButton, Menu, MenuButton, MenuItem, MenuList, Stack, Text } from 'soapbox/components/ui';
import VerificationBadge from 'soapbox/components/verification-badge';
import { useChatContext } from 'soapbox/contexts/chat-context';
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
-import { MessageExpirationValues, useChat, useChatActions, useChats } from 'soapbox/queries/chats';
-import { secondsToDays } from 'soapbox/utils/numbers';
+import { useChat, useChatActions, useChats } from 'soapbox/queries/chats';
import Chat from '../../chat';
@@ -31,15 +29,6 @@ const messages = defineMessages({
unblockUser: { id: 'chat_settings.options.unblock_user', defaultMessage: 'Unblock @{acct}' },
reportUser: { id: 'chat_settings.options.report_user', defaultMessage: 'Report @{acct}' },
leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave Chat' },
- autoDeleteLabel: { id: 'chat_settings.auto_delete.label', defaultMessage: 'Auto-delete messages' },
- autoDeleteHint: { id: 'chat_settings.auto_delete.hint', defaultMessage: 'Sent messages will auto-delete after the time period selected' },
- autoDelete2Minutes: { id: 'chat_settings.auto_delete.2minutes', defaultMessage: '2 minutes' },
- autoDelete7Days: { id: 'chat_settings.auto_delete.7days', defaultMessage: '7 days' },
- autoDelete14Days: { id: 'chat_settings.auto_delete.14days', defaultMessage: '14 days' },
- autoDelete30Days: { id: 'chat_settings.auto_delete.30days', defaultMessage: '30 days' },
- autoDelete90Days: { id: 'chat_settings.auto_delete.90days', defaultMessage: '90 days' },
- autoDeleteMessage: { id: 'chat_window.auto_delete_label', defaultMessage: 'Auto-delete after {day, plural, one {# day} other {# days}}' },
- autoDeleteMessageTooltip: { id: 'chat_window.auto_delete_tooltip', defaultMessage: 'Chat messages are set to auto-delete after {day, plural, one {# day} other {# days}} upon sending.' },
});
const ChatPageMain = () => {
@@ -56,9 +45,7 @@ const ChatPageMain = () => {
const inputRef = useRef(null);
- const { deleteChat, updateChat } = useChatActions(chat?.id as string);
-
- const handleUpdateChat = (value: MessageExpirationValues) => updateChat.mutate({ message_expiration: value });
+ const { deleteChat } = useChatActions(chat?.id as string);
const isBlocking = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocking']));
@@ -139,23 +126,6 @@ const ChatPageMain = () => {
{chat.account.verified && }
-
- {chat.message_expiration && (
-
-
- {intl.formatMessage(messages.autoDeleteMessage, { day: secondsToDays(chat.message_expiration) })}
-
-
- )}
@@ -177,35 +147,6 @@ const ChatPageMain = () => {
- {features.chatsExpiration && (
-
-
- handleUpdateChat(MessageExpirationValues.SEVEN)}
- isSelected={chat.message_expiration === MessageExpirationValues.SEVEN}
- />
- handleUpdateChat(MessageExpirationValues.FOURTEEN)}
- isSelected={chat.message_expiration === MessageExpirationValues.FOURTEEN}
- />
- handleUpdateChat(MessageExpirationValues.THIRTY)}
- isSelected={chat.message_expiration === MessageExpirationValues.THIRTY}
- />
- handleUpdateChat(MessageExpirationValues.NINETY)}
- isSelected={chat.message_expiration === MessageExpirationValues.NINETY}
- />
-
- )}
-
-
+
);
diff --git a/src/features/chats/components/chat-page/components/welcome.tsx b/src/features/chats/components/chat-page/components/welcome.tsx
deleted file mode 100644
index f78de0e32..000000000
--- a/src/features/chats/components/chat-page/components/welcome.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-import React, { useState } from 'react';
-import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-
-import List, { ListItem } from 'soapbox/components/list';
-import { Button, CardBody, CardTitle, Form, Stack, Text, Toggle } from 'soapbox/components/ui';
-import { useOwnAccount } from 'soapbox/hooks';
-import { useUpdateCredentials } from 'soapbox/queries/accounts';
-
-type FormData = {
- accepts_chat_messages?: boolean;
- chats_onboarded: boolean;
-}
-
-const messages = defineMessages({
- title: { id: 'chat.welcome.title', defaultMessage: 'Welcome to {br} Chats!' },
- subtitle: { id: 'chat.welcome.subtitle', defaultMessage: 'Exchange direct messages with other users.' },
- acceptingMessageLabel: { id: 'chat.welcome.accepting_messages.label', defaultMessage: 'Allow users to start a new chat with you' },
- notice: { id: 'chat.welcome.notice', defaultMessage: 'You can change these settings later.' },
- submit: { id: 'chat.welcome.submit', defaultMessage: 'Save & Continue' },
-});
-
-const Welcome = () => {
- const { account } = useOwnAccount();
- const intl = useIntl();
- const updateCredentials = useUpdateCredentials();
-
- const [data, setData] = useState({
- chats_onboarded: true,
- accepts_chat_messages: account?.pleroma?.accepts_chat_messages === true,
- });
-
- const handleSubmit = (event: React.FormEvent) => {
- event.preventDefault();
-
- updateCredentials.mutate(data);
- };
-
- return (
-
-
-
- {intl.formatMessage(messages.title, { br:
})}
-
-
-
- {intl.formatMessage(messages.subtitle)}
-
-
-
-
-
- );
-};
-
-export default Welcome;
diff --git a/src/features/chats/components/chat-pane/chat-pane.test.tsx b/src/features/chats/components/chat-pane/chat-pane.test.tsx
index 3997c242c..fd0358431 100644
--- a/src/features/chats/components/chat-pane/chat-pane.test.tsx
+++ b/src/features/chats/components/chat-pane/chat-pane.test.tsx
@@ -45,21 +45,19 @@ describe('', () => {
// });
// });
- describe('when the software is not Truth Social', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet('/api/v1/pleroma/chats').reply(200, chats, {
- link: '; rel=\'prev\'',
- });
- });
- });
-
- it('does not render the search input', async () => {
- renderComponentWithChatContext();
-
- await waitFor(() => {
- expect(screen.queryAllByTestId('chat-search-input')).toHaveLength(0);
+ beforeEach(() => {
+ __stub((mock) => {
+ mock.onGet('/api/v1/pleroma/chats').reply(200, chats, {
+ link: '; rel=\'prev\'',
});
});
});
+
+ it('does not render the search input', async () => {
+ renderComponentWithChatContext();
+
+ await waitFor(() => {
+ expect(screen.queryAllByTestId('chat-search-input')).toHaveLength(0);
+ });
+ });
});
diff --git a/src/features/chats/components/chat-pane/chat-pane.tsx b/src/features/chats/components/chat-pane/chat-pane.tsx
index 1f0dde8f8..03e4b0555 100644
--- a/src/features/chats/components/chat-pane/chat-pane.tsx
+++ b/src/features/chats/components/chat-pane/chat-pane.tsx
@@ -1,16 +1,14 @@
-import React, { useState } from 'react';
+import React from 'react';
import { FormattedMessage } from 'react-intl';
import { Stack } from 'soapbox/components/ui';
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
import { useStatContext } from 'soapbox/contexts/stat-context';
-import { useDebounce, useFeatures } from 'soapbox/hooks';
import { IChat, useChats } from 'soapbox/queries/chats';
import ChatList from '../chat-list';
import ChatSearch from '../chat-search/chat-search';
import EmptyResultsBlankslate from '../chat-search/empty-results-blankslate';
-import ChatSearchInput from '../chat-search-input';
import ChatPaneHeader from '../chat-widget/chat-pane-header';
import ChatWindow from '../chat-widget/chat-window';
import ChatSearchHeader from '../chat-widget/headers/chat-search-header';
@@ -19,46 +17,21 @@ import { Pane } from '../ui';
import Blankslate from './blankslate';
const ChatPane = () => {
- const features = useFeatures();
- const debounce = useDebounce;
const { unreadChatsCount } = useStatContext();
- const [value, setValue] = useState();
- const debouncedValue = debounce(value as string, 300);
-
const { screen, changeScreen, isOpen, toggleChatPane } = useChatContext();
- const { chatsQuery: { data: chats, isLoading } } = useChats(debouncedValue);
-
- const hasSearchValue = Number(debouncedValue?.length) > 0;
+ const { chatsQuery: { data: chats, isLoading } } = useChats();
const handleClickChat = (nextChat: IChat) => {
changeScreen(ChatWidgetScreens.CHAT, nextChat.id);
- setValue(undefined);
- };
-
- const clearValue = () => {
- if (hasSearchValue) {
- setValue('');
- }
};
const renderBody = () => {
- if (hasSearchValue || Number(chats?.length) > 0 || isLoading) {
+ if (Number(chats?.length) > 0 || isLoading) {
return (
- {features.chatsSearch && (
-
- setValue(event.target.value)}
- onClear={clearValue}
- />
-
- )}
-
{(Number(chats?.length) > 0 || isLoading) ? (
) : (
@@ -105,7 +78,6 @@ const ChatPane = () => {
onToggle={toggleChatPane}
secondaryAction={() => {
changeScreen(ChatWidgetScreens.SEARCH);
- setValue(undefined);
if (!isOpen) {
toggleChatPane();
diff --git a/src/features/chats/components/chat-search-input.tsx b/src/features/chats/components/chat-search-input.tsx
deleted file mode 100644
index 703202ee1..000000000
--- a/src/features/chats/components/chat-search-input.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import React from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-
-import { Icon, Input } from 'soapbox/components/ui';
-
-const messages = defineMessages({
- searchPlaceholder: { id: 'chats.search_placeholder', defaultMessage: 'Start a chat with…' },
-});
-
-interface IChatSearchInput {
- /** Search term. */
- value: string;
- /** Callback when the search value changes. */
- onChange: React.ChangeEventHandler;
- /** Callback when the input is cleared. */
- onClear: React.MouseEventHandler;
-}
-
-/** Search input for filtering chats. */
-const ChatSearchInput: React.FC = ({ value, onChange, onClear }) => {
- const intl = useIntl();
-
- return (
-
-
-
- }
- />
- );
-};
-
-export default ChatSearchInput;
\ No newline at end of file
diff --git a/src/features/chats/components/chat-search/chat-search.tsx b/src/features/chats/components/chat-search/chat-search.tsx
index 094e39d63..ba8af3df6 100644
--- a/src/features/chats/components/chat-search/chat-search.tsx
+++ b/src/features/chats/components/chat-search/chat-search.tsx
@@ -7,7 +7,7 @@ import { useHistory } from 'react-router-dom';
import { Icon, Input, Stack } from 'soapbox/components/ui';
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
import { useDebounce } from 'soapbox/hooks';
-import { useChats, ChatKeys } from 'soapbox/queries/chats';
+import { useChats } from 'soapbox/queries/chats';
import { queryClient } from 'soapbox/queries/client';
import useAccountSearch from 'soapbox/queries/search';
import toast from 'soapbox/toast';
@@ -56,7 +56,7 @@ const ChatSearch = (props: IChatSearch) => {
changeScreen(ChatWidgetScreens.CHAT, response.data.id);
}
- queryClient.invalidateQueries({ queryKey: ChatKeys.chatSearch() });
+ queryClient.invalidateQueries({ queryKey: ['chats', 'search'] });
},
});
diff --git a/src/features/chats/components/chat-widget.test.tsx b/src/features/chats/components/chat-widget.test.tsx
index a183be076..da80ca72c 100644
--- a/src/features/chats/components/chat-widget.test.tsx
+++ b/src/features/chats/components/chat-widget.test.tsx
@@ -12,9 +12,6 @@ const account = buildAccount({
acct: 'justin-username',
display_name: 'Justin L',
avatar: 'test.jpg',
- source: {
- chats_onboarded: true,
- },
});
const store = rootState
diff --git a/src/features/chats/components/chat-widget/chat-settings.tsx b/src/features/chats/components/chat-widget/chat-settings.tsx
index e1b1cabf6..87d535f98 100644
--- a/src/features/chats/components/chat-widget/chat-settings.tsx
+++ b/src/features/chats/components/chat-widget/chat-settings.tsx
@@ -3,12 +3,10 @@ import { defineMessages, useIntl } from 'react-intl';
import { blockAccount, unblockAccount } from 'soapbox/actions/accounts';
import { openModal } from 'soapbox/actions/modals';
-import List, { ListItem } from 'soapbox/components/list';
-import { Avatar, HStack, Icon, Select, Stack, Text } from 'soapbox/components/ui';
+import { Avatar, HStack, Icon, Stack, Text } from 'soapbox/components/ui';
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
-import { messageExpirationOptions, MessageExpirationValues, useChatActions } from 'soapbox/queries/chats';
-import { secondsToDays } from 'soapbox/utils/numbers';
+import { useChatActions } from 'soapbox/queries/chats';
import ChatPaneHeader from './chat-pane-header';
@@ -26,8 +24,6 @@ const messages = defineMessages({
blockUser: { id: 'chat_settings.options.block_user', defaultMessage: 'Block @{acct}' },
unblockUser: { id: 'chat_settings.options.unblock_user', defaultMessage: 'Unblock @{acct}' },
leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave Chat' },
- autoDeleteLabel: { id: 'chat_settings.auto_delete.label', defaultMessage: 'Auto-delete messages' },
- autoDeleteDays: { id: 'chat_settings.auto_delete.days', defaultMessage: '{day, plural, one {# day} other {# days}}' },
});
const ChatSettings = () => {
@@ -36,9 +32,7 @@ const ChatSettings = () => {
const features = useFeatures();
const { chat, changeScreen, toggleChatPane } = useChatContext();
- const { deleteChat, updateChat } = useChatActions(chat?.id as string);
-
- const handleUpdateChat = (value: MessageExpirationValues) => updateChat.mutate({ message_expiration: value });
+ const { deleteChat } = useChatActions(chat?.id as string);
const isBlocking = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocking']));
@@ -116,24 +110,6 @@ const ChatSettings = () => {
- {features.chatsExpiration && (
-
-
-
-
-
- )}
-
diff --git a/src/features/chats/components/chat.tsx b/src/features/chats/components/chat.tsx
index 627fe2972..5b9730709 100644
--- a/src/features/chats/components/chat.tsx
+++ b/src/features/chats/components/chat.tsx
@@ -52,7 +52,7 @@ const Chat: React.FC = ({ chat, inputRef, className }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
- const { createChatMessage, acceptChat } = useChatActions(chat.id);
+ const { createChatMessage } = useChatActions(chat.id);
const attachmentLimit = useAppSelector(state => state.instance.configuration.chats.max_media_attachments);
const [content, setContent] = useState('');
@@ -95,10 +95,6 @@ const Chat: React.FC = ({ chat, inputRef, className }) => {
const sendMessage = () => {
if (!isSubmitDisabled && !createChatMessage.isPending) {
submitMessage();
-
- if (!chat.accepted) {
- acceptChat.mutate();
- }
}
};
diff --git a/src/features/compose/components/reply-group-indicator.tsx b/src/features/compose/components/reply-group-indicator.tsx
index 2554ee67f..eb73a21b3 100644
--- a/src/features/compose/components/reply-group-indicator.tsx
+++ b/src/features/compose/components/reply-group-indicator.tsx
@@ -30,7 +30,7 @@ const ReplyGroupIndicator = (props: IReplyGroupIndicator) => {
defaultMessage='Posting to {groupLink}'
values={{
groupLink: ,
}}
diff --git a/src/features/edit-profile/index.tsx b/src/features/edit-profile/index.tsx
index a01fbe816..2f56a20a7 100644
--- a/src/features/edit-profile/index.tsx
+++ b/src/features/edit-profile/index.tsx
@@ -53,7 +53,6 @@ const messages = defineMessages({
error: { id: 'edit_profile.error', defaultMessage: 'Profile update failed' },
bioPlaceholder: { id: 'edit_profile.fields.bio_placeholder', defaultMessage: 'Tell us about yourself.' },
displayNamePlaceholder: { id: 'edit_profile.fields.display_name_placeholder', defaultMessage: 'Name' },
- websitePlaceholder: { id: 'edit_profile.fields.website_placeholder', defaultMessage: 'Display a Link' },
locationPlaceholder: { id: 'edit_profile.fields.location_placeholder', defaultMessage: 'Location' },
nip05Placeholder: { id: 'edit_profile.fields.nip05_placeholder', defaultMessage: 'user@{domain}' },
cancel: { id: 'common.cancel', defaultMessage: 'Cancel' },
@@ -120,8 +119,6 @@ interface AccountCredentials {
hide_followers_count?: boolean;
/** Pleroma: whether to publicly display follows count. */
hide_follows_count?: boolean;
- /** User's website URL. */
- website?: string;
/** User's location. */
location?: string;
/** User's birthday. */
@@ -147,7 +144,6 @@ const accountToCredentials = (account: Account): AccountCredentials => {
hide_follows: hideNetwork,
hide_followers_count: hideNetwork,
hide_follows_count: hideNetwork,
- website: account.website,
location: account.location,
birthday: account.pleroma?.birthday ?? undefined,
nip05: account.source?.nostr?.nip05 ?? '',
@@ -354,19 +350,6 @@ const EditProfile: React.FC = () => {
)}
- {features.accountWebsite && (
- }
- >
-
-
- )}
-
}
>
diff --git a/src/features/email-confirmation/index.tsx b/src/features/email-confirmation/index.tsx
deleted file mode 100644
index 3088e5b41..000000000
--- a/src/features/email-confirmation/index.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import React from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-import { Redirect } from 'react-router-dom';
-
-import { confirmChangedEmail } from 'soapbox/actions/security';
-import { Spinner } from 'soapbox/components/ui';
-import { useAppDispatch } from 'soapbox/hooks';
-import toast from 'soapbox/toast';
-import { buildErrorMessage } from 'soapbox/utils/errors';
-
-const Statuses = {
- IDLE: 'IDLE',
- SUCCESS: 'SUCCESS',
- FAIL: 'FAIL',
-};
-
-const messages = defineMessages({
- success: { id: 'email_confirmation.success', defaultMessage: 'Your email has been confirmed!' },
-});
-
-const token = new URLSearchParams(window.location.search).get('confirmation_token');
-
-const EmailConfirmation = () => {
- const intl = useIntl();
- const dispatch = useAppDispatch();
-
- const [status, setStatus] = React.useState(Statuses.IDLE);
-
- React.useEffect(() => {
- if (token) {
- dispatch(confirmChangedEmail(token))
- .then(() => {
- setStatus(Statuses.SUCCESS);
-
- toast.success(intl.formatMessage(messages.success));
- })
- .catch((error) => {
- setStatus(Statuses.FAIL);
-
- if (error.response.data.error) {
- const message = buildErrorMessage(error.response.data.error);
-
- toast.error(
- message,
- // intl.formatMessage({
- // id: 'email_confirmation.fail',
- // defaultMessage,
- // }),
- );
- }
- });
- }
- }, [token]);
-
- if (!token || status === Statuses.SUCCESS || status === Statuses.FAIL) {
- return ;
- }
-
- return (
-
- );
-};
-
-export default EmailConfirmation;
diff --git a/src/features/event/event-discussion.tsx b/src/features/event/event-discussion.tsx
index cd11b1916..0d63e19bb 100644
--- a/src/features/event/event-discussion.tsx
+++ b/src/features/event/event-discussion.tsx
@@ -1,10 +1,9 @@
import { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable';
-import debounce from 'lodash/debounce';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { eventDiscussionCompose } from 'soapbox/actions/compose';
-import { fetchStatusWithContext, fetchNext } from 'soapbox/actions/statuses';
+import { fetchStatusWithContext } from 'soapbox/actions/statuses';
import MissingIndicator from 'soapbox/components/missing-indicator';
import ScrollableList from 'soapbox/components/scrollable-list';
import Tombstone from 'soapbox/components/tombstone';
@@ -50,16 +49,14 @@ const EventDiscussion: React.FC = (props) => {
});
const [isLoaded, setIsLoaded] = useState(!!status);
- const [next, setNext] = useState();
const node = useRef(null);
const scroller = useRef(null);
- const fetchData = async() => {
+ const fetchData = () => {
const { params } = props;
const { statusId } = params;
- const { next } = await dispatch(fetchStatusWithContext(statusId));
- setNext(next);
+ return dispatch(fetchStatusWithContext(statusId));
};
useEffect(() => {
@@ -147,14 +144,6 @@ const EventDiscussion: React.FC = (props) => {
});
};
- const handleLoadMore = useCallback(debounce(() => {
- if (next && status) {
- dispatch(fetchNext(status.id, next)).then(({ next }) => {
- setNext(next);
- }).catch(() => {});
- }
- }, 300, { leading: true }), [next, status]);
-
const hasDescendants = descendantsIds.size > 0;
if (!status && isLoaded) {
@@ -182,8 +171,6 @@ const EventDiscussion: React.FC = (props) => {
}
initialTopMostItemIndex={0}
emptyMessage={}
diff --git a/src/features/group/components/group-action-button.tsx b/src/features/group/components/group-action-button.tsx
index ccc80db62..5d26f174f 100644
--- a/src/features/group/components/group-action-button.tsx
+++ b/src/features/group/components/group-action-button.tsx
@@ -3,7 +3,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { fetchGroupRelationshipsSuccess } from 'soapbox/actions/groups';
import { openModal } from 'soapbox/actions/modals';
-import { useCancelMembershipRequest, useJoinGroup, useLeaveGroup, usePendingGroups } from 'soapbox/api/hooks';
+import { useCancelMembershipRequest, useJoinGroup, useLeaveGroup } from 'soapbox/api/hooks';
import { Button } from 'soapbox/components/ui';
import { importEntities } from 'soapbox/entity-store/actions';
import { Entities } from 'soapbox/entity-store/entities';
@@ -33,7 +33,6 @@ const GroupActionButton = ({ group }: IGroupActionButton) => {
const joinGroup = useJoinGroup(group);
const leaveGroup = useLeaveGroup(group);
const cancelRequest = useCancelMembershipRequest(group);
- const { invalidate: invalidatePendingGroups } = usePendingGroups();
const isRequested = group.relationship?.requested;
const isNonMember = !group.relationship?.member && !isRequested;
@@ -44,7 +43,6 @@ const GroupActionButton = ({ group }: IGroupActionButton) => {
const onJoinGroup = () => joinGroup.mutate({}, {
onSuccess(entity) {
joinGroup.invalidate();
- invalidatePendingGroups();
dispatch(fetchGroupRelationshipsSuccess([entity]));
toast.success(
@@ -82,7 +80,6 @@ const GroupActionButton = ({ group }: IGroupActionButton) => {
requested: false,
};
dispatch(importEntities([entity], Entities.GROUP_RELATIONSHIPS));
- invalidatePendingGroups();
},
});
@@ -94,7 +91,7 @@ const GroupActionButton = ({ group }: IGroupActionButton) => {
return (
diff --git a/src/features/group/components/group-member-count.tsx b/src/features/group/components/group-member-count.tsx
index 797d618b2..8c277aabd 100644
--- a/src/features/group/components/group-member-count.tsx
+++ b/src/features/group/components/group-member-count.tsx
@@ -12,7 +12,7 @@ interface IGroupMemberCount {
const GroupMemberCount = ({ group }: IGroupMemberCount) => {
return (
-
+
{shortNumberFormat(group.members_count)}
{' '}
diff --git a/src/features/group/components/group-member-list-item.test.tsx b/src/features/group/components/group-member-list-item.test.tsx
index e91901013..fa0b9d424 100644
--- a/src/features/group/components/group-member-list-item.test.tsx
+++ b/src/features/group/components/group-member-list-item.test.tsx
@@ -27,7 +27,7 @@ describe('', () => {
relationship: buildGroupRelationship(),
});
- render();
+ render();
await waitFor(() => {
expect(screen.getByTestId('group-member-list-item')).toHaveTextContent(groupMember.account.display_name);
@@ -52,7 +52,7 @@ describe('', () => {
});
it('should render the correct badge', async () => {
- render();
+ render();
await waitFor(() => {
expect(screen.getByTestId('role-badge')).toHaveTextContent('owner');
@@ -73,7 +73,7 @@ describe('', () => {
});
it('should render the correct badge', async () => {
- render();
+ render();
await waitFor(() => {
expect(screen.getByTestId('role-badge')).toHaveTextContent('admin');
@@ -94,7 +94,7 @@ describe('', () => {
});
it('should render no correct badge', async () => {
- render();
+ render();
await waitFor(() => {
expect(screen.queryAllByTestId('role-badge')).toHaveLength(0);
@@ -125,36 +125,19 @@ describe('', () => {
});
});
- describe('when "canPromoteToAdmin is true', () => {
- it('should render dropdown with correct Owner actions', async () => {
- const user = userEvent.setup();
+ it('should render dropdown with correct Owner actions', async () => {
+ const user = userEvent.setup();
- render();
+ render();
- await waitFor(async() => {
- await user.click(screen.getByTestId('icon-button'));
- });
-
- const dropdownMenu = screen.getByTestId('dropdown-menu');
- expect(dropdownMenu).toHaveTextContent('Assign admin role');
- expect(dropdownMenu).toHaveTextContent('Kick @tiger from group');
- expect(dropdownMenu).toHaveTextContent('Ban from group');
+ await waitFor(async() => {
+ await user.click(screen.getByTestId('icon-button'));
});
- });
- describe('when "canPromoteToAdmin is false', () => {
- it('should prevent promoting user to Admin', async () => {
- const user = userEvent.setup();
-
- render();
-
- await waitFor(async() => {
- await user.click(screen.getByTestId('icon-button'));
- await user.click(screen.getByTitle('Assign admin role'));
- });
-
- expect(screen.getByTestId('toast')).toHaveTextContent('Admin limit reached');
- });
+ const dropdownMenu = screen.getByTestId('dropdown-menu');
+ expect(dropdownMenu).toHaveTextContent('Assign admin role');
+ expect(dropdownMenu).toHaveTextContent('Kick @tiger from group');
+ expect(dropdownMenu).toHaveTextContent('Ban from group');
});
});
@@ -180,7 +163,7 @@ describe('', () => {
it('should render dropdown with correct Owner actions', async () => {
const user = userEvent.setup();
- render();
+ render();
await waitFor(async() => {
await user.click(screen.getByTestId('icon-button'));
@@ -219,7 +202,7 @@ describe('', () => {
it('should render dropdown with correct Admin actions', async () => {
const user = userEvent.setup();
- render();
+ render();
await waitFor(async() => {
await user.click(screen.getByTestId('icon-button'));
@@ -252,7 +235,7 @@ describe('', () => {
});
it('should not render the dropdown', async () => {
- render();
+ render();
await waitFor(async() => {
expect(screen.queryAllByTestId('icon-button')).toHaveLength(0);
@@ -280,7 +263,7 @@ describe('', () => {
});
it('should not render the dropdown', async () => {
- render();
+ render();
await waitFor(async() => {
expect(screen.queryAllByTestId('icon-button')).toHaveLength(0);
@@ -310,7 +293,7 @@ describe('', () => {
});
it('should not render the dropdown', async () => {
- render();
+ render();
await waitFor(async() => {
expect(screen.queryAllByTestId('icon-button')).toHaveLength(0);
diff --git a/src/features/group/components/group-member-list-item.tsx b/src/features/group/components/group-member-list-item.tsx
index eea6514f8..9f7689b67 100644
--- a/src/features/group/components/group-member-list-item.tsx
+++ b/src/features/group/components/group-member-list-item.tsx
@@ -11,12 +11,10 @@ import { HStack } from 'soapbox/components/ui';
import { deleteEntities } from 'soapbox/entity-store/actions';
import { Entities } from 'soapbox/entity-store/entities';
import PlaceholderAccount from 'soapbox/features/placeholder/components/placeholder-account';
-import { useAppDispatch, useFeatures } from 'soapbox/hooks';
+import { useAppDispatch } from 'soapbox/hooks';
import { GroupRoles } from 'soapbox/schemas/group-member';
import toast from 'soapbox/toast';
-import { MAX_ADMIN_COUNT } from '../group-members';
-
import type { Menu as IMenu } from 'soapbox/components/dropdown-menu';
import type { Group, GroupMember } from 'soapbox/types/entities';
@@ -43,14 +41,12 @@ const messages = defineMessages({
interface IGroupMemberListItem {
member: GroupMember;
group: Group;
- canPromoteToAdmin: boolean;
}
const GroupMemberListItem = (props: IGroupMemberListItem) => {
- const { canPromoteToAdmin, member, group } = props;
+ const { member, group } = props;
const dispatch = useAppDispatch();
- const features = useFeatures();
const intl = useIntl();
const blockGroupMember = useBlockGroupMember(group, member.account);
@@ -95,13 +91,6 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
};
const handleAdminAssignment = () => {
- if (!canPromoteToAdmin) {
- toast.error(intl.formatMessage(messages.adminLimitTitle), {
- summary: intl.formatMessage(messages.adminLimitSummary, { count: MAX_ADMIN_COUNT }),
- });
- return;
- }
-
dispatch(openModal('CONFIRM', {
heading: intl.formatMessage(messages.promoteConfirm),
message: intl.formatMessage(messages.promoteConfirmMessage, { name: account?.username }),
@@ -156,13 +145,11 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => {
(isMemberAdmin || isMemberUser) &&
member.role !== group.relationship.role
) {
- if (features.groupsKick) {
- items.push({
- text: intl.formatMessage(messages.groupModKick, { name: account.username }),
- icon: require('@tabler/icons/outline/user-minus.svg'),
- action: handleKickFromGroup,
- });
- }
+ items.push({
+ text: intl.formatMessage(messages.groupModKick, { name: account.username }),
+ icon: require('@tabler/icons/outline/user-minus.svg'),
+ action: handleKickFromGroup,
+ });
items.push({
text: intl.formatMessage(messages.groupModBlock, { name: account.username }),
diff --git a/src/features/group/components/group-options-button.tsx b/src/features/group/components/group-options-button.tsx
index c52bc1eaa..15ca4b399 100644
--- a/src/features/group/components/group-options-button.tsx
+++ b/src/features/group/components/group-options-button.tsx
@@ -2,29 +2,21 @@ import React, { useMemo } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { openModal } from 'soapbox/actions/modals';
-import { initReport, ReportableEntities } from 'soapbox/actions/reports';
-import { useLeaveGroup, useMuteGroup, useUnmuteGroup } from 'soapbox/api/hooks';
+import { useLeaveGroup } from 'soapbox/api/hooks';
import DropdownMenu, { Menu } from 'soapbox/components/dropdown-menu';
import { IconButton } from 'soapbox/components/ui';
-import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
+import { useAppDispatch } from 'soapbox/hooks';
import { GroupRoles } from 'soapbox/schemas/group-member';
import toast from 'soapbox/toast';
-import type { Account, Group } from 'soapbox/types/entities';
+import type { Group } from 'soapbox/types/entities';
const messages = defineMessages({
confirmationConfirm: { id: 'confirmations.leave_group.confirm', defaultMessage: 'Leave' },
confirmationHeading: { id: 'confirmations.leave_group.heading', defaultMessage: 'Leave group' },
confirmationMessage: { id: 'confirmations.leave_group.message', defaultMessage: 'You are about to leave the group. Do you want to continue?' },
- muteConfirm: { id: 'confirmations.mute_group.confirm', defaultMessage: 'Mute' },
- muteHeading: { id: 'confirmations.mute_group.heading', defaultMessage: 'Mute Group' },
- muteMessage: { id: 'confirmations.mute_group.message', defaultMessage: 'You are about to mute the group. Do you want to continue?' },
- muteSuccess: { id: 'group.mute.success', defaultMessage: 'Muted the group' },
- unmuteSuccess: { id: 'group.unmute.success', defaultMessage: 'Unmuted the group' },
leave: { id: 'group.leave.label', defaultMessage: 'Leave' },
leaveSuccess: { id: 'group.leave.success', defaultMessage: 'Left the group' },
- mute: { id: 'group.mute.label', defaultMessage: 'Mute' },
- unmute: { id: 'group.unmute.label', defaultMessage: 'Unmute' },
report: { id: 'group.report.label', defaultMessage: 'Report' },
share: { id: 'group.share.label', defaultMessage: 'Share' },
});
@@ -34,12 +26,9 @@ interface IGroupActionButton {
}
const GroupOptionsButton = ({ group }: IGroupActionButton) => {
- const { account } = useOwnAccount();
const dispatch = useAppDispatch();
const intl = useIntl();
- const muteGroup = useMuteGroup(group);
- const unmuteGroup = useUnmuteGroup(group);
const leaveGroup = useLeaveGroup(group);
const isMember = group.relationship?.role === GroupRoles.USER;
@@ -57,27 +46,6 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => {
});
};
- const handleMute = () =>
- dispatch(openModal('CONFIRM', {
- heading: intl.formatMessage(messages.muteHeading),
- message: intl.formatMessage(messages.muteMessage),
- confirm: intl.formatMessage(messages.muteConfirm),
- confirmationTheme: 'primary',
- onConfirm: () => muteGroup.mutate(undefined, {
- onSuccess() {
- toast.success(intl.formatMessage(messages.muteSuccess));
- },
- }),
- }));
-
- const handleUnmute = () => {
- unmuteGroup.mutate(undefined, {
- onSuccess() {
- toast.success(intl.formatMessage(messages.unmuteSuccess));
- },
- });
- };
-
const handleLeave = () =>
dispatch(openModal('CONFIRM', {
heading: intl.formatMessage(messages.confirmationHeading),
@@ -103,22 +71,6 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => {
});
}
- if (isInGroup) {
- items.push({
- text: isMuting ? intl.formatMessage(messages.unmute) : intl.formatMessage(messages.mute),
- icon: require('@tabler/icons/outline/volume-3.svg'),
- action: isMuting ? handleUnmute : handleMute,
- });
- }
-
- if (isMember || isAdmin) {
- items.push({
- text: intl.formatMessage(messages.report),
- icon: require('@tabler/icons/outline/flag.svg'),
- action: () => dispatch(initReport(ReportableEntities.GROUP, account as Account, { group })),
- });
- }
-
if (isAdmin) {
items.push(null);
items.push({
diff --git a/src/features/group/components/group-tag-list-item.test.tsx b/src/features/group/components/group-tag-list-item.test.tsx
deleted file mode 100644
index 57c3cffbe..000000000
--- a/src/features/group/components/group-tag-list-item.test.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import React from 'react';
-
-import { buildGroup, buildGroupTag, buildGroupRelationship } from 'soapbox/jest/factory';
-import { render, screen } from 'soapbox/jest/test-helpers';
-import { GroupRoles } from 'soapbox/schemas/group-member';
-
-import GroupTagListItem from './group-tag-list-item';
-
-describe('', () => {
- describe('tag name', () => {
- const name = 'hello';
-
- it('should render the tag name', () => {
- const group = buildGroup();
- const tag = buildGroupTag({ name });
- render();
-
- expect(screen.getByTestId('group-tag-list-item')).toHaveTextContent(`#${name}`);
- });
-
- describe('when the tag is "visible"', () => {
- const group = buildGroup();
- const tag = buildGroupTag({ name, visible: true });
-
- it('renders the default name', () => {
- render();
- expect(screen.getByTestId('group-tag-name')).toHaveClass('text-gray-900');
- });
- });
-
- describe('when the tag is not "visible" and user is Owner', () => {
- const group = buildGroup({
- relationship: buildGroupRelationship({
- role: GroupRoles.OWNER,
- member: true,
- }),
- });
- const tag = buildGroupTag({
- name,
- visible: false,
- });
-
- it('renders the subtle name', () => {
- render();
- expect(screen.getByTestId('group-tag-name')).toHaveClass('text-gray-400');
- });
- });
-
- describe('when the tag is not "visible" and user is Admin or User', () => {
- const group = buildGroup({
- relationship: buildGroupRelationship({
- role: GroupRoles.ADMIN,
- member: true,
- }),
- });
- const tag = buildGroupTag({
- name,
- visible: false,
- });
-
- it('renders the subtle name', () => {
- render();
- expect(screen.getByTestId('group-tag-name')).toHaveClass('text-gray-900');
- });
- });
- });
-
- describe('pinning', () => {
- describe('as an owner', () => {
- const group = buildGroup({
- relationship: buildGroupRelationship({
- role: GroupRoles.OWNER,
- member: true,
- }),
- });
-
- describe('when the tag is visible', () => {
- const tag = buildGroupTag({ visible: true });
-
- it('renders the pin icon', () => {
- render();
- expect(screen.getByTestId('pin-icon')).toBeInTheDocument();
- });
- });
-
- describe('when the tag is not visible', () => {
- const tag = buildGroupTag({ visible: false });
-
- it('does not render the pin icon', () => {
- render();
- expect(screen.queryAllByTestId('pin-icon')).toHaveLength(0);
- });
- });
- });
-
- describe('as a non-owner', () => {
- const group = buildGroup({
- relationship: buildGroupRelationship({
- role: GroupRoles.ADMIN,
- member: true,
- }),
- });
-
- describe('when the tag is pinned', () => {
- const tag = buildGroupTag({ pinned: true, visible: true });
-
- it('does render the pin icon', () => {
- render();
- screen.debug();
- expect(screen.queryAllByTestId('pin-icon')).toHaveLength(1);
- });
- });
-
- describe('when the tag is not pinned', () => {
- const tag = buildGroupTag({ pinned: false, visible: true });
-
- it('does not render the pin icon', () => {
- render();
- expect(screen.queryAllByTestId('pin-icon')).toHaveLength(0);
- });
- });
- });
- });
-});
\ No newline at end of file
diff --git a/src/features/group/components/group-tag-list-item.tsx b/src/features/group/components/group-tag-list-item.tsx
deleted file mode 100644
index 45a5dc82f..000000000
--- a/src/features/group/components/group-tag-list-item.tsx
+++ /dev/null
@@ -1,196 +0,0 @@
-import React from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-import { Link } from 'react-router-dom';
-
-import { useUpdateGroupTag } from 'soapbox/api/hooks';
-import { HStack, Icon, IconButton, Stack, Text, Tooltip } from 'soapbox/components/ui';
-import { importEntities } from 'soapbox/entity-store/actions';
-import { Entities } from 'soapbox/entity-store/entities';
-import { useAppDispatch } from 'soapbox/hooks';
-import { GroupRoles } from 'soapbox/schemas/group-member';
-import toast from 'soapbox/toast';
-import { shortNumberFormat } from 'soapbox/utils/numbers';
-
-import type { Group, GroupTag } from 'soapbox/schemas';
-
-const messages = defineMessages({
- hideTag: { id: 'group.tags.hide', defaultMessage: 'Hide topic' },
- showTag: { id: 'group.tags.show', defaultMessage: 'Show topic' },
- total: { id: 'group.tags.total', defaultMessage: 'Total Posts' },
- pinTag: { id: 'group.tags.pin', defaultMessage: 'Pin topic' },
- unpinTag: { id: 'group.tags.unpin', defaultMessage: 'Unpin topic' },
- pinSuccess: { id: 'group.tags.pin.success', defaultMessage: 'Pinned!' },
- unpinSuccess: { id: 'group.tags.unpin.success', defaultMessage: 'Unpinned!' },
- visibleSuccess: { id: 'group.tags.visible.success', defaultMessage: 'Topic marked as visible' },
- hiddenSuccess: { id: 'group.tags.hidden.success', defaultMessage: 'Topic marked as hidden' },
-});
-
-interface IGroupMemberListItem {
- tag: GroupTag;
- group: Group;
- isPinnable: boolean;
-}
-
-const GroupTagListItem = (props: IGroupMemberListItem) => {
- const { group, tag, isPinnable } = props;
- const dispatch = useAppDispatch();
-
- const intl = useIntl();
- const { updateGroupTag } = useUpdateGroupTag(group.id, tag.id);
-
- const isOwner = group.relationship?.role === GroupRoles.OWNER;
-
- const toggleVisibility = () => {
- const isHiding = tag.visible;
-
- updateGroupTag({
- group_tag_type: isHiding ? 'hidden' : 'normal',
- }, {
- onSuccess() {
- const entity: GroupTag = {
- ...tag,
- visible: !tag.visible,
- pinned: isHiding ? false : tag.pinned, // unpin if we're hiding
- };
- dispatch(importEntities([entity], Entities.GROUP_TAGS));
-
- toast.success(
- entity.visible ?
- intl.formatMessage(messages.visibleSuccess) :
- intl.formatMessage(messages.hiddenSuccess),
- );
- },
- });
- };
-
- const togglePin = () => {
- updateGroupTag({
- group_tag_type: tag.pinned ? 'normal' : 'pinned',
- }, {
- onSuccess() {
- const entity = {
- ...tag,
- pinned: !tag.pinned,
- };
- dispatch(importEntities([entity], Entities.GROUP_TAGS));
-
- toast.success(
- entity.pinned ?
- intl.formatMessage(messages.pinSuccess) :
- intl.formatMessage(messages.unpinSuccess),
- );
- },
- });
- };
-
- const renderPinIcon = () => {
- if (!isOwner && tag.pinned) {
- return (
-
- );
- }
-
- if (!isOwner) {
- return null;
- }
-
- if (isPinnable) {
- return (
-
-
-
- );
- }
-
- if (!isPinnable && tag.pinned) {
- return (
-
-
-
-
- );
- }
- };
-
- return (
-
-
-
-
- #{tag.name}
-
-
- {intl.formatMessage(messages.total)}:
- {' '}
-
- {shortNumberFormat(tag.uses)}
-
-
-
-
-
-
- {tag.visible ? (
- renderPinIcon()
- ) : null}
-
- {isOwner ? (
-
-
-
- ) : null}
-
-
- );
-};
-
-export default GroupTagListItem;
\ No newline at end of file
diff --git a/src/features/group/components/group-tags-field.tsx b/src/features/group/components/group-tags-field.tsx
deleted file mode 100644
index 1a9f3118e..000000000
--- a/src/features/group/components/group-tags-field.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import React, { useMemo } from 'react';
-import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
-
-import { Input, Streamfield } from 'soapbox/components/ui';
-
-import type { StreamfieldComponent } from 'soapbox/components/ui/streamfield/streamfield';
-
-const messages = defineMessages({
- hashtagPlaceholder: { id: 'manage_group.fields.hashtag_placeholder', defaultMessage: 'Add a topic' },
-});
-
-interface IGroupTagsField {
- tags: string[];
- onChange(tags: string[]): void;
- onAddItem(): void;
- onRemoveItem(i: number): void;
- maxItems?: number;
-}
-
-const GroupTagsField: React.FC = ({ tags, onChange, onAddItem, onRemoveItem, maxItems = 3 }) => {
- return (
- }
- hint={}
- component={HashtagField}
- values={tags}
- onChange={onChange}
- onAddItem={onAddItem}
- onRemoveItem={onRemoveItem}
- maxItems={maxItems}
- minItems={1}
- />
- );
-};
-
-const HashtagField: StreamfieldComponent = ({ value, onChange, autoFocus = false }) => {
- const intl = useIntl();
-
- const formattedValue = useMemo(() => {
- return `#${value}`;
- }, [value]);
-
- const handleChange: React.ChangeEventHandler = ({ target }) => {
- onChange(target.value.replace('#', ''));
- };
-
- return (
-
- );
-};
-
-export default GroupTagsField;
\ No newline at end of file
diff --git a/src/features/group/edit-group.tsx b/src/features/group/edit-group.tsx
index aa80d7ce5..13c6279b1 100644
--- a/src/features/group/edit-group.tsx
+++ b/src/features/group/edit-group.tsx
@@ -1,7 +1,7 @@
-import React, { useEffect, useState } from 'react';
+import React, { useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import { useGroup, useGroupTags, useUpdateGroup } from 'soapbox/api/hooks';
+import { useGroup, useUpdateGroup } from 'soapbox/api/hooks';
import { Button, Column, Form, FormActions, FormGroup, Icon, Input, Spinner, Textarea } from 'soapbox/components/ui';
import { useAppSelector, useInstance } from 'soapbox/hooks';
import { useImageField, useTextField } from 'soapbox/hooks/forms';
@@ -11,8 +11,6 @@ import { isDefaultAvatar, isDefaultHeader } from 'soapbox/utils/accounts';
import AvatarPicker from '../edit-profile/components/avatar-picker';
import HeaderPicker from '../edit-profile/components/header-picker';
-import GroupTagsField from './components/group-tags-field';
-
const nonDefaultAvatar = (url: string | undefined) => url && isDefaultAvatar(url) ? undefined : url;
const nonDefaultHeader = (url: string | undefined) => url && isDefaultHeader(url) ? undefined : url;
@@ -35,10 +33,8 @@ const EditGroup: React.FC = ({ params: { groupId } }) => {
const { group, isLoading } = useGroup(groupId);
const { updateGroup } = useUpdateGroup(groupId);
- const { invalidate } = useGroupTags(groupId);
const [isSubmitting, setIsSubmitting] = useState(false);
- const [tags, setTags] = useState(['']);
const avatar = useImageField({ maxPixels: 400 * 400, preview: nonDefaultAvatar(group?.avatar) });
const header = useImageField({ maxPixels: 1920 * 1080, preview: nonDefaultHeader(group?.header) });
@@ -61,10 +57,8 @@ const EditGroup: React.FC = ({ params: { groupId } }) => {
note: note.value,
avatar: avatar.file === null ? '' : avatar.file,
header: header.file === null ? '' : header.file,
- tags,
}, {
onSuccess() {
- invalidate();
toast.success(intl.formatMessage(messages.groupSaved));
},
onError(error) {
@@ -79,22 +73,6 @@ const EditGroup: React.FC = ({ params: { groupId } }) => {
setIsSubmitting(false);
}
- const handleAddTag = () => {
- setTags([...tags, '']);
- };
-
- const handleRemoveTag = (i: number) => {
- const newTags = [...tags];
- newTags.splice(i, 1);
- setTags(newTags);
- };
-
- useEffect(() => {
- if (group) {
- setTags(group.tags.map((t) => t.name));
- }
- }, [group?.id]);
-
if (isLoading) {
return ;
}
@@ -130,15 +108,6 @@ const EditGroup: React.FC = ({ params: { groupId } }) => {
/>
-
-
-
-
-
)}
/>
diff --git a/src/features/group/manage-group.tsx b/src/features/group/manage-group.tsx
index 1fa02f174..0f144f85a 100644
--- a/src/features/group/manage-group.tsx
+++ b/src/features/group/manage-group.tsx
@@ -6,10 +6,9 @@ import { openModal } from 'soapbox/actions/modals';
import { useDeleteGroup, useGroup } from 'soapbox/api/hooks';
import List, { ListItem } from 'soapbox/components/list';
import { CardBody, CardHeader, CardTitle, Column, Spinner, Text } from 'soapbox/components/ui';
-import { useAppDispatch, useBackend, useGroupsPath } from 'soapbox/hooks';
+import { useAppDispatch } from 'soapbox/hooks';
import { GroupRoles } from 'soapbox/schemas/group-member';
import toast from 'soapbox/toast';
-import { TRUTHSOCIAL } from 'soapbox/utils/features';
import ColumnForbidden from '../ui/components/column-forbidden';
@@ -36,9 +35,7 @@ interface IManageGroup {
const ManageGroup: React.FC = ({ params }) => {
const { groupId: id } = params;
- const backend = useBackend();
const dispatch = useAppDispatch();
- const groupsPath = useGroupsPath();
const history = useHistory();
const intl = useIntl();
@@ -70,14 +67,14 @@ const ManageGroup: React.FC = ({ params }) => {
deleteGroup.mutate(group.id, {
onSuccess() {
toast.success(intl.formatMessage(messages.deleteSuccess));
- history.push(groupsPath);
+ history.push('/groups');
},
});
},
}));
return (
-
+
{isOwner && (
<>
@@ -86,7 +83,7 @@ const ManageGroup: React.FC = ({ params }) => {
-
+
@@ -98,11 +95,9 @@ const ManageGroup: React.FC = ({ params }) => {
- {backend.software !== TRUTHSOCIAL && (
-
- )}
+
-
+
{isOwner && (
diff --git a/src/features/groups/components/discover/group-grid-item.tsx b/src/features/groups/components/discover/group-grid-item.tsx
index 523f3f807..900e5bdef 100644
--- a/src/features/groups/components/discover/group-grid-item.tsx
+++ b/src/features/groups/components/discover/group-grid-item.tsx
@@ -27,7 +27,7 @@ const GroupGridItem = forwardRef((props: IGroup, ref: React.ForwardedRef
-
+
{
justifyContent='between'
data-testid='group-list-item'
>
-
+
{
- const { groups, isFetching, isFetched, isError } = usePopularGroups();
- const isEmpty = (isFetched && groups.length === 0) || isError;
-
- const [groupCover, setGroupCover] = useState(null);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- {isEmpty ? (
-
-
-
- ) : (
-
- {({ width }: { width: number }) => (
- <>
- {isFetching ? (
- new Array(4).fill(0).map((_, idx) => (
-
- ))
- ) : (
- groups.map((group) => (
-
- ))
- )}
- >
- )}
-
- )}
-
- );
-};
-
-export default PopularGroups;
\ No newline at end of file
diff --git a/src/features/groups/components/discover/popular-tags.tsx b/src/features/groups/components/discover/popular-tags.tsx
deleted file mode 100644
index 75ff36628..000000000
--- a/src/features/groups/components/discover/popular-tags.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React from 'react';
-import { FormattedMessage } from 'react-intl';
-
-import { usePopularTags } from 'soapbox/api/hooks';
-import Link from 'soapbox/components/link';
-import { HStack, Stack, Text } from 'soapbox/components/ui';
-
-import TagListItem from './tag-list-item';
-
-const PopularTags = () => {
- const { tags, isFetched, isError } = usePopularTags();
- const isEmpty = (isFetched && tags.length === 0) || isError;
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- {isEmpty ? (
-
-
-
- ) : (
-
- {tags.slice(0, 10).map((tag) => (
-
- ))}
-
- )}
-
- );
-};
-
-export default PopularTags;
\ No newline at end of file
diff --git a/src/features/groups/components/discover/search/blankslate.test.tsx b/src/features/groups/components/discover/search/blankslate.test.tsx
deleted file mode 100644
index 4b63badf6..000000000
--- a/src/features/groups/components/discover/search/blankslate.test.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-
-import { render, screen } from 'soapbox/jest/test-helpers';
-
-import Blankslate from './blankslate';
-
-
-describe('', () => {
- describe('with string props', () => {
- it('should render correctly', () => {
- render();
-
- expect(screen.getByTestId('no-results')).toHaveTextContent('Title');
- expect(screen.getByTestId('no-results')).toHaveTextContent('Subtitle');
- });
- });
-
- describe('with node props', () => {
- it('should render correctly', () => {
- render(
- Title}
- subtitle={Subtitle}
- />);
-
- expect(screen.getByTestId('no-results')).toHaveTextContent('Title');
- expect(screen.getByTestId('no-results')).toHaveTextContent('Subtitle');
- });
- });
-});
\ No newline at end of file
diff --git a/src/features/groups/components/discover/search/blankslate.tsx b/src/features/groups/components/discover/search/blankslate.tsx
deleted file mode 100644
index 7d63b8c27..000000000
--- a/src/features/groups/components/discover/search/blankslate.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-
-import { Stack, Text } from 'soapbox/components/ui';
-
-interface Props {
- title: React.ReactNode | string;
- subtitle: React.ReactNode | string;
-}
-
-export default ({ title, subtitle }: Props) => (
-
-
- {title}
-
-
-
- {subtitle}
-
-
-);
\ No newline at end of file
diff --git a/src/features/groups/components/discover/search/recent-searches.tsx b/src/features/groups/components/discover/search/recent-searches.tsx
deleted file mode 100644
index 58b0c43cb..000000000
--- a/src/features/groups/components/discover/search/recent-searches.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import React, { useState } from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Virtuoso } from 'react-virtuoso';
-
-import { HStack, Icon, Stack, Text } from 'soapbox/components/ui';
-import { useOwnAccount } from 'soapbox/hooks';
-import { groupSearchHistory } from 'soapbox/settings';
-import { clearRecentGroupSearches } from 'soapbox/utils/groups';
-
-interface Props {
- onSelect(value: string): void;
-}
-
-export default (props: Props) => {
- const { onSelect } = props;
-
- const { account: me } = useOwnAccount();
-
- const [recentSearches, setRecentSearches] = useState(groupSearchHistory.get(me?.id as string) || []);
-
- const onClearRecentSearches = () => {
- clearRecentGroupSearches(me?.id as string);
- setRecentSearches([]);
- };
-
- return (
-
- {recentSearches.length > 0 ? (
- <>
-
-
-
-
-
-
-
-
- (
-
-
-
- )}
- />
- >
- ) : (
-
-
-
-
-
-
-
-
-
- )}
-
- );
-};
\ No newline at end of file
diff --git a/src/features/groups/components/discover/search/results.test.tsx b/src/features/groups/components/discover/search/results.test.tsx
deleted file mode 100644
index 1c3017c9b..000000000
--- a/src/features/groups/components/discover/search/results.test.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import userEvent from '@testing-library/user-event';
-import React from 'react';
-import { VirtuosoGridMockContext, VirtuosoMockContext } from 'react-virtuoso';
-
-import { buildAccount, buildGroup } from 'soapbox/jest/factory';
-import { render, screen, waitFor } from 'soapbox/jest/test-helpers';
-
-import Results from './results';
-
-const userId = '1';
-const store = {
- me: userId,
- accounts: {
- [userId]: buildAccount({
- id: userId,
- acct: 'justin-username',
- display_name: 'Justin L',
- avatar: 'test.jpg',
- source: {
- chats_onboarded: false,
- },
- }),
- },
-};
-
-const renderApp = (children: React.ReactNode) => (
- render(
-
-
- {children}
-
- ,
- undefined,
- store,
- )
-);
-
-const groupSearchResult = {
- groups: [buildGroup()],
- hasNextPage: false,
- isFetching: false,
- fetchNextPage: vi.fn(),
-} as any;
-
-describe('', () => {
- describe('with a list layout', () => {
- it('should render the GroupListItem components', async () => {
- renderApp();
- await waitFor(() => {
- expect(screen.getByTestId('group-list-item')).toBeInTheDocument();
- });
- });
- });
-
- describe('with a grid layout', () => {
- it('should render the GroupGridItem components', async () => {
- const user = userEvent.setup();
- renderApp();
-
- await user.click(screen.getByTestId('layout-grid-action'));
-
- await waitFor(() => {
- expect(screen.getByTestId('group-grid-item')).toBeInTheDocument();
- });
- });
- });
-});
\ No newline at end of file
diff --git a/src/features/groups/components/discover/search/results.tsx b/src/features/groups/components/discover/search/results.tsx
deleted file mode 100644
index 3a01ea16f..000000000
--- a/src/features/groups/components/discover/search/results.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import clsx from 'clsx';
-import React, { useCallback, useState } from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
-
-import { useGroupSearch } from 'soapbox/api/hooks';
-import { HStack, Stack, Text } from 'soapbox/components/ui';
-
-import GroupGridItem from '../group-grid-item';
-import GroupListItem from '../group-list-item';
-import LayoutButtons, { GroupLayout } from '../layout-buttons';
-
-import type { Group } from 'soapbox/types/entities';
-
-interface Props {
- groupSearchResult: ReturnType;
-}
-
-const GridList: Components['List'] = React.forwardRef((props, ref) => {
- const { context, ...rest } = props;
- return ;
-});
-
-export default (props: Props) => {
- const { groupSearchResult } = props;
-
- const [layout, setLayout] = useState(GroupLayout.LIST);
-
- const { groups, hasNextPage, isFetching, fetchNextPage } = groupSearchResult;
-
- const handleLoadMore = () => {
- if (hasNextPage && !isFetching) {
- fetchNextPage();
- }
- };
-
- const renderGroupList = useCallback((group: Group, index: number) => (
-
-
-
- ), []);
-
- const renderGroupGrid = useCallback((group: Group) => (
-
- ), []);
-
- return (
-
-
-
-
-
-
- setLayout(selectedLayout)}
- />
-
-
- {layout === GroupLayout.LIST ? (
- renderGroupList(group, index)}
- endReached={handleLoadMore}
- />
- ) : (
- renderGroupGrid(group)}
- components={{
- Item: (props) => (
-
- ),
- List: GridList,
- }}
- endReached={handleLoadMore}
- />
- )}
-
- );
-};
\ No newline at end of file
diff --git a/src/features/groups/components/discover/search/search.test.tsx b/src/features/groups/components/discover/search/search.test.tsx
deleted file mode 100644
index 5c25cc5a3..000000000
--- a/src/features/groups/components/discover/search/search.test.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React from 'react';
-
-import { __stub } from 'soapbox/api';
-import { buildGroup } from 'soapbox/jest/factory';
-import { render, screen, waitFor } from 'soapbox/jest/test-helpers';
-import { instanceSchema } from 'soapbox/schemas';
-
-import Search from './search';
-
-const store = {
- instance: instanceSchema.parse({
- version: '3.4.1 (compatible; TruthSocial 1.0.0+unreleased)',
- }),
-};
-
-const renderApp = (children: React.ReactElement) => render(children, undefined, store);
-
-describe('', () => {
- describe('with no results', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet('/api/v1/groups/search').reply(200, []);
- });
- });
-
- it('should render the blankslate', async () => {
- renderApp();
-
- await waitFor(() => {
- expect(screen.getByTestId('no-results')).toBeInTheDocument();
- });
- });
- });
-
- describe('with results', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet('/api/v1/groups/search').reply(200, [
- buildGroup({
- display_name: 'Group',
- id: '1',
- }),
- ]);
- });
- });
-
- it('should render the results', async () => {
- renderApp();
-
- await waitFor(() => {
- expect(screen.getByTestId('results')).toBeInTheDocument();
- });
- });
- });
-
- describe('before starting a search', () => {
- it('should render the RecentSearches component', () => {
- renderApp();
-
- expect(screen.getByTestId('recent-searches')).toBeInTheDocument();
- });
- });
-});
\ No newline at end of file
diff --git a/src/features/groups/components/discover/search/search.tsx b/src/features/groups/components/discover/search/search.tsx
deleted file mode 100644
index 2d414d0c5..000000000
--- a/src/features/groups/components/discover/search/search.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import React, { useEffect } from 'react';
-import { FormattedMessage } from 'react-intl';
-
-import { useGroupSearch } from 'soapbox/api/hooks';
-import { Stack } from 'soapbox/components/ui';
-import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search';
-import { useDebounce, useOwnAccount } from 'soapbox/hooks';
-import { saveGroupSearch } from 'soapbox/utils/groups';
-
-import Blankslate from './blankslate';
-import RecentSearches from './recent-searches';
-import Results from './results';
-
-interface Props {
- onSelect(value: string): void;
- searchValue: string;
-}
-
-export default (props: Props) => {
- const { onSelect, searchValue } = props;
-
- const { account: me } = useOwnAccount();
- const debounce = useDebounce;
-
- const debouncedValue = debounce(searchValue as string, 300);
- const debouncedValueToSave = debounce(searchValue as string, 1000);
-
- const groupSearchResult = useGroupSearch(debouncedValue);
- const { groups, isLoading, isFetched, isError } = groupSearchResult;
-
- const hasSearchResults = isFetched && groups.length > 0;
- const hasNoSearchResults = isFetched && groups.length === 0;
-
- useEffect(() => {
- if (debouncedValueToSave && debouncedValueToSave.length >= 0) {
- saveGroupSearch(me?.id as string, debouncedValueToSave);
- }
- }, [debouncedValueToSave]);
-
- if (isLoading) {
- return (
-
-
-
-
-
- );
- }
-
- if (isError) {
- return (
-
- }
- subtitle={
-
- }
- />
- );
- }
-
- if (hasNoSearchResults) {
- return (
-
- }
- subtitle={
-
- }
- />
- );
- }
-
- if (hasSearchResults) {
- return (
-
- );
- }
-
- return (
-
- );
-};
\ No newline at end of file
diff --git a/src/features/groups/components/discover/suggested-groups.tsx b/src/features/groups/components/discover/suggested-groups.tsx
deleted file mode 100644
index 5d73cc3f0..000000000
--- a/src/features/groups/components/discover/suggested-groups.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import React, { useState } from 'react';
-import { FormattedMessage } from 'react-intl';
-
-import { useSuggestedGroups } from 'soapbox/api/hooks';
-import Link from 'soapbox/components/link';
-import { Carousel, HStack, Stack, Text } from 'soapbox/components/ui';
-import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover';
-
-import GroupGridItem from './group-grid-item';
-
-const SuggestedGroups = () => {
- const { groups, isFetching, isFetched, isError } = useSuggestedGroups();
- const isEmpty = (isFetched && groups.length === 0) || isError;
-
- const [groupCover, setGroupCover] = useState(null);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- {isEmpty ? (
-
-
-
- ) : (
-
- {({ width }: { width: number }) => (
- <>
- {isFetching ? (
- new Array(20).fill(0).map((_, idx) => (
-
- ))
- ) : (
- groups.map((group) => (
-
- ))
- )}
- >
- )}
-
- )}
-
- );
-};
-
-export default SuggestedGroups;
\ No newline at end of file
diff --git a/src/features/groups/components/discover/tag-list-item.test.tsx b/src/features/groups/components/discover/tag-list-item.test.tsx
deleted file mode 100644
index 6d8485d99..000000000
--- a/src/features/groups/components/discover/tag-list-item.test.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from 'react';
-
-import { buildGroupTag } from 'soapbox/jest/factory';
-import { render, screen } from 'soapbox/jest/test-helpers';
-
-import TagListItem from './tag-list-item';
-
-describe(' {
- it('should render correctly', () => {
- const tag = buildGroupTag({ name: 'tag 1', groups: 5 });
- render();
-
- expect(screen.getByTestId('tag-list-item')).toHaveTextContent(tag.name);
- expect(screen.getByTestId('tag-list-item')).toHaveTextContent('Number of groups: 5');
- });
-});
\ No newline at end of file
diff --git a/src/features/groups/components/discover/tag-list-item.tsx b/src/features/groups/components/discover/tag-list-item.tsx
deleted file mode 100644
index 102614105..000000000
--- a/src/features/groups/components/discover/tag-list-item.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react';
-import { FormattedMessage } from 'react-intl';
-import { Link } from 'react-router-dom';
-
-import { Stack, Text } from 'soapbox/components/ui';
-
-import type { GroupTag } from 'soapbox/schemas';
-
-interface ITagListItem {
- tag: GroupTag;
-}
-
-const TagListItem = (props: ITagListItem) => {
- const { tag } = props;
-
- return (
-
-
-
- #{tag.name}
-
-
-
-
- :{' '}
- {tag.groups}
-
-
-
- );
-};
-
-export default TagListItem;
\ No newline at end of file
diff --git a/src/features/groups/components/group-link-preview.tsx b/src/features/groups/components/group-link-preview.tsx
deleted file mode 100644
index 6a7645bc9..000000000
--- a/src/features/groups/components/group-link-preview.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react';
-import { FormattedMessage } from 'react-intl';
-
-import { Avatar, Button, CardTitle, Stack } from 'soapbox/components/ui';
-import { type Card as StatusCard } from 'soapbox/types/entities';
-
-interface IGroupLinkPreview {
- card: StatusCard;
-}
-
-const GroupLinkPreview: React.FC = ({ card }) => {
- const { group } = card;
- if (!group) return null;
-
- return (
-
-
-
-
-
-
- } />
-
-
-
-
- );
-};
-
-export { GroupLinkPreview };
diff --git a/src/features/groups/components/pending-groups-row.tsx b/src/features/groups/components/pending-groups-row.tsx
deleted file mode 100644
index 101da43bc..000000000
--- a/src/features/groups/components/pending-groups-row.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-
-import { usePendingGroups } from 'soapbox/api/hooks';
-import { PendingItemsRow } from 'soapbox/components/pending-items-row';
-import { Divider } from 'soapbox/components/ui';
-import { useFeatures } from 'soapbox/hooks';
-
-export default () => {
- const features = useFeatures();
-
- const { groups, isFetching } = usePendingGroups();
-
- if (!features.groupsPending || isFetching || groups.length === 0) {
- return null;
- }
-
- return (
- <>
-
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/src/features/groups/discover.test.tsx b/src/features/groups/discover.test.tsx
deleted file mode 100644
index 880b17c1c..000000000
--- a/src/features/groups/discover.test.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import userEvent from '@testing-library/user-event';
-import React from 'react';
-
-import { buildAccount } from 'soapbox/jest/factory';
-import { render, screen, waitFor } from 'soapbox/jest/test-helpers';
-import { instanceSchema } from 'soapbox/schemas';
-
-import Discover from './discover';
-
-vi.mock('../../../hooks/useDimensions', () => ({
- useDimensions: () => [{ scrollWidth: 190 }, null, { width: 300 }],
-}));
-
-(window as any).ResizeObserver = class ResizeObserver {
-
- observe() { }
- disconnect() { }
-
-};
-
-const userId = '1';
-const store: any = {
- me: userId,
- accounts: {
- [userId]: buildAccount({
- id: userId,
- acct: 'justin-username',
- display_name: 'Justin L',
- avatar: 'test.jpg',
- source: {
- chats_onboarded: false,
- },
- }),
- },
- instance: instanceSchema.parse({
- version: '3.4.1 (compatible; TruthSocial 1.0.0)',
- software: 'TRUTHSOCIAL',
- }),
-};
-
-const renderApp = () => (
- render(
- ,
- undefined,
- store,
- )
-);
-
-describe('', () => {
- describe('before the user starts searching', () => {
- it('it should render popular groups', async () => {
- renderApp();
-
- await waitFor(() => {
- expect(screen.getByTestId('popular-groups')).toBeInTheDocument();
- expect(screen.getByTestId('suggested-groups')).toBeInTheDocument();
- expect(screen.getByTestId('popular-tags')).toBeInTheDocument();
- expect(screen.queryAllByTestId('recent-searches')).toHaveLength(0);
- expect(screen.queryAllByTestId('group-search-icon')).toHaveLength(0);
-
- });
- });
- });
-
- describe('when the user focuses on the input', () => {
- it('should render the search experience', async () => {
- const user = userEvent.setup();
- renderApp();
-
- await user.click(screen.getByTestId('search'));
-
- await waitFor(() => {
- expect(screen.getByTestId('group-search-icon')).toBeInTheDocument();
- expect(screen.getByTestId('recent-searches')).toBeInTheDocument();
- expect(screen.queryAllByTestId('popular-groups')).toHaveLength(0);
- });
- });
- });
-});
\ No newline at end of file
diff --git a/src/features/groups/discover.tsx b/src/features/groups/discover.tsx
deleted file mode 100644
index 0bb5af179..000000000
--- a/src/features/groups/discover.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import React, { useState } from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-
-import { HStack, Icon, IconButton, Input, Stack } from 'soapbox/components/ui';
-
-import PopularGroups from './components/discover/popular-groups';
-import PopularTags from './components/discover/popular-tags';
-import Search from './components/discover/search/search';
-import SuggestedGroups from './components/discover/suggested-groups';
-import TabBar, { TabItems } from './components/tab-bar';
-
-const messages = defineMessages({
- placeholder: { id: 'groups.discover.search.placeholder', defaultMessage: 'Search' },
-});
-
-const Discover: React.FC = () => {
- const intl = useIntl();
-
- const [isSearching, setIsSearching] = useState(false);
- const [value, setValue] = useState('');
-
- const hasSearchValue = value && value.length > 0;
-
- const cancelSearch = () => {
- clearValue();
- setIsSearching(false);
- };
-
- const clearValue = () => setValue('');
-
- return (
-
-
-
-
-
- {isSearching ? (
-
- ) : null}
-
- setValue(event.target.value)}
- onFocus={() => setIsSearching(true)}
- outerClassName='mt-0 w-full'
- theme='search'
- append={
-
- }
- />
-
-
- {isSearching ? (
- setValue(newValue)}
- />
- ) : (
- <>
-
-
-
- >
- )}
-
-
- );
-};
-
-export default Discover;
diff --git a/src/features/groups/index.tsx b/src/features/groups/index.tsx
index f85b9d474..e09de8985 100644
--- a/src/features/groups/index.tsx
+++ b/src/features/groups/index.tsx
@@ -1,36 +1,23 @@
-import React, { useState } from 'react';
-import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
+import React from 'react';
+import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { openModal } from 'soapbox/actions/modals';
import { useGroups } from 'soapbox/api/hooks';
import GroupCard from 'soapbox/components/group-card';
import ScrollableList from 'soapbox/components/scrollable-list';
-import { Button, Input, Stack, Text } from 'soapbox/components/ui';
-import { useAppDispatch, useAppSelector, useDebounce, useFeatures } from 'soapbox/hooks';
+import { Button, Stack, Text } from 'soapbox/components/ui';
+import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { PERMISSION_CREATE_GROUPS, hasPermission } from 'soapbox/utils/permissions';
import PlaceholderGroupCard from '../placeholder/components/placeholder-group-card';
-import PendingGroupsRow from './components/pending-groups-row';
-import TabBar, { TabItems } from './components/tab-bar';
-
-const messages = defineMessages({
- placeholder: { id: 'groups.search.placeholder', defaultMessage: 'Search My Groups' },
-});
-
const Groups: React.FC = () => {
- const debounce = useDebounce;
const dispatch = useAppDispatch();
- const features = useFeatures();
- const intl = useIntl();
const canCreateGroup = useAppSelector((state) => hasPermission(state, PERMISSION_CREATE_GROUPS));
- const [searchValue, setSearchValue] = useState('');
- const debouncedValue = debounce(searchValue, 300);
-
- const { groups, isLoading, hasNextPage, fetchNextPage } = useGroups(debouncedValue);
+ const { groups, isLoading, hasNextPage, fetchNextPage } = useGroups();
const handleLoadMore = () => {
if (hasNextPage) {
@@ -72,10 +59,6 @@ const Groups: React.FC = () => {
return (
- {features.groupsDiscovery && (
-
- )}
-
{canCreateGroup && (
)}
- {features.groupsSearch ? (
- setSearchValue(event.target.value)}
- placeholder={intl.formatMessage(messages.placeholder)}
- theme='search'
- value={searchValue}
- />
- ) : null}
-
-
-
{
hasMore={hasNextPage}
>
{groups.map((group) => (
-
+
))}
diff --git a/src/features/groups/pending-requests.tsx b/src/features/groups/pending-requests.tsx
deleted file mode 100644
index 34a5a56e0..000000000
--- a/src/features/groups/pending-requests.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import React from 'react';
-import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import { Link } from 'react-router-dom';
-
-import { usePendingGroups } from 'soapbox/api/hooks';
-import GroupCard from 'soapbox/components/group-card';
-import ScrollableList from 'soapbox/components/scrollable-list';
-import { Column, Stack, Text } from 'soapbox/components/ui';
-
-import PlaceholderGroupCard from '../placeholder/components/placeholder-group-card';
-
-const messages = defineMessages({
- label: { id: 'groups.pending.label', defaultMessage: 'Pending Requests' },
-});
-
-export default () => {
- const intl = useIntl();
-
- const { groups, isLoading } = usePendingGroups();
-
- const renderBlankslate = () => (
-
-
-
-
-
-
-
-
-
-
-
- );
-
- return (
-
-
- {groups.map((group) => (
-
-
-
- ))}
-
-
- );
-};
\ No newline at end of file
diff --git a/src/features/groups/popular.tsx b/src/features/groups/popular.tsx
deleted file mode 100644
index a2c464d79..000000000
--- a/src/features/groups/popular.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-import clsx from 'clsx';
-import React, { useCallback, useState } from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
-
-import { usePopularGroups } from 'soapbox/api/hooks';
-import { Column } from 'soapbox/components/ui';
-
-import GroupGridItem from './components/discover/group-grid-item';
-import GroupListItem from './components/discover/group-list-item';
-import LayoutButtons, { GroupLayout } from './components/discover/layout-buttons';
-
-import type { Group } from 'soapbox/schemas';
-
-const messages = defineMessages({
- label: { id: 'groups.popular.label', defaultMessage: 'Suggested Groups' },
-});
-
-const GridList: Components['List'] = React.forwardRef((props, ref) => {
- const { context, ...rest } = props;
- return ;
-});
-
-const Popular: React.FC = () => {
- const intl = useIntl();
-
- const [layout, setLayout] = useState(GroupLayout.LIST);
-
- const { groups, hasNextPage, fetchNextPage } = usePopularGroups();
-
- const handleLoadMore = () => {
- if (hasNextPage) {
- fetchNextPage();
- }
- };
-
- const renderGroupList = useCallback((group: Group, index: number) => (
-
-
-
- ), []);
-
- const renderGroupGrid = useCallback((group: Group) => (
-
- ), []);
-
- return (
- setLayout(selectedLayout)}
- />
- }
- >
- {layout === GroupLayout.LIST ? (
- renderGroupList(group, index)}
- endReached={handleLoadMore}
- />
- ) : (
- renderGroupGrid(group)}
- components={{
- Item: (props) => (
-
- ),
- List: GridList,
- }}
- endReached={handleLoadMore}
- />
- )}
-
- );
-};
-
-export default Popular;
diff --git a/src/features/groups/suggested.tsx b/src/features/groups/suggested.tsx
deleted file mode 100644
index 8a3e570e0..000000000
--- a/src/features/groups/suggested.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-import clsx from 'clsx';
-import React, { useCallback, useState } from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
-
-import { useSuggestedGroups } from 'soapbox/api/hooks';
-import { Column } from 'soapbox/components/ui';
-
-import GroupGridItem from './components/discover/group-grid-item';
-import GroupListItem from './components/discover/group-list-item';
-import LayoutButtons, { GroupLayout } from './components/discover/layout-buttons';
-
-import type { Group } from 'soapbox/schemas';
-
-const messages = defineMessages({
- label: { id: 'groups.suggested.label', defaultMessage: 'Suggested Groups' },
-});
-
-const GridList: Components['List'] = React.forwardRef((props, ref) => {
- const { context, ...rest } = props;
- return ;
-});
-
-const Suggested: React.FC = () => {
- const intl = useIntl();
-
- const [layout, setLayout] = useState(GroupLayout.LIST);
-
- const { groups, hasNextPage, fetchNextPage } = useSuggestedGroups();
-
- const handleLoadMore = () => {
- if (hasNextPage) {
- fetchNextPage();
- }
- };
-
- const renderGroupList = useCallback((group: Group, index: number) => (
-
-
-
- ), []);
-
- const renderGroupGrid = useCallback((group: Group) => (
-
- ), []);
-
- return (
- setLayout(selectedLayout)}
- />
- }
- >
- {layout === GroupLayout.LIST ? (
- renderGroupList(group, index)}
- endReached={handleLoadMore}
- />
- ) : (
- renderGroupGrid(group)}
- components={{
- Item: (props) => (
-
- ),
- List: GridList,
- }}
- endReached={handleLoadMore}
- />
- )}
-
- );
-};
-
-export default Suggested;
diff --git a/src/features/groups/tag.tsx b/src/features/groups/tag.tsx
deleted file mode 100644
index 44d30be0a..000000000
--- a/src/features/groups/tag.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import clsx from 'clsx';
-import React, { useCallback, useState } from 'react';
-import { Components, Virtuoso, VirtuosoGrid } from 'react-virtuoso';
-
-import { useGroupTag, useGroupsFromTag } from 'soapbox/api/hooks';
-import { Column, HStack, Icon } from 'soapbox/components/ui';
-
-import GroupGridItem from './components/discover/group-grid-item';
-import GroupListItem from './components/discover/group-list-item';
-
-import type { Group } from 'soapbox/schemas';
-
-enum Layout {
- LIST = 'LIST',
- GRID = 'GRID'
-}
-
-const GridList: Components['List'] = React.forwardRef((props, ref) => {
- const { context, ...rest } = props;
- return ;
-});
-
-interface ITag {
- params: { id: string };
-}
-
-const Tag: React.FC = (props) => {
- const tagId = props.params.id;
-
- const [layout, setLayout] = useState(Layout.LIST);
-
- const { tag, isLoading } = useGroupTag(tagId);
- const { groups, hasNextPage, fetchNextPage } = useGroupsFromTag(tagId);
-
- const handleLoadMore = () => {
- if (hasNextPage) {
- fetchNextPage();
- }
- };
-
- const renderGroupList = useCallback((group: Group, index: number) => (
-
-
-
- ), []);
-
- const renderGroupGrid = useCallback((group: Group) => (
-
- ), []);
-
- if (isLoading || !tag) {
- return null;
- }
-
- return (
-
-
-
-
-
- }
- >
- {layout === Layout.LIST ? (
- renderGroupList(group, index)}
- endReached={handleLoadMore}
- />
- ) : (
- renderGroupGrid(group)}
- components={{
- Item: (props) => (
-
- ),
- List: GridList,
- }}
- endReached={handleLoadMore}
- />
- )}
-
- );
-};
-
-export default Tag;
diff --git a/src/features/groups/tags.tsx b/src/features/groups/tags.tsx
deleted file mode 100644
index aa37a514b..000000000
--- a/src/features/groups/tags.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import clsx from 'clsx';
-import React from 'react';
-import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
-import { Virtuoso } from 'react-virtuoso';
-
-import { usePopularTags } from 'soapbox/api/hooks';
-import { Column, Text } from 'soapbox/components/ui';
-
-import TagListItem from './components/discover/tag-list-item';
-
-import type { GroupTag } from 'soapbox/schemas';
-
-const messages = defineMessages({
- title: { id: 'groups.tags.title', defaultMessage: 'Browse Topics' },
-});
-
-const Tags: React.FC = () => {
- const intl = useIntl();
-
- const { tags, isFetched, isError, hasNextPage, fetchNextPage } = usePopularTags();
- const isEmpty = (isFetched && tags.length === 0) || isError;
-
- const handleLoadMore = () => {
- if (hasNextPage) {
- fetchNextPage();
- }
- };
-
- const renderItem = (index: number, tag: GroupTag) => (
-
-
-
- );
-
- return (
-
- {isEmpty ? (
-
-
-
- ) : (
-
- )}
-
- );
-};
-
-export default Tags;
diff --git a/src/features/mutes/components/group-list-item.tsx b/src/features/mutes/components/group-list-item.tsx
index 2e839678c..e71b10f4d 100644
--- a/src/features/mutes/components/group-list-item.tsx
+++ b/src/features/mutes/components/group-list-item.tsx
@@ -1,56 +1,28 @@
import React from 'react';
-import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
-import { useUnmuteGroup } from 'soapbox/api/hooks';
import GroupAvatar from 'soapbox/components/groups/group-avatar';
-import { Button, HStack, Text } from 'soapbox/components/ui';
+import { HStack, Text } from 'soapbox/components/ui';
import { type Group } from 'soapbox/schemas';
-import toast from 'soapbox/toast';
interface IGroupListItem {
group: Group;
onUnmute(): void;
}
-const messages = defineMessages({
- unmuteSuccess: { id: 'group.unmute.success', defaultMessage: 'Unmuted the group' },
-});
+const GroupListItem = ({ group, onUnmute }: IGroupListItem) => (
+
+
-const GroupListItem = ({ group, onUnmute }: IGroupListItem) => {
- const intl = useIntl();
-
- const unmuteGroup = useUnmuteGroup(group);
-
- const handleUnmute = () => {
- unmuteGroup.mutate(undefined, {
- onSuccess() {
- onUnmute();
- toast.success(intl.formatMessage(messages.unmuteSuccess));
- },
- });
- };
-
- return (
-
-
-
-
-
-
-
-
-
- );
-};
+
+
+);
export default GroupListItem;
\ No newline at end of file
diff --git a/src/features/mutes/index.tsx b/src/features/mutes/index.tsx
index c7c25bf35..38782db56 100644
--- a/src/features/mutes/index.tsx
+++ b/src/features/mutes/index.tsx
@@ -1,26 +1,18 @@
-import React, { useState } from 'react';
+import React from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
-import { useMutes, useGroupMutes } from 'soapbox/api/hooks';
+import { useMutes } from 'soapbox/api/hooks';
import ScrollableList from 'soapbox/components/scrollable-list';
-import { Column, Stack, Tabs } from 'soapbox/components/ui';
+import { Column, Stack } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account-container';
-import { useFeatures } from 'soapbox/hooks';
-
-import GroupListItem from './components/group-list-item';
const messages = defineMessages({
heading: { id: 'column.mutes', defaultMessage: 'Mutes' },
});
-enum TabItems {
- ACCOUNTS = 'ACCOUNTS',
- GROUPS = 'GROUPS'
-}
const Mutes: React.FC = () => {
const intl = useIntl();
- const features = useFeatures();
const {
accounts,
@@ -29,17 +21,6 @@ const Mutes: React.FC = () => {
isLoading: isLoadingAccounts,
} = useMutes();
- const {
- mutes: groupMutes,
- isLoading: isLoadingGroups,
- hasNextPage: hasNextGroupsPage,
- fetchNextPage: fetchNextGroups,
- fetchEntities: fetchMutedGroups,
- } = useGroupMutes();
-
- const [activeItem, setActiveItem] = useState(TabItems.ACCOUNTS);
- const isAccountsTabSelected = activeItem === TabItems.ACCOUNTS;
-
const scrollableListProps = {
itemClassName: 'pb-4 last:pb-0',
scrollKey: 'mutes',
@@ -49,56 +30,19 @@ const Mutes: React.FC = () => {
return (
- {features.groupsMuting && (
- setActiveItem(TabItems.ACCOUNTS),
- name: TabItems.ACCOUNTS,
- },
- {
- text: 'Groups',
- action: () => setActiveItem(TabItems.GROUPS),
- name: TabItems.GROUPS,
- },
- ]}
- activeItem={activeItem}
- />
- )}
-
- {isAccountsTabSelected ? (
-
- }
- >
- {accounts.map((accounts) =>
- ,
- )}
-
- ) : (
-
- }
- >
- {groupMutes.map((group) =>(
-
- ))}
-
- )}
+
+ }
+ >
+ {accounts.map((accounts) =>
+ ,
+ )}
+
);
diff --git a/src/features/notifications/components/notification.tsx b/src/features/notifications/components/notification.tsx
index 7a05a7d23..c1a44133e 100644
--- a/src/features/notifications/components/notification.tsx
+++ b/src/features/notifications/components/notification.tsx
@@ -1,5 +1,5 @@
import React, { useCallback } from 'react';
-import { defineMessages, useIntl, FormattedMessage, IntlShape, MessageDescriptor, defineMessage } from 'react-intl';
+import { defineMessages, useIntl, IntlShape, MessageDescriptor } from 'react-intl';
import { Link, useHistory } from 'react-router-dom';
import { mentionCompose } from 'soapbox/actions/compose';
@@ -58,11 +58,6 @@ const icons: Record = {
'pleroma:participation_accepted': require('@tabler/icons/outline/calendar-event.svg'),
};
-const nameMessage = defineMessage({
- id: 'notification.name',
- defaultMessage: '{link}{others}',
-});
-
const messages: Record = defineMessages({
follow: {
id: 'notification.follow',
@@ -138,21 +133,10 @@ const buildMessage = (
intl: IntlShape,
type: NotificationType,
account: AccountEntity,
- totalCount: number | null,
targetName: string,
instanceTitle: string,
): React.ReactNode => {
- const link = buildLink(account);
- const name = intl.formatMessage(nameMessage, {
- link,
- others: totalCount && totalCount > 0 ? (
-
- ) : '',
- });
+ const name = buildLink(account);
return intl.formatMessage(messages[type], {
name,
@@ -356,7 +340,7 @@ const Notification: React.FC = (props) => {
const targetName = notification.target && typeof notification.target === 'object' ? notification.target.acct : '';
- const message: React.ReactNode = validType(type) && account && typeof account === 'object' ? buildMessage(intl, type, account, notification.total_count, targetName, instance.title) : null;
+ const message: React.ReactNode = validType(type) && account && typeof account === 'object' ? buildMessage(intl, type, account, targetName, instance.title) : null;
const ariaLabel = validType(type) ? (
notificationForScreenReader(
diff --git a/src/features/status/components/detailed-status.tsx b/src/features/status/components/detailed-status.tsx
index e421ee35b..2c1bbee9a 100644
--- a/src/features/status/components/detailed-status.tsx
+++ b/src/features/status/components/detailed-status.tsx
@@ -67,7 +67,7 @@ const DetailedStatus: React.FC = ({
defaultMessage='Posted in {group}'
values={{
group: (
-
+
diff --git a/src/features/status/components/thread.tsx b/src/features/status/components/thread.tsx
index b6a7c4514..b2b2393fc 100644
--- a/src/features/status/components/thread.tsx
+++ b/src/features/status/components/thread.tsx
@@ -77,15 +77,11 @@ interface IThread {
withMedia?: boolean;
useWindowScroll?: boolean;
itemClassName?: string;
- next: string | undefined;
- handleLoadMore: () => void;
}
const Thread = (props: IThread) => {
const {
- handleLoadMore,
itemClassName,
- next,
status,
useWindowScroll = true,
withMedia = true,
@@ -439,8 +435,6 @@ const Thread = (props: IThread) => {
}
initialTopMostItemIndex={initialTopMostItemIndex}
useWindowScroll={useWindowScroll}
diff --git a/src/features/status/index.tsx b/src/features/status/index.tsx
index 58640403c..19be5f2e3 100644
--- a/src/features/status/index.tsx
+++ b/src/features/status/index.tsx
@@ -1,12 +1,8 @@
-import debounce from 'lodash/debounce';
import React, { useCallback, useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Redirect } from 'react-router-dom';
-import {
- fetchStatusWithContext,
- fetchNext,
-} from 'soapbox/actions/statuses';
+import { fetchStatusWithContext } from 'soapbox/actions/statuses';
import MissingIndicator from 'soapbox/components/missing-indicator';
import PullToRefresh from 'soapbox/components/pull-to-refresh';
import { Column, Stack } from 'soapbox/components/ui';
@@ -38,7 +34,6 @@ const messages = defineMessages({
type RouteParams = {
statusId: string;
groupId?: string;
- groupSlug?: string;
};
interface IStatusDetails {
@@ -54,14 +49,12 @@ const StatusDetails: React.FC = (props) => {
const status = useAppSelector((state) => getStatus(state, { id: props.params.statusId }));
const [isLoaded, setIsLoaded] = useState(!!status);
- const [next, setNext] = useState();
/** Fetch the status (and context) from the API. */
- const fetchData = async () => {
+ const fetchData = () => {
const { params } = props;
const { statusId } = params;
- const { next } = await dispatch(fetchStatusWithContext(statusId));
- setNext(next);
+ return dispatch(fetchStatusWithContext(statusId));
};
// Load data.
@@ -73,14 +66,6 @@ const StatusDetails: React.FC = (props) => {
});
}, [props.params.statusId]);
- const handleLoadMore = useCallback(debounce(() => {
- if (next && status) {
- dispatch(fetchNext(status.id, next)).then(({ next }) => {
- setNext(next);
- }).catch(() => { });
- }
- }, 300, { leading: true }), [next, status]);
-
const handleRefresh = () => {
return fetchData();
};
@@ -104,8 +89,8 @@ const StatusDetails: React.FC = (props) => {
}
if (status.group && typeof status.group === 'object') {
- if (status.group.slug && !props.params.groupSlug) {
- return ;
+ if (status.group.id && !props.params.groupId) {
+ return ;
}
}
@@ -118,11 +103,7 @@ const StatusDetails: React.FC = (props) => {
-
+
diff --git a/src/features/test-timeline/index.tsx b/src/features/test-timeline/index.tsx
index 623ef9d33..21a455019 100644
--- a/src/features/test-timeline/index.tsx
+++ b/src/features/test-timeline/index.tsx
@@ -22,7 +22,6 @@ const MOCK_STATUSES: any[] = [
require('soapbox/__fixtures__/pleroma-status-vertical-video-without-metadata.json'),
require('soapbox/__fixtures__/pleroma-status-with-poll-with-emojis.json'),
require('soapbox/__fixtures__/pleroma-quote-of-quote-post.json'),
- require('soapbox/__fixtures__/truthsocial-status-in-moderation.json'),
];
const timelineId = 'test';
diff --git a/src/features/ui/components/compose-button.tsx b/src/features/ui/components/compose-button.tsx
index 7686f9c55..e2e03ab12 100644
--- a/src/features/ui/components/compose-button.tsx
+++ b/src/features/ui/components/compose-button.tsx
@@ -4,15 +4,15 @@ import { useLocation, useRouteMatch } from 'react-router-dom';
import { groupComposeModal } from 'soapbox/actions/compose';
import { openModal } from 'soapbox/actions/modals';
-import { useGroupLookup } from 'soapbox/api/hooks';
+import { useGroup } from 'soapbox/api/hooks';
import { Avatar, Button, HStack } from 'soapbox/components/ui';
import { useAppDispatch } from 'soapbox/hooks';
const ComposeButton = () => {
const location = useLocation();
const isOnGroupPage = location.pathname.startsWith('/group/');
- const match = useRouteMatch<{ groupSlug: string }>('/group/:groupSlug');
- const { entity: group } = useGroupLookup(match?.params.groupSlug || '');
+ const match = useRouteMatch<{ groupId: string }>('/group/:groupId');
+ const { group } = useGroup(match?.params.groupId || '');
const isGroupMember = !!group?.relationship?.member;
if (isOnGroupPage && isGroupMember) {
@@ -40,8 +40,8 @@ const HomeComposeButton = () => {
const GroupComposeButton = () => {
const dispatch = useAppDispatch();
- const match = useRouteMatch<{ groupSlug: string }>('/group/:groupSlug');
- const { entity: group } = useGroupLookup(match?.params.groupSlug || '');
+ const match = useRouteMatch<{ groupId: string }>('/group/:groupId');
+ const { group } = useGroup(match?.params.groupId || '');
if (!group) return null;
diff --git a/src/features/ui/components/floating-action-button.tsx b/src/features/ui/components/floating-action-button.tsx
index 73c43e7c1..db52a990e 100644
--- a/src/features/ui/components/floating-action-button.tsx
+++ b/src/features/ui/components/floating-action-button.tsx
@@ -5,7 +5,7 @@ import { useLocation, useRouteMatch } from 'react-router-dom';
import { groupComposeModal } from 'soapbox/actions/compose';
import { openModal } from 'soapbox/actions/modals';
-import { useGroupLookup } from 'soapbox/api/hooks';
+import { useGroup } from 'soapbox/api/hooks';
import { Avatar, HStack, Icon } from 'soapbox/components/ui';
import { useAppDispatch } from 'soapbox/hooks';
@@ -53,8 +53,8 @@ const GroupFAB: React.FC = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
- const match = useRouteMatch<{ groupSlug: string }>('/group/:groupSlug');
- const { entity: group } = useGroupLookup(match?.params.groupSlug || '');
+ const match = useRouteMatch<{ groupId: string }>('/group/:groupId');
+ const { group } = useGroup(match?.params.groupId || '');
if (!group) return null;
diff --git a/src/features/ui/components/modals/compose-modal.tsx b/src/features/ui/components/modals/compose-modal.tsx
index b5fc73c33..e9fe0e7b4 100644
--- a/src/features/ui/components/modals/compose-modal.tsx
+++ b/src/features/ui/components/modals/compose-modal.tsx
@@ -2,12 +2,11 @@ import clsx from 'clsx';
import React, { useRef } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import { cancelReplyCompose, setGroupTimelineVisible, uploadCompose } from 'soapbox/actions/compose';
+import { cancelReplyCompose, uploadCompose } from 'soapbox/actions/compose';
import { openModal, closeModal } from 'soapbox/actions/modals';
-import { useGroup } from 'soapbox/api/hooks';
import { checkComposeContent } from 'soapbox/components/modal-root';
-import { HStack, Modal, Text, Toggle } from 'soapbox/components/ui';
-import { useAppDispatch, useAppSelector, useCompose, useDraggedFiles } from 'soapbox/hooks';
+import { Modal } from 'soapbox/components/ui';
+import { useAppDispatch, useCompose, useDraggedFiles } from 'soapbox/hooks';
import ComposeForm from '../../../compose/components/compose-form';
@@ -82,50 +81,9 @@ const ComposeModal: React.FC = ({ onClose, composeId = 'compose-m
'ring-2 ring-offset-2 ring-primary-600': isDraggedOver,
})}
>
- }
- autoFocus
- />
+
);
};
-interface IComposeFormGroupToggle {
- composeId: string;
- groupId: string | null;
-}
-
-const ComposeFormGroupToggle: React.FC = ({ composeId, groupId }) => {
- const dispatch = useAppDispatch();
- const { group } = useGroup(groupId || '', false);
-
- const groupTimelineVisible = useAppSelector((state) => !!state.compose.get(composeId)?.group_timeline_visible);
-
- const handleToggleChange = () => {
- dispatch(setGroupTimelineVisible(composeId, !groupTimelineVisible));
- };
-
- const labelId = `group-timeline-visible+${composeId}`;
-
- if (!group) return null;
- if (group.locked) return null;
-
- return (
-
-
-
-
- );
-};
-
export default ComposeModal;
diff --git a/src/features/ui/components/modals/manage-group-modal/create-group-modal.tsx b/src/features/ui/components/modals/manage-group-modal/create-group-modal.tsx
index 11782047e..e608134b9 100644
--- a/src/features/ui/components/modals/manage-group-modal/create-group-modal.tsx
+++ b/src/features/ui/components/modals/manage-group-modal/create-group-modal.tsx
@@ -3,9 +3,8 @@ import React, { useMemo, useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { z } from 'zod';
-import { useCreateGroup, useGroupValidation, type CreateGroupParams } from 'soapbox/api/hooks';
+import { useCreateGroup, type CreateGroupParams } from 'soapbox/api/hooks';
import { Modal, Stack } from 'soapbox/components/ui';
-import { useDebounce } from 'soapbox/hooks';
import { type Group } from 'soapbox/schemas';
import toast from 'soapbox/toast';
@@ -31,7 +30,6 @@ interface ICreateGroupModal {
const CreateGroupModal: React.FC = ({ onClose }) => {
const intl = useIntl();
- const debounce = useDebounce;
const [group, setGroup] = useState(null);
const [params, setParams] = useState({
@@ -41,9 +39,6 @@ const CreateGroupModal: React.FC = ({ onClose }) => {
const { createGroup, isSubmitting } = useCreateGroup();
- const debouncedName = debounce(params.display_name || '', 300);
- const { data: { isValid } } = useGroupValidation(debouncedName);
-
const handleClose = () => {
onClose('MANAGE_GROUP');
};
@@ -117,7 +112,7 @@ const CreateGroupModal: React.FC = ({ onClose }) => {
title={renderModalTitle()}
confirmationAction={handleNextStep}
confirmationText={confirmationText}
- confirmationDisabled={isSubmitting || (currentStep === Steps.TWO && !isValid)}
+ confirmationDisabled={isSubmitting}
confirmationFullWidth
onClose={handleClose}
>
diff --git a/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx b/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
index 2e4dec53a..a1c47ca65 100644
--- a/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
+++ b/src/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
@@ -1,12 +1,11 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import { CreateGroupParams, useGroupValidation } from 'soapbox/api/hooks';
+import { CreateGroupParams } from 'soapbox/api/hooks';
import { Form, FormGroup, Input, Textarea } from 'soapbox/components/ui';
import AvatarPicker from 'soapbox/features/edit-profile/components/avatar-picker';
import HeaderPicker from 'soapbox/features/edit-profile/components/header-picker';
-import GroupTagsField from 'soapbox/features/group/components/group-tags-field';
-import { useAppSelector, useDebounce, useInstance } from 'soapbox/hooks';
+import { useAppSelector, useInstance } from 'soapbox/hooks';
import { usePreview } from 'soapbox/hooks/forms';
import resizeImage from 'soapbox/utils/resize-image';
@@ -23,18 +22,13 @@ interface IDetailsStep {
const DetailsStep: React.FC = ({ params, onChange }) => {
const intl = useIntl();
- const debounce = useDebounce;
const instance = useInstance();
const {
display_name: displayName = '',
note = '',
- tags = [''],
} = params;
- const debouncedName = debounce(displayName, 300);
- const { data: { isValid, message: errorMessage } } = useGroupValidation(debouncedName);
-
const avatarSrc = usePreview(params.avatar);
const headerSrc = usePreview(params.header);
@@ -65,28 +59,6 @@ const DetailsStep: React.FC = ({ params, onChange }) => {
const handleImageClear = (property: keyof CreateGroupParams) => () => onChange({ [property]: undefined });
- const handleTagsChange = (tags: string[]) => {
- onChange({
- ...params,
- tags,
- });
- };
-
- const handleAddTag = () => {
- onChange({
- ...params,
- tags: [...tags, ''],
- });
- };
-
- const handleRemoveTag = (i: number) => {
- const newTags = [...tags];
- newTags.splice(i, 1);
- onChange({
- ...params,
- tags: newTags,
- });
- };
return (
);
};
diff --git a/src/features/ui/components/modals/media-modal.tsx b/src/features/ui/components/modals/media-modal.tsx
index fe30f7247..a04eb7ac4 100644
--- a/src/features/ui/components/modals/media-modal.tsx
+++ b/src/features/ui/components/modals/media-modal.tsx
@@ -1,11 +1,10 @@
import clsx from 'clsx';
-import debounce from 'lodash/debounce';
import React, { useCallback, useEffect, useState } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { useHistory } from 'react-router-dom';
import ReactSwipeableViews from 'react-swipeable-views';
-import { fetchNext, fetchStatusWithContext } from 'soapbox/actions/statuses';
+import { fetchStatusWithContext } from 'soapbox/actions/statuses';
import ExtendedVideoPlayer from 'soapbox/components/extended-video-player';
import MissingIndicator from 'soapbox/components/missing-indicator';
import StatusActionBar from 'soapbox/components/status-action-bar';
@@ -68,7 +67,6 @@ const MediaModal: React.FC = (props) => {
const actualStatus = useAppSelector((state) => getStatus(state, { id: status?.id as string }));
const [isLoaded, setIsLoaded] = useState(!!status);
- const [next, setNext] = useState();
const [index, setIndex] = useState(null);
const [navigationHidden, setNavigationHidden] = useState(false);
const [isFullScreen, setIsFullScreen] = useState(!status);
@@ -185,19 +183,8 @@ const MediaModal: React.FC = (props) => {
return null;
}).toArray();
- const handleLoadMore = useCallback(debounce(() => {
- if (next && status) {
- dispatch(fetchNext(status?.id, next)).then(({ next }) => {
- setNext(next);
- }).catch(() => { });
- }
- }, 300, { leading: true }), [next, status]);
-
/** Fetch the status (and context) from the API. */
- const fetchData = async () => {
- const { next } = await dispatch(fetchStatusWithContext(status?.id as string));
- setNext(next);
- };
+ const fetchData = () => dispatch(fetchStatusWithContext(status?.id as string));
// Load data.
useEffect(() => {
@@ -351,8 +338,6 @@ const MediaModal: React.FC = (props) => {
withMedia={false}
useWindowScroll={false}
itemClassName='px-4'
- next={next}
- handleLoadMore={handleLoadMore}
/>
)}
diff --git a/src/features/ui/components/modals/report-modal/report-modal.tsx b/src/features/ui/components/modals/report-modal/report-modal.tsx
index 77fbb1946..c38a5952d 100644
--- a/src/features/ui/components/modals/report-modal/report-modal.tsx
+++ b/src/features/ui/components/modals/report-modal/report-modal.tsx
@@ -6,10 +6,8 @@ import { submitReport, submitReportSuccess, submitReportFail, ReportableEntities
import { expandAccountTimeline } from 'soapbox/actions/timelines';
import { useAccount } from 'soapbox/api/hooks';
import AttachmentThumbs from 'soapbox/components/attachment-thumbs';
-import GroupCard from 'soapbox/components/group-card';
-import List, { ListItem } from 'soapbox/components/list';
import StatusContent from 'soapbox/components/status-content';
-import { Avatar, HStack, Icon, Modal, ProgressBar, Stack, Text } from 'soapbox/components/ui';
+import { Modal, ProgressBar, Stack, Text } from 'soapbox/components/ui';
import AccountContainer from 'soapbox/containers/account-container';
import { useAppDispatch, useAppSelector, useInstance } from 'soapbox/hooks';
@@ -22,9 +20,6 @@ const messages = defineMessages({
done: { id: 'report.done', defaultMessage: 'Done' },
next: { id: 'report.next', defaultMessage: 'Next' },
submit: { id: 'report.submit', defaultMessage: 'Submit' },
- reportContext: { id: 'report.chat_message.context', defaultMessage: 'When reporting a user’s message, the five messages before and five messages after the one selected will be passed along to our moderation team for context.' },
- reportMessage: { id: 'report.chat_message.title', defaultMessage: 'Report message' },
- reportGroup: { id: 'report.group.title', defaultMessage: 'Report Group' },
cancel: { id: 'common.cancel', defaultMessage: 'Cancel' },
previous: { id: 'report.previous', defaultMessage: 'Previous' },
});
@@ -36,26 +31,9 @@ enum Steps {
}
const reportSteps = {
- [ReportableEntities.ACCOUNT]: {
- ONE: ReasonStep,
- TWO: OtherActionsStep,
- THREE: ConfirmationStep,
- },
- [ReportableEntities.CHAT_MESSAGE]: {
- ONE: ReasonStep,
- TWO: OtherActionsStep,
- THREE: ConfirmationStep,
- },
- [ReportableEntities.STATUS]: {
- ONE: ReasonStep,
- TWO: OtherActionsStep,
- THREE: ConfirmationStep,
- },
- [ReportableEntities.GROUP]: {
- ONE: ReasonStep,
- TWO: null,
- THREE: ConfirmationStep,
- },
+ ONE: ReasonStep,
+ TWO: OtherActionsStep,
+ THREE: ConfirmationStep,
};
const SelectedStatus = ({ statusId }: { statusId: string }) => {
@@ -107,14 +85,11 @@ const ReportModal = ({ onClose }: IReportModal) => {
const { rules } = useInstance();
const ruleIds = useAppSelector((state) => state.reports.new.rule_ids);
const selectedStatusIds = useAppSelector((state) => state.reports.new.status_ids);
- const selectedChatMessage = useAppSelector((state) => state.reports.new.chat_message);
- const selectedGroup = useAppSelector((state) => state.reports.new.group);
const shouldRequireRule = rules.length > 0;
const isReportingAccount = entityType === ReportableEntities.ACCOUNT;
const isReportingStatus = entityType === ReportableEntities.STATUS;
- const isReportingGroup = entityType === ReportableEntities.GROUP;
const [currentStep, setCurrentStep] = useState(Steps.ONE);
@@ -166,40 +141,23 @@ const ReportModal = ({ onClose }: IReportModal) => {
const confirmationText = useMemo(() => {
switch (currentStep) {
case Steps.ONE:
- if (isReportingGroup) {
- return intl.formatMessage(messages.submit);
- } else {
- return intl.formatMessage(messages.next);
- }
+ return intl.formatMessage(messages.next);
case Steps.TWO:
- if (isReportingGroup) {
- return intl.formatMessage(messages.done);
- } else {
- return intl.formatMessage(messages.submit);
- }
+ return intl.formatMessage(messages.submit);
case Steps.THREE:
return intl.formatMessage(messages.done);
default:
return intl.formatMessage(messages.next);
}
- }, [currentStep, isReportingGroup]);
+ }, [currentStep]);
const handleNextStep = () => {
switch (currentStep) {
case Steps.ONE:
- if (isReportingGroup) {
- handleSubmit();
- } else {
- setCurrentStep(Steps.TWO);
- }
+ setCurrentStep(Steps.TWO);
break;
case Steps.TWO:
- if (isReportingGroup) {
- dispatch(submitReportSuccess());
- onClose();
- } else {
- handleSubmit();
- }
+ handleSubmit();
break;
case Steps.THREE:
dispatch(submitReportSuccess());
@@ -210,64 +168,13 @@ const ReportModal = ({ onClose }: IReportModal) => {
}
};
- const renderSelectedChatMessage = () => {
- if (account) {
- return (
-
-
-
-
-
-
-
-
-
-
- }
- >
- {intl.formatMessage(messages.reportContext)}
-
-
-
- );
- }
- };
-
- const renderSelectedGroup = () => {
- if (selectedGroup) {
- return ;
- }
- };
-
const renderSelectedEntity = () => {
- switch (entityType) {
- case ReportableEntities.STATUS:
- return renderSelectedStatuses();
- case ReportableEntities.CHAT_MESSAGE:
- return renderSelectedChatMessage();
- case ReportableEntities.GROUP:
- if (currentStep === Steps.TWO) {
- return null;
- }
-
- return renderSelectedGroup();
- default:
- return null;
- }
+ if (entityType === ReportableEntities.STATUS) return renderSelectedStatuses();
+ return null;
};
const renderTitle = () => {
- switch (entityType) {
- case ReportableEntities.CHAT_MESSAGE:
- return intl.formatMessage(messages.reportMessage);
- case ReportableEntities.GROUP:
- return intl.formatMessage(messages.reportGroup);
- default:
- return @{account?.acct} }} />;
- }
+ return @{account?.acct} }} />;
};
const isConfirmationButtonDisabled = useMemo(() => {
@@ -301,7 +208,7 @@ const ReportModal = ({ onClose }: IReportModal) => {
return null;
}
- const StepToRender = reportSteps[entityType][currentStep];
+ const StepToRender = reportSteps[currentStep];
return (
(
const ConfirmationStep: React.FC = () => {
const intl = useIntl();
const links = useAppSelector((state) => getSoapboxConfig(state).get('links') as any);
- const entityType = useAppSelector((state) => state.reports.new.entityType);
- const entity = entityType === ReportableEntities.GROUP
- ? intl.formatMessage(messages.groupEntity)
- : intl.formatMessage(messages.accountEntity);
+ const entity = intl.formatMessage(messages.accountEntity);
return (
diff --git a/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx b/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx
index 67a56d66b..d4250b551 100644
--- a/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx
+++ b/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx
@@ -45,43 +45,41 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
return (
- {features.reportMultipleStatuses && (
-
-
- {intl.formatMessage(messages.otherStatuses)}
-
+
+
+ {intl.formatMessage(messages.otherStatuses)}
+
-
- {showAdditionalStatuses ? (
-
-
- {statusIds.map((statusId) => )}
-
+
+ {showAdditionalStatuses ? (
+
+
+ {statusIds.map((statusId) => )}
+
-
-
-
-
- ) : (
-
- )}
-
-
- )}
+
+
+
+
+ ) : (
+
+ )}
+
+
diff --git a/src/features/ui/components/modals/report-modal/steps/reason-step.tsx b/src/features/ui/components/modals/report-modal/steps/reason-step.tsx
index 7703ab995..c72c3ab9c 100644
--- a/src/features/ui/components/modals/report-modal/steps/reason-step.tsx
+++ b/src/features/ui/components/modals/report-modal/steps/reason-step.tsx
@@ -2,12 +2,11 @@ import clsx from 'clsx';
import React, { useEffect, useRef, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
-import { changeReportComment, changeReportRule, ReportableEntities } from 'soapbox/actions/reports';
+import { changeReportComment, changeReportRule } from 'soapbox/actions/reports';
import { FormGroup, Stack, Text, Textarea } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector, useInstance } from 'soapbox/hooks';
import type { Account } from 'soapbox/schemas';
-import type { Rule } from 'soapbox/schemas/rule';
const messages = defineMessages({
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
@@ -29,7 +28,6 @@ const ReasonStep: React.FC = () => {
const [isNearBottom, setNearBottom] = useState(false);
const [isNearTop, setNearTop] = useState(true);
- const entityType = useAppSelector((state) => state.reports.new.entityType);
const comment = useAppSelector((state) => state.reports.new.comment);
const { rules } = useInstance();
const ruleIds = useAppSelector((state) => state.reports.new.rule_ids);
@@ -57,32 +55,6 @@ const ReasonStep: React.FC = () => {
}
};
- const filterRuleType = (rule: Rule) => {
- let ruleTypeToFilter = 'content';
-
- switch (entityType) {
- case ReportableEntities.ACCOUNT:
- ruleTypeToFilter = 'account';
- break;
- case ReportableEntities.STATUS:
- case ReportableEntities.CHAT_MESSAGE:
- ruleTypeToFilter = 'content';
- break;
- case ReportableEntities.GROUP:
- ruleTypeToFilter = 'group';
- break;
- default:
- ruleTypeToFilter = 'content';
- break;
- }
-
- if (rule.rule_type) {
- return rule.rule_type === ruleTypeToFilter;
- }
-
- return true;
- };
-
useEffect(() => {
if (rules.length > 0 && rulesListRef.current) {
const { clientHeight } = rulesListRef.current;
@@ -108,7 +80,7 @@ const ReasonStep: React.FC = () => {
onScroll={handleRulesScrolling}
ref={rulesListRef}
>
- {rules.filter(filterRuleType).map((rule, idx) => {
+ {rules.map((rule, idx) => {
const isSelected = ruleIds.includes(String(rule.id));
return (
diff --git a/src/features/ui/components/panels/suggested-groups-panel.tsx b/src/features/ui/components/panels/suggested-groups-panel.tsx
deleted file mode 100644
index d2671bc14..000000000
--- a/src/features/ui/components/panels/suggested-groups-panel.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React from 'react';
-
-import { useSuggestedGroups } from 'soapbox/api/hooks';
-import { Widget } from 'soapbox/components/ui';
-import GroupListItem from 'soapbox/features/groups/components/discover/group-list-item';
-import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search';
-
-const SuggestedGroupsPanel = () => {
- const { groups, isFetching, isFetched, isError } = useSuggestedGroups();
- const isEmpty = (isFetched && groups.length === 0) || isError;
-
- if (isEmpty) {
- return null;
- }
-
- return (
-
- {isFetching ? (
- new Array(3).fill(0).map((_, idx) => (
-
- ))
- ) : (
- groups.slice(0, 3).map((group) => (
-
- ))
- )}
-
- );
-};
-
-export default SuggestedGroupsPanel;
diff --git a/src/features/ui/components/profile-info-panel.tsx b/src/features/ui/components/profile-info-panel.tsx
index 9f89bfeb8..0aa56c765 100644
--- a/src/features/ui/components/profile-info-panel.tsx
+++ b/src/features/ui/components/profile-info-panel.tsx
@@ -15,16 +15,6 @@ import ProfileStats from './profile-stats';
import type { Account } from 'soapbox/schemas';
-/** Basically ensure the URL isn't `javascript:alert('hi')` or something like that */
-const isSafeUrl = (text: string): boolean => {
- try {
- const url = new URL(text);
- return ['http:', 'https:'].includes(url.protocol);
- } catch (e) {
- return false;
- }
-};
-
const messages = defineMessages({
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' },
@@ -205,25 +195,6 @@ const ProfileInfoPanel: React.FC = ({ account, username }) =>
) : null}
- {account.website ? (
-
-
-
-
-
- {isSafeUrl(account.website) ? (
- {account.website}
- ) : (
- account.website
- )}
-
-
-
- ) : null}
-
{renderBirthday()}
diff --git a/src/features/ui/index.tsx b/src/features/ui/index.tsx
index f31315c02..b409d7cfa 100644
--- a/src/features/ui/index.tsx
+++ b/src/features/ui/index.tsx
@@ -26,7 +26,6 @@ import EventPage from 'soapbox/pages/event-page';
import EventsPage from 'soapbox/pages/events-page';
import GroupPage from 'soapbox/pages/group-page';
import GroupsPage from 'soapbox/pages/groups-page';
-import GroupsPendingPage from 'soapbox/pages/groups-pending-page';
import HomePage from 'soapbox/pages/home-page';
import LandingPage from 'soapbox/pages/landing-page';
import ManageGroupsPage from 'soapbox/pages/manage-groups-page';
@@ -71,7 +70,6 @@ import {
EditProfile,
EditEmail,
EditPassword,
- EmailConfirmation,
DeleteAccount,
SoapboxConfig,
ExportData,
@@ -111,15 +109,7 @@ import {
Events,
GroupGallery,
Groups,
- GroupsDiscover,
- GroupsPopular,
- GroupsSuggested,
- GroupsTag,
- GroupsTags,
- PendingGroupRequests,
GroupMembers,
- GroupTags,
- GroupTagTimeline,
GroupTimeline,
ManageGroup,
GroupBlockedMembers,
@@ -131,7 +121,6 @@ import {
RegistrationPage,
LoginPage,
PasswordReset,
- PasswordResetConfirm,
RegisterInvite,
ExternalLogin,
LandingTimeline,
@@ -173,7 +162,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) =>
{standalone && }
-
{isLoggedIn ? (
@@ -289,14 +277,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) =>
{features.groups && }
- {features.groupsDiscovery && }
- {features.groupsDiscovery && }
- {features.groupsDiscovery && }
- {features.groupsDiscovery && }
- {features.groupsDiscovery && }
- {features.groupsPending && }
- {features.groupsTags && }
- {features.groupsTags && }
{features.groups && }
{features.groups && }
{features.groups && }
@@ -361,7 +341,6 @@ const SwitchingColumnsArea: React.FC = ({ children }) =>
-
diff --git a/src/features/ui/util/async-components.ts b/src/features/ui/util/async-components.ts
index 738cfc847..1b955faca 100644
--- a/src/features/ui/util/async-components.ts
+++ b/src/features/ui/util/async-components.ts
@@ -65,7 +65,6 @@ export const RegistrationPage = lazy(() => import('soapbox/features/auth-login/c
export const Settings = lazy(() => import('soapbox/features/settings'));
export const EditProfile = lazy(() => import('soapbox/features/edit-profile'));
export const EditEmail = lazy(() => import('soapbox/features/edit-email'));
-export const EmailConfirmation = lazy(() => import('soapbox/features/email-confirmation'));
export const EditPassword = lazy(() => import('soapbox/features/edit-password'));
export const DeleteAccount = lazy(() => import('soapbox/features/delete-account'));
export const SoapboxConfig = lazy(() => import('soapbox/features/soapbox-config'));
@@ -73,7 +72,6 @@ export const ExportData = lazy(() => import('soapbox/features/export-data'));
export const ImportData = lazy(() => import('soapbox/features/import-data'));
export const Backups = lazy(() => import('soapbox/features/backups'));
export const PasswordReset = lazy(() => import('soapbox/features/auth-login/components/password-reset'));
-export const PasswordResetConfirm = lazy(() => import('soapbox/features/auth-login/components/password-reset-confirm'));
export const MfaForm = lazy(() => import('soapbox/features/security/mfa-form'));
export const ChatIndex = lazy(() => import('soapbox/features/chats'));
export const ChatWidget = lazy(() => import('soapbox/features/chats/components/chat-widget/chat-widget'));
@@ -136,15 +134,7 @@ export const EventMapModal = lazy(() => import('soapbox/features/ui/components/m
export const EventParticipantsModal = lazy(() => import('soapbox/features/ui/components/modals/event-participants-modal'));
export const Events = lazy(() => import('soapbox/features/events'));
export const Groups = lazy(() => import('soapbox/features/groups'));
-export const GroupsDiscover = lazy(() => import('soapbox/features/groups/discover'));
-export const GroupsPopular = lazy(() => import('soapbox/features/groups/popular'));
-export const GroupsSuggested = lazy(() => import('soapbox/features/groups/suggested'));
-export const GroupsTag = lazy(() => import('soapbox/features/groups/tag'));
-export const GroupsTags = lazy(() => import('soapbox/features/groups/tags'));
-export const PendingGroupRequests = lazy(() => import('soapbox/features/groups/pending-requests'));
export const GroupMembers = lazy(() => import('soapbox/features/group/group-members'));
-export const GroupTags = lazy(() => import('soapbox/features/group/group-tags'));
-export const GroupTagTimeline = lazy(() => import('soapbox/features/group/group-tag-timeline'));
export const GroupTimeline = lazy(() => import('soapbox/features/group/group-timeline'));
export const ManageGroup = lazy(() => import('soapbox/features/group/manage-group'));
export const EditGroup = lazy(() => import('soapbox/features/group/edit-group'));
@@ -154,7 +144,6 @@ export const GroupGallery = lazy(() => import('soapbox/features/group/group-gall
export const CreateGroupModal = lazy(() => import('soapbox/features/ui/components/modals/manage-group-modal/create-group-modal'));
export const NewGroupPanel = lazy(() => import('soapbox/features/ui/components/panels/new-group-panel'));
export const MyGroupsPanel = lazy(() => import('soapbox/features/ui/components/panels/my-groups-panel'));
-export const SuggestedGroupsPanel = lazy(() => import('soapbox/features/ui/components/panels/suggested-groups-panel'));
export const GroupMediaPanel = lazy(() => import('soapbox/features/ui/components/group-media-panel'));
export const NewEventPanel = lazy(() => import('soapbox/features/ui/components/panels/new-event-panel'));
export const Announcements = lazy(() => import('soapbox/features/admin/announcements'));
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index 1da5fb9e4..8d3b7a510 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -7,7 +7,6 @@ export { useCompose } from './useCompose';
export { useDebounce } from './useDebounce';
export { useDraggedFiles } from './useDraggedFiles';
export { useGetState } from './useGetState';
-export { useGroupsPath } from './useGroupsPath';
export { useDimensions } from './useDimensions';
export { useFeatures } from './useFeatures';
export { useInstance } from './useInstance';
diff --git a/src/hooks/useGroupsPath.test.ts b/src/hooks/useGroupsPath.test.ts
deleted file mode 100644
index 72af53731..000000000
--- a/src/hooks/useGroupsPath.test.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { __stub } from 'soapbox/api';
-import { buildAccount, buildGroup, buildGroupRelationship } from 'soapbox/jest/factory';
-import { renderHook, waitFor } from 'soapbox/jest/test-helpers';
-import { instanceSchema } from 'soapbox/schemas';
-
-import { useGroupsPath } from './useGroupsPath';
-
-describe('useGroupsPath()', () => {
- test('without the groupsDiscovery feature', () => {
- const store = {
- instance: instanceSchema.parse({
- version: '2.7.2 (compatible; Pleroma 2.3.0)',
- }),
- };
-
- const { result } = renderHook(useGroupsPath, undefined, store);
-
- expect(result.current).toEqual('/groups');
- });
-
- describe('with the "groupsDiscovery" feature', () => {
- let store: any;
-
- beforeEach(() => {
- const userId = '1';
- store = {
- instance: instanceSchema.parse({
- version: '3.4.1 (compatible; TruthSocial 1.0.0+unreleased)',
- }),
- me: userId,
- accounts: {
- [userId]: buildAccount({
- id: userId,
- acct: 'justin-username',
- display_name: 'Justin L',
- avatar: 'test.jpg',
- source: {
- chats_onboarded: false,
- },
- }),
- },
- };
- });
-
- describe('when the user has no groups', () => {
- test('should default to the discovery page', () => {
- const { result } = renderHook(useGroupsPath, undefined, store);
-
- expect(result.current).toEqual('/groups/discover');
- });
- });
-
- describe('when the user has groups', () => {
- beforeEach(() => {
- __stub((mock) => {
- mock.onGet('/api/v1/groups').reply(200, [
- buildGroup({
- display_name: 'Group',
- id: '1',
- }),
- ]);
-
- mock.onGet('/api/v1/groups/relationships?id[]=1').reply(200, [
- buildGroupRelationship({
- id: '1',
- }),
- ]);
- });
- });
-
- test('should default to the "My Groups" page', async () => {
- const { result } = renderHook(useGroupsPath, undefined, store);
-
- await waitFor(() => {
- expect(result.current).toEqual('/groups');
- });
- });
- });
- });
-});
diff --git a/src/hooks/useGroupsPath.ts b/src/hooks/useGroupsPath.ts
deleted file mode 100644
index 71aa3c8da..000000000
--- a/src/hooks/useGroupsPath.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { useGroups } from 'soapbox/api/hooks/groups/useGroups';
-
-import { useFeatures } from './useFeatures';
-
-/**
- * Determine the correct URL to use for /groups.
- * If the user does not have any Groups, let's default to the discovery tab.
- * Otherwise, let's default to My Groups.
- *
- * @returns String (as link)
- */
-const useGroupsPath = () => {
- const features = useFeatures();
- const { groups } = useGroups();
-
- if (!features.groupsDiscovery) {
- return '/groups';
- }
-
- return groups.length > 0 ? '/groups' : '/groups/discover';
-};
-
-export { useGroupsPath };
\ No newline at end of file
diff --git a/src/jest/factory.ts b/src/jest/factory.ts
index 3bb61f77c..62817d4aa 100644
--- a/src/jest/factory.ts
+++ b/src/jest/factory.ts
@@ -6,7 +6,6 @@ import {
groupMemberSchema,
groupRelationshipSchema,
groupSchema,
- groupTagSchema,
relationshipSchema,
statusSchema,
type Account,
@@ -14,7 +13,6 @@ import {
type Group,
type GroupMember,
type GroupRelationship,
- type GroupTag,
type Relationship,
type Status,
Instance,
@@ -55,13 +53,6 @@ function buildGroupRelationship(props: PartialDeep = {}): Gro
}, props));
}
-function buildGroupTag(props: PartialDeep = {}): GroupTag {
- return groupTagSchema.parse(Object.assign({
- id: uuidv4(),
- name: uuidv4(),
- }, props));
-}
-
function buildGroupMember(
props: PartialDeep = {},
accountProps: PartialDeep = {},
@@ -96,7 +87,6 @@ export {
buildGroup,
buildGroupMember,
buildGroupRelationship,
- buildGroupTag,
buildInstance,
buildRelationship,
buildStatus,
diff --git a/src/jest/fixtures/chats.json b/src/jest/fixtures/chats.json
index e1d60383d..101851fc7 100644
--- a/src/jest/fixtures/chats.json
+++ b/src/jest/fixtures/chats.json
@@ -2,20 +2,17 @@
{
"id": "1",
"unread": 0,
- "created_by_account": "2",
"last_message": {
"account_id": "2",
"chat_id": "85",
"content": "last message content",
"created_at": "2022-09-28T17:43:01.432Z",
"id": "1166",
- "unread": false,
- "discarded_at": "2022-09-29T19:09:30.253Z"
+ "unread": false
},
"created_at": "2022-08-26T14:49:16.360Z",
"updated_at": "2022-09-29T19:09:30.257Z",
"accepted": true,
- "discarded_at": null,
"account": {
"id": "2",
"username": "leonard",
@@ -25,27 +22,23 @@
"avatar": "original.jpg",
"avatar_static": "original.jpg",
"verified": false,
- "accepting_messages": true,
- "chats_onboarded": true
+ "accepting_messages": true
}
},
{
"id": "2",
"unread": 0,
- "created_by_account": "3",
"last_message": {
"account_id": "3",
"chat_id": "125",
"content": "\u003cp\u003eInventore enim numquam nihil facilis nostrum eum natus provident quis veritatis esse dolorem praesentium rem cumque.\u003c/p\u003e",
"created_at": "2022-09-23T14:09:29.625Z",
"id": "1033",
- "unread": false,
- "discarded_at": null
+ "unread": false
},
"created_at": "2022-09-22T15:06:49.675Z",
"updated_at": "2022-09-23T14:09:29.628Z",
"accepted": true,
- "discarded_at": null,
"account": {
"id": "3",
"username": "sheldon",
@@ -55,8 +48,7 @@
"avatar": "original.jpg",
"avatar_static": "original.jpg",
"verified": false,
- "accepting_messages": true,
- "chats_onboarded": true
+ "accepting_messages": true
}
}
]
\ No newline at end of file
diff --git a/src/locales/en.json b/src/locales/en.json
index b3aa5d72d..b719ef896 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -261,11 +261,6 @@
"chat.page_settings.submit": "Save",
"chat.page_settings.title": "Message Settings",
"chat.retry": "Retry?",
- "chat.welcome.accepting_messages.label": "Allow users to start a new chat with you",
- "chat.welcome.notice": "You can change these settings later.",
- "chat.welcome.submit": "Save & Continue",
- "chat.welcome.subtitle": "Exchange direct messages with other users.",
- "chat.welcome.title": "Welcome to {br} Chats!",
"chat_composer.unblock": "Unblock",
"chat_list_item.blocked_you": "This user has blocked you",
"chat_list_item.blocking": "You have blocked this user",
@@ -274,14 +269,6 @@
"chat_message_list.network_failure.action": "Try again",
"chat_message_list.network_failure.subtitle": "We encountered a network failure.",
"chat_message_list.network_failure.title": "Whoops!",
- "chat_message_list_intro.actions.accept": "Accept",
- "chat_message_list_intro.actions.leave_chat": "Leave chat",
- "chat_message_list_intro.actions.message_lifespan": "Messages older than {day, plural, one {# day} other {# days}} are deleted.",
- "chat_message_list_intro.actions.report": "Report",
- "chat_message_list_intro.intro": "wants to start a chat with you",
- "chat_message_list_intro.leave_chat.confirm": "Leave Chat",
- "chat_message_list_intro.leave_chat.heading": "Leave Chat",
- "chat_message_list_intro.leave_chat.message": "Are you sure you want to leave this chat? Messages will be deleted for you and this chat will be removed from your inbox.",
"chat_pane.blankslate.action": "Message someone",
"chat_pane.blankslate.body": "Search for someone to chat with.",
"chat_pane.blankslate.title": "No messages yet",
@@ -291,14 +278,6 @@
"chat_search.empty_results_blankslate.title": "No matches found",
"chat_search.placeholder": "Type a name",
"chat_search.title": "Messages",
- "chat_settings.auto_delete.14days": "14 days",
- "chat_settings.auto_delete.2minutes": "2 minutes",
- "chat_settings.auto_delete.30days": "30 days",
- "chat_settings.auto_delete.7days": "7 days",
- "chat_settings.auto_delete.90days": "90 days",
- "chat_settings.auto_delete.days": "{day, plural, one {# day} other {# days}}",
- "chat_settings.auto_delete.hint": "Sent messages will auto-delete after the time period selected",
- "chat_settings.auto_delete.label": "Auto-delete messages",
"chat_settings.block.confirm": "Block",
"chat_settings.block.heading": "Block @{acct}",
"chat_settings.block.message": "Blocking will prevent this profile from direct messaging you and viewing your content. You can unblock later.",
@@ -313,8 +292,6 @@
"chat_settings.unblock.confirm": "Unblock",
"chat_settings.unblock.heading": "Unblock @{acct}",
"chat_settings.unblock.message": "Unblocking will allow this profile to direct message you and view your content.",
- "chat_window.auto_delete_label": "Auto-delete after {day, plural, one {# day} other {# days}}",
- "chat_window.auto_delete_tooltip": "Chat messages are set to auto-delete after {day, plural, one {# day} other {# days}} upon sending.",
"chats.actions.copy": "Copy",
"chats.actions.delete": "Delete for both",
"chats.actions.delete_for_me": "Delete for me",
@@ -326,7 +303,6 @@
"chats.main.blankslate.title": "No messages yet",
"chats.main.blankslate_with_chats.subtitle": "Select from one of your open chats or create a new message.",
"chats.main.blankslate_with_chats.title": "Select a chat",
- "chats.search_placeholder": "Start a chat with…",
"column.admin.announcements": "Announcements",
"column.admin.awaiting_approval": "Awaiting Approval",
"column.admin.create_announcement": "Create announcement",
@@ -570,9 +546,6 @@
"confirmations.mute.confirm": "Mute",
"confirmations.mute.heading": "Mute @{name}",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
- "confirmations.mute_group.confirm": "Mute",
- "confirmations.mute_group.heading": "Mute Group",
- "confirmations.mute_group.message": "You are about to mute the group. Do you want to continue?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.heading": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this post and re-draft it? Favorites and reposts will be lost, and replies to the original post will be orphaned.",
@@ -663,8 +636,6 @@
"edit_profile.fields.nip05_placeholder": "user@{domain}",
"edit_profile.fields.nip05_unverified": "Name could not be verified and won't be used.",
"edit_profile.fields.stranger_notifications_label": "Block notifications from strangers",
- "edit_profile.fields.website_label": "Website",
- "edit_profile.fields.website_placeholder": "Display a Link",
"edit_profile.header": "Edit Profile",
"edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.",
"edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored",
@@ -675,7 +646,6 @@
"edit_profile.hints.stranger_notifications": "Only show notifications from people you follow",
"edit_profile.save": "Save",
"edit_profile.success": "Your profile has been successfully saved!",
- "email_confirmation.success": "Your email has been confirmed!",
"embed.instructions": "Embed this post on your website by copying the code below.",
"emoji_button.activity": "Activity",
"emoji_button.add_custom": "Add custom emoji",
@@ -849,9 +819,6 @@
"group.manage": "Manage Group",
"group.member.admin.limit.summary": "You can assign up to {count, plural, one {admin} other {admins}} for the group at this time.",
"group.member.admin.limit.title": "Admin limit reached",
- "group.mute.label": "Mute",
- "group.mute.long_label": "Mute Group",
- "group.mute.success": "Muted the group",
"group.popover.action": "View Group",
"group.popover.summary": "You must be a member of the group in order to reply to this status.",
"group.popover.title": "Membership required",
@@ -873,56 +840,14 @@
"group.tabs.media": "Media",
"group.tabs.members": "Members",
"group.tabs.tags": "Topics",
- "group.tags.empty": "There are no topics in this group yet.",
- "group.tags.hidden.success": "Topic marked as hidden",
- "group.tags.hide": "Hide topic",
- "group.tags.hint": "Add up to 3 keywords that will serve as core topics of discussion in the group.",
- "group.tags.label": "Tags",
- "group.tags.pin": "Pin topic",
- "group.tags.pin.success": "Pinned!",
- "group.tags.show": "Show topic",
- "group.tags.total": "Total Posts",
- "group.tags.unpin": "Unpin topic",
- "group.tags.unpin.success": "Unpinned!",
- "group.tags.visible.success": "Topic marked as visible",
- "group.unmute.label": "Unmute",
- "group.unmute.long_label": "Unmute Group",
- "group.unmute.success": "Unmuted the group",
"group.update.success": "Group successfully saved",
"group.upload_avatar": "Upload avatar",
"group.upload_banner": "Upload photo",
"group.upload_banner.title": "Upload background picture",
- "groups.discover.popular.empty": "Unable to fetch popular groups at this time. Please check back later.",
- "groups.discover.popular.show_more": "Show More",
- "groups.discover.popular.title": "Popular Groups",
- "groups.discover.search.error.subtitle": "Please try again later.",
- "groups.discover.search.error.title": "An error occurred",
- "groups.discover.search.no_results.subtitle": "Try searching for another group.",
- "groups.discover.search.no_results.title": "No matches found",
- "groups.discover.search.placeholder": "Search",
- "groups.discover.search.recent_searches.blankslate.subtitle": "Search group names, topics or keywords",
- "groups.discover.search.recent_searches.blankslate.title": "No recent searches",
- "groups.discover.search.recent_searches.clear_all": "Clear all",
- "groups.discover.search.recent_searches.title": "Recent searches",
- "groups.discover.search.results.groups": "Groups",
"groups.discover.search.results.member_count": "{members, plural, one {member} other {members}}",
- "groups.discover.suggested.empty": "Unable to fetch suggested groups at this time. Please check back later.",
- "groups.discover.suggested.show_more": "Show More",
- "groups.discover.suggested.title": "Suggested For You",
- "groups.discover.tags.empty": "Unable to fetch popular topics at this time. Please check back later.",
- "groups.discover.tags.show_more": "Show More",
- "groups.discover.tags.title": "Browse Topics",
- "groups.discovery.tags.no_of_groups": "Number of groups",
"groups.empty.subtitle": "Start discovering groups to join or create your own.",
"groups.empty.title": "No Groups yet",
"groups.pending.count": "{number, plural, one {# pending request} other {# pending requests}}",
- "groups.pending.empty.subtitle": "You have no pending requests at this time.",
- "groups.pending.empty.title": "No pending requests",
- "groups.pending.label": "Pending Requests",
- "groups.popular.label": "Suggested Groups",
- "groups.search.placeholder": "Search My Groups",
- "groups.suggested.label": "Suggested Groups",
- "groups.tags.title": "Browse Topics",
"hashtag.follow": "Follow hashtag",
"header.login.label": "Log in",
"header.register.label": "Register",
@@ -1092,7 +1017,6 @@
"mute_modal.auto_expire": "Automatically expire mute?",
"mute_modal.duration": "Duration",
"mute_modal.hide_notifications": "Hide notifications from this user?",
- "mutes.empty.groups": "You haven't muted any groups yet.",
"navbar.login.action": "Log in",
"navbar.login.email.placeholder": "E-mail address",
"navbar.login.forgot_password": "Forgot password?",
@@ -1162,8 +1086,6 @@
"notification.mention": "{name} mentioned you",
"notification.mentioned": "{name} mentioned you",
"notification.move": "{name} moved to {targetName}",
- "notification.name": "{link}{others}",
- "notification.others": "+ {count, plural, one {# other} other {# others}}",
"notification.pleroma:chat_mention": "{name} sent you a message",
"notification.pleroma:emoji_reaction": "{name} reacted to your post",
"notification.pleroma:event_reminder": "An event you are participating in starts soon",
@@ -1343,16 +1265,12 @@
"reply_mentions.reply_empty": "Replying to post",
"report.block": "Block {target}",
"report.block_hint": "Do you also want to block this account?",
- "report.chat_message.context": "When reporting a user’s message, the five messages before and five messages after the one selected will be passed along to our moderation team for context.",
- "report.chat_message.title": "Report message",
"report.confirmation.content": "If we find that this {entity} is violating the {link} we will take further action on the matter.",
"report.confirmation.entity.account": "account",
- "report.confirmation.entity.group": "group",
"report.confirmation.title": "Thanks for submitting your report.",
"report.done": "Done",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send a copy of the report there as well?",
- "report.group.title": "Report Group",
"report.next": "Next",
"report.other_actions.add_additional": "Would you like to add additional statuses to this report?",
"report.other_actions.add_more": "Add more",
@@ -1365,10 +1283,6 @@
"report.reason.title": "Reason for reporting",
"report.submit": "Submit",
"report.target": "Reporting {target}",
- "reset_password.fail": "Expired token, please try again.",
- "reset_password.header": "Set New Password",
- "reset_password.password.label": "Password",
- "reset_password.password.placeholder": "Placeholder",
"save": "Save",
"schedule.post_time": "Post Date/Time",
"schedule.remove": "Remove schedule",
diff --git a/src/normalizers/account.test.ts b/src/normalizers/account.test.ts
index 15a26ecdc..fa5335c97 100644
--- a/src/normalizers/account.test.ts
+++ b/src/normalizers/account.test.ts
@@ -86,30 +86,12 @@ describe('normalizeAccount()', () => {
expect(result.verified).toBe(false);
});
- it('normalizes a verified Truth Social user', async () => {
- const account = await import('soapbox/__fixtures__/realDonaldTrump.json');
- const result = normalizeAccount(account);
- expect(result.verified).toBe(true);
- });
-
it('normalizes Fedibird location', async () => {
const account = await import('soapbox/__fixtures__/fedibird-account.json');
const result = normalizeAccount(account);
expect(result.location).toBe('Texas, USA');
});
- it('normalizes Truth Social location', async () => {
- const account = await import('soapbox/__fixtures__/truthsocial-account.json');
- const result = normalizeAccount(account);
- expect(result.location).toBe('Texas');
- });
-
- it('normalizes Truth Social website', async () => {
- const account = await import('soapbox/__fixtures__/truthsocial-account.json');
- const result = normalizeAccount(account);
- expect(result.website).toBe('https://soapbox.pub');
- });
-
it('sets display_name from username', () => {
const account = { username: 'alex' };
const result = normalizeAccount(account);
diff --git a/src/normalizers/account.ts b/src/normalizers/account.ts
index 74a84e46b..4ffbe007d 100644
--- a/src/normalizers/account.ts
+++ b/src/normalizers/account.ts
@@ -27,7 +27,6 @@ export const AccountRecord = ImmutableRecord({
avatar_static: '',
birthday: '',
bot: false,
- chats_onboarded: true,
created_at: '',
discoverable: false,
display_name: '',
@@ -52,7 +51,6 @@ export const AccountRecord = ImmutableRecord({
uri: '',
url: '',
username: '',
- website: '',
verified: false,
// Internal fields
@@ -147,7 +145,7 @@ const getTags = (account: ImmutableMap): ImmutableList => {
return ImmutableList(ImmutableList.isList(tags) ? tags : []);
};
-/** Normalize Truth Social/Pleroma verified */
+/** Normalize Pleroma verified */
const normalizeVerified = (account: ImmutableMap) => {
return account.update('verified', verified => {
return [
@@ -164,7 +162,7 @@ const normalizeDonor = (account: ImmutableMap) => {
return account.setIn(['pleroma', 'tags'], updated);
};
-/** Normalize Fedibird/Truth Social/Pleroma location */
+/** Normalize Fedibird/Pleroma location */
const normalizeLocation = (account: ImmutableMap) => {
return account.update('location', location => {
return [
@@ -265,10 +263,9 @@ const normalizeDiscoverable = (account: ImmutableMap) => {
return account.set('discoverable', discoverable);
};
-/** Normalize message acceptance between Pleroma and Truth Social. */
+/** Normalize message acceptance. */
const normalizeMessageAcceptance = (account: ImmutableMap) => {
- const acceptance = Boolean(account.getIn(['pleroma', 'accepts_chat_messages']) || account.get('accepting_messages'));
- return account.set('accepts_chat_messages', acceptance);
+ return account.set('accepts_chat_messages', account.getIn(['pleroma', 'accepts_chat_messages']));
};
/** Normalize undefined/null birthday to empty string. */
diff --git a/src/normalizers/chat-message.ts b/src/normalizers/chat-message.ts
index 5ec03bb59..eb0ec7120 100644
--- a/src/normalizers/chat-message.ts
+++ b/src/normalizers/chat-message.ts
@@ -6,10 +6,8 @@ import {
} from 'immutable';
import { normalizeAttachment } from 'soapbox/normalizers/attachment';
-import { emojiReactionSchema } from 'soapbox/schemas';
-import { filteredArray } from 'soapbox/schemas/utils';
-import type { Attachment, Card, Emoji, EmojiReaction } from 'soapbox/types/entities';
+import type { Attachment, Card, Emoji } from 'soapbox/types/entities';
export const ChatMessageRecord = ImmutableRecord({
account_id: '',
@@ -20,7 +18,6 @@ export const ChatMessageRecord = ImmutableRecord({
created_at: '',
emojis: ImmutableList(),
expiration: null as number | null,
- emoji_reactions: null as readonly EmojiReaction[] | null,
id: '',
unread: false,
deleting: false,
@@ -40,11 +37,6 @@ const normalizeMedia = (status: ImmutableMap) => {
}
};
-const normalizeChatMessageEmojiReaction = (chatMessage: ImmutableMap) => {
- const emojiReactions = ImmutableList(chatMessage.get('emoji_reactions') || []);
- return chatMessage.set('emoji_reactions', filteredArray(emojiReactionSchema).parse(emojiReactions.toJS()));
-};
-
/** Rewrite `` to empty string. */
const fixContent = (chatMessage: ImmutableMap) => {
if (chatMessage.get('content') === '') {
@@ -58,7 +50,6 @@ export const normalizeChatMessage = (chatMessage: Record) => {
return ChatMessageRecord(
ImmutableMap(fromJS(chatMessage)).withMutations(chatMessage => {
normalizeMedia(chatMessage);
- normalizeChatMessageEmojiReaction(chatMessage);
fixContent(chatMessage);
}),
);
diff --git a/src/normalizers/notification.ts b/src/normalizers/notification.ts
index 45eb93fb3..4c12b017f 100644
--- a/src/normalizers/notification.ts
+++ b/src/normalizers/notification.ts
@@ -22,7 +22,6 @@ export const NotificationRecord = ImmutableRecord({
status: null as EmbeddedEntity,
target: null as EmbeddedEntity, // move
type: '',
- total_count: null as number | null, // grouped notifications
});
const normalizeType = (notification: ImmutableMap) => {
diff --git a/src/pages/group-page.tsx b/src/pages/group-page.tsx
index e2fbfccdd..a1e2bf545 100644
--- a/src/pages/group-page.tsx
+++ b/src/pages/group-page.tsx
@@ -10,9 +10,8 @@ import {
CtaBanner,
GroupMediaPanel,
SignUpPanel,
- SuggestedGroupsPanel,
} from 'soapbox/features/ui/util/async-components';
-import { useFeatures, useOwnAccount } from 'soapbox/hooks';
+import { useOwnAccount } from 'soapbox/hooks';
import type { Group } from 'soapbox/schemas';
@@ -90,7 +89,6 @@ const BlockedBlankslate = ({ group }: { group: Group }) => (
/** Page to display a group. */
const GroupPage: React.FC = ({ params, children }) => {
const intl = useIntl();
- const features = useFeatures();
const match = useRouteMatch();
const { account: me } = useOwnAccount();
@@ -108,34 +106,26 @@ const GroupPage: React.FC = ({ params, children }) => {
const items = [];
items.push({
text: intl.formatMessage(messages.all),
- to: `/group/${group?.slug}`,
- name: '/group/:groupSlug',
+ to: `/group/${id}`,
+ name: '/group/:groupId',
});
- if (features.groupsTags) {
- items.push({
- text: intl.formatMessage(messages.tags),
- to: `/group/${group?.slug}/tags`,
- name: '/group/:groupSlug/tags',
- });
- }
-
items.push(
{
text: intl.formatMessage(messages.media),
- to: `/group/${group?.slug}/media`,
- name: '/group/:groupSlug/media',
+ to: `/group/${id}/media`,
+ name: '/group/:groupId/media',
},
{
text: intl.formatMessage(messages.members),
- to: `/group/${group?.slug}/members`,
- name: '/group/:groupSlug/members',
+ to: `/group/${id}/members`,
+ name: '/group/:groupId/members',
count: pending.length,
},
);
return items;
- }, [features.groupsTags, pending.length, group?.slug]);
+ }, [pending.length, id]);
const renderChildren = () => {
if (isDeleted) {
@@ -174,7 +164,6 @@ const GroupPage: React.FC = ({ params, children }) => {
)}
-
>
diff --git a/src/pages/groups-page.tsx b/src/pages/groups-page.tsx
index ed3f62501..26db8c562 100644
--- a/src/pages/groups-page.tsx
+++ b/src/pages/groups-page.tsx
@@ -1,9 +1,8 @@
import React from 'react';
-import { Route, Routes } from 'react-router-dom-v5-compat';
import { Column, Layout } from 'soapbox/components/ui';
import LinkFooter from 'soapbox/features/ui/components/link-footer';
-import { MyGroupsPanel, NewGroupPanel, SuggestedGroupsPanel } from 'soapbox/features/ui/util/async-components';
+import { MyGroupsPanel, NewGroupPanel } from 'soapbox/features/ui/util/async-components';
interface IGroupsPage {
children: React.ReactNode;
@@ -22,10 +21,7 @@ const GroupsPage: React.FC = ({ children }) => (
-
- } />
- } />
-
+
diff --git a/src/pages/groups-pending-page.tsx b/src/pages/groups-pending-page.tsx
deleted file mode 100644
index f692cf7bf..000000000
--- a/src/pages/groups-pending-page.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from 'react';
-
-import { Layout } from 'soapbox/components/ui';
-import LinkFooter from 'soapbox/features/ui/components/link-footer';
-import { NewGroupPanel, SuggestedGroupsPanel } from 'soapbox/features/ui/util/async-components';
-
-interface IGroupsPage {
- children: React.ReactNode;
-}
-
-/** Page to display groups. */
-const GroupsPendingPage: React.FC = ({ children }) => (
- <>
-
- {children}
-
-
-
-
-
-
-
- >
-);
-
-export default GroupsPendingPage;
diff --git a/src/pages/search-page.tsx b/src/pages/search-page.tsx
index 338076d42..041560a0f 100644
--- a/src/pages/search-page.tsx
+++ b/src/pages/search-page.tsx
@@ -6,7 +6,6 @@ import {
TrendsPanel,
SignUpPanel,
CtaBanner,
- SuggestedGroupsPanel,
} from 'soapbox/features/ui/util/async-components';
import { useAppSelector, useFeatures } from 'soapbox/hooks';
@@ -43,9 +42,6 @@ const SearchPage: React.FC = ({ children }) => {
)}
- {features.groups && (
-
- )}
diff --git a/src/queries/accounts.ts b/src/queries/accounts.ts
index 06b7cb514..8b6fbc419 100644
--- a/src/queries/accounts.ts
+++ b/src/queries/accounts.ts
@@ -26,12 +26,10 @@ export type IAccount = {
url: string;
username: string;
verified: boolean;
- website: string;
}
type UpdateCredentialsData = {
accepts_chat_messages?: boolean;
- chats_onboarded?: boolean;
}
const useUpdateCredentials = () => {
diff --git a/src/queries/chats.test.ts b/src/queries/chats.test.ts
index 21a7ebd0d..66aafc3c9 100644
--- a/src/queries/chats.test.ts
+++ b/src/queries/chats.test.ts
@@ -7,13 +7,11 @@ import { buildAccount, buildRelationship } from 'soapbox/jest/factory';
import { createTestStore, mockStore, queryClient, renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers';
import { normalizeChatMessage } from 'soapbox/normalizers';
import { Store } from 'soapbox/store';
-import { ChatMessage } from 'soapbox/types/entities';
import { flattenPages } from 'soapbox/utils/queries';
-import { ChatKeys, IChat, isLastMessage, useChat, useChatActions, useChatMessages, useChats } from './chats';
+import { ChatKeys, IChat, useChat, useChatActions, useChatMessages, useChats } from './chats';
const chat: IChat = {
- accepted: true,
account: buildAccount({
username: 'username',
verified: true,
@@ -23,15 +21,9 @@ const chat: IChat = {
avatar_static: 'avatar',
display_name: 'my name',
}),
- chat_type: 'direct',
created_at: '2020-06-10T02:05:06.000Z',
- created_by_account: '1',
- discarded_at: null,
id: '1',
last_message: null,
- latest_read_message_by_account: [],
- latest_read_message_created_at: null,
- message_expiration: 1209600,
unread: 0,
};
@@ -41,7 +33,6 @@ const buildChatMessage = (id: string) => normalizeChatMessage({
account_id: '1',
content: `chat message #${id}`,
created_at: '2020-06-10T02:05:06.000Z',
- emoji_reactions: null,
expiration: 1209600,
unread: true,
});
@@ -58,53 +49,6 @@ describe('ChatKeys', () => {
expect(ChatKeys.chatMessages(id)).toEqual(['chats', 'messages', id]);
});
-
- it('has a "chatSearch" key', () => {
- const searchQuery = 'che';
-
- expect(ChatKeys.chatSearch()).toEqual(['chats', 'search']);
- expect(ChatKeys.chatSearch(searchQuery)).toEqual(['chats', 'search', searchQuery]);
- });
-});
-
-describe('isLastMessage', () => {
- describe('when its the last message', () => {
- it('is truthy', () => {
- const id = '5';
- const newChat = { ...chat, last_message: { id } } as any;
- const initialQueryData = {
- pages: [
- { result: [newChat], hasMore: false, link: undefined },
- ],
- pageParams: [undefined],
- };
- const initialFlattenedData = flattenPages(initialQueryData);
- expect(sumBy(initialFlattenedData, (chat: IChat) => chat.unread)).toBe(0);
-
- queryClient.setQueryData(ChatKeys.chatSearch(), initialQueryData);
-
- expect(isLastMessage(id)).toBeTruthy();
- });
- });
-
- describe('when its not the last message', () => {
- it('is not truthy', () => {
- const id = '5';
- const newChat = { ...chat, last_message: { id } } as any;
- const initialQueryData = {
- pages: [
- { result: [newChat], hasMore: false, link: undefined },
- ],
- pageParams: [undefined],
- };
- const initialFlattenedData = flattenPages(initialQueryData);
- expect(sumBy(initialFlattenedData, (chat: IChat) => chat.unread)).toBe(0);
-
- queryClient.setQueryData(ChatKeys.chatSearch(), initialQueryData);
-
- expect(isLastMessage('10')).not.toBeTruthy();
- });
- });
});
describe('useChatMessages', () => {
@@ -298,7 +242,7 @@ describe('useChatActions', () => {
const initialFlattenedData = flattenPages(initialQueryData);
expect(sumBy(initialFlattenedData, (chat: IChat) => chat.unread)).toBe(0);
- queryClient.setQueryData(ChatKeys.chatSearch(), initialQueryData);
+ queryClient.setQueryData(['chats', 'search'], initialQueryData);
const { result } = renderHook(() => useChatActions(chat.id).markChatAsRead('2'));
@@ -306,7 +250,7 @@ describe('useChatActions', () => {
expect(result.current).resolves.toBeDefined();
});
- const nextQueryData = queryClient.getQueryData(ChatKeys.chatSearch());
+ const nextQueryData = queryClient.getQueryData(['chats', 'search']);
const nextFlattenedData = flattenPages(nextQueryData as any);
expect(sumBy(nextFlattenedData as any, (chat: IChat) => chat.unread)).toBe(nextUnreadCount);
});
@@ -348,87 +292,4 @@ describe('useChatActions', () => {
expect(result.current.data.data).toEqual({ hello: 'world' });
});
});
-
- describe('updateChat()', () => {
- const nextUnreadCount = 5;
-
- beforeEach(() => {
- __stub((mock) => {
- mock
- .onPatch(`/api/v1/pleroma/chats/${chat.id}`)
- .reply(200, { ...chat, unread: nextUnreadCount });
- });
- });
-
- it('updates the queryCache for the chat', async() => {
- const initialQueryData = { ...chat };
- expect(initialQueryData.message_expiration).toBe(1209600);
- queryClient.setQueryData(ChatKeys.chat(chat.id), initialQueryData);
-
- const { result } = renderHook(() => {
- const { updateChat } = useChatActions(chat.id);
-
- useEffect(() => {
- updateChat.mutate({ message_expiration: 1200 });
- }, []);
-
- return updateChat;
- });
-
- await waitFor(() => {
- expect(result.current.isLoading).toBe(false);
- });
-
- const nextQueryData = queryClient.getQueryData(ChatKeys.chat(chat.id));
- expect((nextQueryData as any).message_expiration).toBe(1200);
- });
- });
-
- describe('createReaction()', () => {
- const chatMessage = buildChatMessage('1');
-
- beforeEach(() => {
- __stub((mock) => {
- mock
- .onPost(`/api/v1/pleroma/chats/${chat.id}/messages/${chatMessage.id}/reactions`)
- .reply(200, { ...chatMessage.toJS(), emoji_reactions: [{ name: '👍', count: 1, me: true }] });
- });
- });
-
- it('successfully updates the Chat Message record', async () => {
- const initialQueryData = {
- pages: [
- { result: [chatMessage], hasMore: false, link: undefined },
- ],
- pageParams: [undefined],
- };
-
- queryClient.setQueryData(ChatKeys.chatMessages(chat.id), initialQueryData);
-
- const { result } = renderHook(() => {
- const { createReaction } = useChatActions(chat.id);
-
- useEffect(() => {
- createReaction.mutate({
- messageId: chatMessage.id,
- emoji: '👍',
- chatMessage,
- });
- }, []);
-
- return createReaction;
- });
-
- await waitFor(() => {
- expect(result.current.isLoading).toBe(false);
- });
-
- const updatedChatMessage = (queryClient.getQueryData(ChatKeys.chatMessages(chat.id)) as any).pages[0].result[0] as ChatMessage;
- expect(updatedChatMessage.emoji_reactions).toEqual([{
- name: '👍',
- count: 1,
- me: true,
- }]);
- });
- });
});
diff --git a/src/queries/chats.ts b/src/queries/chats.ts
index 8bf382900..ae14d0e4b 100644
--- a/src/queries/chats.ts
+++ b/src/queries/chats.ts
@@ -7,9 +7,8 @@ import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context
import { useStatContext } from 'soapbox/contexts/stat-context';
import { useApi, useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
import { normalizeChatMessage } from 'soapbox/normalizers';
-import toast from 'soapbox/toast';
import { ChatMessage } from 'soapbox/types/entities';
-import { reOrderChatListItems, updateChatMessage } from 'soapbox/utils/chats';
+import { reOrderChatListItems } from 'soapbox/utils/chats';
import { flattenPages, PaginatedResult, updatePageItem } from 'soapbox/utils/queries';
import { queryClient } from './client';
@@ -17,64 +16,24 @@ import { useFetchRelationships } from './relationships';
import type { Account } from 'soapbox/schemas';
-export const messageExpirationOptions = [604800, 1209600, 2592000, 7776000];
-
-export enum MessageExpirationValues {
- 'SEVEN' = messageExpirationOptions[0],
- 'FOURTEEN' = messageExpirationOptions[1],
- 'THIRTY' = messageExpirationOptions[2],
- 'NINETY' = messageExpirationOptions[3]
-}
-
export interface IChat {
- accepted: boolean;
account: Account;
- chat_type: 'channel' | 'direct';
created_at: string;
- created_by_account: string;
- discarded_at: null | string;
id: string;
last_message: null | {
account_id: string;
chat_id: string;
content: string;
created_at: string;
- discarded_at: string | null;
id: string;
unread: boolean;
};
- latest_read_message_by_account?: {
- id: string;
- date: string;
- }[];
- latest_read_message_created_at: null | string;
- message_expiration?: MessageExpirationValues;
unread: number;
}
-type UpdateChatVariables = {
- message_expiration: MessageExpirationValues;
-}
-
-type CreateReactionVariables = {
- messageId: string;
- emoji: string;
- chatMessage?: ChatMessage;
-}
-
const ChatKeys = {
chat: (chatId?: string) => ['chats', 'chat', chatId] as const,
chatMessages: (chatId: string) => ['chats', 'messages', chatId] as const,
- chatSearch: (searchQuery?: string) => searchQuery ? ['chats', 'search', searchQuery] : ['chats', 'search'] as const,
-};
-
-/** Check if item is most recent */
-const isLastMessage = (chatMessageId: string): boolean => {
- const queryData = queryClient.getQueryData>>(ChatKeys.chatSearch());
- const items = flattenPages(queryData);
- const chat = items?.find((item) => item.last_message?.id === chatMessageId);
-
- return !!chat;
};
const useChatMessages = (chat: IChat) => {
@@ -122,7 +81,7 @@ const useChatMessages = (chat: IChat) => {
};
};
-const useChats = (search?: string) => {
+const useChats = () => {
const api = useApi();
const dispatch = useAppDispatch();
const features = useFeatures();
@@ -133,11 +92,7 @@ const useChats = (search?: string) => {
const endpoint = features.chatsV2 ? '/api/v2/pleroma/chats' : '/api/v1/pleroma/chats';
const nextPageLink = pageParam?.link;
const uri = nextPageLink || endpoint;
- const response = await api.get(uri, {
- params: search ? {
- search,
- } : undefined,
- });
+ const response = await api.get(uri);
const { data } = response;
const link = getNextLink(response);
@@ -157,7 +112,7 @@ const useChats = (search?: string) => {
};
const queryInfo = useInfiniteQuery({
- queryKey: ChatKeys.chatSearch(search),
+ queryKey: ['chats', 'search'],
queryFn: ({ pageParam }) => getChats(pageParam),
placeholderData: keepPreviousData,
enabled: features.chats,
@@ -219,8 +174,8 @@ const useChatActions = (chatId: string) => {
const markChatAsRead = async (lastReadId: string) => {
return api.post(`/api/v1/pleroma/chats/${chatId}/read`, { last_read_id: lastReadId })
.then(({ data }) => {
- updatePageItem(ChatKeys.chatSearch(), data, (o, n) => o.id === n.id);
- const queryData = queryClient.getQueryData>>(ChatKeys.chatSearch());
+ updatePageItem(['chats', 'search'], data, (o, n) => o.id === n.id);
+ const queryData = queryClient.getQueryData>>(['chats', 'search']);
if (queryData) {
const flattenedQueryData: any = flattenPages(queryData)?.map((chat: any) => {
@@ -293,7 +248,7 @@ const useChatActions = (chatId: string) => {
},
onSuccess: (response: any, variables, context) => {
const nextChat = { ...chat, last_message: response.data };
- updatePageItem(ChatKeys.chatSearch(), nextChat, (o, n) => o.id === n.id);
+ updatePageItem(['chats', 'search'], nextChat, (o, n) => o.id === n.id);
updatePageItem(
ChatKeys.chatMessages(variables.chatId),
normalizeChatMessage(response.data),
@@ -302,86 +257,23 @@ const useChatActions = (chatId: string) => {
reOrderChatListItems();
},
});
-
- const updateChat = useMutation({
- mutationFn: (data: UpdateChatVariables) => api.patch(`/api/v1/pleroma/chats/${chatId}`, data),
- onMutate: async (data) => {
- // Cancel any outgoing refetches (so they don't overwrite our optimistic update)
- await queryClient.cancelQueries({
- queryKey: ChatKeys.chat(chatId),
- });
-
- // Snapshot the previous value
- const prevChat = { ...chat };
- const nextChat = { ...chat, ...data };
-
- // Optimistically update to the new value
- queryClient.setQueryData(ChatKeys.chat(chatId), nextChat);
-
- // Return a context object with the snapshotted value
- return { prevChat };
- },
- // If the mutation fails, use the context returned from onMutate to roll back
- onError: (_error: any, _newData: any, context: any) => {
- changeScreen(ChatWidgetScreens.CHAT, context.prevChat.id);
- queryClient.setQueryData(ChatKeys.chat(chatId), context.prevChat);
- toast.error('Chat Settings failed to update.');
- },
- onSuccess() {
- queryClient.invalidateQueries({ queryKey: ChatKeys.chat(chatId) });
- queryClient.invalidateQueries({ queryKey: ChatKeys.chatSearch() });
- toast.success('Chat Settings updated successfully');
- },
- });
-
const deleteChatMessage = (chatMessageId: string) => api.delete(`/api/v1/pleroma/chats/${chatId}/messages/${chatMessageId}`);
- const acceptChat = useMutation({
- mutationFn: () => api.post(`/api/v1/pleroma/chats/${chatId}/accept`),
- onSuccess(response) {
- changeScreen(ChatWidgetScreens.CHAT, response.data.id);
- queryClient.invalidateQueries({ queryKey: ChatKeys.chat(chatId) });
- queryClient.invalidateQueries({ queryKey: ChatKeys.chatMessages(chatId) });
- queryClient.invalidateQueries({ queryKey: ChatKeys.chatSearch() });
- },
- });
-
const deleteChat = useMutation({
mutationFn: () => api.delete(`/api/v1/pleroma/chats/${chatId}`),
onSuccess() {
changeScreen(ChatWidgetScreens.INBOX);
queryClient.invalidateQueries({ queryKey: ChatKeys.chatMessages(chatId) });
- queryClient.invalidateQueries({ queryKey: ChatKeys.chatSearch() });
- },
- });
-
- const createReaction = useMutation({
- mutationFn: (data: CreateReactionVariables) => api.post(`/api/v1/pleroma/chats/${chatId}/messages/${data.messageId}/reactions`, {
- emoji: data.emoji,
- }),
- // TODO: add optimistic updates
- onSuccess(response) {
- updateChatMessage(response.data);
- },
- });
-
- const deleteReaction = useMutation({
- mutationFn: (data: CreateReactionVariables) => api.delete(`/api/v1/pleroma/chats/${chatId}/messages/${data.messageId}/reactions/${data.emoji}`),
- onSuccess() {
- queryClient.invalidateQueries({ queryKey: ChatKeys.chatMessages(chatId) });
+ queryClient.invalidateQueries({ queryKey: ['chats', 'search'] });
},
});
return {
- acceptChat,
createChatMessage,
- createReaction,
deleteChat,
deleteChatMessage,
- deleteReaction,
markChatAsRead,
- updateChat,
};
};
-export { ChatKeys, useChat, useChatActions, useChats, useChatMessages, isLastMessage };
+export { ChatKeys, useChat, useChatActions, useChats, useChatMessages };
diff --git a/src/reducers/compose.ts b/src/reducers/compose.ts
index 624ea0b3a..9c0f60a2a 100644
--- a/src/reducers/compose.ts
+++ b/src/reducers/compose.ts
@@ -52,7 +52,6 @@ import {
COMPOSE_SET_STATUS,
COMPOSE_EVENT_REPLY,
COMPOSE_EDITOR_STATE_SET,
- COMPOSE_SET_GROUP_TIMELINE_VISIBLE,
ComposeAction,
COMPOSE_CHANGE_MEDIA_ORDER,
} from '../actions/compose';
@@ -108,7 +107,6 @@ export const ReducerCompose = ImmutableRecord({
tagHistory: ImmutableList(),
text: '',
to: ImmutableOrderedSet(),
- group_timeline_visible: false, // TruthSocial
});
type State = ImmutableMap;
@@ -345,12 +343,8 @@ export default function compose(state = initialState, action: ComposeAction | Ev
map.set('spoiler_text', '');
if (action.status.visibility === 'group') {
- if (action.status.group?.group_visibility === 'everyone') {
- map.set('privacy', privacyPreference('public', defaultCompose.privacy));
- } else if (action.status.group?.group_visibility === 'members_only') {
- map.set('group_id', action.status.getIn(['group', 'id']) as string);
- map.set('privacy', 'group');
- }
+ map.set('group_id', action.status.getIn(['group', 'id']) as string);
+ map.set('privacy', 'group');
}
}));
case COMPOSE_SUBMIT_REQUEST:
@@ -508,8 +502,6 @@ export default function compose(state = initialState, action: ComposeAction | Ev
return updateCompose(state, action.id, compose => compose.update('to', mentions => mentions!.add(action.account)));
case COMPOSE_REMOVE_FROM_MENTIONS:
return updateCompose(state, action.id, compose => compose.update('to', mentions => mentions!.delete(action.account)));
- case COMPOSE_SET_GROUP_TIMELINE_VISIBLE:
- return updateCompose(state, action.id, compose => compose.set('group_timeline_visible', action.groupTimelineVisible));
case ME_FETCH_SUCCESS:
case ME_PATCH_SUCCESS:
return updateCompose(state, 'default', compose => importAccount(compose, action.me));
diff --git a/src/schemas/account.ts b/src/schemas/account.ts
index b085120b7..e9a8fa08a 100644
--- a/src/schemas/account.ts
+++ b/src/schemas/account.ts
@@ -97,7 +97,6 @@ const baseAccountSchema = z.object({
roles: filteredArray(roleSchema),
source: z.object({
approved: z.boolean().catch(true),
- chats_onboarded: z.boolean().catch(true),
fields: filteredArray(fieldSchema),
note: z.string().catch(''),
pleroma: z.object({
@@ -114,7 +113,6 @@ const baseAccountSchema = z.object({
url: z.string().url(),
username: z.string().catch(''),
verified: z.boolean().catch(false),
- website: z.string().catch(''),
});
type BaseAccount = z.infer;
diff --git a/src/schemas/card.ts b/src/schemas/card.ts
index dc4ba2e6b..a1a2b43e8 100644
--- a/src/schemas/card.ts
+++ b/src/schemas/card.ts
@@ -3,8 +3,6 @@ import punycode from 'punycode';
import DOMPurify from 'isomorphic-dompurify';
import { z } from 'zod';
-import { groupSchema } from './group';
-
const IDNA_PREFIX = 'xn--';
/**
@@ -17,7 +15,6 @@ const cardSchema = z.object({
blurhash: z.string().nullable().catch(null),
description: z.string().catch(''),
embed_url: z.string().url().catch(''),
- group: groupSchema.nullable().catch(null), // TruthSocial
height: z.number().catch(0),
html: z.string().catch(''),
image: z.string().nullable().catch(null),
diff --git a/src/schemas/chat-message.ts b/src/schemas/chat-message.ts
index fe0ff0f6b..cac922347 100644
--- a/src/schemas/chat-message.ts
+++ b/src/schemas/chat-message.ts
@@ -3,7 +3,7 @@ import { z } from 'zod';
import { attachmentSchema } from './attachment';
import { cardSchema } from './card';
import { customEmojiSchema } from './custom-emoji';
-import { contentSchema, emojiSchema, filteredArray } from './utils';
+import { contentSchema, filteredArray } from './utils';
const chatMessageSchema = z.object({
account_id: z.string(),
@@ -13,8 +13,6 @@ const chatMessageSchema = z.object({
content: contentSchema,
created_at: z.string().datetime().catch(new Date().toUTCString()),
emojis: filteredArray(customEmojiSchema),
- expiration: z.number().optional().catch(undefined),
- emoji_reactions: z.array(emojiSchema).min(1).nullable().catch(null),
id: z.string(),
unread: z.coerce.boolean(),
deleting: z.coerce.boolean(),
diff --git a/src/schemas/group-tag.ts b/src/schemas/group-tag.ts
deleted file mode 100644
index 0d07003ff..000000000
--- a/src/schemas/group-tag.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import z from 'zod';
-
-const groupTagSchema = z.object({
- id: z.string(),
- name: z.string(),
- groups: z.number().optional(),
- url: z.string().optional(),
- uses: z.number().optional(),
- pinned: z.boolean().optional().catch(false),
- visible: z.boolean().optional().default(true),
-});
-
-type GroupTag = z.infer;
-
-export { groupTagSchema, type GroupTag };
diff --git a/src/schemas/group.test.ts b/src/schemas/group.test.ts
deleted file mode 100644
index b227ad856..000000000
--- a/src/schemas/group.test.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { groupSchema } from './group';
-
-test('groupSchema with a TruthSocial group', async () => {
- const data = await import('soapbox/__fixtures__/group-truthsocial.json');
- const group = groupSchema.parse(data);
- expect(group.display_name_html).toEqual('PATRIOT PATRIOTS');
-});
\ No newline at end of file
diff --git a/src/schemas/group.ts b/src/schemas/group.ts
index 9d97a4047..239d8eb35 100644
--- a/src/schemas/group.ts
+++ b/src/schemas/group.ts
@@ -6,7 +6,6 @@ import { unescapeHTML } from 'soapbox/utils/html';
import { customEmojiSchema } from './custom-emoji';
import { groupRelationshipSchema } from './group-relationship';
-import { groupTagSchema } from './group-tag';
import { filteredArray, makeCustomEmojiMap } from './utils';
const avatarMissing = require('soapbox/assets/images/avatar-missing.png');
@@ -20,7 +19,6 @@ const groupSchema = z.object({
display_name: z.string().catch(''),
domain: z.string().catch(''),
emojis: filteredArray(customEmojiSchema),
- group_visibility: z.string().catch(''), // TruthSocial
header: z.string().catch(headerMissing),
header_static: z.string().catch(''),
id: z.coerce.string(),
@@ -30,18 +28,15 @@ const groupSchema = z.object({
owner: z.object({ id: z.string() }),
note: z.string().transform(note => note === '' ? '' : note).catch(''),
relationship: groupRelationshipSchema.nullable().catch(null), // Dummy field to be overwritten later
- slug: z.string().catch(''), // TruthSocial
source: z.object({
note: z.string(),
}).optional(), // TruthSocial
statuses_visibility: z.string().catch('public'),
- tags: z.array(groupTagSchema).catch([]),
uri: z.string().catch(''),
url: z.string().catch(''),
}).transform(group => {
group.avatar_static = group.avatar_static || group.avatar;
group.header_static = group.header_static || group.header;
- group.locked = group.locked || group.group_visibility === 'members_only'; // TruthSocial
const customEmojiMap = makeCustomEmojiMap(group.emojis);
return {
diff --git a/src/schemas/index.ts b/src/schemas/index.ts
index 3e8d00f7f..de9031130 100644
--- a/src/schemas/index.ts
+++ b/src/schemas/index.ts
@@ -11,7 +11,6 @@ export { emojiReactionSchema, type EmojiReaction } from './emoji-reaction';
export { groupSchema, type Group } from './group';
export { groupMemberSchema, type GroupMember } from './group-member';
export { groupRelationshipSchema, type GroupRelationship } from './group-relationship';
-export { groupTagSchema, type GroupTag } from './group-tag';
export { instanceSchema, type Instance } from './instance';
export { mentionSchema, type Mention } from './mention';
export { moderationLogEntrySchema, type ModerationLogEntry } from './moderation-log-entry';
diff --git a/src/schemas/notification.ts b/src/schemas/notification.ts
index 3c77de6bf..535bce068 100644
--- a/src/schemas/notification.ts
+++ b/src/schemas/notification.ts
@@ -10,7 +10,6 @@ const baseNotificationSchema = z.object({
created_at: z.string().datetime().catch(new Date().toUTCString()),
id: z.string(),
type: z.string(),
- total_count: z.number().optional().catch(undefined), // TruthSocial
});
const mentionNotificationSchema = baseNotificationSchema.extend({
diff --git a/src/schemas/rule.ts b/src/schemas/rule.ts
index 888ee3d50..bc32491ff 100644
--- a/src/schemas/rule.ts
+++ b/src/schemas/rule.ts
@@ -4,7 +4,6 @@ const baseRuleSchema = z.object({
id: z.string(),
text: z.string().catch(''),
hint: z.string().catch(''),
- rule_type: z.enum(['account', 'content', 'group']).nullable().catch(null),
});
const ruleSchema = z.preprocess((data: any) => {
diff --git a/src/settings.ts b/src/settings.ts
index ce713f17e..27b473e44 100644
--- a/src/settings.ts
+++ b/src/settings.ts
@@ -51,6 +51,3 @@ export const pushNotificationsSetting = new Settings('soapbox_push_notification_
/** Remember hashtag usage. */
export const tagHistory = new Settings('soapbox_tag_history');
-
-/** Remember group usage. */
-export const groupSearchHistory = new Settings('soapbox_group_search_history');
diff --git a/src/utils/chats.test.ts b/src/utils/chats.test.ts
index c7eb306c3..79f24725a 100644
--- a/src/utils/chats.test.ts
+++ b/src/utils/chats.test.ts
@@ -6,7 +6,6 @@ import { queryClient } from 'soapbox/queries/client';
import { updateChatMessage } from './chats';
const chat: IChat = {
- accepted: true,
account: buildAccount({
username: 'username',
verified: true,
@@ -16,15 +15,9 @@ const chat: IChat = {
avatar_static: 'avatar',
display_name: 'my name',
}),
- chat_type: 'direct',
created_at: '2020-06-10T02:05:06.000Z',
- created_by_account: '1',
- discarded_at: null,
id: '1',
last_message: null,
- latest_read_message_by_account: [],
- latest_read_message_created_at: null,
- message_expiration: 1209600,
unread: 0,
};
@@ -34,8 +27,6 @@ const buildChatMessage = (id: string) => normalizeChatMessage({
account_id: '1',
content: `chat message #${id}`,
created_at: '2020-06-10T02:05:06.000Z',
- emoji_reactions: null,
- expiration: 1209600,
unread: true,
});
diff --git a/src/utils/chats.ts b/src/utils/chats.ts
index 423565e49..e8083b464 100644
--- a/src/utils/chats.ts
+++ b/src/utils/chats.ts
@@ -18,14 +18,14 @@ interface ChatPayload extends Omit {
* @param newChat - Chat entity.
*/
const updateChatInChatSearchQuery = (newChat: ChatPayload) => {
- updatePageItem(ChatKeys.chatSearch(), newChat as any, (o, n) => o.id === n.id);
+ updatePageItem(['chats', 'search'], newChat as any, (o, n) => o.id === n.id);
};
/**
* Re-order the ChatSearch query by the last message timestamp.
*/
const reOrderChatListItems = () => {
- sortQueryData(ChatKeys.chatSearch(), (chatA, chatB) => {
+ sortQueryData(['chats', 'search'], (chatA, chatB) => {
return compareDate(
chatA.last_message?.created_at as string,
chatB.last_message?.created_at as string,
@@ -40,7 +40,7 @@ const reOrderChatListItems = () => {
*/
const checkIfChatExists = (chatId: string) => {
const currentChats = flattenPages(
- queryClient.getQueryData>>(ChatKeys.chatSearch()),
+ queryClient.getQueryData>>(['chats', 'search']),
);
return currentChats?.find((chat: Chat) => chat.id === chatId);
@@ -51,7 +51,7 @@ const checkIfChatExists = (chatId: string) => {
*/
const invalidateChatSearchQuery = () => {
queryClient.invalidateQueries({
- queryKey: ChatKeys.chatSearch(),
+ queryKey: ['chats', 'search'],
});
};
@@ -80,7 +80,7 @@ const updateChatListItem = (newChat: ChatPayload) => {
/** Get unread chats count. */
const getUnreadChatsCount = (): number => {
const chats = flattenPages(
- queryClient.getQueryData>>(ChatKeys.chatSearch()),
+ queryClient.getQueryData>>(['chats', 'search']),
);
return sumBy(chats, chat => chat.unread);
diff --git a/src/utils/features.test.ts b/src/utils/features.test.ts
index 248085876..d3a995ab1 100644
--- a/src/utils/features.test.ts
+++ b/src/utils/features.test.ts
@@ -34,15 +34,6 @@ describe('parseVersion', () => {
});
});
- it('with a Truth Social version string', () => {
- const version = '3.4.1 (compatible; TruthSocial 1.0.0)';
- expect(parseVersion(version)).toEqual({
- software: 'TruthSocial',
- version: '1.0.0',
- compatVersion: '3.4.1',
- });
- });
-
it('with a Mastodon fork', () => {
const version = '3.5.1+glitch';
expect(parseVersion(version)).toEqual({
diff --git a/src/utils/features.ts b/src/utils/features.ts
index 9e04d0821..f492e6ce5 100644
--- a/src/utils/features.ts
+++ b/src/utils/features.ts
@@ -68,12 +68,6 @@ export const PLEROMA = 'Pleroma';
*/
export const TAKAHE = 'Takahe';
-/**
- * Truth Social, the Mastodon fork powering truthsocial.com
- * @see {@link https://help.truthsocial.com/open-source}
- */
-export const TRUTHSOCIAL = 'TruthSocial';
-
/**
* Wildebeest, backend running on top of Cloudflare Pages.
*/
@@ -124,7 +118,7 @@ const getInstanceFeatures = (instance: Instance) => {
* Ability to create accounts.
* @see POST /api/v1/accounts
*/
- accountCreation: v.software !== TRUTHSOCIAL,
+ accountCreation: true,
/**
* Ability to pin other accounts on one's profile.
@@ -138,10 +132,7 @@ const getInstanceFeatures = (instance: Instance) => {
* Ability to set one's location on their profile.
* @see PATCH /api/v1/accounts/update_credentials
*/
- accountLocation: any([
- v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.4.50'),
- v.software === TRUTHSOCIAL,
- ]),
+ accountLocation: v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.4.50'),
/**
* Look up an account by the acct.
@@ -153,7 +144,6 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === MASTODON && gte(v.compatVersion, '3.4.0'),
v.software === PLEROMA && gte(v.version, '2.4.50'),
v.software === TAKAHE && gte(v.version, '0.6.1'),
- v.software === TRUTHSOCIAL,
v.software === DITTO,
]),
@@ -170,7 +160,6 @@ const getInstanceFeatures = (instance: Instance) => {
accountNotifies: any([
v.software === MASTODON && gte(v.compatVersion, '3.3.0'),
v.software === PLEROMA && gte(v.version, '2.4.50'),
- v.software === TRUTHSOCIAL,
]),
/**
@@ -180,12 +169,6 @@ const getInstanceFeatures = (instance: Instance) => {
*/
accountSubscriptions: v.software === PLEROMA && gte(v.version, '1.0.0'),
- /**
- * Ability to set one's website on their profile.
- * @see PATCH /api/v1/accounts/update_credentials
- */
- accountWebsite: v.software === TRUTHSOCIAL,
-
/**
* Ability to manage announcements by admins.
* @see GET /api/v1/pleroma/admin/announcements
@@ -285,72 +268,29 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === PLEROMA,
]),
- /**
- * Ability to accept a chat.
- * POST /api/v1/pleroma/chats/:id/accept
- */
- chatAcceptance: v.software === TRUTHSOCIAL,
-
- /**
- * Ability to add reactions to chat messages.
- */
- chatEmojiReactions: v.software === TRUTHSOCIAL,
-
/**
* Pleroma chats API.
* @see {@link https://docs.pleroma.social/backend/development/API/chats/}
*/
- chats: any([
- v.software === TRUTHSOCIAL,
- features.includes('pleroma_chat_messages'),
- ]),
+ chats: features.includes('pleroma_chat_messages'),
/**
* Ability to delete a chat.
* @see DELETE /api/v1/pleroma/chats/:id
*/
- chatsDelete: any([
- v.software === TRUTHSOCIAL,
- v.build === REBASED,
- ]),
-
- /**
- * Ability to set disappearing messages on chats.
- * @see PATCH /api/v1/pleroma/chats/:id
- */
- chatsExpiration: v.software === TRUTHSOCIAL,
+ chatsDelete: v.build === REBASED,
/**
* Whether chat messages can accept a `media_id` attachment.
* @see POST /api/v1/pleroma/chats/:id/messages
*/
- chatsMedia: v.software !== TRUTHSOCIAL || v.build === UNRELEASED,
-
- /**
- * Whether chat messages have read receipts.
- * @see GET /api/v1/pleroma/chats/:id/messages
- */
- chatsReadReceipts: v.software === TRUTHSOCIAL,
-
- /**
- * Ability to search among chats.
- * @see GET /api/v1/pleroma/chats
- */
- chatsSearch: v.software === TRUTHSOCIAL,
+ chatsMedia: v.build === UNRELEASED,
/**
* Paginated chats API.
* @see GET /api/v2/pleroma/chats
*/
- chatsV2: any([
- v.software === TRUTHSOCIAL,
- v.software === PLEROMA && gte(v.version, '2.3.0'),
- ]),
-
- /**
- * Ability to only chat with people that follow you.
- */
- chatsWithFollowers: v.software === TRUTHSOCIAL,
+ chatsV2: v.software === PLEROMA && gte(v.version, '2.3.0'),
/**
* Mastodon's newer solution for direct messaging.
@@ -414,7 +354,6 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === PIXELFED,
v.software === PLEROMA,
v.software === TAKAHE && gte(v.version, '0.7.0'),
- v.software === TRUTHSOCIAL,
v.software === WILDEBEEST,
]),
@@ -444,10 +383,7 @@ const getInstanceFeatures = (instance: Instance) => {
* Ability to embed posts on external sites.
* @see GET /api/oembed
*/
- embeds: any([
- v.software === MASTODON,
- v.software === TRUTHSOCIAL,
- ]),
+ embeds: v.software === MASTODON,
/**
* Ability to add emoji reactions to a status.
@@ -490,10 +426,7 @@ const getInstanceFeatures = (instance: Instance) => {
* Ability to address recipients of a status explicitly (with `to`).
* @see POST /api/v1/statuses
*/
- explicitAddressing: any([
- v.software === PLEROMA && gte(v.version, '1.0.0'),
- v.software === TRUTHSOCIAL,
- ]),
+ explicitAddressing: v.software === PLEROMA && gte(v.version, '1.0.0'),
/** Whether to allow exporting follows/blocks/mutes to CSV by paginating the API. */
exportData: true,
@@ -505,7 +438,6 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === ICESHRIMP,
v.software === MASTODON,
v.software === TAKAHE && gte(v.version, '0.6.1'),
- v.software === TRUTHSOCIAL,
features.includes('exposable_reactions'),
]),
@@ -610,52 +542,7 @@ const getInstanceFeatures = (instance: Instance) => {
* @see POST /api/v1/admin/groups/:group_id/unsuspend
* @see DELETE /api/v1/admin/groups/:group_id
*/
- groups: v.software === TRUTHSOCIAL,
-
- /**
- * Cap # of Group Admins to 5
- */
- groupsAdminMax: v.software === TRUTHSOCIAL,
-
- /**
- * Can see trending/suggested Groups.
- */
- groupsDiscovery: v.software === TRUTHSOCIAL,
-
- /**
- * Can kick user from Group.
- */
- groupsKick: v.software !== TRUTHSOCIAL,
-
- /**
- * Can mute a Group.
- */
- groupsMuting: v.software === TRUTHSOCIAL,
-
- /**
- * Can query pending Group requests.
- */
- groupsPending: v.software === TRUTHSOCIAL,
-
- /**
- * Can promote members to Admins.
- */
- groupsPromoteToAdmin: v.software !== TRUTHSOCIAL,
-
- /**
- * Can search my own groups.
- */
- groupsSearch: v.software === TRUTHSOCIAL,
-
- /**
- * Can see topics for Groups.
- */
- groupsTags: v.software === TRUTHSOCIAL,
-
- /**
- * Can validate group names.
- */
- groupsValidation: v.software === TRUTHSOCIAL,
+ groups: false,
/**
* Can hide follows/followers lists and counts.
@@ -705,10 +592,7 @@ const getInstanceFeatures = (instance: Instance) => {
/**
* Can sign in using username instead of e-mail address.
*/
- logInWithUsername: any([
- v.software === PLEROMA,
- v.software === TRUTHSOCIAL,
- ]),
+ logInWithUsername: v.software === PLEROMA,
/**
* Can perform moderation actions with account and reports.
@@ -802,13 +686,6 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === TAKAHE && gte(v.version, '0.6.2'),
]),
- /**
- * Supports pagination in threads.
- * @see GET /api/v1/statuses/:id/context/ancestors
- * @see GET /api/v1/statuses/:id/context/descendants
- */
- paginatedContext: v.software === TRUTHSOCIAL,
-
/**
* Displays a form to follow a user when logged out.
* @see POST /main/ostatus
@@ -825,14 +702,13 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === MASTODON && gte(v.version, '2.8.0'),
v.software === PLEROMA,
v.software === TAKAHE && gte(v.version, '0.8.0'),
- v.software === TRUTHSOCIAL,
]),
/**
* Can set privacy scopes on statuses.
* @see POST /api/v1/statuses
*/
- privacyScopes: ![TRUTHSOCIAL, DITTO].includes(v.software!),
+ privacyScopes: v.software !== DITTO,
/**
* A directory of discoverable profiles from the instance.
@@ -896,18 +772,6 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === PLEROMA && v.build === REBASED && gte(v.version, '2.4.50'),
]),
- /**
- * Ability to report chat messages.
- * @see POST /api/v1/reports
- */
- reportChats: v.software === TRUTHSOCIAL,
-
- /**
- * Ability to select more than one status when reporting.
- * @see POST /api/v1/reports
- */
- reportMultipleStatuses: v.software !== TRUTHSOCIAL,
-
/**
* Can request a password reset email through the API.
* @see POST /auth/password
@@ -959,10 +823,7 @@ const getInstanceFeatures = (instance: Instance) => {
* @see POST /api/pleroma/change_email
* @see POST /api/pleroma/delete_account
*/
- security: any([
- v.software === PLEROMA,
- v.software === TRUTHSOCIAL,
- ]),
+ security: v.software === PLEROMA,
/**
* Ability to manage account sessions.
@@ -975,16 +836,13 @@ const getInstanceFeatures = (instance: Instance) => {
* Can store client settings in the database.
* @see PATCH /api/v1/accounts/update_credentials
*/
- settingsStore: any([
- v.software === PLEROMA,
- v.software === TRUTHSOCIAL,
- ]),
+ settingsStore: v.software === PLEROMA,
/**
* Can set content warnings on statuses.
* @see POST /api/v1/statuses
*/
- spoilers: v.software !== TRUTHSOCIAL,
+ spoilers: true,
/**
* Can display suggested accounts.
@@ -992,7 +850,6 @@ const getInstanceFeatures = (instance: Instance) => {
*/
suggestions: any([
v.software === MASTODON && gte(v.compatVersion, '2.4.3'),
- v.software === TRUTHSOCIAL,
features.includes('v2_suggestions'),
]),
@@ -1004,7 +861,6 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === FRIENDICA,
v.software === ICESHRIMP,
v.software === MASTODON && gte(v.compatVersion, '3.4.0'),
- v.software === TRUTHSOCIAL,
features.includes('v2_suggestions'),
]),
@@ -1032,7 +888,6 @@ const getInstanceFeatures = (instance: Instance) => {
v.software === FRIENDICA && gte(v.version, '2022.12.0'),
v.software === ICESHRIMP,
v.software === MASTODON && gte(v.compatVersion, '3.0.0'),
- v.software === TRUTHSOCIAL,
v.software === DITTO,
]),
diff --git a/src/utils/groups.ts b/src/utils/groups.ts
deleted file mode 100644
index 28264e090..000000000
--- a/src/utils/groups.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { groupSearchHistory } from 'soapbox/settings';
-
-const RECENT_SEARCHES_KEY = 'soapbox:recent-group-searches';
-
-const clearRecentGroupSearches = (currentUserId: string) => groupSearchHistory.remove(currentUserId);
-
-const saveGroupSearch = (currentUserId: string, search: string) => {
- let currentSearches: string[] = [];
-
- if (groupSearchHistory.get(currentUserId)) {
- currentSearches = groupSearchHistory.get(currentUserId);
- }
-
- if (currentSearches.indexOf(search) === -1) {
- currentSearches.unshift(search);
- if (currentSearches.length > 10) {
- currentSearches.pop();
- }
-
- groupSearchHistory.set(currentUserId, currentSearches);
-
- return currentSearches;
- } else {
- // The search term has already been searched. Move it to the beginning
- // of the cached list.
- const indexOfSearch = currentSearches.indexOf(search);
- const nextCurrentSearches = [...currentSearches];
- nextCurrentSearches.splice(0, 0, ...nextCurrentSearches.splice(indexOfSearch, 1));
- localStorage.setItem(RECENT_SEARCHES_KEY, JSON.stringify(nextCurrentSearches));
-
- return nextCurrentSearches;
- }
-};
-
-export { clearRecentGroupSearches, saveGroupSearch };
diff --git a/src/utils/notification.ts b/src/utils/notification.ts
index fdd8e25fe..43e73be11 100644
--- a/src/utils/notification.ts
+++ b/src/utils/notification.ts
@@ -22,7 +22,6 @@ const NOTIFICATION_TYPES = [
/** Notification types to exclude from the "All" filter by default. */
const EXCLUDE_TYPES = [
'pleroma:chat_mention',
- 'chat', // TruthSocial
] as const;
type NotificationType = typeof NOTIFICATION_TYPES[number];