Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"fs-extra": "9.0.0",
"glob": "10.3.10",
"image-type": "^4.1.0",
"libsession_util_nodejs": "https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.10/libsession_util_nodejs-v0.4.10.tar.gz",
"libsession_util_nodejs": "https://github.com/session-foundation/libsession-util-nodejs/releases/download/v0.4.11/libsession_util_nodejs-v0.4.11.tar.gz",
"libsodium-wrappers-sumo": "^0.7.9",
"linkify-it": "^4.0.1",
"lodash": "^4.17.21",
Expand Down
2 changes: 1 addition & 1 deletion preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ window.sessionFeatureFlags = {
useOnionRequests: true,
useTestNet: isTestNet() || isTestIntegration(),
useClosedGroupV2: true, // TODO DO NOT MERGE Remove after QA
useClosedGroupV2QAButtons: false, // TODO DO NOT MERGE Remove after QA
useClosedGroupV2QAButtons: true, // TODO DO NOT MERGE Remove after QA
replaceLocalizedStringsWithKeys: false,
debug: {
debugLogging: !_.isEmpty(process.env.SESSION_DEBUG),
Expand Down
6 changes: 2 additions & 4 deletions ts/components/MemberListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ function localisedStatusFromMemberStatus(memberStatus: MemberStateGroupV2) {
case 'REMOVED_UNKNOWN': // fallback, hopefully won't happen in production
case 'REMOVED_MEMBER': // we want pending removal members at the end of the "invite" states
case 'REMOVED_MEMBER_AND_MESSAGES':
return null; // no text for those 3 pending removal states
return window.i18n('groupPendingRemoval'); // no text for those 3 pending removal states
case 'PROMOTION_FAILED':
return window.i18n('adminPromotionFailed');
case 'PROMOTION_NOT_SENT':
Expand Down Expand Up @@ -259,14 +259,12 @@ const ResendButton = ({ groupPk, pubkey }: { pubkey: PubkeyType; groupPk: GroupP
window.log.warn('tried to resend invite but we do not have correct details');
return;
}
await MetaGroupWrapperActions.memberSetInviteNotSent(groupPk, pubkey);

// if we tried to invite that member as admin right away, let's retry it as such.
const inviteAsAdmin = member.nominatedAdmin;
await GroupInvite.addJob({
groupPk,
member: pubkey,
inviteAsAdmin,
inviteAsAdmin: member.nominatedAdmin,
forceUnrevoke: true,
});
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { compact, flatten, isEqual } from 'lodash';
import { SessionDataTestId, useEffect, useState } from 'react';

import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import useInterval from 'react-use/lib/useInterval';
import styled from 'styled-components';
import { Data } from '../../../../data/data';
Expand All @@ -11,13 +11,14 @@ import {
useConversationUsername,
useDisappearingMessageSettingText,
useIsClosedGroup,
useIsGroupDestroyed,
useIsKickedFromGroup,
useIsPublic,
useLastMessageIsLeaveError,
} from '../../../../hooks/useParamSelector';
import { useIsRightPanelShowing } from '../../../../hooks/useUI';
import {
showAddModeratorsByConvoId,
showDeleteGroupByConvoId,
showInviteContactByConvoId,
showLeaveGroupByConvoId,
showRemoveModeratorsByConvoId,
Expand Down Expand Up @@ -57,7 +58,7 @@ import {
showDeleteGroupItem,
showLeaveGroupItem,
} from '../../../menu/items/LeaveAndDeleteGroup/guard';
import { getIsMessageRequestOverlayShown } from '../../../../state/selectors/section';
import { useIsMessageRequestOverlayShown } from '../../../../state/selectors/section';
import { showLeaveCommunityItem } from '../../../menu/items/LeaveCommunity/guard';

async function getMediaGalleryProps(conversationId: string): Promise<{
Expand Down Expand Up @@ -229,16 +230,18 @@ const LeaveCommunityPanelButton = () => {
const DeleteGroupPanelButton = () => {
const convoId = useSelectedConversationKey();
const isGroup = useIsClosedGroup(convoId);
const isMessageRequestShown = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequestShown = useIsMessageRequestOverlayShown();
const isKickedFromGroup = useIsKickedFromGroup(convoId) || false;
const lastMessageIsLeaveError = useLastMessageIsLeaveError(convoId);
const selectedUsername = useConversationUsername(convoId) || convoId;
const isPublic = useIsPublic(convoId);
const isGroupDestroyed = useIsGroupDestroyed(convoId);

const showItem = showDeleteGroupItem({
isGroup,
isKickedFromGroup,
isMessageRequestShown,
lastMessageIsLeaveError,
isPublic,
isGroupDestroyed,
});

if (!showItem || !convoId) {
Expand All @@ -251,7 +254,7 @@ const DeleteGroupPanelButton = () => {
<PanelIconButton
text={window.i18n(token)}
dataTestId="leave-group-button"
onClick={() => void showLeaveGroupByConvoId(convoId, selectedUsername)}
onClick={() => void showDeleteGroupByConvoId(convoId, selectedUsername)}
color={'var(--danger-color)'}
iconType={'delete'}
/>
Expand All @@ -262,15 +265,17 @@ const LeaveGroupPanelButton = () => {
const selectedConvoKey = useSelectedConversationKey();
const isGroup = useIsClosedGroup(selectedConvoKey);
const username = useConversationUsername(selectedConvoKey) || selectedConvoKey;
const isMessageRequestShown = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequestShown = useIsMessageRequestOverlayShown();
const isKickedFromGroup = useIsKickedFromGroup(selectedConvoKey) || false;
const lastMessageIsLeaveError = useLastMessageIsLeaveError(selectedConvoKey);
const isPublic = useIsPublic(selectedConvoKey);
const isGroupDestroyed = useIsGroupDestroyed(selectedConvoKey);

const showItem = showLeaveGroupItem({
isGroup,
isKickedFromGroup,
isMessageRequestShown,
lastMessageIsLeaveError,
isPublic,
isGroupDestroyed,
});

if (!selectedConvoKey || !showItem) {
Expand Down
5 changes: 2 additions & 3 deletions ts/components/leftpane/conversation-list-item/MessageItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import classNames from 'classnames';
import { isEmpty } from 'lodash';

import { useSelector } from 'react-redux';
import { useConvoIdFromContext } from '../../../contexts/ConvoIdContext';
import {
useHasUnread,
Expand All @@ -12,7 +11,7 @@ import {
} from '../../../hooks/useParamSelector';
import { LastMessageStatusType } from '../../../state/ducks/types';
import { useIsSearching } from '../../../state/selectors/search';
import { getIsMessageRequestOverlayShown } from '../../../state/selectors/section';
import { useIsMessageRequestOverlayShown } from '../../../state/selectors/section';
import { assertUnreachable } from '../../../types/sqlSharedTypes';
import { TypingAnimation } from '../../conversation/TypingAnimation';
import { MessageBody } from '../../conversation/message/message-content/MessageBody';
Expand All @@ -26,7 +25,7 @@ export const MessageItem = () => {

const hasUnread = useHasUnread(conversationId);
const isConvoTyping = useIsTyping(conversationId);
const isMessageRequest = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequest = useIsMessageRequestOverlayShown();
const isOutgoingRequest = useIsOutgoingRequest(conversationId);

const isSearching = useIsSearching();
Expand Down
4 changes: 2 additions & 2 deletions ts/components/menu/ConversationListItemContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { useConvoIdFromContext } from '../../contexts/ConvoIdContext';
import { useIsPinned, useIsPrivate, useIsPrivateAndFriend } from '../../hooks/useParamSelector';
import { ConvoHub } from '../../session/conversations';
import {
getIsMessageRequestOverlayShown,
getIsMessageSection,
useIsMessageRequestOverlayShown,
} from '../../state/selectors/section';
import { useIsSearching } from '../../state/selectors/search';
import { SessionContextMenuContainer } from '../SessionContextMenuContainer';
Expand Down Expand Up @@ -91,7 +91,7 @@ export const PinConversationMenuItem = (): JSX.Element | null => {
const isPrivateAndFriend = useIsPrivateAndFriend(conversationId);
const isPrivate = useIsPrivate(conversationId);
const isPinned = useIsPinned(conversationId);
const isMessageRequest = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequest = useIsMessageRequestOverlayShown();

if (isMessagesSection && !isMessageRequest && (!isPrivate || (isPrivate && isPrivateAndFriend))) {
const conversation = ConvoHub.use().get(conversationId);
Expand Down
8 changes: 4 additions & 4 deletions ts/components/menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ import {
} from '../../state/ducks/modalDialog';
import { useConversationIdOrigin } from '../../state/selectors/conversations';
import {
getIsMessageRequestOverlayShown,
getIsMessageSection,
useIsMessageRequestOverlayShown,
} from '../../state/selectors/section';
import { useSelectedConversationKey } from '../../state/selectors/selectedConversation';
import type { LocalizerToken } from '../../types/localizer';
Expand Down Expand Up @@ -84,7 +84,7 @@ export const MarkConversationUnreadMenuItem = (): JSX.Element | null => {
const isMessagesSection = useSelector(getIsMessageSection);
const isPrivate = useIsPrivate(conversationId);
const isPrivateAndFriend = useIsPrivateAndFriend(conversationId);
const isMessageRequestShown = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequestShown = useIsMessageRequestOverlayShown();

if (
isMessagesSection &&
Expand Down Expand Up @@ -358,7 +358,7 @@ export const ChangeNicknameMenuItem = () => {
*/
export const DeleteMessagesMenuItem = () => {
const convoId = useConvoIdFromContext();
const isMessageRequestShown = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequestShown = useIsMessageRequestOverlayShown();

if (!convoId || isMessageRequestShown) {
return null;
Expand Down Expand Up @@ -495,7 +495,7 @@ export const NotificationForConvoMenuItem = (): JSX.Element | null => {

const isFriend = useIsPrivateAndFriend(convoId);
const isPrivate = useIsPrivate(convoId);
const isMessageRequestShown = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequestShown = useIsMessageRequestOverlayShown();

if (
!convoId ||
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useSelector } from 'react-redux';
import { useConvoIdFromContext } from '../../../../contexts/ConvoIdContext';
import {
useConversationUsername,
useIsKickedFromGroup,
useIsClosedGroup,
useLastMessageIsLeaveError,
useIsPublic,
useIsGroupDestroyed,
} from '../../../../hooks/useParamSelector';
import { showLeaveGroupByConvoId } from '../../../../interactions/conversationInteractions';
import { showDeleteGroupByConvoId } from '../../../../interactions/conversationInteractions';
import { PubKey } from '../../../../session/types';
import { getIsMessageRequestOverlayShown } from '../../../../state/selectors/section';
import { useIsMessageRequestOverlayShown } from '../../../../state/selectors/section';
import { ItemWithDataTestId } from '../MenuItemWithDataTestId';
import { showDeleteGroupItem } from './guard';
import { Localizer } from '../../../basic/Localizer';
Expand All @@ -17,15 +17,17 @@ export const DeleteGroupMenuItem = () => {
const convoId = useConvoIdFromContext();
const username = useConversationUsername(convoId) || convoId;
const isGroup = useIsClosedGroup(convoId);
const isMessageRequestShown = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequestShown = useIsMessageRequestOverlayShown();
const isKickedFromGroup = useIsKickedFromGroup(convoId) || false;
const lastMessageIsLeaveError = useLastMessageIsLeaveError(convoId);
const isPublic = useIsPublic(convoId);
const isGroupDestroyed = useIsGroupDestroyed(convoId);

const showLeave = showDeleteGroupItem({
isGroup,
isKickedFromGroup,
isMessageRequestShown,
lastMessageIsLeaveError,
isPublic,
isGroupDestroyed,
});

if (!showLeave) {
Expand All @@ -37,7 +39,7 @@ export const DeleteGroupMenuItem = () => {
return (
<ItemWithDataTestId
onClick={() => {
void showLeaveGroupByConvoId(convoId, username);
void showDeleteGroupByConvoId(convoId, username);
}}
>
<Localizer token={token} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import { useSelector } from 'react-redux';
import { useConvoIdFromContext } from '../../../../contexts/ConvoIdContext';
import {
useConversationUsername,
useIsKickedFromGroup,
useIsClosedGroup,
useLastMessageIsLeaveError,
useIsPublic,
useIsGroupDestroyed,
} from '../../../../hooks/useParamSelector';
import { showLeaveGroupByConvoId } from '../../../../interactions/conversationInteractions';
import { getIsMessageRequestOverlayShown } from '../../../../state/selectors/section';
import { useIsMessageRequestOverlayShown } from '../../../../state/selectors/section';
import { ItemWithDataTestId } from '../MenuItemWithDataTestId';
import { showLeaveGroupItem } from './guard';
import { Localizer } from '../../../basic/Localizer';

export const LeaveGroupMenuItem = () => {
const convoId = useConvoIdFromContext();
const isGroup = useIsClosedGroup(convoId);
const isPublic = useIsPublic(convoId);
const username = useConversationUsername(convoId) || convoId;
const isMessageRequestShown = useSelector(getIsMessageRequestOverlayShown);
const isMessageRequestShown = useIsMessageRequestOverlayShown();
const isKickedFromGroup = useIsKickedFromGroup(convoId) || false;
const lastMessageIsLeaveError = useLastMessageIsLeaveError(convoId);
const isGroupDestroyed = useIsGroupDestroyed(convoId);

const showLeave = showLeaveGroupItem({
isGroup,
isMessageRequestShown,
isKickedFromGroup,
lastMessageIsLeaveError,
isPublic,
isGroupDestroyed,
});

if (!showLeave) {
Expand Down
49 changes: 30 additions & 19 deletions ts/components/menu/items/LeaveAndDeleteGroup/guard.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,53 @@
function sharedEnabled({
isGroup,
isPublic,
isMessageRequestShown,
}: Pick<Parameters<typeof showLeaveGroupItem>[0], 'isGroup' | 'isMessageRequestShown'>) {
return isGroup && !isMessageRequestShown;
}: Pick<
Parameters<typeof showLeaveGroupItem>[0],
'isGroup' | 'isMessageRequestShown' | 'isPublic'
>) {
return isGroup && !isMessageRequestShown && !isPublic;
}

/**
* We can try leave a group if
* - we are an admin of the group (that group would be marked as destroyed on delete)
* and
* - we are a **not kicked** member (if we are kicked without knowing about it and try to leave, we will silently remove the group)
*
* Note: Those actions are hidden if the group is a group request (as we have other buttons to accept/decline a group request).
*
* Note: If we fail to leave the group but that error is retryable, we will keep the group displaying the "leave" option.
*/
export function showLeaveGroupItem({
isGroup,
isPublic,
isKickedFromGroup,
isMessageRequestShown,
lastMessageIsLeaveError,
isGroupDestroyed,
}: {
isGroup: boolean;
isPublic: boolean;
isMessageRequestShown: boolean;
lastMessageIsLeaveError: boolean;
isKickedFromGroup: boolean;
isGroupDestroyed: boolean;
}) {
// we can't try to leave the group if we were kicked from it, or if we've already tried to (lastMessageIsLeaveError is true)
return (
sharedEnabled({ isGroup, isMessageRequestShown }) &&
sharedEnabled({ isGroup, isMessageRequestShown, isPublic }) &&
!isKickedFromGroup &&
!lastMessageIsLeaveError
!isGroupDestroyed
);
}

export function showDeleteGroupItem({
isGroup,
isKickedFromGroup,
isMessageRequestShown,
lastMessageIsLeaveError,
}: {
/**
* We can try to delete a group only if the `showLeaveGroupItem` returns false.
* Note: those actions are hidden if the group is a group request (as we have other buttons to accept/decline a group request)
*/
export function showDeleteGroupItem(args: {
isGroup: boolean;
isPublic: boolean;
isMessageRequestShown: boolean;
lastMessageIsLeaveError: boolean;
isKickedFromGroup: boolean;
isGroupDestroyed: boolean;
}) {
return (
sharedEnabled({ isGroup, isMessageRequestShown }) &&
(isKickedFromGroup || lastMessageIsLeaveError)
);
return sharedEnabled(args) && !showLeaveGroupItem(args);
}
4 changes: 2 additions & 2 deletions ts/data/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ async function removeMessage(id: string): Promise<void> {
// it needs to delete all associated on-disk files along with the database delete.
if (message) {
await channels.removeMessage(id);
await message.cleanup();
await message.cleanup(true);
}
}

Expand Down Expand Up @@ -554,7 +554,7 @@ async function removeAllMessagesInConversation(conversationId: string): Promise<
for (let index = 0; index < messages.length; index++) {
const message = messages.at(index);
// eslint-disable-next-line no-await-in-loop
await message.cleanup();
await message.cleanup(false); // not triggering UI updates, as we remove them from the store just below
}
window.log.info(
`removeAllMessagesInConversation messages.cleanup() ${conversationId} took ${
Expand Down
2 changes: 1 addition & 1 deletion ts/hooks/useParamSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export function useIsKickedFromGroup(convoId?: string) {
export function useIsGroupDestroyed(convoId?: string) {
const libIsDestroyed = useLibGroupDestroyed(convoId);
if (convoId && PubKey.is03Pubkey(convoId)) {
return libIsDestroyed;
return !!libIsDestroyed;
}
return false;
}
Expand Down
Loading
Loading