Permissions popup context iso
This commit is contained in:
parent
f3715411c6
commit
7b5faa1cc1
49 changed files with 562 additions and 506 deletions
|
@ -1,8 +1,9 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
|
||||
export type PropsType = {
|
||||
closeAbout: () => unknown;
|
||||
|
@ -17,21 +18,7 @@ export const About = ({
|
|||
environment,
|
||||
version,
|
||||
}: PropsType): JSX.Element => {
|
||||
useEffect(() => {
|
||||
const handler = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
closeAbout();
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', handler);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handler);
|
||||
};
|
||||
}, [closeAbout]);
|
||||
useEscapeHandling(closeAbout);
|
||||
|
||||
return (
|
||||
<div className="About">
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Inbox } from './Inbox';
|
|||
import { Install } from './Install';
|
||||
import { StandaloneRegistration } from './StandaloneRegistration';
|
||||
import { ThemeType } from '../types/Util';
|
||||
import { usePageVisibility } from '../util/hooks';
|
||||
import { usePageVisibility } from '../hooks/usePageVisibility';
|
||||
|
||||
type PropsType = {
|
||||
appView: AppViewType;
|
||||
|
|
|
@ -5,7 +5,7 @@ import * as React from 'react';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { Avatar, Props as AvatarProps } from './Avatar';
|
||||
import { useRestoreFocus } from '../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../hooks/useRestoreFocus';
|
||||
|
||||
import { LocalizerType } from '../types/Util';
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
import { AvatarColors } from '../types/Colors';
|
||||
import { SetRendererCanvasType } from '../state/ducks/calling';
|
||||
import { useGetCallingFrameBuffer } from '../calling/useGetCallingFrameBuffer';
|
||||
import { usePageVisibility } from '../util/hooks';
|
||||
import { usePageVisibility } from '../hooks/usePageVisibility';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
import { nonRenderedRemoteParticipant } from '../util/ringrtc/nonRenderedRemoteParticipant';
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import React, {
|
|||
ReactNode,
|
||||
} from 'react';
|
||||
|
||||
import { usePrevious } from '../util/hooks';
|
||||
import { usePrevious } from '../hooks/usePrevious';
|
||||
import { scrollToBottom } from '../util/scrollToBottom';
|
||||
|
||||
type PropsType = {
|
||||
|
|
|
@ -22,7 +22,7 @@ import { Avatar, AvatarSize } from './Avatar';
|
|||
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||
import { Intl } from './Intl';
|
||||
import { ContactName } from './conversation/ContactName';
|
||||
import { useIntersectionObserver } from '../util/hooks';
|
||||
import { useIntersectionObserver } from '../hooks/useIntersectionObserver';
|
||||
import { MAX_FRAME_SIZE } from '../calling/constants';
|
||||
|
||||
const MAX_TIME_TO_SHOW_STALE_VIDEO_FRAMES = 5000;
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
} from '../types/Calling';
|
||||
import { useGetCallingFrameBuffer } from '../calling/useGetCallingFrameBuffer';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { usePageVisibility } from '../util/hooks';
|
||||
import { usePageVisibility } from '../hooks/usePageVisibility';
|
||||
import { nonRenderedRemoteParticipant } from '../util/ringrtc/nonRenderedRemoteParticipant';
|
||||
import * as log from '../logging/log';
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ import {
|
|||
|
||||
import * as OS from '../OS';
|
||||
import { LocalizerType, ScrollBehavior } from '../types/Util';
|
||||
import { usePrevious } from '../util/hooks';
|
||||
import { usePrevious } from '../hooks/usePrevious';
|
||||
import { missingCaseError } from '../util/missingCaseError';
|
||||
|
||||
import { ConversationList } from './ConversationList';
|
||||
|
|
|
@ -21,7 +21,7 @@ import { IMAGE_PNG, isImage, isVideo } from '../types/MIME';
|
|||
import { LocalizerType } from '../types/Util';
|
||||
import { MediaItemType, MessageAttributesType } from '../types/MediaItem';
|
||||
import { formatDuration } from '../util/formatDuration';
|
||||
import { useRestoreFocus } from '../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../hooks/useRestoreFocus';
|
||||
import * as log from '../logging/log';
|
||||
|
||||
export type PropsType = {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { LocalizerType } from '../types/Util';
|
|||
import { ModalHost } from './ModalHost';
|
||||
import { Theme } from '../util/theme';
|
||||
import { getClassNamesFor } from '../util/getClassNamesFor';
|
||||
import { useHasWrapped } from '../util/hooks';
|
||||
import { useHasWrapped } from '../hooks/useHasWrapped';
|
||||
|
||||
type PropsType = {
|
||||
children: ReactNode;
|
||||
|
|
|
@ -5,6 +5,7 @@ import React, { useEffect } from 'react';
|
|||
import classNames from 'classnames';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Theme, themeClassName } from '../util/theme';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
|
||||
export type PropsType = {
|
||||
readonly noMouseClose?: boolean;
|
||||
|
@ -30,25 +31,7 @@ export const ModalHost = React.memo(
|
|||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
if (onEscape) {
|
||||
onEscape();
|
||||
} else {
|
||||
onClose();
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', handler);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handler);
|
||||
};
|
||||
}, [onEscape, onClose]);
|
||||
useEscapeHandling(onEscape || onClose);
|
||||
|
||||
// This makes it easier to write dialogs to be hosted here; they won't have to worry
|
||||
// as much about preventing propagation of mouse events.
|
||||
|
|
51
ts/components/PermissionsPopup.tsx
Normal file
51
ts/components/PermissionsPopup.tsx
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
|
||||
export type PropsType = {
|
||||
i18n: LocalizerType;
|
||||
message: string;
|
||||
onAccept: () => unknown;
|
||||
onClose: () => unknown;
|
||||
};
|
||||
|
||||
function focusRef(el: HTMLElement | null) {
|
||||
if (el) {
|
||||
el.focus();
|
||||
}
|
||||
}
|
||||
|
||||
export const PermissionsPopup = ({
|
||||
i18n,
|
||||
message,
|
||||
onAccept,
|
||||
onClose,
|
||||
}: PropsType): JSX.Element => {
|
||||
useEscapeHandling(onClose);
|
||||
|
||||
return (
|
||||
<div className="PermissionsPopup">
|
||||
<div className="PermissionsPopup__body">{message}</div>
|
||||
<div className="PermissionsPopup__buttons">
|
||||
<Button
|
||||
onClick={onClose}
|
||||
ref={focusRef}
|
||||
variant={ButtonVariant.Secondary}
|
||||
>
|
||||
{i18n('confirmation-dialog--Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onAccept}
|
||||
ref={focusRef}
|
||||
variant={ButtonVariant.Primary}
|
||||
>
|
||||
{i18n('allowAccess')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -33,6 +33,7 @@ import {
|
|||
DEFAULT_DURATIONS_SET,
|
||||
format as formatExpirationTimer,
|
||||
} from '../util/expirationTimer';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
|
||||
type CheckboxChangeHandlerType = (value: boolean) => unknown;
|
||||
type SelectChangeHandlerType<T = string | number> = (value: T) => unknown;
|
||||
|
@ -280,21 +281,7 @@ export const Preferences = ({
|
|||
doneRendering();
|
||||
}, [doneRendering]);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
closeSettings();
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', handler);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handler);
|
||||
};
|
||||
}, [closeSettings]);
|
||||
useEscapeHandling(closeSettings);
|
||||
|
||||
const onZoomSelectChange = useCallback(
|
||||
(value: string) => {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useRestoreFocus } from '../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../hooks/useRestoreFocus';
|
||||
import { LocalizerType } from '../types/Util';
|
||||
|
||||
export type Props = {
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
getCallingIcon,
|
||||
getCallingNotificationText,
|
||||
} from '../../util/callingNotification';
|
||||
import { usePrevious } from '../../util/hooks';
|
||||
import { usePrevious } from '../../hooks/usePrevious';
|
||||
import { missingCaseError } from '../../util/missingCaseError';
|
||||
import { Tooltip, TooltipPlacement } from '../Tooltip';
|
||||
import type { TimelineItemType } from './TimelineItem';
|
||||
|
|
|
@ -6,7 +6,7 @@ import classNames from 'classnames';
|
|||
|
||||
import { Modal } from '../Modal';
|
||||
|
||||
import { useRestoreFocus } from '../../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Modal } from '../Modal';
|
|||
import { Intl } from '../Intl';
|
||||
import { Emojify } from './Emojify';
|
||||
|
||||
import { useRestoreFocus } from '../../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import * as React from 'react';
|
||||
import { convertShortName } from '../emoji/lib';
|
||||
import { Props as EmojiPickerProps } from '../emoji/EmojiPicker';
|
||||
import { useRestoreFocus } from '../../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
import { canCustomizePreferredReactions } from '../../util/canCustomizePreferredReactions';
|
||||
import {
|
||||
|
|
|
@ -7,9 +7,10 @@ import classNames from 'classnames';
|
|||
import { ContactName } from './ContactName';
|
||||
import { Avatar, Props as AvatarProps } from '../Avatar';
|
||||
import { Emoji } from '../emoji/Emoji';
|
||||
import { useRestoreFocus } from '../../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
import { ConversationType } from '../../state/ducks/conversations';
|
||||
import { emojiToData, EmojiData } from '../emoji/lib';
|
||||
import { useEscapeHandling } from '../../hooks/useEscapeHandling';
|
||||
|
||||
export type Reaction = {
|
||||
emoji: string;
|
||||
|
@ -124,20 +125,9 @@ export const ReactionViewer = React.forwardRef<HTMLDivElement, Props>(
|
|||
selectedReactionCategory,
|
||||
setSelectedReactionCategory,
|
||||
] = React.useState(pickedReaction || 'all');
|
||||
|
||||
// Handle escape key
|
||||
React.useEffect(() => {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
if (onClose && e.key === 'Escape') {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', handler);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handler);
|
||||
};
|
||||
}, [onClose]);
|
||||
useEscapeHandling(onClose);
|
||||
|
||||
// Focus first button and restore focus on unmount
|
||||
const [focusRef] = useRestoreFocus();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useRestoreFocus } from '../../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
import { StickerPackType, StickerType } from '../../state/ducks/stickers';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { ConfirmationDialog } from '../ConfirmationDialog';
|
|||
import { LocalizerType } from '../../types/Util';
|
||||
import { StickerPackType } from '../../state/ducks/stickers';
|
||||
import { Spinner } from '../Spinner';
|
||||
import { useRestoreFocus } from '../../util/hooks/useRestoreFocus';
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
|
||||
export type OwnProps = {
|
||||
readonly onClose: () => unknown;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue