Story viewing improvements
This commit is contained in:
parent
d4e0f6a38d
commit
7d8464757b
4 changed files with 149 additions and 2 deletions
|
@ -40,6 +40,7 @@ $color-black-alpha-05: rgba($color-black, 0.05);
|
|||
$color-black-alpha-06: rgba($color-black, 0.06);
|
||||
$color-black-alpha-08: rgba($color-black, 0.08);
|
||||
$color-black-alpha-12: rgba($color-black, 0.12);
|
||||
$color-black-alpha-16: rgba($color-black, 0.16);
|
||||
$color-black-alpha-20: rgba($color-black, 0.2);
|
||||
$color-black-alpha-30: rgba($color-black, 0.3);
|
||||
$color-black-alpha-40: rgba($color-black, 0.4);
|
||||
|
@ -49,6 +50,8 @@ $color-black-alpha-70: rgba($color-black, 0.7);
|
|||
$color-black-alpha-80: rgba($color-black, 0.8);
|
||||
$color-black-alpha-90: rgba($color-black, 0.9);
|
||||
|
||||
$color-transparent: rgba(0, 0, 0, 0);
|
||||
|
||||
$color-ultramarine-dark: #1851b4;
|
||||
$color-ultramarine-icon: #3a76f0;
|
||||
$color-ultramarine-light: #6191f3;
|
||||
|
|
|
@ -72,7 +72,8 @@
|
|||
padding: 0 16px;
|
||||
position: absolute;
|
||||
transform: translateX(-50%);
|
||||
width: 284px;
|
||||
min-width: 284px;
|
||||
width: 56.25vh;
|
||||
z-index: $z-index-above-base;
|
||||
|
||||
&--group-avatar {
|
||||
|
@ -93,7 +94,7 @@
|
|||
}
|
||||
|
||||
&__caption {
|
||||
@include font-body-1-bold;
|
||||
@include font-body-1;
|
||||
color: $color-gray-05;
|
||||
padding: 4px 0;
|
||||
margin-bottom: 24px;
|
||||
|
@ -146,4 +147,69 @@
|
|||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&__arrow {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
width: 25%;
|
||||
|
||||
button {
|
||||
@include button-reset;
|
||||
height: 24px;
|
||||
opacity: 0;
|
||||
width: 24px;
|
||||
transition: opacity 200ms ease-in-out;
|
||||
}
|
||||
|
||||
&--left {
|
||||
justify-content: flex-start;
|
||||
left: 0;
|
||||
|
||||
button {
|
||||
margin-left: 24px;
|
||||
@include color-svg(
|
||||
'../images/icons/v2/chevron-left-24.svg',
|
||||
$color-white
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
&--right {
|
||||
justify-content: flex-end;
|
||||
right: 0;
|
||||
|
||||
button {
|
||||
margin-right: 24px;
|
||||
@include color-svg(
|
||||
'../images/icons/v2/chevron-right-24.svg',
|
||||
$color-white
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
&--visible button {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
&__protection {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: $z-index-above-base;
|
||||
|
||||
&--top {
|
||||
background: linear-gradient($color-black-alpha-16, $color-transparent);
|
||||
top: 0;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
&--bottom {
|
||||
background: linear-gradient($color-transparent, $color-black-alpha-40);
|
||||
bottom: 0;
|
||||
height: 180px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ function getDefaultProps(): PropsType {
|
|||
stories: [
|
||||
{
|
||||
attachment: fakeAttachment({
|
||||
path: 'snow.jpg',
|
||||
url: '/fixtures/snow.jpg',
|
||||
}),
|
||||
messageId: '123',
|
||||
|
@ -60,6 +61,7 @@ story.add('Wide story', () => (
|
|||
stories={[
|
||||
{
|
||||
attachment: fakeAttachment({
|
||||
path: 'file.jpg',
|
||||
url: '/fixtures/nathan-anderson-316188-unsplash.jpg',
|
||||
}),
|
||||
messageId: '123',
|
||||
|
@ -89,6 +91,7 @@ story.add('Multi story', () => {
|
|||
stories={[
|
||||
{
|
||||
attachment: fakeAttachment({
|
||||
path: 'snow.jpg',
|
||||
url: '/fixtures/snow.jpg',
|
||||
}),
|
||||
messageId: '123',
|
||||
|
@ -97,6 +100,7 @@ story.add('Multi story', () => {
|
|||
},
|
||||
{
|
||||
attachment: fakeAttachment({
|
||||
path: 'file.jpg',
|
||||
url: '/fixtures/nathan-anderson-316188-unsplash.jpg',
|
||||
}),
|
||||
messageId: '456',
|
||||
|
@ -115,6 +119,7 @@ story.add('Caption', () => (
|
|||
{
|
||||
attachment: fakeAttachment({
|
||||
caption: 'This place looks lovely',
|
||||
path: 'file.jpg',
|
||||
url: '/fixtures/nathan-anderson-316188-unsplash.jpg',
|
||||
}),
|
||||
messageId: '123',
|
||||
|
@ -133,6 +138,7 @@ story.add('Long Caption', () => (
|
|||
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',
|
||||
path: 'file.jpg',
|
||||
url: '/fixtures/snow.jpg',
|
||||
}),
|
||||
messageId: '123',
|
||||
|
|
|
@ -9,6 +9,7 @@ import React, {
|
|||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useSpring, animated, to } from '@react-spring/web';
|
||||
import type { BodyRangeType, LocalizerType } from '../types/Util';
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
|
@ -76,6 +77,13 @@ export type PropsType = {
|
|||
const CAPTION_BUFFER = 20;
|
||||
const CAPTION_INITIAL_LENGTH = 200;
|
||||
const CAPTION_MAX_LENGTH = 700;
|
||||
const MOUSE_IDLE_TIME = 3000;
|
||||
|
||||
enum Arrow {
|
||||
None,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
export const StoryViewer = ({
|
||||
conversationId,
|
||||
|
@ -313,6 +321,38 @@ export const StoryViewer = ({
|
|||
loadStoryReplies(conversationId, messageId);
|
||||
}, [conversationId, isGroupStory, loadStoryReplies, messageId]);
|
||||
|
||||
const [arrowToShow, setArrowToShow] = useState<Arrow>(Arrow.None);
|
||||
|
||||
useEffect(() => {
|
||||
if (arrowToShow === Arrow.None) {
|
||||
return;
|
||||
}
|
||||
|
||||
let lastMouseMove: number | undefined;
|
||||
|
||||
function updateLastMouseMove() {
|
||||
lastMouseMove = Date.now();
|
||||
}
|
||||
|
||||
function checkMouseIdle() {
|
||||
requestAnimationFrame(() => {
|
||||
if (lastMouseMove && Date.now() - lastMouseMove > MOUSE_IDLE_TIME) {
|
||||
setArrowToShow(Arrow.None);
|
||||
} else {
|
||||
checkMouseIdle();
|
||||
}
|
||||
});
|
||||
}
|
||||
checkMouseIdle();
|
||||
|
||||
document.addEventListener('mousemove', updateLastMouseMove);
|
||||
|
||||
return () => {
|
||||
lastMouseMove = undefined;
|
||||
document.removeEventListener('mousemove', updateLastMouseMove);
|
||||
};
|
||||
}, [arrowToShow]);
|
||||
|
||||
const replies =
|
||||
replyState && replyState.messageId === messageId ? replyState.replies : [];
|
||||
|
||||
|
@ -327,6 +367,22 @@ export const StoryViewer = ({
|
|||
style={{ background: getStoryBackground(attachment) }}
|
||||
/>
|
||||
<div className="StoryViewer__content">
|
||||
<div
|
||||
className={classNames(
|
||||
'StoryViewer__arrow StoryViewer__arrow--left',
|
||||
{
|
||||
'StoryViewer__arrow--visible': arrowToShow === Arrow.Left,
|
||||
}
|
||||
)}
|
||||
onMouseMove={() => setArrowToShow(Arrow.Left)}
|
||||
>
|
||||
<button
|
||||
aria-label={i18n('back')}
|
||||
onClick={showPrevStory}
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
<div className="StoryViewer__protection StoryViewer__protection--top" />
|
||||
<div className="StoryViewer__container">
|
||||
<StoryImage
|
||||
attachment={attachment}
|
||||
|
@ -481,6 +537,22 @@ export const StoryViewer = ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
'StoryViewer__arrow StoryViewer__arrow--right',
|
||||
{
|
||||
'StoryViewer__arrow--visible': arrowToShow === Arrow.Right,
|
||||
}
|
||||
)}
|
||||
onMouseMove={() => setArrowToShow(Arrow.Right)}
|
||||
>
|
||||
<button
|
||||
aria-label={i18n('forward')}
|
||||
onClick={showNextStory}
|
||||
type="button"
|
||||
/>
|
||||
</div>
|
||||
<div className="StoryViewer__protection StoryViewer__protection--bottom" />
|
||||
<button
|
||||
aria-label={i18n('MyStories__more')}
|
||||
className="StoryViewer__more"
|
||||
|
|
Loading…
Reference in a new issue