Mini Apps: Support icons in Mini App buttons (#6880)
This commit is contained in:
parent
e42616655e
commit
dcb01114ba
@ -238,6 +238,25 @@
|
|||||||
.secondary-button-spinner,
|
.secondary-button-spinner,
|
||||||
.main-button-spinner {
|
.main-button-spinner {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
:global(.Spinner__inner) {
|
||||||
|
animation-play-state: running !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-emoji {
|
||||||
|
--custom-emoji-size: 1.25rem;
|
||||||
|
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-emoji-with-label {
|
||||||
|
margin-inline-end: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-label {
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.web-app-popup {
|
.web-app-popup {
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import buildStyle from '../../../util/buildStyle.ts';
|
|||||||
import download from '../../../util/download';
|
import download from '../../../util/download';
|
||||||
import { extractCurrentThemeParams, validateHexColor } from '../../../util/themeStyle';
|
import { extractCurrentThemeParams, validateHexColor } from '../../../util/themeStyle';
|
||||||
import { callApi } from '../../../api/gramjs';
|
import { callApi } from '../../../api/gramjs';
|
||||||
|
import { REM } from '../../common/helpers/mediaDimensions';
|
||||||
import renderText from '../../common/helpers/renderText';
|
import renderText from '../../common/helpers/renderText';
|
||||||
|
|
||||||
import { getIsWebAppsFullscreenSupported } from '../../../hooks/useAppLayout';
|
import { getIsWebAppsFullscreenSupported } from '../../../hooks/useAppLayout';
|
||||||
@ -44,6 +45,7 @@ import useFullscreen, { checkIfFullscreen } from '../../../hooks/window/useFulls
|
|||||||
import usePopupLimit from './hooks/usePopupLimit';
|
import usePopupLimit from './hooks/usePopupLimit';
|
||||||
import useWebAppFrame from './hooks/useWebAppFrame';
|
import useWebAppFrame from './hooks/useWebAppFrame';
|
||||||
|
|
||||||
|
import CustomEmoji from '../../common/CustomEmoji';
|
||||||
import Icon from '../../common/icons/Icon';
|
import Icon from '../../common/icons/Icon';
|
||||||
import Button from '../../ui/Button';
|
import Button from '../../ui/Button';
|
||||||
import ConfirmDialog from '../../ui/ConfirmDialog';
|
import ConfirmDialog from '../../ui/ConfirmDialog';
|
||||||
@ -60,6 +62,8 @@ type WebAppButton = {
|
|||||||
color: string;
|
color: string;
|
||||||
textColor: string;
|
textColor: string;
|
||||||
isProgressVisible: boolean;
|
isProgressVisible: boolean;
|
||||||
|
iconCustomEmojiId?: string;
|
||||||
|
hasShineEffect?: boolean;
|
||||||
position?: 'left' | 'right' | 'top' | 'bottom';
|
position?: 'left' | 'right' | 'top' | 'bottom';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -262,8 +266,18 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
|
|||||||
if (isActive) registerReloadFrameCallback(reloadFrame);
|
if (isActive) registerReloadFrameCallback(reloadFrame);
|
||||||
}, [reloadFrame, registerReloadFrameCallback, isActive]);
|
}, [reloadFrame, registerReloadFrameCallback, isActive]);
|
||||||
|
|
||||||
const isMainButtonVisible = isLoaded && mainButton?.isVisible && mainButton.text.trim().length > 0;
|
function hasBottomButtonContent(text: string | undefined, iconCustomEmojiId?: string) {
|
||||||
const isSecondaryButtonVisible = isLoaded && secondaryButton?.isVisible && secondaryButton.text.trim().length > 0;
|
return Boolean(text?.trim().length || iconCustomEmojiId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isMainButtonVisible = isLoaded && mainButton?.isVisible && hasBottomButtonContent(
|
||||||
|
mainButton.text,
|
||||||
|
mainButton.iconCustomEmojiId,
|
||||||
|
);
|
||||||
|
const isSecondaryButtonVisible = isLoaded && secondaryButton?.isVisible && hasBottomButtonContent(
|
||||||
|
secondaryButton.text,
|
||||||
|
secondaryButton.iconCustomEmojiId,
|
||||||
|
);
|
||||||
|
|
||||||
const handleHideCloseModal = useLastCallback(() => {
|
const handleHideCloseModal = useLastCallback(() => {
|
||||||
updateCurrentWebApp({ isCloseModalOpen: false });
|
updateCurrentWebApp({ isCloseModalOpen: false });
|
||||||
@ -651,12 +665,14 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
|
|||||||
const color = eventData.color;
|
const color = eventData.color;
|
||||||
const textColor = eventData.text_color;
|
const textColor = eventData.text_color;
|
||||||
setMainButton({
|
setMainButton({
|
||||||
isVisible: eventData.is_visible && Boolean(eventData.text?.trim().length),
|
isVisible: eventData.is_visible && hasBottomButtonContent(eventData.text, eventData.icon_custom_emoji_id),
|
||||||
isActive: eventData.is_active,
|
isActive: eventData.is_active,
|
||||||
text: eventData.text,
|
text: eventData.text,
|
||||||
color,
|
color,
|
||||||
textColor,
|
textColor,
|
||||||
isProgressVisible: eventData.is_progress_visible,
|
isProgressVisible: eventData.is_progress_visible,
|
||||||
|
iconCustomEmojiId: eventData.icon_custom_emoji_id,
|
||||||
|
hasShineEffect: eventData.has_shine_effect,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,12 +680,14 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
|
|||||||
const color = eventData.color;
|
const color = eventData.color;
|
||||||
const textColor = eventData.text_color;
|
const textColor = eventData.text_color;
|
||||||
setSecondaryButton({
|
setSecondaryButton({
|
||||||
isVisible: eventData.is_visible && Boolean(eventData.text?.trim().length),
|
isVisible: eventData.is_visible && hasBottomButtonContent(eventData.text, eventData.icon_custom_emoji_id),
|
||||||
isActive: eventData.is_active,
|
isActive: eventData.is_active,
|
||||||
text: eventData.text,
|
text: eventData.text,
|
||||||
color,
|
color,
|
||||||
textColor,
|
textColor,
|
||||||
isProgressVisible: eventData.is_progress_visible,
|
isProgressVisible: eventData.is_progress_visible,
|
||||||
|
iconCustomEmojiId: eventData.icon_custom_emoji_id,
|
||||||
|
hasShineEffect: eventData.has_shine_effect,
|
||||||
position: eventData.position,
|
position: eventData.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1084,6 +1102,32 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderBottomButtonContent(text: string | undefined, iconCustomEmojiId?: string) {
|
||||||
|
const hasText = Boolean(text?.trim().length);
|
||||||
|
if (!hasText && !iconCustomEmojiId) return undefined;
|
||||||
|
|
||||||
|
const textContent = hasText ? renderText(text, ['emoji']) : undefined;
|
||||||
|
if (!iconCustomEmojiId) {
|
||||||
|
return textContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CustomEmoji
|
||||||
|
className={buildClassName(styles.buttonEmoji, hasText && styles.buttonEmojiWithLabel)}
|
||||||
|
documentId={iconCustomEmojiId}
|
||||||
|
size={1.25 * REM}
|
||||||
|
forceAlways
|
||||||
|
/>
|
||||||
|
{hasText && (
|
||||||
|
<span className={styles.buttonLabel}>
|
||||||
|
{textContent}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
@ -1133,9 +1177,13 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
|
|||||||
style={`background-color: ${secondaryButtonCurrentColor}; color: ${secondaryButtonCurrentTextColor}`}
|
style={`background-color: ${secondaryButtonCurrentColor}; color: ${secondaryButtonCurrentTextColor}`}
|
||||||
disabled={!secondaryButtonCurrentIsActive && !secondaryButton?.isProgressVisible}
|
disabled={!secondaryButtonCurrentIsActive && !secondaryButton?.isProgressVisible}
|
||||||
nonInteractive={secondaryButton?.isProgressVisible}
|
nonInteractive={secondaryButton?.isProgressVisible}
|
||||||
|
isShiny={secondaryButton?.hasShineEffect && !secondaryButton?.isProgressVisible}
|
||||||
onClick={handleSecondaryButtonClick}
|
onClick={handleSecondaryButtonClick}
|
||||||
>
|
>
|
||||||
{!secondaryButton?.isProgressVisible && secondaryButtonCurrentText}
|
{!secondaryButton?.isProgressVisible && renderBottomButtonContent(
|
||||||
|
secondaryButtonCurrentText,
|
||||||
|
secondaryButton?.iconCustomEmojiId,
|
||||||
|
)}
|
||||||
{secondaryButton?.isProgressVisible
|
{secondaryButton?.isProgressVisible
|
||||||
&& <Spinner className={styles.mainButtonSpinner} color="blue" />}
|
&& <Spinner className={styles.mainButtonSpinner} color="blue" />}
|
||||||
</Button>
|
</Button>
|
||||||
@ -1149,9 +1197,13 @@ const WebAppModalTabContent: FC<OwnProps & StateProps> = ({
|
|||||||
style={`background-color: ${mainButtonCurrentColor}; color: ${mainButtonCurrentTextColor}`}
|
style={`background-color: ${mainButtonCurrentColor}; color: ${mainButtonCurrentTextColor}`}
|
||||||
disabled={!mainButtonCurrentIsActive && !mainButton?.isProgressVisible}
|
disabled={!mainButtonCurrentIsActive && !mainButton?.isProgressVisible}
|
||||||
nonInteractive={mainButton?.isProgressVisible}
|
nonInteractive={mainButton?.isProgressVisible}
|
||||||
|
isShiny={mainButton?.hasShineEffect && !mainButton?.isProgressVisible}
|
||||||
onClick={handleMainButtonClick}
|
onClick={handleMainButtonClick}
|
||||||
>
|
>
|
||||||
{!mainButton?.isProgressVisible && mainButtonCurrentText}
|
{!mainButton?.isProgressVisible && renderBottomButtonContent(
|
||||||
|
mainButtonCurrentText,
|
||||||
|
mainButton?.iconCustomEmojiId,
|
||||||
|
)}
|
||||||
{mainButton?.isProgressVisible && <Spinner className={styles.mainButtonSpinner} color="white" />}
|
{mainButton?.isProgressVisible && <Spinner className={styles.mainButtonSpinner} color="white" />}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -50,6 +50,8 @@ export type WebAppButtonOptions = {
|
|||||||
color: string;
|
color: string;
|
||||||
text_color: string;
|
text_color: string;
|
||||||
is_progress_visible: boolean;
|
is_progress_visible: boolean;
|
||||||
|
icon_custom_emoji_id?: string;
|
||||||
|
has_shine_effect?: boolean;
|
||||||
position?: 'left' | 'right' | 'top' | 'bottom';
|
position?: 'left' | 'right' | 'top' | 'bottom';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user