Full width/height stories

This commit is contained in:
Josh Perez 2022-04-22 14:36:34 -04:00 committed by GitHub
parent 3a1df01c9e
commit 4602cef6da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 163 additions and 88 deletions

View file

@ -122,3 +122,38 @@ story.add('So many stories', () => {
/>
);
});
story.add('Caption', () => (
<StoryViewer
{...getDefaultProps()}
stories={[
{
attachment: fakeAttachment({
caption: 'This place looks lovely',
url: '/fixtures/nathan-anderson-316188-unsplash.jpg',
}),
messageId: '123',
sender: getDefaultConversation(),
timestamp: Date.now(),
},
]}
/>
));
story.add('Long Caption', () => (
<StoryViewer
{...getDefaultProps()}
stories={[
{
attachment: fakeAttachment({
caption:
'Snowycle, snowycle, snowycle\nI want to ride my snowycle, snowycle, snowycle\nI want to ride my snowycle\nI want to ride my snow\nI want to ride my snowycle\nI want to ride it where I like\nSnowycle, snowycle, snowycle\nI want to ride my snowycle, snowycle, snowycle\nI want to ride my snowycle\nI want to ride my snow\nI want to ride my snowycle\nI want to ride it where I like\nSnowycle, snowycle, snowycle\nI want to ride my snowycle, snowycle, snowycle\nI want to ride my snowycle\nI want to ride my snow\nI want to ride my snowycle\nI want to ride it where I like',
url: '/fixtures/snow.jpg',
}),
messageId: '123',
sender: getDefaultConversation(),
timestamp: Date.now(),
},
]}
/>
));

View file

@ -17,6 +17,7 @@ import { MessageTimestamp } from './conversation/MessageTimestamp';
import { StoryImage } from './StoryImage';
import { StoryViewsNRepliesModal } from './StoryViewsNRepliesModal';
import { getAvatarColor } from '../types/Colors';
import { getStoryBackground } from '../util/getStoryBackground';
import { getStoryDuration } from '../util/getStoryDuration';
import { graphemeAwareSlice } from '../util/graphemeAwareSlice';
import { isDownloaded, isDownloading } from '../types/Attachment';
@ -209,12 +210,12 @@ export const StoryViewer = ({
}, [currentStoryIndex, spring, storyDuration]);
useEffect(() => {
if (hasReplyModal) {
if (hasReplyModal || hasExpandedCaption) {
spring.pause();
} else {
spring.resume();
}
}, [hasReplyModal, spring]);
}, [hasExpandedCaption, hasReplyModal, spring]);
useEffect(() => {
markStoryRead(messageId);
@ -273,21 +274,11 @@ export const StoryViewer = ({
return (
<FocusTrap focusTrapOptions={{ allowOutsideClick: true }}>
<div className="StoryViewer">
<div className="StoryViewer__overlay" />
<div
className="StoryViewer__overlay"
style={{ background: getStoryBackground(attachment) }}
/>
<div className="StoryViewer__content">
<button
aria-label={i18n('MyStories__more')}
className="StoryViewer__more"
tabIndex={0}
type="button"
/>
<button
aria-label={i18n('close')}
className="StoryViewer__close-button"
onClick={onClose}
tabIndex={0}
type="button"
/>
<div className="StoryViewer__container">
<StoryImage
attachment={attachment}
@ -298,7 +289,12 @@ export const StoryViewer = ({
storyId={messageId}
/>
{hasExpandedCaption && (
<div className="StoryViewer__caption__overlay" />
<button
aria-label={i18n('close-popup')}
className="StoryViewer__caption__overlay"
onClick={() => setHasExpandedCaption(false)}
type="button"
/>
)}
<div className="StoryViewer__meta">
{caption && (
@ -391,54 +387,67 @@ export const StoryViewer = ({
</div>
))}
</div>
<div className="StoryViewer__actions">
{isMe ? (
<>
{viewCount &&
(viewCount === 1 ? (
<Intl
i18n={i18n}
id="MyStories__views--singular"
components={[<strong>{viewCount}</strong>]}
/>
) : (
<Intl
i18n={i18n}
id="MyStories__views--plural"
components={[<strong>{viewCount}</strong>]}
/>
))}
{viewCount && replyCount && ' '}
{replyCount &&
(replyCount === 1 ? (
<Intl
i18n={i18n}
id="MyStories__replies--singular"
components={[<strong>{replyCount}</strong>]}
/>
) : (
<Intl
i18n={i18n}
id="MyStories__replies--plural"
components={[<strong>{replyCount}</strong>]}
/>
))}
</>
) : (
canReply && (
<button
className="StoryViewer__reply"
onClick={() => setHasReplyModal(true)}
tabIndex={0}
type="button"
>
{i18n('StoryViewer__reply')}
</button>
)
)}
</div>
</div>
</div>
<div className="StoryViewer__actions">
{isMe ? (
<>
{viewCount &&
(viewCount === 1 ? (
<Intl
i18n={i18n}
id="MyStories__views--singular"
components={[<strong>{viewCount}</strong>]}
/>
) : (
<Intl
i18n={i18n}
id="MyStories__views--plural"
components={[<strong>{viewCount}</strong>]}
/>
))}
{viewCount && replyCount && ' '}
{replyCount &&
(replyCount === 1 ? (
<Intl
i18n={i18n}
id="MyStories__replies--singular"
components={[<strong>{replyCount}</strong>]}
/>
) : (
<Intl
i18n={i18n}
id="MyStories__replies--plural"
components={[<strong>{replyCount}</strong>]}
/>
))}
</>
) : (
canReply && (
<button
className="StoryViewer__reply"
onClick={() => setHasReplyModal(true)}
tabIndex={0}
type="button"
>
{i18n('StoryViewer__reply')}
</button>
)
)}
</div>
<button
aria-label={i18n('MyStories__more')}
className="StoryViewer__more"
tabIndex={0}
type="button"
/>
<button
aria-label={i18n('close')}
className="StoryViewer__close-button"
onClick={onClose}
tabIndex={0}
type="button"
/>
</div>
{hasReplyModal && canReply && (
<StoryViewsNRepliesModal

View file

@ -13,6 +13,10 @@ import { TextAttachmentStyleType } from '../types/Attachment';
import { count } from '../util/grapheme';
import { getDomain } from '../types/LinkPreview';
import { getFontNameByTextScript } from '../util/getFontNameByTextScript';
import {
getHexFromNumber,
getBackgroundColor,
} from '../util/getStoryBackground';
const renderNewLines: RenderTextCallbackType = ({
text: textWithNewLines,
@ -53,20 +57,6 @@ function getTextSize(text: string): TextSize {
return TextSize.Small;
}
function getHexFromNumber(color: number): string {
return `#${color.toString(16).slice(2)}`;
}
function getBackground({ color, gradient }: TextAttachmentType): string {
if (gradient) {
return `linear-gradient(${gradient.angle}deg, ${getHexFromNumber(
gradient.startColor || COLOR_WHITE_INT
)}, ${getHexFromNumber(gradient.endColor || COLOR_WHITE_INT)})`;
}
return getHexFromNumber(color || COLOR_WHITE_INT);
}
function getFont(
text: string,
textSize: TextSize,
@ -123,7 +113,7 @@ export const TextAttachment = ({
<div
className="TextAttachment__story"
style={{
background: getBackground(textAttachment),
background: getBackgroundColor(textAttachment),
transform: `scale(${(contentRect.bounds?.height || 1) / 1280})`,
}}
>

View file

@ -0,0 +1,40 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { AttachmentType, TextAttachmentType } from '../types/Attachment';
const COLOR_BLACK_ALPHA_90 = 'rgba(0, 0, 0, 0.9)';
const COLOR_WHITE_INT = 4294704123;
export function getHexFromNumber(color: number): string {
return `#${color.toString(16).slice(2)}`;
}
export function getBackgroundColor({
color,
gradient,
}: TextAttachmentType): string {
if (gradient) {
return `linear-gradient(${gradient.angle}deg, ${getHexFromNumber(
gradient.startColor || COLOR_WHITE_INT
)}, ${getHexFromNumber(gradient.endColor || COLOR_WHITE_INT)})`;
}
return getHexFromNumber(color || COLOR_WHITE_INT);
}
export function getStoryBackground(attachment?: AttachmentType): string {
if (!attachment) {
return COLOR_BLACK_ALPHA_90;
}
if (attachment.textAttachment) {
return getBackgroundColor(attachment.textAttachment);
}
if (attachment.url) {
return `url("${attachment.url}")`;
}
return COLOR_BLACK_ALPHA_90;
}