Update header actions/add hiddenFromConversationSearch
This commit is contained in:
parent
00250e535c
commit
af4ad55c68
11 changed files with 204 additions and 27 deletions
|
@ -368,11 +368,11 @@
|
||||||
"description": "Undoes Archive Conversation action, and moves archived conversation back to the main conversation list"
|
"description": "Undoes Archive Conversation action, and moves archived conversation back to the main conversation list"
|
||||||
},
|
},
|
||||||
"icu:pinConversation": {
|
"icu:pinConversation": {
|
||||||
"messageformat": "Pin Chat",
|
"messageformat": "Pin chat",
|
||||||
"description": "Shown in menu for conversation, and pins the conversation to the top of the conversation list"
|
"description": "Shown in menu for conversation, and pins the conversation to the top of the conversation list"
|
||||||
},
|
},
|
||||||
"icu:unpinConversation": {
|
"icu:unpinConversation": {
|
||||||
"messageformat": "Unpin Chat",
|
"messageformat": "Unpin chat",
|
||||||
"description": "Undoes Archive Conversation action, and unpins the conversation from the top of the conversation list"
|
"description": "Undoes Archive Conversation action, and unpins the conversation from the top of the conversation list"
|
||||||
},
|
},
|
||||||
"icu:pinnedConversationsFull": {
|
"icu:pinnedConversationsFull": {
|
||||||
|
@ -1282,7 +1282,35 @@
|
||||||
},
|
},
|
||||||
"icu:deleteConversationConfirmation": {
|
"icu:deleteConversationConfirmation": {
|
||||||
"messageformat": "Permanently delete this chat?",
|
"messageformat": "Permanently delete this chat?",
|
||||||
"description": "Confirmation dialog text that asks the user if they really wish to delete the conversation. Answer buttons use the strings 'ok' and 'cancel'. The deletion is permanent, i.e. it cannot be undone."
|
"description": "(deleted 06/27/2023) Confirmation dialog text that asks the user if they really wish to delete the conversation. Answer buttons use the strings 'ok' and 'cancel'. The deletion is permanent, i.e. it cannot be undone."
|
||||||
|
},
|
||||||
|
"icu:ConversationHeader__DeleteMessagesConfirmation__title": {
|
||||||
|
"messageformat": "Delete chat?",
|
||||||
|
"description": "Conversation Header > Delete Action > Delete Messages Confirmation Modal > Title"
|
||||||
|
},
|
||||||
|
"icu:ConversationHeader__DeleteMessagesConfirmation__description": {
|
||||||
|
"messageformat": "This chat will be deleted from this device.",
|
||||||
|
"description": "Conversation Header > Delete Action > Delete Messages Confirmation Modal > Description"
|
||||||
|
},
|
||||||
|
"icu:ConversationHeader__ContextMenu__LeaveGroupAction__title": {
|
||||||
|
"messageformat": "Leave group",
|
||||||
|
"description": "This is a button to leave a group"
|
||||||
|
},
|
||||||
|
"icu:ConversationHeader__LeaveGroupConfirmation__title": {
|
||||||
|
"messageformat": "Do you really want to leave?",
|
||||||
|
"description": "Conversation Header > Leave Group Action > Leave Group Confirmation Modal > Title"
|
||||||
|
},
|
||||||
|
"icu:ConversationHeader__LeaveGroupConfirmation__description": {
|
||||||
|
"messageformat": "You will no longer be able to send or receive messages in this group.",
|
||||||
|
"description": "Conversation Header > Leave Group Action > Leave Group Confirmation Modal > Description"
|
||||||
|
},
|
||||||
|
"icu:ConversationHeader__LeaveGroupConfirmation__confirmButton": {
|
||||||
|
"messageformat": "Leave",
|
||||||
|
"description": "Conversation Header > Leave Group Action > Leave Group Confirmation Modal > Confirm Button"
|
||||||
|
},
|
||||||
|
"icu:ConversationHeader__CannotLeaveGroupBecauseYouAreLastAdminAlert__description": {
|
||||||
|
"messageformat": "Before you leave, you must choose at least one new admin for this group.",
|
||||||
|
"description": "Conversation Header > Leave Group Action > Cannot Leave Group Because You Are Last Admin Alert > Description"
|
||||||
},
|
},
|
||||||
"icu:sessionEnded": {
|
"icu:sessionEnded": {
|
||||||
"messageformat": "Secure session reset",
|
"messageformat": "Secure session reset",
|
||||||
|
|
|
@ -32,6 +32,7 @@ type ItemsType = Array<{
|
||||||
const commonProps = {
|
const commonProps = {
|
||||||
...getDefaultConversation(),
|
...getDefaultConversation(),
|
||||||
|
|
||||||
|
cannotLeaveBecauseYouAreLastAdmin: false,
|
||||||
showBackButton: false,
|
showBackButton: false,
|
||||||
outgoingCallButtonStyle: OutgoingCallButtonStyle.Both,
|
outgoingCallButtonStyle: OutgoingCallButtonStyle.Both,
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ const commonProps = {
|
||||||
|
|
||||||
setDisappearingMessages: action('setDisappearingMessages'),
|
setDisappearingMessages: action('setDisappearingMessages'),
|
||||||
destroyMessages: action('destroyMessages'),
|
destroyMessages: action('destroyMessages'),
|
||||||
|
leaveGroup: action('leaveGroup'),
|
||||||
onOutgoingAudioCallInConversation: action(
|
onOutgoingAudioCallInConversation: action(
|
||||||
'onOutgoingAudioCallInConversation'
|
'onOutgoingAudioCallInConversation'
|
||||||
),
|
),
|
||||||
|
|
|
@ -39,6 +39,7 @@ import {
|
||||||
} from '../../hooks/useKeyboardShortcuts';
|
} from '../../hooks/useKeyboardShortcuts';
|
||||||
import { PanelType } from '../../types/Panels';
|
import { PanelType } from '../../types/Panels';
|
||||||
import { UserText } from '../UserText';
|
import { UserText } from '../UserText';
|
||||||
|
import { Alert } from '../Alert';
|
||||||
|
|
||||||
export enum OutgoingCallButtonStyle {
|
export enum OutgoingCallButtonStyle {
|
||||||
None,
|
None,
|
||||||
|
@ -49,6 +50,7 @@ export enum OutgoingCallButtonStyle {
|
||||||
|
|
||||||
export type PropsDataType = {
|
export type PropsDataType = {
|
||||||
badge?: BadgeType;
|
badge?: BadgeType;
|
||||||
|
cannotLeaveBecauseYouAreLastAdmin: boolean;
|
||||||
conversationTitle?: string;
|
conversationTitle?: string;
|
||||||
hasStories?: HasStories;
|
hasStories?: HasStories;
|
||||||
isMissingMandatoryProfileSharing?: boolean;
|
isMissingMandatoryProfileSharing?: boolean;
|
||||||
|
@ -86,6 +88,7 @@ export type PropsDataType = {
|
||||||
|
|
||||||
export type PropsActionsType = {
|
export type PropsActionsType = {
|
||||||
destroyMessages: (conversationId: string) => void;
|
destroyMessages: (conversationId: string) => void;
|
||||||
|
leaveGroup: (conversationId: string) => void;
|
||||||
onArchive: (conversationId: string) => void;
|
onArchive: (conversationId: string) => void;
|
||||||
onMarkUnread: (conversationId: string) => void;
|
onMarkUnread: (conversationId: string) => void;
|
||||||
toggleSelectMode: (on: boolean) => void;
|
toggleSelectMode: (on: boolean) => void;
|
||||||
|
@ -119,6 +122,8 @@ enum ModalState {
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
hasDeleteMessagesConfirmation: boolean;
|
hasDeleteMessagesConfirmation: boolean;
|
||||||
|
hasLeaveGroupConfirmation: boolean;
|
||||||
|
hasCannotLeaveGroupBecauseYouAreLastAdminAlert: boolean;
|
||||||
isNarrow: boolean;
|
isNarrow: boolean;
|
||||||
modalState: ModalState;
|
modalState: ModalState;
|
||||||
};
|
};
|
||||||
|
@ -139,6 +144,8 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
hasDeleteMessagesConfirmation: false,
|
hasDeleteMessagesConfirmation: false,
|
||||||
|
hasLeaveGroupConfirmation: false,
|
||||||
|
hasCannotLeaveGroupBecauseYouAreLastAdminAlert: false,
|
||||||
isNarrow: false,
|
isNarrow: false,
|
||||||
modalState: ModalState.NothingOpen,
|
modalState: ModalState.NothingOpen,
|
||||||
};
|
};
|
||||||
|
@ -338,6 +345,7 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
const {
|
const {
|
||||||
acceptedMessageRequest,
|
acceptedMessageRequest,
|
||||||
canChangeTimer,
|
canChangeTimer,
|
||||||
|
cannotLeaveBecauseYouAreLastAdmin,
|
||||||
expireTimer,
|
expireTimer,
|
||||||
groupVersion,
|
groupVersion,
|
||||||
i18n,
|
i18n,
|
||||||
|
@ -532,11 +540,6 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
{i18n('icu:viewRecentMedia')}
|
{i18n('icu:viewRecentMedia')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem divider />
|
<MenuItem divider />
|
||||||
{!markedUnread ? (
|
|
||||||
<MenuItem onClick={() => onMarkUnread(id)}>
|
|
||||||
{i18n('icu:markUnread')}
|
|
||||||
</MenuItem>
|
|
||||||
) : null}
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
toggleSelectMode(true);
|
toggleSelectMode(true);
|
||||||
|
@ -544,6 +547,21 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
>
|
>
|
||||||
{i18n('icu:ConversationHeader__menu__selectMessages')}
|
{i18n('icu:ConversationHeader__menu__selectMessages')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem divider />
|
||||||
|
{!markedUnread ? (
|
||||||
|
<MenuItem onClick={() => onMarkUnread(id)}>
|
||||||
|
{i18n('icu:markUnread')}
|
||||||
|
</MenuItem>
|
||||||
|
) : null}
|
||||||
|
{isPinned ? (
|
||||||
|
<MenuItem onClick={() => setPinned(id, false)}>
|
||||||
|
{i18n('icu:unpinConversation')}
|
||||||
|
</MenuItem>
|
||||||
|
) : (
|
||||||
|
<MenuItem onClick={() => setPinned(id, true)}>
|
||||||
|
{i18n('icu:pinConversation')}
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
{isArchived ? (
|
{isArchived ? (
|
||||||
<MenuItem onClick={() => onMoveToInbox(id)}>
|
<MenuItem onClick={() => onMoveToInbox(id)}>
|
||||||
{i18n('icu:moveConversationToInbox')}
|
{i18n('icu:moveConversationToInbox')}
|
||||||
|
@ -558,20 +576,28 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
>
|
>
|
||||||
{i18n('icu:deleteMessages')}
|
{i18n('icu:deleteMessages')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{isPinned ? (
|
{isGroup && (
|
||||||
<MenuItem onClick={() => setPinned(id, false)}>
|
<MenuItem
|
||||||
{i18n('icu:unpinConversation')}
|
onClick={() => {
|
||||||
</MenuItem>
|
if (cannotLeaveBecauseYouAreLastAdmin) {
|
||||||
) : (
|
this.setState({
|
||||||
<MenuItem onClick={() => setPinned(id, true)}>
|
hasCannotLeaveGroupBecauseYouAreLastAdminAlert: true,
|
||||||
{i18n('icu:pinConversation')}
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({ hasLeaveGroupConfirmation: true });
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n(
|
||||||
|
'icu:ConversationHeader__ContextMenu__LeaveGroupAction__title'
|
||||||
|
)}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderConfirmationDialog(): ReactNode {
|
private renderDeleteMessagesConfirmationDialog(): ReactNode {
|
||||||
const { hasDeleteMessagesConfirmation } = this.state;
|
const { hasDeleteMessagesConfirmation } = this.state;
|
||||||
const { destroyMessages, i18n, id } = this.props;
|
const { destroyMessages, i18n, id } = this.props;
|
||||||
|
|
||||||
|
@ -582,6 +608,9 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
return (
|
return (
|
||||||
<ConfirmationDialog
|
<ConfirmationDialog
|
||||||
dialogName="ConversationHeader.destroyMessages"
|
dialogName="ConversationHeader.destroyMessages"
|
||||||
|
title={i18n(
|
||||||
|
'icu:ConversationHeader__DeleteMessagesConfirmation__title'
|
||||||
|
)}
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
action: () => {
|
action: () => {
|
||||||
|
@ -597,11 +626,79 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
this.setState({ hasDeleteMessagesConfirmation: false });
|
this.setState({ hasDeleteMessagesConfirmation: false });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n('icu:deleteConversationConfirmation')}
|
{i18n(
|
||||||
|
'icu:ConversationHeader__DeleteMessagesConfirmation__description'
|
||||||
|
)}
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderLeaveGroupConfirmationDialog(): ReactNode {
|
||||||
|
const { hasLeaveGroupConfirmation } = this.state;
|
||||||
|
const { cannotLeaveBecauseYouAreLastAdmin, leaveGroup, i18n, id } =
|
||||||
|
this.props;
|
||||||
|
|
||||||
|
if (!hasLeaveGroupConfirmation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationDialog
|
||||||
|
dialogName="ConversationHeader.leaveGroup"
|
||||||
|
title={i18n('icu:ConversationHeader__LeaveGroupConfirmation__title')}
|
||||||
|
actions={[
|
||||||
|
{
|
||||||
|
disabled: cannotLeaveBecauseYouAreLastAdmin,
|
||||||
|
action: () => {
|
||||||
|
this.setState({ hasLeaveGroupConfirmation: false });
|
||||||
|
if (!cannotLeaveBecauseYouAreLastAdmin) {
|
||||||
|
leaveGroup(id);
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
hasLeaveGroupConfirmation: false,
|
||||||
|
hasCannotLeaveGroupBecauseYouAreLastAdminAlert: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: 'negative',
|
||||||
|
text: i18n(
|
||||||
|
'icu:ConversationHeader__LeaveGroupConfirmation__confirmButton'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
i18n={i18n}
|
||||||
|
onClose={() => {
|
||||||
|
this.setState({ hasLeaveGroupConfirmation: false });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n('icu:ConversationHeader__LeaveGroupConfirmation__description')}
|
||||||
|
</ConfirmationDialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderCannotLeaveGroupBecauseYouAreLastAdminAlert() {
|
||||||
|
const { hasCannotLeaveGroupBecauseYouAreLastAdminAlert } = this.state;
|
||||||
|
const { i18n } = this.props;
|
||||||
|
|
||||||
|
if (!hasCannotLeaveGroupBecauseYouAreLastAdminAlert) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
i18n={i18n}
|
||||||
|
body={i18n(
|
||||||
|
'icu:ConversationHeader__CannotLeaveGroupBecauseYouAreLastAdminAlert__description'
|
||||||
|
)}
|
||||||
|
onClose={() => {
|
||||||
|
this.setState({
|
||||||
|
hasCannotLeaveGroupBecauseYouAreLastAdminAlert: false,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private renderHeader(): ReactNode {
|
private renderHeader(): ReactNode {
|
||||||
const { conversationTitle, groupVersion, pushPanelForConversation, type } =
|
const { conversationTitle, groupVersion, pushPanelForConversation, type } =
|
||||||
this.props;
|
this.props;
|
||||||
|
@ -711,7 +808,9 @@ export class ConversationHeader extends React.Component<PropsType, StateType> {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{modalNode}
|
{modalNode}
|
||||||
{this.renderConfirmationDialog()}
|
{this.renderDeleteMessagesConfirmationDialog()}
|
||||||
|
{this.renderLeaveGroupConfirmationDialog()}
|
||||||
|
{this.renderCannotLeaveGroupBecauseYouAreLastAdminAlert()}
|
||||||
<Measure
|
<Measure
|
||||||
bounds
|
bounds
|
||||||
onResize={({ bounds }) => {
|
onResize={({ bounds }) => {
|
||||||
|
|
|
@ -133,6 +133,20 @@ type ActionProps = {
|
||||||
|
|
||||||
export type Props = StateProps & ActionProps;
|
export type Props = StateProps & ActionProps;
|
||||||
|
|
||||||
|
export function getCannotLeaveBecauseYouAreLastAdmin(
|
||||||
|
memberships: ReadonlyArray<GroupV2Membership>,
|
||||||
|
isAdmin: boolean
|
||||||
|
): boolean {
|
||||||
|
const otherMemberships = memberships.filter(({ member }) => !member.isMe);
|
||||||
|
const isJustMe = otherMemberships.length === 0;
|
||||||
|
const isAnyoneElseAnAdmin = otherMemberships.some(
|
||||||
|
membership => membership.isAdmin
|
||||||
|
);
|
||||||
|
const cannotLeaveBecauseYouAreLastAdmin =
|
||||||
|
isAdmin && !isJustMe && !isAnyoneElseAnAdmin;
|
||||||
|
return cannotLeaveBecauseYouAreLastAdmin;
|
||||||
|
}
|
||||||
|
|
||||||
export function ConversationDetails({
|
export function ConversationDetails({
|
||||||
acceptConversation,
|
acceptConversation,
|
||||||
addMembersToGroup,
|
addMembersToGroup,
|
||||||
|
@ -196,13 +210,8 @@ export function ConversationDetails({
|
||||||
const invitesCount =
|
const invitesCount =
|
||||||
pendingMemberships.length + pendingApprovalMemberships.length;
|
pendingMemberships.length + pendingApprovalMemberships.length;
|
||||||
|
|
||||||
const otherMemberships = memberships.filter(({ member }) => !member.isMe);
|
|
||||||
const isJustMe = otherMemberships.length === 0;
|
|
||||||
const isAnyoneElseAnAdmin = otherMemberships.some(
|
|
||||||
membership => membership.isAdmin
|
|
||||||
);
|
|
||||||
const cannotLeaveBecauseYouAreLastAdmin =
|
const cannotLeaveBecauseYouAreLastAdmin =
|
||||||
isAdmin && !isJustMe && !isAnyoneElseAnAdmin;
|
getCannotLeaveBecauseYouAreLastAdmin(memberships, isAdmin);
|
||||||
|
|
||||||
const onCloseModal = useCallback(() => {
|
const onCloseModal = useCallback(() => {
|
||||||
setModalState(ModalState.NothingOpen);
|
setModalState(ModalState.NothingOpen);
|
||||||
|
|
1
ts/model-types.d.ts
vendored
1
ts/model-types.d.ts
vendored
|
@ -313,6 +313,7 @@ export type ConversationAttributesType = {
|
||||||
draftBodyRanges?: DraftBodyRanges;
|
draftBodyRanges?: DraftBodyRanges;
|
||||||
draftTimestamp?: number | null;
|
draftTimestamp?: number | null;
|
||||||
hideStory?: boolean;
|
hideStory?: boolean;
|
||||||
|
hiddenFromConversationSearch?: boolean;
|
||||||
inbox_position?: number;
|
inbox_position?: number;
|
||||||
// When contact is removed - it is initially placed into `justNotification`
|
// When contact is removed - it is initially placed into `justNotification`
|
||||||
// removal stage. In this stage user can still send messages (which will
|
// removal stage. In this stage user can still send messages (which will
|
||||||
|
|
|
@ -361,6 +361,7 @@ export class ConversationModel extends window.Backbone
|
||||||
this.unset('tokens');
|
this.unset('tokens');
|
||||||
|
|
||||||
this.on('change:members change:membersV2', this.fetchContacts);
|
this.on('change:members change:membersV2', this.fetchContacts);
|
||||||
|
this.on('change:isArchived', this.onArchiveChange);
|
||||||
|
|
||||||
this.typingRefreshTimer = null;
|
this.typingRefreshTimer = null;
|
||||||
this.typingPauseTimer = null;
|
this.typingPauseTimer = null;
|
||||||
|
@ -4196,6 +4197,17 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onArchiveChange() {
|
||||||
|
const isArchived = this.get('isArchived');
|
||||||
|
if (isArchived) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.get('hiddenFromConversationSearch')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.set('hiddenFromConversationSearch', false);
|
||||||
|
}
|
||||||
|
|
||||||
setMarkedUnread(markedUnread: boolean): void {
|
setMarkedUnread(markedUnread: boolean): void {
|
||||||
const previousMarkedUnread = this.get('markedUnread');
|
const previousMarkedUnread = this.get('markedUnread');
|
||||||
|
|
||||||
|
@ -4892,6 +4904,9 @@ export class ConversationModel extends window.Backbone
|
||||||
active_at: null,
|
active_at: null,
|
||||||
pendingUniversalTimer: undefined,
|
pendingUniversalTimer: undefined,
|
||||||
});
|
});
|
||||||
|
if (isGroup(this.attributes)) {
|
||||||
|
this.set('hiddenFromConversationSearch', true);
|
||||||
|
}
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
window.Signal.Data.updateConversation(this.attributes);
|
||||||
|
|
||||||
await window.Signal.Data.removeAllMessagesInConversation(this.id, {
|
await window.Signal.Data.removeAllMessagesInConversation(this.id, {
|
||||||
|
|
|
@ -242,6 +242,7 @@ export type ConversationType = ReadonlyDeep<
|
||||||
customColorId?: string;
|
customColorId?: string;
|
||||||
discoveredUnregisteredAt?: number;
|
discoveredUnregisteredAt?: number;
|
||||||
hideStory?: boolean;
|
hideStory?: boolean;
|
||||||
|
hiddenFromConversationSearch?: boolean;
|
||||||
isArchived?: boolean;
|
isArchived?: boolean;
|
||||||
isBlocked?: boolean;
|
isBlocked?: boolean;
|
||||||
removalStage?: 'justNotification' | 'messageRequest';
|
removalStage?: 'justNotification' | 'messageRequest';
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
} from '../../components/conversation/ConversationHeader';
|
} from '../../components/conversation/ConversationHeader';
|
||||||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||||
import {
|
import {
|
||||||
|
getConversationByUuidSelector,
|
||||||
getConversationSelector,
|
getConversationSelector,
|
||||||
getConversationTitle,
|
getConversationTitle,
|
||||||
isMissingRequiredProfileSharing,
|
isMissingRequiredProfileSharing,
|
||||||
|
@ -35,6 +36,8 @@ import { strictAssert } from '../../util/assert';
|
||||||
import { isSignalConversation } from '../../util/isSignalConversation';
|
import { isSignalConversation } from '../../util/isSignalConversation';
|
||||||
import { useSearchActions } from '../ducks/search';
|
import { useSearchActions } from '../ducks/search';
|
||||||
import { useStoriesActions } from '../ducks/stories';
|
import { useStoriesActions } from '../ducks/stories';
|
||||||
|
import { getCannotLeaveBecauseYouAreLastAdmin } from '../../components/conversation/conversation-details/ConversationDetails';
|
||||||
|
import { getGroupMemberships } from '../../util/getGroupMemberships';
|
||||||
|
|
||||||
export type OwnProps = {
|
export type OwnProps = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -79,6 +82,7 @@ export function SmartConversationHeader({ id }: OwnProps): JSX.Element {
|
||||||
if (!conversation) {
|
if (!conversation) {
|
||||||
throw new Error('Could not find conversation');
|
throw new Error('Could not find conversation');
|
||||||
}
|
}
|
||||||
|
const isAdmin = Boolean(conversation.areWeAdmin);
|
||||||
const hasStoriesSelector = useSelector(getHasStoriesSelector);
|
const hasStoriesSelector = useSelector(getHasStoriesSelector);
|
||||||
const hasStories = hasStoriesSelector(id);
|
const hasStories = hasStoriesSelector(id);
|
||||||
|
|
||||||
|
@ -97,6 +101,7 @@ export function SmartConversationHeader({ id }: OwnProps): JSX.Element {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
destroyMessages,
|
destroyMessages,
|
||||||
|
leaveGroup,
|
||||||
onArchive,
|
onArchive,
|
||||||
onMarkUnread,
|
onMarkUnread,
|
||||||
onMoveToInbox,
|
onMoveToInbox,
|
||||||
|
@ -114,6 +119,14 @@ export function SmartConversationHeader({ id }: OwnProps): JSX.Element {
|
||||||
const { searchInConversation } = useSearchActions();
|
const { searchInConversation } = useSearchActions();
|
||||||
const { viewUserStories } = useStoriesActions();
|
const { viewUserStories } = useStoriesActions();
|
||||||
|
|
||||||
|
const conversationByUuidSelector = useSelector(getConversationByUuidSelector);
|
||||||
|
const groupMemberships = getGroupMemberships(
|
||||||
|
conversation,
|
||||||
|
conversationByUuidSelector
|
||||||
|
);
|
||||||
|
const cannotLeaveBecauseYouAreLastAdmin =
|
||||||
|
getCannotLeaveBecauseYouAreLastAdmin(groupMemberships.memberships, isAdmin);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConversationHeader
|
<ConversationHeader
|
||||||
{...pick(conversation, [
|
{...pick(conversation, [
|
||||||
|
@ -141,6 +154,7 @@ export function SmartConversationHeader({ id }: OwnProps): JSX.Element {
|
||||||
'unblurredAvatarPath',
|
'unblurredAvatarPath',
|
||||||
])}
|
])}
|
||||||
badge={badge}
|
badge={badge}
|
||||||
|
cannotLeaveBecauseYouAreLastAdmin={cannotLeaveBecauseYouAreLastAdmin}
|
||||||
conversationTitle={conversationTitle}
|
conversationTitle={conversationTitle}
|
||||||
destroyMessages={destroyMessages}
|
destroyMessages={destroyMessages}
|
||||||
hasStories={hasStories}
|
hasStories={hasStories}
|
||||||
|
@ -151,6 +165,7 @@ export function SmartConversationHeader({ id }: OwnProps): JSX.Element {
|
||||||
)}
|
)}
|
||||||
isSignalConversation={isSignalConversation(conversation)}
|
isSignalConversation={isSignalConversation(conversation)}
|
||||||
isSMSOnly={isConversationSMSOnly(conversation)}
|
isSMSOnly={isConversationSMSOnly(conversation)}
|
||||||
|
leaveGroup={leaveGroup}
|
||||||
onArchive={onArchive}
|
onArchive={onArchive}
|
||||||
onMarkUnread={onMarkUnread}
|
onMarkUnread={onMarkUnread}
|
||||||
onMoveToInbox={onMoveToInbox}
|
onMoveToInbox={onMoveToInbox}
|
||||||
|
|
|
@ -70,7 +70,7 @@ describe('storage service', function needsName() {
|
||||||
await moreButton.click();
|
await moreButton.click();
|
||||||
|
|
||||||
const pinButton = conversationStack.locator(
|
const pinButton = conversationStack.locator(
|
||||||
'.react-contextmenu-item >> "Pin Chat"'
|
'.react-contextmenu-item >> "Pin chat"'
|
||||||
);
|
);
|
||||||
await pinButton.click();
|
await pinButton.click();
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ describe('storage service', function needsName() {
|
||||||
await moreButton.click();
|
await moreButton.click();
|
||||||
|
|
||||||
const pinButton = conversationStack.locator(
|
const pinButton = conversationStack.locator(
|
||||||
'.react-contextmenu-item >> "Pin Chat"'
|
'.react-contextmenu-item >> "Pin chat"'
|
||||||
);
|
);
|
||||||
await pinButton.click();
|
await pinButton.click();
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,10 @@ function searchConversations(
|
||||||
|
|
||||||
const phoneNumber = parseAndFormatPhoneNumber(searchTerm, regionCode);
|
const phoneNumber = parseAndFormatPhoneNumber(searchTerm, regionCode);
|
||||||
|
|
||||||
|
const currentConversations = conversations.filter(conversation => {
|
||||||
|
return !conversation.left && !conversation.hiddenFromConversationSearch;
|
||||||
|
});
|
||||||
|
|
||||||
// Escape the search term
|
// Escape the search term
|
||||||
let extendedSearchTerm = searchTerm;
|
let extendedSearchTerm = searchTerm;
|
||||||
|
|
||||||
|
@ -98,7 +102,7 @@ function searchConversations(
|
||||||
extendedSearchTerm += ` | ${phoneNumber.e164}`;
|
extendedSearchTerm += ` | ${phoneNumber.e164}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = getCachedFuseIndex(conversations, FUSE_OPTIONS);
|
const index = getCachedFuseIndex(currentConversations, FUSE_OPTIONS);
|
||||||
|
|
||||||
return index.search(extendedSearchTerm);
|
return index.search(extendedSearchTerm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,6 +173,9 @@ export function getConversation(model: ConversationModel): ConversationType {
|
||||||
groupId: attributes.groupId,
|
groupId: attributes.groupId,
|
||||||
groupLink: buildGroupLink(attributes),
|
groupLink: buildGroupLink(attributes),
|
||||||
hideStory: Boolean(attributes.hideStory),
|
hideStory: Boolean(attributes.hideStory),
|
||||||
|
hiddenFromConversationSearch: Boolean(
|
||||||
|
attributes.hiddenFromConversationSearch
|
||||||
|
),
|
||||||
inboxPosition,
|
inboxPosition,
|
||||||
isArchived: attributes.isArchived,
|
isArchived: attributes.isArchived,
|
||||||
isBlocked: isBlocked(attributes),
|
isBlocked: isBlocked(attributes),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue