Story: Fix unsupported display (#6452)

This commit is contained in:
zubiden 2025-11-11 14:37:40 +01:00 committed by Alexander Zinchuk
parent 4180270eb5
commit 96b41e8663
7 changed files with 52 additions and 19 deletions

View File

@ -2315,3 +2315,4 @@
"UserNoteHint" = "only visible to you"; "UserNoteHint" = "only visible to you";
"EditUserNoteHint" = "Notes are only visible to you."; "EditUserNoteHint" = "Notes are only visible to you.";
"AriaStoryTogglerOpen" = "Open Story List"; "AriaStoryTogglerOpen" = "Open Story List";
"StoryUnsupported" = "This story is not supported in Telegram Web A. Try viewing it in the Telegram app.";

View File

@ -22,7 +22,7 @@
object-fit: cover; object-fit: cover;
} }
.expiredIcon { .mainIcon {
font-size: 1.25rem; font-size: 1.25rem;
line-height: 0.9375rem; line-height: 0.9375rem;
vertical-align: -0.1875rem; vertical-align: -0.1875rem;

View File

@ -1,4 +1,3 @@
import type React from '../../lib/teact/teact';
import { import {
memo, useCallback, useEffect, useRef, memo, useCallback, useEffect, useRef,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
@ -14,6 +13,7 @@ import stopEvent from '../../util/stopEvent';
import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur'; import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur';
import useContextMenuHandlers from '../../hooks/useContextMenuHandlers'; import useContextMenuHandlers from '../../hooks/useContextMenuHandlers';
import useLang from '../../hooks/useLang';
import useLastCallback from '../../hooks/useLastCallback'; import useLastCallback from '../../hooks/useLastCallback';
import useMedia from '../../hooks/useMedia'; import useMedia from '../../hooks/useMedia';
import useOldLang from '../../hooks/useOldLang'; import useOldLang from '../../hooks/useOldLang';
@ -47,7 +47,8 @@ function MediaStory({
showNotification, showNotification,
} = getActions(); } = getActions();
const lang = useOldLang(); const lang = useLang();
const oldLang = useOldLang();
const containerRef = useRef<HTMLDivElement>(); const containerRef = useRef<HTMLDivElement>();
const getTriggerElement = useLastCallback(() => containerRef.current); const getTriggerElement = useLastCallback(() => containerRef.current);
@ -59,6 +60,7 @@ function MediaStory({
const isFullyLoaded = story && 'content' in story; const isFullyLoaded = story && 'content' in story;
const isOwn = isFullyLoaded && story.isOut; const isOwn = isFullyLoaded && story.isOut;
const isDeleted = story && 'isDeleted' in story; const isDeleted = story && 'isDeleted' in story;
const isUnsupportedStory = isFullyLoaded && Object.keys(story.content).length === 0;
const video = isFullyLoaded ? (story).content.video : undefined; const video = isFullyLoaded ? (story).content.video : undefined;
const duration = video && formatMediaDuration(video.duration); const duration = video && formatMediaDuration(video.duration);
const imageHash = isFullyLoaded ? getStoryMediaHash(story) : undefined; const imageHash = isFullyLoaded ? getStoryMediaHash(story) : undefined;
@ -97,7 +99,7 @@ function MediaStory({
toggleStoryInProfile({ peerId, storyId: story.id, isInProfile: true }); toggleStoryInProfile({ peerId, storyId: story.id, isInProfile: true });
showNotification({ showNotification({
message: lang('Story.ToastSavedToProfileText'), message: oldLang('Story.ToastSavedToProfileText'),
}); });
handleContextMenuClose(); handleContextMenuClose();
}); });
@ -107,7 +109,7 @@ function MediaStory({
toggleStoryInProfile({ peerId, storyId: story.id, isInProfile: false }); toggleStoryInProfile({ peerId, storyId: story.id, isInProfile: false });
showNotification({ showNotification({
message: lang('Story.ToastRemovedFromProfileText'), message: oldLang('Story.ToastRemovedFromProfileText'),
}); });
handleContextMenuClose(); handleContextMenuClose();
}); });
@ -127,8 +129,14 @@ function MediaStory({
> >
{isDeleted && ( {isDeleted && (
<span> <span>
<Icon className={styles.expiredIcon} name="story-expired" /> <Icon className={styles.mainIcon} name="story-expired" />
{lang('ExpiredStory')} {oldLang('ExpiredStory')}
</span>
)}
{isUnsupportedStory && (
<span>
<Icon className={styles.mainIcon} name="warning" />
{lang('StoryUnsupported')}
</span> </span>
)} )}
{isPinned && <Icon className={buildClassName(styles.overlayIcon, styles.pinnedIcon)} name="pin-badge" />} {isPinned && <Icon className={buildClassName(styles.overlayIcon, styles.pinnedIcon)} name="pin-badge" />}
@ -162,22 +170,22 @@ function MediaStory({
> >
{isArchive && ( {isArchive && (
<MenuItem icon="archive" onClick={handleUnarchiveClick}> <MenuItem icon="archive" onClick={handleUnarchiveClick}>
{lang('StoryList.SaveToProfile')} {oldLang('StoryList.SaveToProfile')}
</MenuItem> </MenuItem>
)} )}
{!isArchive && ( {!isArchive && (
<MenuItem icon="archive" onClick={handleArchiveClick}> <MenuItem icon="archive" onClick={handleArchiveClick}>
{lang('Story.Context.RemoveFromProfile')} {oldLang('Story.Context.RemoveFromProfile')}
</MenuItem> </MenuItem>
)} )}
{!isArchive && !isPinned && canPin && ( {!isArchive && !isPinned && canPin && (
<MenuItem icon="pin" onClick={handleTogglePinned}> <MenuItem icon="pin" onClick={handleTogglePinned}>
{lang('StoryList.ItemAction.Pin')} {oldLang('StoryList.ItemAction.Pin')}
</MenuItem> </MenuItem>
)} )}
{!isArchive && isPinned && ( {!isArchive && isPinned && (
<MenuItem icon="unpin" onClick={handleTogglePinned}> <MenuItem icon="unpin" onClick={handleTogglePinned}>
{lang('StoryList.ItemAction.Unpin')} {oldLang('StoryList.ItemAction.Unpin')}
</MenuItem> </MenuItem>
)} )}
</Menu> </Menu>

View File

@ -197,6 +197,7 @@ function Story({
const isChatStory = !isUserStory; const isChatStory = !isUserStory;
const isChannelStory = isChatStory && isChatChannel(peer as ApiChat); const isChannelStory = isChatStory && isChatChannel(peer as ApiChat);
const isOut = isLoadedStory && story.isOut; const isOut = isLoadedStory && story.isOut;
const isUnsupportedStory = isLoadedStory && Object.keys(story.content).length === 0;
const canPinToProfile = useCurrentOrPrev( const canPinToProfile = useCurrentOrPrev(
isOut ? !story.isInProfile : undefined, isOut ? !story.isInProfile : undefined,
@ -229,7 +230,8 @@ function Story({
); );
const canPlayStory = Boolean( const canPlayStory = Boolean(
hasFullData && !shouldForcePause && isAppFocused && !isComposerHasFocus && !isCaptionExpanded (hasFullData || isUnsupportedStory)
&& !shouldForcePause && isAppFocused && !isComposerHasFocus && !isCaptionExpanded
&& !isPausedBySpacebar && !isPausedByLongPress, && !isPausedBySpacebar && !isPausedByLongPress,
); );
@ -244,11 +246,11 @@ function Story({
const { const {
shouldRender: shouldRenderSkeleton, shouldRender: shouldRenderSkeleton,
transitionClassNames: skeletonTransitionClassNames, transitionClassNames: skeletonTransitionClassNames,
} = useShowTransitionDeprecated(!hasFullData); } = useShowTransitionDeprecated(!hasFullData && !isUnsupportedStory);
const { const {
transitionClassNames: mediaTransitionClassNames, transitionClassNames: mediaTransitionClassNames,
} = useShowTransitionDeprecated(Boolean(fullMediaData)); } = useShowTransitionDeprecated(Boolean(fullMediaData) && !isUnsupportedStory);
const thumbRef = useCanvasBlur(thumbnail, !hasThumb); const thumbRef = useCanvasBlur(thumbnail, !hasThumb);
const previewTransitionClassNames = useMediaTransitionDeprecated(previewBlobUrl); const previewTransitionClassNames = useMediaTransitionDeprecated(previewBlobUrl);
@ -340,17 +342,17 @@ function Story({
onEnd: handleLongPressEnd, onEnd: handleLongPressEnd,
}); });
const isUnsupported = useUnsupportedMedia( const isUnsupportedVideo = useUnsupportedMedia(
videoRef, videoRef,
undefined, undefined,
!isVideo || !fullMediaData || isStreamingSupported, !isVideo || !fullMediaData || isStreamingSupported,
); );
const hasAllData = fullMediaData && (!altMediaHash || altMediaData); const hasAllData = fullMediaData && (!altMediaHash || altMediaData);
// Play story after media has been downloaded
useEffect(() => { useEffect(() => {
if (hasAllData && !isUnsupported) handlePlayStory(); // Start progress to the nest slide after media has been downloaded or it is unsupported
}, [hasAllData, isUnsupported]); if (hasAllData || isUnsupportedVideo || isUnsupportedStory) handlePlayStory();
}, [hasAllData, isUnsupportedVideo, isUnsupportedStory]);
useBackgroundMode(unmarkAppFocused, markAppFocused); useBackgroundMode(unmarkAppFocused, markAppFocused);
@ -842,6 +844,12 @@ function Story({
</OptimizedVideo> </OptimizedVideo>
)} )}
{isUnsupportedStory && (
<div className={buildClassName(styles.media, styles.unsupportedMedia)}>
<span>{lang('StoryUnsupported')}</span>
</div>
)}
{!isPausedByLongPress && !isComposerHasFocus && ( {!isPausedByLongPress && !isComposerHasFocus && (
<> <>
<button <button

View File

@ -848,3 +848,13 @@
text-decoration: underline; text-decoration: underline;
} }
} }
.unsupportedMedia {
display: flex;
align-items: center;
justify-content: center;
color: var(--color-white);
text-align: center;
text-wrap: balance;
}

View File

@ -14,6 +14,7 @@ export function getStoryMediaHash(
story: ApiStory, size: StorySize = 'preview', isAlt?: boolean, story: ApiStory, size: StorySize = 'preview', isAlt?: boolean,
) { ) {
const isVideo = Boolean(story.content.video); const isVideo = Boolean(story.content.video);
const isPhoto = Boolean(story.content.photo);
if (isVideo) { if (isVideo) {
if (isAlt && !story.content.altVideos) return undefined; if (isAlt && !story.content.altVideos) return undefined;
@ -21,7 +22,11 @@ export function getStoryMediaHash(
return getVideoMediaHash(media, size); return getVideoMediaHash(media, size);
} }
return getPhotoMediaHash(story.content.photo!, size); if (isPhoto) {
return getPhotoMediaHash(story.content.photo!, size);
}
return undefined;
} }
function getPreferredAlt(alts: ApiVideo[]) { function getPreferredAlt(alts: ApiVideo[]) {

View File

@ -1729,6 +1729,7 @@ export interface LangPair {
'UserNoteHint': undefined; 'UserNoteHint': undefined;
'EditUserNoteHint': undefined; 'EditUserNoteHint': undefined;
'AriaStoryTogglerOpen': undefined; 'AriaStoryTogglerOpen': undefined;
'StoryUnsupported': undefined;
} }
export interface LangPairWithVariables<V = LangVariable> { export interface LangPairWithVariables<V = LangVariable> {