One lightbox at a time; proper dismiss of "read more" screen; proper in-progress draft HEIC images
This commit is contained in:
parent
01b015680b
commit
9ca9f743c3
7 changed files with 26 additions and 37 deletions
|
@ -22,6 +22,7 @@ import { IMAGE_PNG, isImage, isVideo } from '../types/MIME';
|
||||||
import { LocalizerType } from '../types/Util';
|
import { LocalizerType } from '../types/Util';
|
||||||
import { MediaItemType, MessageAttributesType } from '../types/MediaItem';
|
import { MediaItemType, MessageAttributesType } from '../types/MediaItem';
|
||||||
import { formatDuration } from '../util/formatDuration';
|
import { formatDuration } from '../util/formatDuration';
|
||||||
|
import { useRestoreFocus } from '../util/hooks/useRestoreFocus';
|
||||||
|
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
|
@ -55,20 +56,13 @@ export function Lightbox({
|
||||||
initialSelectedIndex
|
initialSelectedIndex
|
||||||
);
|
);
|
||||||
|
|
||||||
const [previousFocus, setPreviousFocus] = useState<HTMLElement | undefined>();
|
|
||||||
const [videoElement, setVideoElement] = useState<HTMLVideoElement | null>(
|
const [videoElement, setVideoElement] = useState<HTMLVideoElement | null>(
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [videoTime, setVideoTime] = useState<number | undefined>();
|
const [videoTime, setVideoTime] = useState<number | undefined>();
|
||||||
const [zoomed, setZoomed] = useState(false);
|
const [zoomed, setZoomed] = useState(false);
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const focusRef = useRef<HTMLDivElement | null>(null);
|
const [focusRef] = useRestoreFocus();
|
||||||
|
|
||||||
const restorePreviousFocus = useCallback(() => {
|
|
||||||
if (previousFocus && previousFocus.focus) {
|
|
||||||
previousFocus.focus();
|
|
||||||
}
|
|
||||||
}, [previousFocus]);
|
|
||||||
|
|
||||||
const onPrevious = useCallback(() => {
|
const onPrevious = useCallback(() => {
|
||||||
setSelectedIndex(prevSelectedIndex => Math.max(prevSelectedIndex - 1, 0));
|
setSelectedIndex(prevSelectedIndex => Math.max(prevSelectedIndex - 1, 0));
|
||||||
|
@ -167,18 +161,6 @@ export function Lightbox({
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!previousFocus) {
|
|
||||||
setPreviousFocus(document.activeElement as HTMLElement);
|
|
||||||
}
|
|
||||||
}, [previousFocus]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
restorePreviousFocus();
|
|
||||||
};
|
|
||||||
}, [restorePreviousFocus]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const useCapture = true;
|
const useCapture = true;
|
||||||
document.addEventListener('keydown', onKeyDown, useCapture);
|
document.addEventListener('keydown', onKeyDown, useCapture);
|
||||||
|
@ -191,10 +173,6 @@ export function Lightbox({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
playVideo();
|
playVideo();
|
||||||
|
|
||||||
if (focusRef && focusRef.current) {
|
|
||||||
focusRef.current.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (videoElement && isViewOnce) {
|
if (videoElement && isViewOnce) {
|
||||||
videoElement.addEventListener('timeupdate', onTimeUpdate);
|
videoElement.addEventListener('timeupdate', onTimeUpdate);
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,9 @@ export function Modal({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalHost noMouseClose={noMouseClose} onClose={onClose} theme={theme}>
|
<ModalHost noMouseClose={noMouseClose} onClose={onClose} theme={theme}>
|
||||||
|
{/* We don't want the click event to propagate to its container node. */}
|
||||||
|
{/* eslint-disable jsx-a11y/no-static-element-interactions */}
|
||||||
|
{/* eslint-disable jsx-a11y/click-events-have-key-events */}
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
getClassName(''),
|
getClassName(''),
|
||||||
|
@ -63,7 +66,12 @@ export function Modal({
|
||||||
hasStickyButtons && getClassName('--sticky-buttons')
|
hasStickyButtons && getClassName('--sticky-buttons')
|
||||||
)}
|
)}
|
||||||
ref={modalRef}
|
ref={modalRef}
|
||||||
|
onClick={event => {
|
||||||
|
event.stopPropagation();
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
|
{/* eslint-enable jsx-a11y/no-static-element-interactions */}
|
||||||
|
{/* eslint-enable jsx-a11y/click-events-have-key-events */}
|
||||||
{hasHeader && (
|
{hasHeader && (
|
||||||
<div className={getClassName('__header')}>
|
<div className={getClassName('__header')}>
|
||||||
{hasXButton && (
|
{hasXButton && (
|
||||||
|
|
|
@ -66,7 +66,7 @@ export const AttachmentList = ({
|
||||||
const isImage = isImageAttachment(attachment);
|
const isImage = isImageAttachment(attachment);
|
||||||
const isVideo = isVideoAttachment(attachment);
|
const isVideo = isVideoAttachment(attachment);
|
||||||
|
|
||||||
if (isImage || isVideo) {
|
if (isImage || isVideo || attachment.pending) {
|
||||||
const clickCallback =
|
const clickCallback =
|
||||||
attachments.length > 1 ? onClickAttachment : undefined;
|
attachments.length > 1 ? onClickAttachment : undefined;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ export function shouldUseFullSizeLinkPreviewImage({
|
||||||
isStickerPack,
|
isStickerPack,
|
||||||
image,
|
image,
|
||||||
}: Readonly<LinkPreviewType>): boolean {
|
}: Readonly<LinkPreviewType>): boolean {
|
||||||
if (isStickerPack || !isImageAttachment(image)) {
|
if (isStickerPack || !image || !isImageAttachment(image)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -626,9 +626,7 @@ export function isImage(attachments?: Array<AttachmentType>): boolean {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isImageAttachment(
|
export function isImageAttachment(attachment?: AttachmentType): boolean {
|
||||||
attachment?: AttachmentType
|
|
||||||
): attachment is AttachmentType {
|
|
||||||
return Boolean(
|
return Boolean(
|
||||||
attachment &&
|
attachment &&
|
||||||
attachment.contentType &&
|
attachment.contentType &&
|
||||||
|
@ -640,7 +638,9 @@ export function canBeTranscoded(
|
||||||
attachment?: AttachmentType
|
attachment?: AttachmentType
|
||||||
): attachment is AttachmentType {
|
): attachment is AttachmentType {
|
||||||
return Boolean(
|
return Boolean(
|
||||||
isImageAttachment(attachment) && !MIME.isGif(attachment.contentType)
|
attachment &&
|
||||||
|
isImageAttachment(attachment) &&
|
||||||
|
!MIME.isGif(attachment.contentType)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13295,13 +13295,6 @@
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2021-08-23T18:39:37.081Z"
|
"updated": "2021-08-23T18:39:37.081Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"rule": "React-useRef",
|
|
||||||
"path": "ts/components/Lightbox.tsx",
|
|
||||||
"line": " const focusRef = useRef<HTMLDivElement | null>(null);",
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2021-08-23T18:39:37.081Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"rule": "React-createRef",
|
"rule": "React-createRef",
|
||||||
"path": "ts/components/MainHeader.js",
|
"path": "ts/components/MainHeader.js",
|
||||||
|
|
|
@ -3084,6 +3084,11 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.lightboxView) {
|
||||||
|
this.lightboxView.remove();
|
||||||
|
this.lightboxView = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
this.lightboxView = new Whisper.ReactWrapperView({
|
this.lightboxView = new Whisper.ReactWrapperView({
|
||||||
className: 'lightbox-wrapper',
|
className: 'lightbox-wrapper',
|
||||||
Component: window.Signal.Components.Lightbox,
|
Component: window.Signal.Components.Lightbox,
|
||||||
|
@ -3206,6 +3211,11 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
|
||||||
mediaItem.attachment.path === selectedMediaItem.attachment.path
|
mediaItem.attachment.path === selectedMediaItem.attachment.path
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (this.lightboxView) {
|
||||||
|
this.lightboxView.remove();
|
||||||
|
this.lightboxView = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
this.lightboxView = new Whisper.ReactWrapperView({
|
this.lightboxView = new Whisper.ReactWrapperView({
|
||||||
className: 'lightbox-wrapper',
|
className: 'lightbox-wrapper',
|
||||||
Component: window.Signal.Components.Lightbox,
|
Component: window.Signal.Components.Lightbox,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue