diff --git a/src/components/common/Avatar.scss b/src/components/common/Avatar.scss index e6589bc0e..a4be623dd 100644 --- a/src/components/common/Avatar.scss +++ b/src/components/common/Avatar.scss @@ -24,6 +24,7 @@ width: 100%; height: 100%; display: flex; + z-index: 1; align-items: center; justify-content: center; background-image: linear-gradient(var(--color-white) -125%, var(--color-user)); @@ -168,32 +169,49 @@ left: -0.25rem; top: -0.25rem; border-radius: 50%; - padding: 0.125rem; - background: var(--color-borders-read-story); - mask: linear-gradient(to bottom, #fff 0%, #fff 100%) content-box, linear-gradient(to bottom, #fff 0%, #fff 100%); - mask-composite: exclude; - box-shadow: none; + } + + &::after { + content: ""; + position: absolute; + width: 3.25rem; + height: 3.25rem; + left: -0.125rem; + top: -0.125rem; + border-radius: 50%; + z-index: 0; + background: var(--color-background); } &.size-tiny { - width: 2rem; - height: 2rem; + width: 1.75rem; + height: 1.75rem; &::before { width: 2.25rem; height: 2.25rem; } + + &::after { + width: 2rem; + height: 2rem; + } } &.size-medium { - width: 2.75rem; - height: 2.75rem; + width: 2.5rem; + height: 2.5rem; &::before { width: 3rem; height: 3rem; } + + &::after { + width: 2.75rem; + height: 2.75rem; + } } &.online::after { diff --git a/src/components/common/Avatar.tsx b/src/components/common/Avatar.tsx index 2921debad..5356eda74 100644 --- a/src/components/common/Avatar.tsx +++ b/src/components/common/Avatar.tsx @@ -244,6 +244,7 @@ const Avatar: FC = ({ ref={ref} className={fullClassName} id={peer?.id && withStory ? getUserStoryHtmlId(peer.id) : undefined} + data-peer-id={peer?.id} data-test-sender-id={IS_TEST ? peer?.id : undefined} aria-label={typeof content === 'string' ? author : undefined} onClick={handleClick} diff --git a/src/components/left/ArchivedChats.scss b/src/components/left/ArchivedChats.scss index 28f2e826a..7451f6dcc 100644 --- a/src/components/left/ArchivedChats.scss +++ b/src/components/left/ArchivedChats.scss @@ -1,6 +1,7 @@ .ArchivedChats { height: 100%; overflow: hidden; + background: var(--color-background); .left-header { position: relative; diff --git a/src/components/left/ArchivedChats.tsx b/src/components/left/ArchivedChats.tsx index 4512d526a..418bcb0e2 100644 --- a/src/components/left/ArchivedChats.tsx +++ b/src/components/left/ArchivedChats.tsx @@ -6,7 +6,9 @@ import type { GlobalState } from '../../global/types'; import type { FolderEditDispatch } from '../../hooks/reducers/useFoldersReducer'; import type { LeftColumnContent, SettingsScreens } from '../../types'; +import { ANIMATION_END_DELAY } from '../../config'; import buildClassName from '../../util/buildClassName'; +import { ANIMATION_DURATION } from '../story/helpers/ribbonAnimation'; import useForumPanelRender from '../../hooks/useForumPanelRender'; import useHistoryBack from '../../hooks/useHistoryBack'; @@ -80,7 +82,7 @@ const ArchivedChats: FC = ({ shouldRender: shouldRenderStoryRibbon, transitionClassNames: storyRibbonClassNames, isClosing: isStoryRibbonClosing, - } = useShowTransition(isStoryRibbonShown, undefined, undefined, ''); + } = useShowTransition(isStoryRibbonShown, undefined, undefined, '', false, ANIMATION_DURATION + ANIMATION_END_DELAY); return (
diff --git a/src/components/left/main/LeftMain.scss b/src/components/left/main/LeftMain.scss index bd38722d3..2e2962fc2 100644 --- a/src/components/left/main/LeftMain.scss +++ b/src/components/left/main/LeftMain.scss @@ -4,6 +4,7 @@ display: flex; flex-direction: column; overflow: hidden; + background: var(--color-background); > .Transition { flex: 1; @@ -47,6 +48,7 @@ padding-left: 0.625rem; padding-right: 0.625rem; + /* stylelint-disable-next-line */ > span { padding-left: 0.5rem; padding-right: 0.5rem; diff --git a/src/components/mediaViewer/helpers/ghostAnimation.ts b/src/components/mediaViewer/helpers/ghostAnimation.ts index 05f41a442..11d5f674d 100644 --- a/src/components/mediaViewer/helpers/ghostAnimation.ts +++ b/src/components/mediaViewer/helpers/ghostAnimation.ts @@ -1,19 +1,21 @@ +import { requestMutation } from '../../../lib/fasterdom/fasterdom'; + import type { ApiDimensions, ApiMessage } from '../../../api/types'; import { MediaViewerOrigin } from '../../../types'; import { ANIMATION_END_DELAY, MESSAGE_CONTENT_SELECTOR } from '../../../config'; -import { requestMutation } from '../../../lib/fasterdom/fasterdom'; -import { getMessageHtmlId } from '../../../global/helpers'; -import { isElementInViewport } from '../../../util/isElementInViewport'; -import stopEvent from '../../../util/stopEvent'; -import { IS_TOUCH_ENV } from '../../../util/windowEnvironment'; -import windowSize from '../../../util/windowSize'; import { calculateDimensions, getMediaViewerAvailableDimensions, MEDIA_VIEWER_MEDIA_QUERY, REM, } from '../../common/helpers/mediaDimensions'; +import windowSize from '../../../util/windowSize'; +import stopEvent from '../../../util/stopEvent'; +import { IS_TOUCH_ENV } from '../../../util/windowEnvironment'; +import { getMessageHtmlId } from '../../../global/helpers'; +import { isElementInViewport } from '../../../util/isElementInViewport'; +import { applyStyles } from '../../../util/animation'; const ANIMATION_DURATION = 200; @@ -283,10 +285,6 @@ function getTopOffset(hasFooter: boolean) { return topOffsetRem * REM; } -function applyStyles(element: HTMLElement, styles: Record) { - Object.assign(element.style, styles); -} - function getNodes(origin: MediaViewerOrigin, message?: ApiMessage) { let containerSelector; let mediaSelector; diff --git a/src/components/story/StoryRibbon.module.scss b/src/components/story/StoryRibbon.module.scss index 6c33bef5f..040b019c3 100644 --- a/src/components/story/StoryRibbon.module.scss +++ b/src/components/story/StoryRibbon.module.scss @@ -4,7 +4,6 @@ column-gap: 0.625rem; padding: 0.25rem 0.5rem 0.5rem 1rem; overflow-x: auto; - overflow-y: hidden; white-space: nowrap; max-height: 5.5rem; position: relative; @@ -37,6 +36,10 @@ &:focus { outline: none; } + + &:global(.animating) { + opacity: 0; + } } .name { @@ -44,6 +47,7 @@ overflow: hidden; text-overflow: ellipsis; unicode-bidi: plaintext; + white-space: nowrap; max-width: 110%; &_hasUnreadStory { diff --git a/src/components/story/StoryRibbon.tsx b/src/components/story/StoryRibbon.tsx index 99469a4e4..5f9c8f681 100644 --- a/src/components/story/StoryRibbon.tsx +++ b/src/components/story/StoryRibbon.tsx @@ -44,6 +44,7 @@ function StoryRibbon({ return (
diff --git a/src/components/story/StoryRibbonButton.tsx b/src/components/story/StoryRibbonButton.tsx index efb2d1e7f..5fd393db4 100644 --- a/src/components/story/StoryRibbonButton.tsx +++ b/src/components/story/StoryRibbonButton.tsx @@ -95,6 +95,7 @@ function StoryRibbonButton({ user, isArchived }: OwnProps) {
; } @@ -36,6 +39,7 @@ function StoryToggler({ canShow, isShown, isArchived, + withAnimation, }: OwnProps & StateProps) { const { toggleStoryRibbon } = getActions(); @@ -58,8 +62,20 @@ function StoryToggler({ }, [orderedUserIds]); useStoryPreloader(preloadUserIds); + const isVisible = canShow && isShown; // For some reason, setting 'slow' here also fixes scroll freezes on iOS when collapsing Story Ribbon - const { shouldRender, transitionClassNames } = useShowTransition(canShow && isShown, undefined, undefined, 'slow'); + const { shouldRender, transitionClassNames } = useShowTransition(isVisible, undefined, undefined, 'slow'); + + useEffect(() => { + if (!withAnimation) return; + if (isVisible) { + dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY); + animateClosing(isArchived); + } else { + dispatchHeavyAnimationEvent(ANIMATION_DURATION + ANIMATION_END_DELAY); + animateOpening(isArchived); + } + }, [isArchived, isVisible, withAnimation]); if (!shouldRender) { return undefined; @@ -68,6 +84,7 @@ function StoryToggler({ return (