mirror of
https://github.com/lux-tel/session-desktop.git
synced 2026-10-30 20:33:24 +00:00
115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
import { useRef } from 'react';
|
|
import { useSelector } from 'react-redux';
|
|
import useKey from 'react-use/lib/useKey';
|
|
import { getAppDispatch } from '../../../state/dispatch';
|
|
|
|
import { deleteMessagesForX } from '../../../interactions/conversations/unsendingInteractions';
|
|
import { resetSelectedMessageIds } from '../../../state/ducks/conversations';
|
|
import { getSelectedMessageIds } from '../../../state/selectors/conversations';
|
|
import {
|
|
useSelectedConversationKey,
|
|
useSelectedIsPublic,
|
|
} from '../../../state/selectors/selectedConversation';
|
|
import {
|
|
SessionButton,
|
|
SessionButtonColor,
|
|
SessionButtonShape,
|
|
SessionButtonType,
|
|
} from '../../basic/SessionButton';
|
|
import { SessionFocusTrap } from '../../SessionFocusTrap';
|
|
import { tr } from '../../../localization/localeTools';
|
|
import { SessionLucideIconButton } from '../../icon/SessionIconButton';
|
|
import { LUCIDE_ICONS_UNICODE } from '../../icon/lucide';
|
|
|
|
export const SelectionOverlay = () => {
|
|
const selectedMessageIds = useSelector(getSelectedMessageIds);
|
|
const selectedConversationKey = useSelectedConversationKey();
|
|
const isPublic = useSelectedIsPublic();
|
|
const dispatch = getAppDispatch();
|
|
const ref = useRef(null);
|
|
|
|
function onCloseOverlay() {
|
|
dispatch(resetSelectedMessageIds());
|
|
}
|
|
/**
|
|
* This is a duplicate with the onKeyDown of SessionConversation.
|
|
* At some point we'll make a global handler to deal with the key presses
|
|
* and handle them depending on what is visible, but that's not part of this PR
|
|
*/
|
|
useKey(
|
|
shouldProcess => {
|
|
return (
|
|
shouldProcess.code === 'Escape' ||
|
|
shouldProcess.code === 'Backspace' ||
|
|
shouldProcess.code === 'Delete'
|
|
);
|
|
},
|
|
event => {
|
|
const selectionMode = !!selectedMessageIds.length;
|
|
switch (event.key) {
|
|
case 'Escape':
|
|
if (selectionMode) {
|
|
onCloseOverlay();
|
|
}
|
|
return true;
|
|
case 'Backspace':
|
|
case 'Delete':
|
|
if (selectionMode && selectedConversationKey) {
|
|
void deleteMessagesForX(selectedMessageIds, selectedConversationKey, isPublic);
|
|
}
|
|
return true;
|
|
default:
|
|
}
|
|
return false;
|
|
}
|
|
);
|
|
|
|
// `enforceDeleteServerSide` should check for message statuses too, but when we have multiple selected,
|
|
// some might be sent and some in an error state. We default to trying to delete all of them server side first,
|
|
// which might fail. If that fails, the user will need to do a delete for all the ones sent already, and a manual delete
|
|
// for each ones which is in an error state.
|
|
const enforceDeleteServerSide = isPublic;
|
|
|
|
return (
|
|
<SessionFocusTrap
|
|
initialFocus={() => ref.current}
|
|
containerDivStyle={{
|
|
position: 'absolute',
|
|
display: 'flex',
|
|
left: '0px',
|
|
right: '0px',
|
|
padding: '0px var(--margins-md)',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
height: 'var(--main-view-header-height)',
|
|
background: 'var(--background-primary-color)',
|
|
}}
|
|
>
|
|
<SessionLucideIconButton
|
|
unicode={LUCIDE_ICONS_UNICODE.X}
|
|
iconColor="var(--chat-buttons-icon-color)"
|
|
iconSize="large"
|
|
onClick={onCloseOverlay}
|
|
aria-label={tr('close')}
|
|
ref={ref}
|
|
/>
|
|
|
|
<SessionButton
|
|
buttonColor={SessionButtonColor.Danger}
|
|
buttonShape={SessionButtonShape.Square}
|
|
buttonType={SessionButtonType.Solid}
|
|
text={tr('delete')}
|
|
onClick={async () => {
|
|
if (selectedConversationKey) {
|
|
await deleteMessagesForX(
|
|
selectedMessageIds,
|
|
selectedConversationKey,
|
|
enforceDeleteServerSide
|
|
);
|
|
}
|
|
}}
|
|
/>
|
|
</SessionFocusTrap>
|
|
);
|
|
};
|