Story: Support clickable gifts (#5477)
This commit is contained in:
parent
4c974d982b
commit
36639f1c2a
@ -166,36 +166,37 @@ function buildApiMediaAreaCoordinates(coordinates: GramJs.TypeMediaAreaCoordinat
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function buildApiMediaArea(area: GramJs.TypeMediaArea): ApiMediaArea | undefined {
|
export function buildApiMediaArea(area: GramJs.TypeMediaArea): ApiMediaArea | undefined {
|
||||||
|
const coordinates = buildApiMediaAreaCoordinates(area.coordinates);
|
||||||
if (area instanceof GramJs.MediaAreaVenue) {
|
if (area instanceof GramJs.MediaAreaVenue) {
|
||||||
const { geo, title, coordinates } = area;
|
const { geo, title } = area;
|
||||||
const point = buildGeoPoint(geo);
|
const point = buildGeoPoint(geo);
|
||||||
|
|
||||||
if (!point) return undefined;
|
if (!point) return undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'venue',
|
type: 'venue',
|
||||||
coordinates: buildApiMediaAreaCoordinates(coordinates),
|
coordinates,
|
||||||
geo: point,
|
geo: point,
|
||||||
title,
|
title,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area instanceof GramJs.MediaAreaGeoPoint) {
|
if (area instanceof GramJs.MediaAreaGeoPoint) {
|
||||||
const { geo, coordinates } = area;
|
const { geo } = area;
|
||||||
const point = buildGeoPoint(geo);
|
const point = buildGeoPoint(geo);
|
||||||
|
|
||||||
if (!point) return undefined;
|
if (!point) return undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'geoPoint',
|
type: 'geoPoint',
|
||||||
coordinates: buildApiMediaAreaCoordinates(coordinates),
|
coordinates,
|
||||||
geo: point,
|
geo: point,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area instanceof GramJs.MediaAreaSuggestedReaction) {
|
if (area instanceof GramJs.MediaAreaSuggestedReaction) {
|
||||||
const {
|
const {
|
||||||
coordinates, reaction, dark, flipped,
|
reaction, dark, flipped,
|
||||||
} = area;
|
} = area;
|
||||||
|
|
||||||
const apiReaction = buildApiReaction(reaction);
|
const apiReaction = buildApiReaction(reaction);
|
||||||
@ -205,7 +206,7 @@ export function buildApiMediaArea(area: GramJs.TypeMediaArea): ApiMediaArea | un
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'suggestedReaction',
|
type: 'suggestedReaction',
|
||||||
coordinates: buildApiMediaAreaCoordinates(coordinates),
|
coordinates,
|
||||||
reaction: apiReaction,
|
reaction: apiReaction,
|
||||||
...(dark && { isDark: true }),
|
...(dark && { isDark: true }),
|
||||||
...(flipped && { isFlipped: true }),
|
...(flipped && { isFlipped: true }),
|
||||||
@ -213,40 +214,50 @@ export function buildApiMediaArea(area: GramJs.TypeMediaArea): ApiMediaArea | un
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (area instanceof GramJs.MediaAreaChannelPost) {
|
if (area instanceof GramJs.MediaAreaChannelPost) {
|
||||||
const { coordinates, channelId, msgId } = area;
|
const { channelId, msgId } = area;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'channelPost',
|
type: 'channelPost',
|
||||||
coordinates: buildApiMediaAreaCoordinates(coordinates),
|
coordinates,
|
||||||
channelId: buildApiPeerId(channelId, 'channel'),
|
channelId: buildApiPeerId(channelId, 'channel'),
|
||||||
messageId: msgId,
|
messageId: msgId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area instanceof GramJs.MediaAreaUrl) {
|
if (area instanceof GramJs.MediaAreaUrl) {
|
||||||
const { coordinates, url } = area;
|
const { url } = area;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'url',
|
type: 'url',
|
||||||
coordinates: buildApiMediaAreaCoordinates(coordinates),
|
coordinates,
|
||||||
url,
|
url,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area instanceof GramJs.MediaAreaWeather) {
|
if (area instanceof GramJs.MediaAreaWeather) {
|
||||||
const {
|
const {
|
||||||
coordinates, emoji, temperatureC, color,
|
emoji, temperatureC, color,
|
||||||
} = area;
|
} = area;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'weather',
|
type: 'weather',
|
||||||
coordinates: buildApiMediaAreaCoordinates(coordinates),
|
coordinates,
|
||||||
emoji,
|
emoji,
|
||||||
temperatureC,
|
temperatureC,
|
||||||
color,
|
color,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (area instanceof GramJs.MediaAreaStarGift) {
|
||||||
|
const { slug } = area;
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'uniqueGift',
|
||||||
|
coordinates,
|
||||||
|
slug,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -176,5 +176,11 @@ export type ApiMediaAreaWeather = {
|
|||||||
color: number;
|
color: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ApiMediaAreaUniqueGift = {
|
||||||
|
type: 'uniqueGift';
|
||||||
|
coordinates: ApiMediaAreaCoordinates;
|
||||||
|
slug: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type ApiMediaArea = ApiMediaAreaVenue | ApiMediaAreaGeoPoint | ApiMediaAreaSuggestedReaction
|
export type ApiMediaArea = ApiMediaAreaVenue | ApiMediaAreaGeoPoint | ApiMediaAreaSuggestedReaction
|
||||||
| ApiMediaAreaChannelPost | ApiMediaAreaUrl | ApiMediaAreaWeather;
|
| ApiMediaAreaChannelPost | ApiMediaAreaUrl | ApiMediaAreaWeather | ApiMediaAreaUniqueGift;
|
||||||
|
|||||||
@ -72,8 +72,6 @@ interface OwnProps {
|
|||||||
storyId: number;
|
storyId: number;
|
||||||
dimensions: IDimensions;
|
dimensions: IDimensions;
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
// eslint-disable-next-line react/no-unused-prop-types
|
||||||
isReportModalOpen?: boolean;
|
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
|
||||||
isDeleteModalOpen?: boolean;
|
isDeleteModalOpen?: boolean;
|
||||||
isPrivateStories?: boolean;
|
isPrivateStories?: boolean;
|
||||||
isArchivedStories?: boolean;
|
isArchivedStories?: boolean;
|
||||||
@ -908,7 +906,6 @@ function Story({
|
|||||||
export default memo(withGlobal<OwnProps>((global, {
|
export default memo(withGlobal<OwnProps>((global, {
|
||||||
peerId,
|
peerId,
|
||||||
storyId,
|
storyId,
|
||||||
isReportModalOpen,
|
|
||||||
isDeleteModalOpen,
|
isDeleteModalOpen,
|
||||||
}): StateProps => {
|
}): StateProps => {
|
||||||
const { appConfig } = global;
|
const { appConfig } = global;
|
||||||
@ -927,13 +924,15 @@ export default memo(withGlobal<OwnProps>((global, {
|
|||||||
premiumModal,
|
premiumModal,
|
||||||
safeLinkModalUrl,
|
safeLinkModalUrl,
|
||||||
mapModal,
|
mapModal,
|
||||||
|
reportModal,
|
||||||
|
giftInfoModal,
|
||||||
} = tabState;
|
} = tabState;
|
||||||
const { isOpen: isPremiumModalOpen } = premiumModal || {};
|
const { isOpen: isPremiumModalOpen } = premiumModal || {};
|
||||||
const story = selectPeerStory(global, peerId, storyId);
|
const story = selectPeerStory(global, peerId, storyId);
|
||||||
const isLoadedStory = story && 'content' in story;
|
const isLoadedStory = story && 'content' in story;
|
||||||
const shouldForcePause = Boolean(
|
const shouldForcePause = Boolean(
|
||||||
viewModal || forwardedStoryId || tabState.reactionPicker?.storyId || isReportModalOpen || isPrivacyModalOpen
|
viewModal || forwardedStoryId || tabState.reactionPicker?.storyId || reportModal || isPrivacyModalOpen
|
||||||
|| isPremiumModalOpen || isDeleteModalOpen || safeLinkModalUrl || isStealthModalOpen || mapModal,
|
|| isPremiumModalOpen || isDeleteModalOpen || safeLinkModalUrl || isStealthModalOpen || mapModal || giftInfoModal,
|
||||||
);
|
);
|
||||||
|
|
||||||
const forwardInfo = isLoadedStory ? story.forwardInfo : undefined;
|
const forwardInfo = isLoadedStory ? story.forwardInfo : undefined;
|
||||||
|
|||||||
@ -43,7 +43,6 @@ import styles from './StoryViewer.module.scss';
|
|||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
isReportModalOpen?: boolean;
|
|
||||||
isDeleteModalOpen?: boolean;
|
isDeleteModalOpen?: boolean;
|
||||||
onDelete: (story: ApiTypeStory) => void;
|
onDelete: (story: ApiTypeStory) => void;
|
||||||
onReport: NoneToVoidFunction;
|
onReport: NoneToVoidFunction;
|
||||||
@ -80,7 +79,6 @@ function StorySlides({
|
|||||||
isPrivate,
|
isPrivate,
|
||||||
isArchive,
|
isArchive,
|
||||||
byPeerId,
|
byPeerId,
|
||||||
isReportModalOpen,
|
|
||||||
isDeleteModalOpen,
|
isDeleteModalOpen,
|
||||||
onDelete,
|
onDelete,
|
||||||
onClose,
|
onClose,
|
||||||
@ -380,7 +378,6 @@ function StorySlides({
|
|||||||
dimensions={slideSizes.activeSlide}
|
dimensions={slideSizes.activeSlide}
|
||||||
isPrivateStories={renderingIsPrivate}
|
isPrivateStories={renderingIsPrivate}
|
||||||
isArchivedStories={renderingIsArchive}
|
isArchivedStories={renderingIsArchive}
|
||||||
isReportModalOpen={isReportModalOpen}
|
|
||||||
isDeleteModalOpen={isDeleteModalOpen}
|
isDeleteModalOpen={isDeleteModalOpen}
|
||||||
isSingleStory={isSingleStory}
|
isSingleStory={isSingleStory}
|
||||||
getIsAnimating={getIsAnimating}
|
getIsAnimating={getIsAnimating}
|
||||||
@ -438,7 +435,6 @@ function StorySlides({
|
|||||||
dimensions={slideSizes.activeSlide}
|
dimensions={slideSizes.activeSlide}
|
||||||
isPrivateStories={renderingIsPrivate}
|
isPrivateStories={renderingIsPrivate}
|
||||||
isArchivedStories={renderingIsArchive}
|
isArchivedStories={renderingIsArchive}
|
||||||
isReportModalOpen={isReportModalOpen}
|
|
||||||
isDeleteModalOpen={isDeleteModalOpen}
|
isDeleteModalOpen={isDeleteModalOpen}
|
||||||
isSingleStory={isSingleStory}
|
isSingleStory={isSingleStory}
|
||||||
getIsAnimating={getIsAnimating}
|
getIsAnimating={getIsAnimating}
|
||||||
|
|||||||
@ -48,7 +48,6 @@ interface StateProps {
|
|||||||
shouldSkipHistoryAnimations?: boolean;
|
shouldSkipHistoryAnimations?: boolean;
|
||||||
withAnimation?: boolean;
|
withAnimation?: boolean;
|
||||||
isPrivacyModalOpen?: boolean;
|
isPrivacyModalOpen?: boolean;
|
||||||
isReportModalOpen?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function StoryViewer({
|
function StoryViewer({
|
||||||
@ -60,7 +59,6 @@ function StoryViewer({
|
|||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
withAnimation,
|
withAnimation,
|
||||||
isPrivacyModalOpen,
|
isPrivacyModalOpen,
|
||||||
isReportModalOpen,
|
|
||||||
}: StateProps) {
|
}: StateProps) {
|
||||||
const { closeStoryViewer, closeStoryPrivacyEditor, reportStory } = getActions();
|
const { closeStoryViewer, closeStoryPrivacyEditor, reportStory } = getActions();
|
||||||
|
|
||||||
@ -165,7 +163,6 @@ function StoryViewer({
|
|||||||
|
|
||||||
<StorySlides
|
<StorySlides
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
isReportModalOpen={isReportModalOpen}
|
|
||||||
isDeleteModalOpen={isDeleteModalOpen}
|
isDeleteModalOpen={isDeleteModalOpen}
|
||||||
onReport={openMessageReport}
|
onReport={openMessageReport}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
@ -188,17 +185,14 @@ export default memo(withGlobal((global): StateProps => {
|
|||||||
const {
|
const {
|
||||||
shouldSkipHistoryAnimations, storyViewer: {
|
shouldSkipHistoryAnimations, storyViewer: {
|
||||||
storyId, peerId, isPrivacyModalOpen, origin,
|
storyId, peerId, isPrivacyModalOpen, origin,
|
||||||
}, reportModal,
|
},
|
||||||
} = selectTabState(global);
|
} = selectTabState(global);
|
||||||
const story = peerId && storyId ? selectPeerStory(global, peerId, storyId) : undefined;
|
const story = peerId && storyId ? selectPeerStory(global, peerId, storyId) : undefined;
|
||||||
const withAnimation = selectPerformanceSettingsValue(global, 'mediaViewerAnimations');
|
const withAnimation = selectPerformanceSettingsValue(global, 'mediaViewerAnimations');
|
||||||
|
|
||||||
const isReportModalOpen = Boolean(reportModal);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isOpen: selectIsStoryViewerOpen(global),
|
isOpen: selectIsStoryViewerOpen(global),
|
||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
isReportModalOpen,
|
|
||||||
peerId: peerId!,
|
peerId: peerId!,
|
||||||
storyId,
|
storyId,
|
||||||
story,
|
story,
|
||||||
|
|||||||
@ -27,11 +27,13 @@ type OwnProps = {
|
|||||||
const STORY_ASPECT_RATIO = 9 / 16;
|
const STORY_ASPECT_RATIO = 9 / 16;
|
||||||
const PERCENTAGE_BASE = 100;
|
const PERCENTAGE_BASE = 100;
|
||||||
|
|
||||||
|
const NO_SHINY_TYPES = new Set<ApiMediaArea['type']>(['channelPost', 'uniqueGift']);
|
||||||
|
|
||||||
const MediaAreaOverlay = ({
|
const MediaAreaOverlay = ({
|
||||||
story, isActive, className, isStoryPlaying,
|
story, isActive, className, isStoryPlaying,
|
||||||
}: OwnProps) => {
|
}: OwnProps) => {
|
||||||
const {
|
const {
|
||||||
openMapModal, focusMessage, closeStoryViewer, openUrl,
|
openMapModal, openUniqueGiftBySlug, focusMessage, closeStoryViewer, openUrl,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -85,6 +87,10 @@ const MediaAreaOverlay = ({
|
|||||||
openUrl({ url: mediaArea.url });
|
openUrl({ url: mediaArea.url });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'uniqueGift': {
|
||||||
|
openUniqueGiftBySlug({ slug: mediaArea.slug });
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,8 +106,9 @@ const MediaAreaOverlay = ({
|
|||||||
case 'geoPoint':
|
case 'geoPoint':
|
||||||
case 'venue':
|
case 'venue':
|
||||||
case 'channelPost':
|
case 'channelPost':
|
||||||
case 'url': {
|
case 'url':
|
||||||
const isShiny = isActive && (mediaArea.type !== 'channelPost');
|
case 'uniqueGift': {
|
||||||
|
const isShiny = isActive && !NO_SHINY_TYPES.has(mediaArea.type);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={buildClassName(styles.mediaArea, isShiny && styles.shiny)}
|
className={buildClassName(styles.mediaArea, isShiny && styles.shiny)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user