diff --git a/lib/actions/message-actions.js b/lib/actions/message-actions.js --- a/lib/actions/message-actions.js +++ b/lib/actions/message-actions.js @@ -15,6 +15,10 @@ SearchMessagesResponse, } from '../types/message-types.js'; import type { MediaMessageServerDBContent } from '../types/messages/media.js'; +import type { + ToggleMessagePinRequest, + ToggleMessagePinResult, +} from '../types/thread-types.js'; import { extractKeyserverIDFromID, sortThreadIDsPerKeyserver, @@ -456,6 +460,36 @@ return useKeyserverCall(searchMessages); } +const toggleMessagePinActionTypes = Object.freeze({ + started: 'TOGGLE_MESSAGE_PIN_STARTED', + success: 'TOGGLE_MESSAGE_PIN_SUCCESS', + failed: 'TOGGLE_MESSAGE_PIN_FAILED', +}); +const toggleMessagePin = + ( + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: ToggleMessagePinRequest) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.messageID); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint( + 'toggle_message_pin', + requests, + ); + const response = responses[keyserverID]; + return { + newMessageInfos: response.newMessageInfos, + threadID: response.threadID, + }; + }; + +function useToggleMessagePin(): ( + input: ToggleMessagePinRequest, +) => Promise { + return useKeyserverCall(toggleMessagePin); +} + export { fetchMessagesBeforeCursorActionTypes, useFetchMessagesBeforeCursor, @@ -480,4 +514,6 @@ useSendEditMessage, useFetchPinnedMessages, fetchPinnedMessageActionTypes, + toggleMessagePinActionTypes, + useToggleMessagePin, }; diff --git a/lib/actions/thread-actions.js b/lib/actions/thread-actions.js --- a/lib/actions/thread-actions.js +++ b/lib/actions/thread-actions.js @@ -2,6 +2,7 @@ import invariant from 'invariant'; +import genesis from '../facts/genesis.js'; import type { ChangeThreadSettingsPayload, LeaveThreadPayload, @@ -12,14 +13,15 @@ ThreadJoinPayload, ThreadFetchMediaRequest, ThreadFetchMediaResult, - ToggleMessagePinRequest, - ToggleMessagePinResult, RoleModificationRequest, RoleModificationPayload, RoleDeletionRequest, RoleDeletionPayload, } from '../types/thread-types.js'; +import { extractKeyserverIDFromID } from '../utils/action-utils.js'; import type { CallServerEndpoint } from '../utils/call-server-endpoint.js'; +import type { CallKeyserverEndpoint } from '../utils/keyserver-call'; +import { useKeyserverCall } from '../utils/keyserver-call.js'; import { values } from '../utils/objects.js'; const deleteThreadActionTypes = Object.freeze({ @@ -66,6 +68,11 @@ }; }; +export type RemoveUsersFromThreadInput = { + +threadID: string, + +memberIDs: $ReadOnlyArray, +}; + const removeUsersFromThreadActionTypes = Object.freeze({ started: 'REMOVE_USERS_FROM_THREAD_STARTED', success: 'REMOVE_USERS_FROM_THREAD_SUCCESS', @@ -73,23 +80,35 @@ }); const removeUsersFromThread = ( - callServerEndpoint: CallServerEndpoint, + callKeyserverEndpoint: CallKeyserverEndpoint, ): (( - threadID: string, - memberIDs: $ReadOnlyArray, + input: RemoveUsersFromThreadInput, ) => Promise) => - async (threadID, memberIDs) => { - const response = await callServerEndpoint('remove_members', { - threadID, - memberIDs, - }); + async input => { + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint('remove_members', requests); + const response = responses[keyserverID]; return { - threadID, + threadID: input.threadID, updatesResult: response.updatesResult, newMessageInfos: response.newMessageInfos, }; }; +function useRemoveUsersFromThread(): ( + input: RemoveUsersFromThreadInput, +) => Promise { + return useKeyserverCall(removeUsersFromThread); +} + +export type ChangeThreadMemberRolesInput = { + +threadID: string, + +memberIDs: $ReadOnlyArray, + +newRole: string, +}; + const changeThreadMemberRolesActionTypes = Object.freeze({ started: 'CHANGE_THREAD_MEMBER_ROLES_STARTED', success: 'CHANGE_THREAD_MEMBER_ROLES_SUCCESS', @@ -97,18 +116,23 @@ }); const changeThreadMemberRoles = ( - callServerEndpoint: CallServerEndpoint, + callKeyserverEndpoint: CallKeyserverEndpoint, ): (( - threadID: string, - memberIDs: $ReadOnlyArray, - newRole: string, + input: ChangeThreadMemberRolesInput, ) => Promise) => - async (threadID, memberIDs, newRole) => { - const response = await callServerEndpoint('update_role', { - threadID, - memberIDs, - role: newRole, - }); + async input => { + const { threadID, memberIDs, newRole } = input; + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { + [keyserverID]: { + threadID, + memberIDs, + role: newRole, + }, + }; + + const responses = await callKeyserverEndpoint('update_role', requests); + const response = responses[keyserverID]; return { threadID, updatesResult: response.updatesResult, @@ -116,6 +140,12 @@ }; }; +function useChangeThreadMemberRoles(): ( + input: ChangeThreadMemberRolesInput, +) => Promise { + return useKeyserverCall(changeThreadMemberRoles); +} + const newThreadActionTypes = Object.freeze({ started: 'NEW_THREAD_STARTED', success: 'NEW_THREAD_SUCCESS', @@ -123,10 +153,16 @@ }); const newThread = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: ClientNewThreadRequest) => Promise) => - async request => { - const response = await callServerEndpoint('create_thread', request); + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: ClientNewThreadRequest) => Promise) => + async input => { + const parentThreadID = input.parentThreadID ?? genesis.id; + const keyserverID = extractKeyserverIDFromID(parentThreadID); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint('create_thread', requests); + const response = responses[keyserverID]; + return { newThreadID: response.newThreadID, updatesResult: response.updatesResult, @@ -135,6 +171,12 @@ }; }; +function useNewThread(): ( + input: ClientNewThreadRequest, +) => Promise { + return useKeyserverCall(newThread); +} + const joinThreadActionTypes = Object.freeze({ started: 'JOIN_THREAD_STARTED', success: 'JOIN_THREAD_SUCCESS', @@ -142,10 +184,14 @@ }); const joinThread = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: ClientThreadJoinRequest) => Promise) => - async request => { - const response = await callServerEndpoint('join_thread', request); + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: ClientThreadJoinRequest) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint('join_thread', requests); + const response = responses[keyserverID]; const userInfos = values(response.userInfos); return { updatesResult: response.updatesResult, @@ -155,6 +201,15 @@ }; }; +function useJoinThread(): ( + input: ClientThreadJoinRequest, +) => Promise { + return useKeyserverCall(joinThread); +} + +export type LeaveThreadInput = { + +threadID: string, +}; const leaveThreadActionTypes = Object.freeze({ started: 'LEAVE_THREAD_STARTED', success: 'LEAVE_THREAD_SUCCESS', @@ -162,41 +217,47 @@ }); const leaveThread = ( - callServerEndpoint: CallServerEndpoint, - ): ((threadID: string) => Promise) => - async threadID => { - const response = await callServerEndpoint('leave_thread', { threadID }); + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: LeaveThreadInput) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint('leave_thread', requests); + const response = responses[keyserverID]; return { updatesResult: response.updatesResult, }; }; +function useLeaveThread(): ( + input: LeaveThreadInput, +) => Promise { + return useKeyserverCall(leaveThread); +} + const fetchThreadMedia = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: ThreadFetchMediaRequest) => Promise) => - async request => { - const response = await callServerEndpoint('fetch_thread_media', request); - return response; - }; + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: ThreadFetchMediaRequest) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.threadID); + const requests = { [keyserverID]: input }; -const toggleMessagePinActionTypes = Object.freeze({ - started: 'TOGGLE_MESSAGE_PIN_STARTED', - success: 'TOGGLE_MESSAGE_PIN_SUCCESS', - failed: 'TOGGLE_MESSAGE_PIN_FAILED', -}); -const toggleMessagePin = - ( - callServerEndpoint: CallServerEndpoint, - ): ((request: ToggleMessagePinRequest) => Promise) => - async request => { - const response = await callServerEndpoint('toggle_message_pin', request); - return { - newMessageInfos: response.newMessageInfos, - threadID: response.threadID, - }; + const responses = await callKeyserverEndpoint( + 'fetch_thread_media', + requests, + ); + const response = responses[keyserverID]; + return { media: response.media }; }; +function useFetchThreadMedia(): ( + input: ThreadFetchMediaRequest, +) => Promise { + return useKeyserverCall(fetchThreadMedia); +} + const modifyCommunityRoleActionTypes = Object.freeze({ started: 'MODIFY_COMMUNITY_ROLE_STARTED', success: 'MODIFY_COMMUNITY_ROLE_SUCCESS', @@ -204,16 +265,29 @@ }); const modifyCommunityRole = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: RoleModificationRequest) => Promise) => - async request => { - const response = await callServerEndpoint('modify_community_role', request); + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: RoleModificationRequest) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.community); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint( + 'modify_community_role', + requests, + ); + const response = responses[keyserverID]; return { threadInfo: response.threadInfo, updatesResult: response.updatesResult, }; }; +function useModifyCommunityRole(): ( + input: RoleModificationRequest, +) => Promise { + return useKeyserverCall(modifyCommunityRole); +} + const deleteCommunityRoleActionTypes = Object.freeze({ started: 'DELETE_COMMUNITY_ROLE_STARTED', success: 'DELETE_COMMUNITY_ROLE_SUCCESS', @@ -221,36 +295,47 @@ }); const deleteCommunityRole = ( - callServerEndpoint: CallServerEndpoint, - ): ((request: RoleDeletionRequest) => Promise) => - async request => { - const response = await callServerEndpoint('delete_community_role', request); + callKeyserverEndpoint: CallKeyserverEndpoint, + ): ((input: RoleDeletionRequest) => Promise) => + async input => { + const keyserverID = extractKeyserverIDFromID(input.community); + const requests = { [keyserverID]: input }; + + const responses = await callKeyserverEndpoint( + 'delete_community_role', + requests, + ); + const response = responses[keyserverID]; return { threadInfo: response.threadInfo, updatesResult: response.updatesResult, }; }; +function useDeleteCommunityRole(): ( + input: RoleDeletionRequest, +) => Promise { + return useKeyserverCall(deleteCommunityRole); +} + export { deleteThreadActionTypes, deleteThread, changeThreadSettingsActionTypes, changeThreadSettings, removeUsersFromThreadActionTypes, - removeUsersFromThread, + useRemoveUsersFromThread, changeThreadMemberRolesActionTypes, - changeThreadMemberRoles, + useChangeThreadMemberRoles, newThreadActionTypes, - newThread, + useNewThread, joinThreadActionTypes, - joinThread, + useJoinThread, leaveThreadActionTypes, - leaveThread, - fetchThreadMedia, - toggleMessagePinActionTypes, - toggleMessagePin, + useLeaveThread, + useFetchThreadMedia, modifyCommunityRoleActionTypes, - modifyCommunityRole, + useModifyCommunityRole, deleteCommunityRoleActionTypes, - deleteCommunityRole, + useDeleteCommunityRole, }; diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js --- a/lib/reducers/message-reducer.js +++ b/lib/reducers/message-reducer.js @@ -21,6 +21,7 @@ restoreEntryActionTypes, } from '../actions/entry-actions.js'; import { + toggleMessagePinActionTypes, fetchMessagesBeforeCursorActionTypes, fetchMostRecentMessagesActionTypes, sendTextMessageActionTypes, @@ -43,7 +44,6 @@ removeUsersFromThreadActionTypes, changeThreadMemberRolesActionTypes, joinThreadActionTypes, - toggleMessagePinActionTypes, } from '../actions/thread-actions.js'; import { updateMultimediaMessageMediaActionType } from '../actions/upload-actions.js'; import { diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -16,6 +16,7 @@ fetchMostRecentMessagesActionTypes, useFetchMostRecentMessages, } from '../actions/message-actions.js'; +import type { RemoveUsersFromThreadInput } from '../actions/thread-actions'; import { changeThreadMemberRolesActionTypes, newThreadActionTypes, @@ -1432,14 +1433,16 @@ memberInfo: RelativeMemberInfo, dispatchActionPromise: DispatchActionPromise, removeUserFromThreadServerCall: ( - threadID: string, - memberIDs: $ReadOnlyArray, + input: RemoveUsersFromThreadInput, ) => Promise, ) { const customKeyName = `${removeUsersFromThreadActionTypes.started}:${memberInfo.id}`; dispatchActionPromise( removeUsersFromThreadActionTypes, - removeUserFromThreadServerCall(threadInfo.id, [memberInfo.id]), + removeUserFromThreadServerCall({ + threadID: threadInfo.id, + memberIDs: [memberInfo.id], + }), { customKeyName }, ); } diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js --- a/native/chat/chat-input-bar.react.js +++ b/native/chat/chat-input-bar.react.js @@ -28,7 +28,7 @@ } from 'lib/actions/draft-actions.js'; import { joinThreadActionTypes, - joinThread, + useJoinThread, newThreadActionTypes, } from 'lib/actions/thread-actions.js'; import { @@ -83,7 +83,6 @@ import { type UserInfos } from 'lib/types/user-types.js'; import { type DispatchActionPromise, - useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; @@ -1264,7 +1263,7 @@ const dispatch = useDispatch(); const dispatchActionPromise = useDispatchActionPromise(); - const callJoinThread = useServerCall(joinThread); + const callJoinThread = useJoinThread(); const userSearchIndex = useSelector(userStoreMentionSearchIndex); diff --git a/native/chat/compose-subchannel.react.js b/native/chat/compose-subchannel.react.js --- a/native/chat/compose-subchannel.react.js +++ b/native/chat/compose-subchannel.react.js @@ -7,7 +7,10 @@ import * as React from 'react'; import { View, Text } from 'react-native'; -import { newThreadActionTypes, newThread } from 'lib/actions/thread-actions.js'; +import { + newThreadActionTypes, + useNewThread, +} from 'lib/actions/thread-actions.js'; import { useENSNames } from 'lib/hooks/ens-cache.js'; import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import { @@ -19,10 +22,7 @@ import { type ThreadType, threadTypes } from 'lib/types/thread-types-enum.js'; import { type ThreadInfo } from 'lib/types/thread-types.js'; import { type AccountUserInfo } from 'lib/types/user-types.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import type { ChatNavigationProp } from './chat.react.js'; import { useNavigateToThread } from './message-list-types.js'; @@ -74,7 +74,7 @@ const { threadType, parentThreadInfo } = props.route.params; const userInfoInputIDs = userInfoInputArray.map(userInfo => userInfo.id); - const callNewThread = useServerCall(newThread); + const callNewThread = useNewThread(); const calendarQuery = useCalendarQuery(); const newChatThreadAction = React.useCallback(async () => { try { diff --git a/native/chat/settings/thread-settings-leave-thread.react.js b/native/chat/settings/thread-settings-leave-thread.react.js --- a/native/chat/settings/thread-settings-leave-thread.react.js +++ b/native/chat/settings/thread-settings-leave-thread.react.js @@ -6,8 +6,9 @@ import { leaveThreadActionTypes, - leaveThread, + useLeaveThread, } from 'lib/actions/thread-actions.js'; +import type { LeaveThreadInput } from 'lib/actions/thread-actions.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { otherUsersButNoOtherAdmins } from 'lib/selectors/thread-selectors.js'; import { identifyInvalidatedThreads } from 'lib/shared/thread-utils.js'; @@ -15,7 +16,6 @@ import type { ThreadInfo, LeaveThreadPayload } from 'lib/types/thread-types.js'; import { type DispatchActionPromise, - useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; @@ -44,7 +44,7 @@ // Redux dispatch functions +dispatchActionPromise: DispatchActionPromise, // async functions that hit server APIs - +leaveThread: (threadID: string) => Promise, + +leaveThread: (input: LeaveThreadInput) => Promise, // withNavContext +navContext: ?NavContextType, }; @@ -113,7 +113,7 @@ payload: { threadIDs: [threadID] }, }); try { - const result = await this.props.leaveThread(threadID); + const result = await this.props.leaveThread({ threadID }); const invalidated = identifyInvalidatedThreads( result.updatesResult.newUpdates, ); @@ -165,7 +165,7 @@ const colors = useColors(); const styles = useStyles(unboundStyles); const dispatchActionPromise = useDispatchActionPromise(); - const callLeaveThread = useServerCall(leaveThread); + const callLeaveThread = useLeaveThread(); const navContext = React.useContext(NavContext); return ( { const fetchData = async () => { diff --git a/native/chat/settings/thread-settings-member-tooltip-modal.react.js b/native/chat/settings/thread-settings-member-tooltip-modal.react.js --- a/native/chat/settings/thread-settings-member-tooltip-modal.react.js +++ b/native/chat/settings/thread-settings-member-tooltip-modal.react.js @@ -2,14 +2,11 @@ import * as React from 'react'; -import { removeUsersFromThread } from 'lib/actions/thread-actions.js'; +import { useRemoveUsersFromThread } from 'lib/actions/thread-actions.js'; import { removeMemberFromThread } from 'lib/shared/thread-utils.js'; import { stringForUser } from 'lib/shared/user-utils.js'; import type { ThreadInfo, RelativeMemberInfo } from 'lib/types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import ThreadSettingsMemberTooltipButton from './thread-settings-member-tooltip-button.react.js'; import type { AppNavigationProp } from '../../navigation/app-navigator.react'; @@ -32,7 +29,7 @@ route: TooltipRoute<'ThreadSettingsMemberTooltipModal'>, ) { const { memberInfo, threadInfo } = route.params; - const boundRemoveUsersFromThread = useServerCall(removeUsersFromThread); + const boundRemoveUsersFromThread = useRemoveUsersFromThread(); const dispatchActionPromise = useDispatchActionPromise(); const onConfirmRemoveUser = React.useCallback( diff --git a/native/chat/toggle-pin-modal.react.js b/native/chat/toggle-pin-modal.react.js --- a/native/chat/toggle-pin-modal.react.js +++ b/native/chat/toggle-pin-modal.react.js @@ -5,15 +5,12 @@ import { Text, View } from 'react-native'; import { - toggleMessagePin, + useToggleMessagePin, toggleMessagePinActionTypes, -} from 'lib/actions/thread-actions.js'; +} from 'lib/actions/message-actions.js'; import type { RawMessageInfo } from 'lib/types/message-types.js'; import { type ThreadInfo } from 'lib/types/thread-types.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import MessageResult from './message-result.react.js'; import Button from '../components/button.react.js'; @@ -39,7 +36,7 @@ const { messageInfo, isPinned } = item; const styles = useStyles(unboundStyles); - const callToggleMessagePin = useServerCall(toggleMessagePin); + const callToggleMessagePin = useToggleMessagePin(); const dispatchActionPromise = useDispatchActionPromise(); const modalInfo = React.useMemo(() => { diff --git a/native/community-creation/community-configuration.react.js b/native/community-creation/community-configuration.react.js --- a/native/community-creation/community-configuration.react.js +++ b/native/community-creation/community-configuration.react.js @@ -3,15 +3,15 @@ import * as React from 'react'; import { Text, View } from 'react-native'; -import { newThread, newThreadActionTypes } from 'lib/actions/thread-actions.js'; +import { + useNewThread, + newThreadActionTypes, +} from 'lib/actions/thread-actions.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import type { LoadingStatus } from 'lib/types/loading-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import type { NewThreadResult } from 'lib/types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import CommunityCreationKeyserverLabel from './community-creation-keyserver-label.react.js'; import type { CommunityCreationNavigationProp } from './community-creation-navigator.react.js'; @@ -50,7 +50,7 @@ const dispatchActionPromise = useDispatchActionPromise(); - const callNewThread = useServerCall(newThread); + const callNewThread = useNewThread(); const calendarQueryFunc = useCalendarQuery(); const createNewCommunityLoadingStatus: LoadingStatus = useSelector( diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js --- a/native/input/input-state-container.react.js +++ b/native/input/input-state-container.react.js @@ -19,7 +19,7 @@ SendTextMessageInput, } from 'lib/actions/message-actions.js'; import { queueReportsActionType } from 'lib/actions/report-actions.js'; -import { newThread } from 'lib/actions/thread-actions.js'; +import { useNewThread } from 'lib/actions/thread-actions.js'; import { uploadMultimedia, uploadMediaMetadata, @@ -1697,7 +1697,7 @@ const callBlobServiceUpload = useServerCall(blobServiceUpload); const callSendMultimediaMessage = useSendMultimediaMessage(); const callSendTextMessage = useSendTextMessage(); - const callNewThread = useServerCall(newThread); + const callNewThread = useNewThread(); const dispatchActionPromise = useDispatchActionPromise(); const dispatch = useDispatch(); const mediaReportsEnabled = useIsReportEnabled('mediaReports'); diff --git a/native/navigation/invite-link-modal.react.js b/native/navigation/invite-link-modal.react.js --- a/native/navigation/invite-link-modal.react.js +++ b/native/navigation/invite-link-modal.react.js @@ -5,15 +5,12 @@ import { View, Text, ActivityIndicator } from 'react-native'; import { - joinThread, + useJoinThread, joinThreadActionTypes, } from 'lib/actions/thread-actions.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import type { InviteLinkVerificationResponse } from 'lib/types/link-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { nonThreadCalendarQuery } from './nav-selectors.js'; import { NavContext } from './navigation-context.js'; @@ -72,7 +69,7 @@ styles.invitation, ]); - const callJoinThread = useServerCall(joinThread); + const callJoinThread = useJoinThread(); const navContext = React.useContext(NavContext); const calendarQuery = useSelector(state => nonThreadCalendarQuery({ diff --git a/native/roles/change-roles-header-right-button.react.js b/native/roles/change-roles-header-right-button.react.js --- a/native/roles/change-roles-header-right-button.react.js +++ b/native/roles/change-roles-header-right-button.react.js @@ -7,13 +7,10 @@ import { TouchableOpacity } from 'react-native-gesture-handler'; import { - changeThreadMemberRoles, + useChangeThreadMemberRoles, changeThreadMemberRolesActionTypes, } from 'lib/actions/thread-actions.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import type { NavigationRoute } from '../navigation/route-names'; import { useColors } from '../themes/colors.js'; @@ -31,7 +28,7 @@ invariant(selectedRole, 'Expected selected role to be defined'); const navigation = useNavigation(); - const callChangeThreadMemberRoles = useServerCall(changeThreadMemberRoles); + const callChangeThreadMemberRoles = useChangeThreadMemberRoles(); const dispatchActionPromise = useDispatchActionPromise(); const { disabledButton, purpleLink } = useColors(); @@ -51,7 +48,11 @@ dispatchActionPromise( changeThreadMemberRolesActionTypes, - callChangeThreadMemberRoles(threadInfo.id, [memberInfo.id], selectedRole), + callChangeThreadMemberRoles({ + threadID: threadInfo.id, + memberIDs: [memberInfo.id], + newRole: selectedRole, + }), ); navigation.goBack(); diff --git a/native/roles/create-roles-header-right-button.react.js b/native/roles/create-roles-header-right-button.react.js --- a/native/roles/create-roles-header-right-button.react.js +++ b/native/roles/create-roles-header-right-button.react.js @@ -6,13 +6,10 @@ import { TouchableOpacity, Text } from 'react-native'; import { - modifyCommunityRole, + useModifyCommunityRole, modifyCommunityRoleActionTypes, } from 'lib/actions/thread-actions.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { values } from 'lib/utils/objects.js'; import type { NavigationRoute } from '../navigation/route-names'; @@ -30,7 +27,7 @@ const navigation = useNavigation(); const styles = useStyles(unboundStyles); - const callModifyCommunityRole = useServerCall(modifyCommunityRole); + const callModifyCommunityRole = useModifyCommunityRole(); const dispatchActionPromise = useDispatchActionPromise(); const threadRoleNames = React.useMemo( diff --git a/native/roles/role-utils.react.js b/native/roles/role-utils.react.js --- a/native/roles/role-utils.react.js +++ b/native/roles/role-utils.react.js @@ -3,14 +3,11 @@ import * as React from 'react'; import { - deleteCommunityRole, + useDeleteCommunityRole, deleteCommunityRoleActionTypes, } from 'lib/actions/thread-actions.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { constructRoleDeletionMessagePrompt } from 'lib/utils/role-utils.js'; import Alert from '../utils/alert.js'; @@ -22,7 +19,7 @@ memberCount: number, ): () => void { const defaultRoleName = threadInfo.roles[defaultRoleID].name; - const callDeleteCommunityRole = useServerCall(deleteCommunityRole); + const callDeleteCommunityRole = useDeleteCommunityRole(); const dispatchActionPromise = useDispatchActionPromise(); const onDeleteRole = React.useCallback(() => { diff --git a/web/chat/chat-input-bar.react.js b/web/chat/chat-input-bar.react.js --- a/web/chat/chat-input-bar.react.js +++ b/web/chat/chat-input-bar.react.js @@ -6,7 +6,7 @@ import { joinThreadActionTypes, - joinThread, + useJoinThread, newThreadActionTypes, } from 'lib/actions/thread-actions.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; @@ -45,7 +45,6 @@ import { type UserInfos } from 'lib/types/user-types.js'; import { type DispatchActionPromise, - useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils.js'; @@ -582,7 +581,7 @@ const threadCreationInProgress = createThreadLoadingStatus === 'loading'; const calendarQuery = useSelector(nonThreadCalendarQuery); const dispatchActionPromise = useDispatchActionPromise(); - const callJoinThread = useServerCall(joinThread); + const callJoinThread = useJoinThread(); const userSearchIndex = useSelector(userStoreMentionSearchIndex); const { getChatMentionSearchIndex } = useChatMentionContext(); const chatMentionSearchIndex = getChatMentionSearchIndex(props.threadInfo); diff --git a/web/chat/thread-menu.react.js b/web/chat/thread-menu.react.js --- a/web/chat/thread-menu.react.js +++ b/web/chat/thread-menu.react.js @@ -3,7 +3,7 @@ import * as React from 'react'; import { - leaveThread, + useLeaveThread, leaveThreadActionTypes, } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; @@ -18,10 +18,7 @@ import { threadPermissions } from 'lib/types/thread-permission-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import { type ThreadInfo } from 'lib/types/thread-types.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import css from './thread-menu.css'; import MenuItem from '../components/menu-item.react.js'; @@ -195,12 +192,12 @@ }, [canCreateSubchannels, onClickCreateSubchannel]); const dispatchActionPromise = useDispatchActionPromise(); - const callLeaveThread = useServerCall(leaveThread); + const callLeaveThread = useLeaveThread(); const onConfirmLeaveThread = React.useCallback(() => { dispatchActionPromise( leaveThreadActionTypes, - callLeaveThread(threadInfo.id), + callLeaveThread({ threadID: threadInfo.id }), ); popModal(); }, [callLeaveThread, popModal, dispatchActionPromise, threadInfo.id]); diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js --- a/web/input/input-state-container.react.js +++ b/web/input/input-state-container.react.js @@ -23,7 +23,7 @@ SendTextMessageInput, } from 'lib/actions/message-actions.js'; import { queueReportsActionType } from 'lib/actions/report-actions.js'; -import { newThread } from 'lib/actions/thread-actions.js'; +import { useNewThread } from 'lib/actions/thread-actions.js'; import { uploadMultimedia, uploadMediaMetadata, @@ -1616,7 +1616,7 @@ const callDeleteUpload = useServerCall(deleteUpload); const callSendMultimediaMessage = useLegacySendMultimediaMessage(); const callSendTextMessage = useSendTextMessage(); - const callNewThread = useServerCall(newThread); + const callNewThread = useNewThread(); const dispatch = useDispatch(); const dispatchActionPromise = useDispatchActionPromise(); const modalContext = useModalContext(); diff --git a/web/invite-links/accept-invite-modal.react.js b/web/invite-links/accept-invite-modal.react.js --- a/web/invite-links/accept-invite-modal.react.js +++ b/web/invite-links/accept-invite-modal.react.js @@ -4,17 +4,14 @@ import * as React from 'react'; import { - joinThread, + useJoinThread, joinThreadActionTypes, } from 'lib/actions/thread-actions.js'; import ModalOverlay from 'lib/components/modal-overlay.react.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { type InviteLinkVerificationResponse } from 'lib/types/link-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import css from './accept-invite-modal.css'; import Button, { buttonThemes } from '../components/button.react.js'; @@ -39,7 +36,7 @@ } }, [popModal, verificationResponse.status]); - const callJoinThread = useServerCall(joinThread); + const callJoinThread = useJoinThread(); const calendarQuery = useSelector(nonThreadCalendarQuery); const communityID = verificationResponse.community?.id; const createJoinCommunityAction = React.useCallback(async () => { diff --git a/web/modals/chat/toggle-pin-modal.react.js b/web/modals/chat/toggle-pin-modal.react.js --- a/web/modals/chat/toggle-pin-modal.react.js +++ b/web/modals/chat/toggle-pin-modal.react.js @@ -4,18 +4,15 @@ import * as React from 'react'; import { - toggleMessagePin, + useToggleMessagePin, toggleMessagePinActionTypes, -} from 'lib/actions/thread-actions.js'; +} from 'lib/actions/message-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js'; import { modifyItemForResultScreen } from 'lib/shared/message-utils.js'; import type { RawMessageInfo } from 'lib/types/message-types.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import css from './toggle-pin-modal.css'; import Button, { buttonThemes } from '../../components/button.react.js'; @@ -32,7 +29,7 @@ const { messageInfo, isPinned } = item; const { popModal } = useModalContext(); - const callToggleMessagePin = useServerCall(toggleMessagePin); + const callToggleMessagePin = useToggleMessagePin(); const dispatchActionPromise = useDispatchActionPromise(); const modalInfo = React.useMemo(() => { diff --git a/web/modals/threads/create/compose-subchannel-modal.react.js b/web/modals/threads/create/compose-subchannel-modal.react.js --- a/web/modals/threads/create/compose-subchannel-modal.react.js +++ b/web/modals/threads/create/compose-subchannel-modal.react.js @@ -2,14 +2,14 @@ import * as React from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { newThread, newThreadActionTypes } from 'lib/actions/thread-actions.js'; +import { + useNewThread, + newThreadActionTypes, +} from 'lib/actions/thread-actions.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; import { trimText } from 'lib/utils/text-utils.js'; @@ -78,7 +78,7 @@ const [errorMessage, setErrorMessage] = React.useState(''); const calendarQuery = useSelector(nonThreadCalendarQuery); - const callNewThread = useServerCall(newThread); + const callNewThread = useNewThread(); const dispatchActionPromise = useDispatchActionPromise(); const dispatch = useDispatch(); diff --git a/web/modals/threads/gallery/thread-settings-media-gallery.react.js b/web/modals/threads/gallery/thread-settings-media-gallery.react.js --- a/web/modals/threads/gallery/thread-settings-media-gallery.react.js +++ b/web/modals/threads/gallery/thread-settings-media-gallery.react.js @@ -2,7 +2,7 @@ import * as React from 'react'; -import { fetchThreadMedia } from 'lib/actions/thread-actions.js'; +import { useFetchThreadMedia } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import { encryptedMediaBlobURI, @@ -10,7 +10,6 @@ } from 'lib/media/media-utils.js'; import type { Media } from 'lib/types/media-types.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import { useServerCall } from 'lib/utils/action-utils.js'; import GalleryItem from './thread-settings-media-gallery-item.react.js'; import css from './thread-settings-media-gallery.css'; @@ -35,7 +34,7 @@ const { id: threadID } = parentThreadInfo; const modalName = 'Media'; - const callFetchThreadMedia = useServerCall(fetchThreadMedia); + const callFetchThreadMedia = useFetchThreadMedia(); const [mediaInfos, setMediaInfos] = React.useState([]); const [tab, setTab] = React.useState(activeTab); diff --git a/web/modals/threads/members/change-member-role-modal.react.js b/web/modals/threads/members/change-member-role-modal.react.js --- a/web/modals/threads/members/change-member-role-modal.react.js +++ b/web/modals/threads/members/change-member-role-modal.react.js @@ -4,7 +4,7 @@ import * as React from 'react'; import { - changeThreadMemberRoles, + useChangeThreadMemberRoles, changeThreadMemberRolesActionTypes, } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; @@ -12,10 +12,7 @@ import { otherUsersButNoOtherAdmins } from 'lib/selectors/thread-selectors.js'; import { roleIsAdminRole } from 'lib/shared/thread-utils.js'; import type { RelativeMemberInfo, ThreadInfo } from 'lib/types/thread-types'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { values } from 'lib/utils/objects.js'; import css from './change-member-role-modal.css'; @@ -35,7 +32,7 @@ const { memberInfo, threadInfo } = props; const { pushModal, popModal } = useModalContext(); const dispatchActionPromise = useDispatchActionPromise(); - const callChangeThreadMemberRoles = useServerCall(changeThreadMemberRoles); + const callChangeThreadMemberRoles = useChangeThreadMemberRoles(); const otherUsersButNoOtherAdminsValue = useSelector( otherUsersButNoOtherAdmins(threadInfo.id), ); @@ -89,7 +86,11 @@ } const createChangeThreadMemberRolesPromise = () => - callChangeThreadMemberRoles(threadInfo.id, [memberInfo.id], selectedRole); + callChangeThreadMemberRoles({ + threadID: threadInfo.id, + memberIDs: [memberInfo.id], + newRole: selectedRole, + }); dispatchActionPromise( changeThreadMemberRolesActionTypes, diff --git a/web/modals/threads/members/member.react.js b/web/modals/threads/members/member.react.js --- a/web/modals/threads/members/member.react.js +++ b/web/modals/threads/members/member.react.js @@ -2,7 +2,7 @@ import * as React from 'react'; -import { removeUsersFromThread } from 'lib/actions/thread-actions.js'; +import { useRemoveUsersFromThread } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; import { @@ -15,10 +15,7 @@ type RelativeMemberInfo, type ThreadInfo, } from 'lib/types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { useRolesFromCommunityThreadInfo } from 'lib/utils/role-utils.js'; import ChangeMemberRoleModal from './change-member-role-modal.react.js'; @@ -58,7 +55,7 @@ ); const dispatchActionPromise = useDispatchActionPromise(); - const boundRemoveUsersFromThread = useServerCall(removeUsersFromThread); + const boundRemoveUsersFromThread = useRemoveUsersFromThread(); const onClickRemoveUser = React.useCallback( () => diff --git a/web/roles/create-roles-modal.react.js b/web/roles/create-roles-modal.react.js --- a/web/roles/create-roles-modal.react.js +++ b/web/roles/create-roles-modal.react.js @@ -5,7 +5,7 @@ import * as React from 'react'; import { - modifyCommunityRole, + useModifyCommunityRole, modifyCommunityRoleActionTypes, } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; @@ -19,10 +19,7 @@ ThreadInfo, RoleModificationRequest, } from 'lib/types/thread-types.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { values } from 'lib/utils/objects.js'; import { useFilterPermissionOptionsByThreadType } from 'lib/utils/role-utils.js'; @@ -55,7 +52,7 @@ props; const modalName = action === 'create_role' ? 'Create role' : 'Edit role'; - const callModifyCommunityRole = useServerCall(modifyCommunityRole); + const callModifyCommunityRole = useModifyCommunityRole(); const dispatchActionPromise = useDispatchActionPromise(); const createRolesLoadingStatus: LoadingStatus = useSelector( diff --git a/web/roles/delete-role-modal.react.js b/web/roles/delete-role-modal.react.js --- a/web/roles/delete-role-modal.react.js +++ b/web/roles/delete-role-modal.react.js @@ -3,7 +3,7 @@ import * as React from 'react'; import { - deleteCommunityRole, + useDeleteCommunityRole, deleteCommunityRoleActionTypes, } from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; @@ -11,10 +11,7 @@ import { useRoleMemberCountsForCommunity } from 'lib/shared/thread-utils.js'; import type { LoadingStatus } from 'lib/types/loading-types.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; -import { - useServerCall, - useDispatchActionPromise, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import { constructRoleDeletionMessagePrompt } from 'lib/utils/role-utils.js'; import css from './delete-role-modal.css'; @@ -37,7 +34,7 @@ const { threadInfo, defaultRoleID, roleID } = props; const { popModal } = useModalContext(); - const callDeleteCommunityRole = useServerCall(deleteCommunityRole); + const callDeleteCommunityRole = useDeleteCommunityRole(); const dispatchActionPromise = useDispatchActionPromise(); const deleteRoleLoadingStatus: LoadingStatus = useSelector( diff --git a/web/sidebar/community-creation/community-creation-modal.react.js b/web/sidebar/community-creation/community-creation-modal.react.js --- a/web/sidebar/community-creation/community-creation-modal.react.js +++ b/web/sidebar/community-creation/community-creation-modal.react.js @@ -3,16 +3,16 @@ import * as React from 'react'; import { useDispatch } from 'react-redux'; -import { newThread, newThreadActionTypes } from 'lib/actions/thread-actions.js'; +import { + useNewThread, + newThreadActionTypes, +} from 'lib/actions/thread-actions.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import type { LoadingStatus } from 'lib/types/loading-types.js'; import { threadTypes } from 'lib/types/thread-types-enum.js'; import type { NewThreadResult } from 'lib/types/thread-types.js'; -import { - useDispatchActionPromise, - useServerCall, -} from 'lib/utils/action-utils.js'; +import { useDispatchActionPromise } from 'lib/utils/action-utils.js'; import CommunityCreationKeyserverLabel from './community-creation-keyserver-label.react.js'; import CommunityCreationMembersModal from './community-creation-members-modal.react.js'; @@ -48,7 +48,7 @@ const dispatch = useDispatch(); const dispatchActionPromise = useDispatchActionPromise(); - const callNewThread = useServerCall(newThread); + const callNewThread = useNewThread(); const calendarQueryFunc = useSelector(nonThreadCalendarQuery); const [errorMessage, setErrorMessage] = React.useState();