Skip to content

Commit 8a87b9c

Browse files
committed
chore: made all of the message types selectable
1 parent 61b5bf4 commit 8a87b9c

File tree

57 files changed

+1492
-1464
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1492
-1464
lines changed

ts/components/SessionToastContainer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Slide, ToastContainer, ToastContainerProps } from 'react-toastify';
22
import styled from 'styled-components';
3+
import { isTestIntegration } from '../shared/env_vars';
34

45
// NOTE: https://styled-components.com/docs/faqs#how-can-i-override-styles-with-higher-specificity
56
const StyledToastContainer = styled(ToastContainer)`
@@ -40,7 +41,7 @@ export const SessionToastContainer = () => {
4041
return (
4142
<WrappedToastContainer
4243
position="bottom-right"
43-
autoClose={5000}
44+
autoClose={isTestIntegration() ? 1000 : 5000}
4445
hideProgressBar={true}
4546
newestOnTop={true}
4647
closeOnClick={true}

ts/components/SessionTooltip.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
useRef,
66
useState,
77
useEffect,
8+
type Dispatch,
89
} from 'react';
910
import styled, { type CSSProperties } from 'styled-components';
1011
import useDebounce from 'react-use/lib/useDebounce';
@@ -47,6 +48,11 @@ export type PopoverTriggerPosition = {
4748
offsetX?: number;
4849
};
4950

51+
export type WithPopoverPosition = { triggerPosition: PopoverTriggerPosition | null };
52+
export type WithSetPopoverPosition = {
53+
setTriggerPosition: Dispatch<PopoverTriggerPosition | null>;
54+
};
55+
5056
export const defaultTriggerPos: PopoverTriggerPosition = { x: 0, y: 0, width: 0, height: 0 };
5157

5258
export function getTriggerPositionFromBoundingClientRect(rect: DOMRect): PopoverTriggerPosition {

ts/components/basic/SessionRadioGroup.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type SessionRadioItems = Array<{
1010
label: string;
1111
inputDataTestId: SessionDataTestId;
1212
labelDataTestId: SessionDataTestId;
13+
disabled?: boolean;
1314
}>;
1415

1516
interface Props {
@@ -50,6 +51,7 @@ export const SessionRadioGroup = (props: Props) => {
5051
label={item.label}
5152
active={itemIsActive}
5253
value={item.value}
54+
disabled={item.disabled}
5355
inputDataTestId={item.inputDataTestId}
5456
labelDataTestId={item.labelDataTestId}
5557
inputName={group}

ts/components/conversation/SessionConversation.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,10 @@ export class SessionConversation extends Component<Props, State> {
226226
if (msg.body.replace(/\s/g, '').includes(recoveryPhrase.replace(/\s/g, ''))) {
227227
window.inboxStore?.dispatch(
228228
updateConfirmModal({
229-
title: tr('warning'),
229+
title: { token: 'warning' },
230230
i18nMessage: { token: 'recoveryPasswordWarningSendDescription' },
231231
okTheme: SessionButtonColor.Danger,
232-
okText: tr('send'),
232+
okText: { token: 'send' },
233233
onClickOk: () => {
234234
void sendAndScroll();
235235
},

ts/components/conversation/SessionEmojiReactBarPopover.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import { MessageReactBar } from './message/message-content/MessageReactBar';
66
import { THEME_GLOBALS } from '../../themes/globals';
77
import { SessionEmojiPanelPopover } from './SessionEmojiPanelPopover';
88
import { closeContextMenus } from '../../util/contextMenu';
9-
import { useMessageInteractions } from '../../hooks/useMessageInteractions';
109
import { useFocusedMessageId } from '../../state/selectors/conversations';
10+
import { useReactToMessage } from '../../hooks/useMessageInteractions';
1111

1212
export function SessionEmojiReactBarPopover({
1313
messageId,
@@ -25,7 +25,7 @@ export function SessionEmojiReactBarPopover({
2525
const emojiPanelRef = useRef<HTMLDivElement>(null);
2626
const emojiReactionBarRef = useRef<HTMLDivElement>(null);
2727
const [showEmojiPanel, setShowEmojiPanel] = useState<boolean>(false);
28-
const { reactToMessage } = useMessageInteractions(messageId);
28+
const reactToMessage = useReactToMessage(messageId);
2929
const focusedMessageId = useFocusedMessageId();
3030

3131
const closeEmojiPanel = () => {
@@ -41,7 +41,7 @@ export function SessionEmojiReactBarPopover({
4141
const onEmojiClick = async (args: any) => {
4242
const emoji = args.native ?? args;
4343
closeEmojiPanel();
44-
await reactToMessage(emoji);
44+
await reactToMessage?.(emoji);
4545
};
4646

4747
useClickAway(emojiPanelRef, () => {

ts/components/conversation/SessionMessagesList.tsx

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useLayoutEffect, useState, type FC } from 'react';
1+
import { useLayoutEffect, useState } from 'react';
22
import { useSelector } from 'react-redux';
33

44
import useKey from 'react-use/lib/useKey';
@@ -7,43 +7,23 @@ import {
77
getOldTopMessageId,
88
getSortedMessagesTypesOfSelectedConversation,
99
useFocusedMessageId,
10-
type MessagePropsType,
1110
} from '../../state/selectors/conversations';
1211
import { useSelectedConversationKey } from '../../state/selectors/selectedConversation';
1312
import { MessageDateBreak } from './message/message-item/DateBreak';
14-
import { CommunityInvitation } from './message/message-item/CommunityInvitation';
15-
import { GroupUpdateMessage } from './message/message-item/GroupUpdateMessage';
16-
import { Message } from './message/message-item/Message';
17-
import { MessageRequestResponse } from './message/message-item/MessageRequestResponse';
18-
import { CallNotification } from './message/message-item/notification-bubble/CallNotification';
1913

2014
import { IsDetailMessageViewContext } from '../../contexts/isDetailViewContext';
2115
import { SessionLastSeenIndicator } from './SessionLastSeenIndicator';
22-
import { TimerNotification } from './TimerNotification';
23-
import { DataExtractionNotification } from './message/message-item/DataExtractionNotification';
24-
import { InteractionNotification } from './message/message-item/InteractionNotification';
25-
import type { WithMessageId } from '../../session/types/with';
2616
import { useKeyboardShortcut } from '../../hooks/useKeyboardShortcut';
2717
import { KbdShortcut } from '../../util/keyboardShortcuts';
28-
import { useMessageInteractions } from '../../hooks/useMessageInteractions';
18+
import { GenericReadableMessage } from './message/message-item/GenericReadableMessage';
19+
import { useCopyText, useReply } from '../../hooks/useMessageInteractions';
2920

3021
function isNotTextboxEvent(e: KeyboardEvent) {
3122
return (e?.target as any)?.type === undefined;
3223
}
3324

3425
let previousRenderedConvo: string | undefined;
3526

36-
const componentForMessageType: Record<MessagePropsType, FC<WithMessageId>> = {
37-
'group-notification': GroupUpdateMessage,
38-
'group-invitation': CommunityInvitation,
39-
'message-request-response': MessageRequestResponse,
40-
'data-extraction': DataExtractionNotification,
41-
'timer-notification': TimerNotification,
42-
'call-notification': CallNotification,
43-
'interaction-notification': InteractionNotification,
44-
'regular-message': Message,
45-
};
46-
4727
export const SessionMessagesList = (props: {
4828
scrollAfterLoadMore: (
4929
messageIdToScrollTo: string,
@@ -60,8 +40,9 @@ export const SessionMessagesList = (props: {
6040
const [didScroll, setDidScroll] = useState(false);
6141
const oldTopMessageId = useSelector(getOldTopMessageId);
6242
const oldBottomMessageId = useSelector(getOldBottomMessageId);
63-
const focusedMessageId = useFocusedMessageId();
64-
const { reply, copyText } = useMessageInteractions(focusedMessageId);
43+
const focusedMessageId = useFocusedMessageId() ?? undefined;
44+
const reply = useReply(focusedMessageId);
45+
const copyText = useCopyText(focusedMessageId);
6546

6647
useKeyboardShortcut({ shortcut: KbdShortcut.messageToggleReply, handler: reply, scopeId: 'all' });
6748
useKeyboardShortcut({ shortcut: KbdShortcut.messageCopyText, handler: copyText, scopeId: 'all' });
@@ -113,8 +94,6 @@ export const SessionMessagesList = (props: {
11394
.map(messageProps => {
11495
const { messageId } = messageProps;
11596

116-
const ComponentToRender = componentForMessageType[messageProps.message.messageType];
117-
11897
const unreadIndicator = messageProps.showUnreadIndicator ? (
11998
<SessionLastSeenIndicator
12099
key={'unread-indicator'}
@@ -136,7 +115,7 @@ export const SessionMessagesList = (props: {
136115
return [
137116
dateBreak,
138117
unreadIndicator,
139-
<ComponentToRender key={messageId} messageId={messageId} />,
118+
<GenericReadableMessage key={messageId} messageId={messageId} />,
140119
];
141120
})
142121
// TODO: check if we reverse this upstream, we might be reversing twice

ts/components/conversation/TimerNotification.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { Localizer } from '../basic/Localizer';
2424
import { SessionButtonColor } from '../basic/SessionButton';
2525
import { SessionIcon } from '../icon';
2626
import { getTimerNotificationStr } from '../../models/timerNotifications';
27-
import type { WithMessageId } from '../../session/types/with';
27+
import type { WithContextMenuId, WithMessageId } from '../../session/types/with';
2828
import {
2929
useMessageAuthor,
3030
useMessageAuthorIsUs,
@@ -34,6 +34,7 @@ import {
3434
useMessageExpirationUpdateTimespanText,
3535
} from '../../state/selectors';
3636
import { tr, type TrArgs } from '../../localization/localeTools';
37+
import type { WithPopoverPosition, WithSetPopoverPosition } from '../SessionTooltip';
3738

3839
const FollowSettingButton = styled.button`
3940
color: var(--primary-color);
@@ -65,13 +66,11 @@ function useFollowSettingsButtonClick({ messageId }: WithMessageId) {
6566
disappearing_messages_type: localizedMode,
6667
};
6768

68-
const okText = tr('confirm');
69-
7069
dispatch(
7170
updateConfirmModal({
72-
title: tr('disappearingMessagesFollowSetting'),
71+
title: { token: 'disappearingMessagesFollowSetting' },
7372
i18nMessage,
74-
okText,
73+
okText: { token: 'confirm' },
7574
okTheme: SessionButtonColor.Danger,
7675
onClickOk: async () => {
7776
if (!selectedConvoKey) {
@@ -149,7 +148,9 @@ const FollowSettingsButton = ({ messageId }: WithMessageId) => {
149148
);
150149
};
151150

152-
export const TimerNotification = (props: WithMessageId) => {
151+
export const TimerNotification = (
152+
props: WithMessageId & WithPopoverPosition & WithSetPopoverPosition & WithContextMenuId
153+
) => {
153154
const { messageId } = props;
154155
const timespanSeconds = useMessageExpirationUpdateTimespanSeconds(messageId);
155156
const expirationMode = useMessageExpirationUpdateMode(messageId);
@@ -177,8 +178,9 @@ export const TimerNotification = (props: WithMessageId) => {
177178

178179
return (
179180
<ExpirableReadableMessage
181+
contextMenuId={props.contextMenuId}
182+
setTriggerPosition={props.setTriggerPosition}
180183
messageId={messageId}
181-
isControlMessage={true}
182184
key={`readable-message-${messageId}`}
183185
dataTestId={'disappear-control-message'}
184186
>

ts/components/conversation/header/ConversationHeader.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,10 @@ function useShowRecreateModal() {
111111
(name: string, members: Array<PubkeyType>) => {
112112
dispatch(
113113
updateConfirmModal({
114-
title: tr('recreateGroup'),
114+
title: { token: 'recreateGroup' },
115115
i18nMessage: { token: 'legacyGroupChatHistory' },
116-
okText: tr('theContinue'),
117-
cancelText: tr('cancel'),
116+
okText: { token: 'theContinue' },
117+
cancelText: { token: 'cancel' },
118118
okTheme: SessionButtonColor.Danger,
119119
onClickOk: () => {
120120
openCreateGroup(name, members);

ts/components/conversation/header/ConversationHeaderSelectionOverlay.tsx

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,9 @@ import { useSelector } from 'react-redux';
33
import useKey from 'react-use/lib/useKey';
44
import { getAppDispatch } from '../../../state/dispatch';
55

6-
import { deleteMessagesForX } from '../../../interactions/conversations/unsendingInteractions';
76
import { resetSelectedMessageIds } from '../../../state/ducks/conversations';
87
import { getSelectedMessageIds } from '../../../state/selectors/conversations';
9-
import {
10-
useSelectedConversationKey,
11-
useSelectedIsPublic,
12-
} from '../../../state/selectors/selectedConversation';
8+
import { useSelectedConversationKey } from '../../../state/selectors/selectedConversation';
139
import {
1410
SessionButton,
1511
SessionButtonColor,
@@ -21,11 +17,12 @@ import { tr } from '../../../localization/localeTools';
2117
import { SessionLucideIconButton } from '../../icon/SessionIconButton';
2218
import { LUCIDE_ICONS_UNICODE } from '../../icon/lucide';
2319
import { isBackspace, isDeleteKey, isEscapeKey } from '../../../util/keyboardShortcuts';
20+
import { useDeleteMessagesCb } from '../../menuAndSettingsHooks/useDeleteMessagesCb';
2421

2522
export const SelectionOverlay = () => {
2623
const selectedMessageIds = useSelector(getSelectedMessageIds);
2724
const selectedConversationKey = useSelectedConversationKey();
28-
const isPublic = useSelectedIsPublic();
25+
const deleteMessagesCb = useDeleteMessagesCb(selectedConversationKey);
2926
const dispatch = getAppDispatch();
3027
const ref = useRef(null);
3128

@@ -51,8 +48,8 @@ export const SelectionOverlay = () => {
5148
return true;
5249
case 'Backspace':
5350
case 'Delete':
54-
if (selectionMode && selectedConversationKey) {
55-
void deleteMessagesForX(selectedMessageIds, selectedConversationKey, isPublic);
51+
if (selectionMode) {
52+
void deleteMessagesCb?.(selectedMessageIds);
5653
}
5754
return true;
5855
default:
@@ -61,12 +58,6 @@ export const SelectionOverlay = () => {
6158
}
6259
);
6360

64-
// `enforceDeleteServerSide` should check for message statuses too, but when we have multiple selected,
65-
// some might be sent and some in an error state. We default to trying to delete all of them server side first,
66-
// which might fail. If that fails, the user will need to do a delete for all the ones sent already, and a manual delete
67-
// for each ones which is in an error state.
68-
const enforceDeleteServerSide = isPublic;
69-
7061
return (
7162
<SessionFocusTrap
7263
initialFocus={() => ref.current}
@@ -96,14 +87,8 @@ export const SelectionOverlay = () => {
9687
buttonShape={SessionButtonShape.Square}
9788
buttonType={SessionButtonType.Solid}
9889
text={tr('delete')}
99-
onClick={async () => {
100-
if (selectedConversationKey) {
101-
await deleteMessagesForX(
102-
selectedMessageIds,
103-
selectedConversationKey,
104-
enforceDeleteServerSide
105-
);
106-
}
90+
onClick={() => {
91+
void deleteMessagesCb?.(selectedMessageIds);
10792
}}
10893
/>
10994
</SessionFocusTrap>

ts/components/conversation/message/message-content/ClickToTrustSender.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const ClickToTrustSender = (props: { messageId: string }) => {
4444
const convo = ConvoHub.use().get(sender);
4545
window.inboxStore?.dispatch(
4646
updateConfirmModal({
47-
title: tr('attachmentsAutoDownloadModalTitle'),
47+
title: { token: 'attachmentsAutoDownloadModalTitle' },
4848
i18nMessage: {
4949
token: 'attachmentsAutoDownloadModalDescription',
5050
conversation_name: convo.getNicknameOrRealUsernameOrPlaceholder(),
@@ -114,8 +114,8 @@ export const ClickToTrustSender = (props: { messageId: string }) => {
114114
onClickClose: () => {
115115
window.inboxStore?.dispatch(updateConfirmModal(null));
116116
},
117-
okText: tr('yes'),
118-
cancelText: tr('no'),
117+
okText: { token: 'yes' },
118+
cancelText: { token: 'no' },
119119
})
120120
);
121121
};

0 commit comments

Comments
 (0)