feat: marking pending member as invited when he sends a message to group

pull/2963/head
Audric Ackermann 1 year ago
parent 77fdc97bcf
commit 3224fec04b

@ -181,6 +181,7 @@ export async function handleSwarmDataMessage({
} }
// we handle legacy group updates from our other devices in handleLegacyClosedGroupControlMessage() // we handle legacy group updates from our other devices in handleLegacyClosedGroupControlMessage()
if (cleanDataMessage.closedGroupControlMessage) { if (cleanDataMessage.closedGroupControlMessage) {
// TODO DEPRECATED
await handleLegacyClosedGroupControlMessage( await handleLegacyClosedGroupControlMessage(
envelope, envelope,
cleanDataMessage.closedGroupControlMessage as SignalService.DataMessage.ClosedGroupControlMessage, cleanDataMessage.closedGroupControlMessage as SignalService.DataMessage.ClosedGroupControlMessage,

@ -38,7 +38,9 @@ type GroupInviteDetails = {
} & WithEnvelopeTimestamp & } & WithEnvelopeTimestamp &
WithAuthor; WithAuthor;
type GroupUpdateGeneric<T> = { change: T } & WithEnvelopeTimestamp & WithGroupPubkey & WithAuthor; type GroupUpdateGeneric<T> = { change: Omit<T, 'toJSON'> } & WithEnvelopeTimestamp &
WithGroupPubkey &
WithAuthor;
type GroupUpdateDetails = { type GroupUpdateDetails = {
updateMessage: SignalService.GroupUpdateMessage; updateMessage: SignalService.GroupUpdateMessage;
@ -381,7 +383,7 @@ async function handleGroupUpdateInviteResponseMessage({
groupPk, groupPk,
change, change,
author, author,
}: GroupUpdateGeneric<SignalService.GroupUpdateInviteResponseMessage>) { }: Omit<GroupUpdateGeneric<SignalService.GroupUpdateInviteResponseMessage>, 'envelopeTimestamp'>) {
// no sig verify for this type of message // no sig verify for this type of message
const convo = ConvoHub.use().get(groupPk); const convo = ConvoHub.use().get(groupPk);
if (!convo) { if (!convo) {
@ -536,4 +538,8 @@ async function handleGroupUpdateMessage(
window.log.warn('received group update of unknown type. Discarding...'); window.log.warn('received group update of unknown type. Discarding...');
} }
export const GroupV2Receiver = { handleGroupUpdateMessage, sendInviteResponseToGroup }; export const GroupV2Receiver = {
handleGroupUpdateMessage,
sendInviteResponseToGroup,
handleGroupUpdateInviteResponseMessage,
};

@ -1,4 +1,4 @@
import _, { isEmpty, isNumber } from 'lodash'; import _, { isEmpty, isNumber, toNumber } from 'lodash';
import { queueAttachmentDownloads } from './attachments'; import { queueAttachmentDownloads } from './attachments';
import { Data } from '../data/data'; import { Data } from '../data/data';
@ -16,9 +16,11 @@ import { PubKey } from '../session/types';
import { UserUtils } from '../session/utils'; import { UserUtils } from '../session/utils';
import { PropsForMessageWithoutConvoProps, lookupQuote } from '../state/ducks/conversations'; import { PropsForMessageWithoutConvoProps, lookupQuote } from '../state/ducks/conversations';
import { showMessageRequestBannerOutsideRedux } from '../state/ducks/userConfig'; import { showMessageRequestBannerOutsideRedux } from '../state/ducks/userConfig';
import { getMemberInvitePendingOutsideRedux } from '../state/selectors/groups';
import { getHideMessageRequestBannerOutsideRedux } from '../state/selectors/userConfig'; import { getHideMessageRequestBannerOutsideRedux } from '../state/selectors/userConfig';
import { GoogleChrome } from '../util'; import { GoogleChrome } from '../util';
import { LinkPreviews } from '../util/linkPreviews'; import { LinkPreviews } from '../util/linkPreviews';
import { GroupV2Receiver } from './groupv2/handleGroupV2Message';
function contentTypeSupported(type: string): boolean { function contentTypeSupported(type: string): boolean {
const Chrome = GoogleChrome; const Chrome = GoogleChrome;
@ -212,6 +214,66 @@ export function toRegularMessage(rawDataMessage: SignalService.DataMessage): Reg
}; };
} }
async function toggleMsgRequestBannerIfNeeded(
conversation: ConversationModel,
message: MessageModel,
source: string
) {
if (!conversation.isPrivate() || !message.isIncoming()) {
return;
}
const incomingMessageCount = await Data.getMessageCountByType(
conversation.id,
MessageDirection.incoming
);
const isFirstRequestMessage = incomingMessageCount < 2;
if (
conversation.isIncomingRequest() &&
isFirstRequestMessage &&
getHideMessageRequestBannerOutsideRedux()
) {
showMessageRequestBannerOutsideRedux();
}
// For edge case when messaging a client that's unable to explicitly send request approvals
if (conversation.isOutgoingRequest()) {
// Conversation was not approved before so a sync is needed
await conversation.addIncomingApprovalMessage(toNumber(message.get('sent_at')) - 1, source);
}
// should only occur after isOutgoing request as it relies on didApproveMe being false.
await conversation.setDidApproveMe(true);
}
async function handleMessageFromPendingMember(
conversation: ConversationModel,
message: MessageModel,
source: string
) {
const convoId = conversation.id;
if (
!conversation.isClosedGroupV2() ||
!message.isIncoming() ||
!conversation.weAreAdminUnblinded() || // this checks on libsession of that group if we are an admin
!conversation.getGroupMembers().includes(source) || // this check that the sender of that message is indeed a member of the group
!PubKey.is03Pubkey(convoId) ||
!PubKey.is05Pubkey(source)
) {
return;
}
const isMemberInvitePending = getMemberInvitePendingOutsideRedux(source, convoId);
if (!isMemberInvitePending) {
return; // nothing else to do
}
// we are an admin and we received a message from a member whose invite is `pending`. Update that member state now and push a change.
await GroupV2Receiver.handleGroupUpdateInviteResponseMessage({
groupPk: convoId,
author: source,
change: { isApproved: true },
});
}
async function handleRegularMessage( async function handleRegularMessage(
conversation: ConversationModel, conversation: ConversationModel,
sendingDeviceConversation: ConversationModel, sendingDeviceConversation: ConversationModel,
@ -220,7 +282,6 @@ async function handleRegularMessage(
source: string, source: string,
messageHash: string messageHash: string
): Promise<void> { ): Promise<void> {
const type = message.get('type');
// this does not trigger a UI update nor write to the db // this does not trigger a UI update nor write to the db
await copyFromQuotedMessage(message, rawDataMessage.quote); await copyFromQuotedMessage(message, rawDataMessage.quote);
@ -251,33 +312,8 @@ async function handleRegularMessage(
await sendingDeviceConversation.updateBlocksSogsMsgReqsTimestamp(updateBlockTimestamp, false); await sendingDeviceConversation.updateBlocksSogsMsgReqsTimestamp(updateBlockTimestamp, false);
} }
if (type === 'incoming') { await toggleMsgRequestBannerIfNeeded(conversation, message, source);
if (conversation.isPrivate()) { await handleMessageFromPendingMember(conversation, message, source);
const incomingMessageCount = await Data.getMessageCountByType(
conversation.id,
MessageDirection.incoming
);
const isFirstRequestMessage = incomingMessageCount < 2;
if (
conversation.isIncomingRequest() &&
isFirstRequestMessage &&
getHideMessageRequestBannerOutsideRedux()
) {
showMessageRequestBannerOutsideRedux();
}
// For edge case when messaging a client that's unable to explicitly send request approvals
if (conversation.isOutgoingRequest()) {
// Conversation was not approved before so a sync is needed
await conversation.addIncomingApprovalMessage(
_.toNumber(message.get('sent_at')) - 1,
source
);
}
// should only occur after isOutgoing request as it relies on didApproveMe being false.
await conversation.setDidApproveMe(true);
}
}
const conversationActiveAt = conversation.getActiveAt(); const conversationActiveAt = conversation.getActiveAt();
if ( if (

@ -110,6 +110,14 @@ export function getLibGroupAdminsOutsideRedux(convoId: string): Array<string> {
return state ? getLibAdminsPubkeys(state, convoId) : []; return state ? getLibAdminsPubkeys(state, convoId) : [];
} }
export function getMemberInvitePendingOutsideRedux(
member: PubkeyType,
convoId: GroupPubkeyType
): boolean {
const state = window.inboxStore?.getState();
return state ? getMemberInvitePending(state, member, convoId) : false;
}
export function useIsCreatingGroupFromUIPending() { export function useIsCreatingGroupFromUIPending() {
return useSelector(getIsCreatingGroupFromUI); return useSelector(getIsCreatingGroupFromUI);
} }

Loading…
Cancel
Save