Functional context menu in story viewer

This commit is contained in:
Josh Perez 2022-04-29 13:43:24 -04:00 committed by GitHub
parent d6b58d23d6
commit 6e7092c294
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 20 deletions

View file

@ -12,6 +12,8 @@ import type { RenderEmojiPickerProps } from './conversation/ReactionPicker';
import type { ReplyStateType } from '../types/Stories';
import type { StoryViewType } from './StoryListItem';
import { Avatar, AvatarSize } from './Avatar';
import { ConfirmationDialog } from './ConfirmationDialog';
import { ContextMenuPopper } from './ContextMenu';
import { Intl } from './Intl';
import { MessageTimestamp } from './conversation/MessageTimestamp';
import { StoryImage } from './StoryImage';
@ -41,6 +43,8 @@ export type PropsType = {
loadStoryReplies: (conversationId: string, messageId: string) => unknown;
markStoryRead: (mId: string) => unknown;
onClose: () => unknown;
onGoToConversation: (conversationId: string) => unknown;
onHideStory: (conversationId: string) => unknown;
onNextUserStories: () => unknown;
onPrevUserStories: () => unknown;
onSetSkinTone: (tone: number) => unknown;
@ -76,6 +80,8 @@ export const StoryViewer = ({
loadStoryReplies,
markStoryRead,
onClose,
onGoToConversation,
onHideStory,
onNextUserStories,
onPrevUserStories,
onReactToStory,
@ -96,15 +102,21 @@ export const StoryViewer = ({
const [currentStoryIndex, setCurrentStoryIndex] =
useState(selectedStoryIndex);
const [storyDuration, setStoryDuration] = useState<number | undefined>();
const [isShowingContextMenu, setIsShowingContextMenu] = useState(false);
const [hasConfirmHideStory, setHasConfirmHideStory] = useState(false);
const [referenceElement, setReferenceElement] =
useState<HTMLButtonElement | null>(null);
const visibleStory = stories[currentStoryIndex];
const { attachment, canReply, messageId, timestamp } = visibleStory;
const { attachment, canReply, isHidden, messageId, timestamp } = visibleStory;
const {
acceptedMessageRequest,
avatarPath,
color,
isMe,
id,
firstName,
name,
profileName,
sharedGroupNames,
@ -226,13 +238,19 @@ export const StoryViewer = ({
};
}, [currentStoryIndex, spring, storyDuration]);
const shouldPauseViewing =
hasConfirmHideStory ||
hasExpandedCaption ||
hasReplyModal ||
isShowingContextMenu;
useEffect(() => {
if (hasReplyModal || hasExpandedCaption) {
if (shouldPauseViewing) {
spring.pause();
} else {
spring.resume();
}
}, [hasExpandedCaption, hasReplyModal, spring]);
}, [shouldPauseViewing, spring]);
useEffect(() => {
markStoryRead(messageId);
@ -248,7 +266,7 @@ export const StoryViewer = ({
.map(story => story.messageId);
}, [stories]);
useEffect(() => {
storiesToDownload.forEach(id => queueStoryDownload(id));
storiesToDownload.forEach(storyId => queueStoryDownload(storyId));
}, [queueStoryDownload, storiesToDownload]);
const navigateStories = useCallback(
@ -452,6 +470,8 @@ export const StoryViewer = ({
<button
aria-label={i18n('MyStories__more')}
className="StoryViewer__more"
onClick={() => setIsShowingContextMenu(true)}
ref={setReferenceElement}
tabIndex={0}
type="button"
/>
@ -463,6 +483,37 @@ export const StoryViewer = ({
type="button"
/>
</div>
<ContextMenuPopper
isMenuShowing={isShowingContextMenu}
menuOptions={[
{
icon: 'StoryListItem__icon--hide',
label: isHidden
? i18n('StoryListItem__unhide')
: i18n('StoryListItem__hide'),
onClick: () => {
if (isHidden) {
onHideStory(id);
} else {
setHasConfirmHideStory(true);
}
},
},
{
icon: 'StoryListItem__icon--chat',
label: i18n('StoryListItem__go-to-chat'),
onClick: () => {
onGoToConversation(id);
},
},
]}
onClose={() => setIsShowingContextMenu(false)}
popperOptions={{
placement: 'bottom',
strategy: 'absolute',
}}
referenceElement={referenceElement}
/>
{hasReplyModal && canReply && (
<StoryViewsNRepliesModal
authorTitle={title}
@ -492,6 +543,23 @@ export const StoryViewer = ({
views={[]}
/>
)}
{hasConfirmHideStory && (
<ConfirmationDialog
actions={[
{
action: () => onHideStory(id),
style: 'affirmative',
text: i18n('StoryListItem__hide-modal--confirm'),
},
]}
i18n={i18n}
onClose={() => {
setHasConfirmHideStory(false);
}}
>
{i18n('StoryListItem__hide-modal--body', [String(firstName)])}
</ConfirmationDialog>
)}
</div>
</FocusTrap>
);