Invoice Media: Better animation; Message Select Toolbar: Hide unavailable actions (#2121)

This commit is contained in:
Alexander Zinchuk 2022-11-10 18:28:07 +04:00
parent d10df1a705
commit ecd4155fff
8 changed files with 51 additions and 35 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -7,20 +7,21 @@ import type { MessageListType } from '../../global/types';
import {
selectCanDeleteSelectedMessages,
selectCanDownloadSelectedMessages,
selectCanForwardMessages,
selectCanReportSelectedMessages,
selectCurrentMessageList,
selectHasProtectedMessage,
selectSelectedMessagesCount,
} from '../../global/selectors';
import useFlag from '../../hooks/useFlag';
import captureKeyboardListeners from '../../util/captureKeyboardListeners';
import buildClassName from '../../util/buildClassName';
import useFlag from '../../hooks/useFlag';
import usePrevious from '../../hooks/usePrevious';
import useLang from '../../hooks/useLang';
import useCopySelectedMessages from './hooks/useCopySelectedMessages';
import Button from '../ui/Button';
import DeleteSelectedMessageModal from './DeleteSelectedMessageModal';
import ReportModal from '../common/ReportModal';
@ -38,6 +39,7 @@ type StateProps = {
canDeleteMessages?: boolean;
canReportMessages?: boolean;
canDownloadMessages?: boolean;
canForwardMessages?: boolean;
hasProtectedMessage?: boolean;
isAnyModalOpen?: boolean;
selectedMessageIds?: number[];
@ -52,6 +54,7 @@ const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
canDeleteMessages,
canReportMessages,
canDownloadMessages,
canForwardMessages,
hasProtectedMessage,
isAnyModalOpen,
selectedMessageIds,
@ -107,7 +110,7 @@ const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
);
const renderButton = (
icon: string, label: string, onClick: AnyToVoidFunction, disabled?: boolean, destructive?: boolean,
icon: string, label: string, onClick: AnyToVoidFunction, destructive?: boolean,
) => {
return (
<div
@ -115,10 +118,9 @@ const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
tabIndex={0}
className={buildClassName(
'item',
disabled && 'disabled',
destructive && 'destructive',
)}
onClick={!disabled ? onClick : undefined}
onClick={onClick}
title={label}
>
<i className={`icon-${icon}`} />
@ -143,19 +145,23 @@ const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
{Boolean(selectedMessagesCount) && (
<div className="MessageSelectToolbar-actions">
{messageListType !== 'scheduled' && (
{messageListType !== 'scheduled' && canForwardMessages && (
renderButton(
'forward', lang('Chat.ForwardActionHeader'), openForwardMenuForSelectedMessages, hasProtectedMessage,
'forward', lang('Chat.ForwardActionHeader'), openForwardMenuForSelectedMessages,
)
)}
{canReportMessages && (
renderButton('flag', lang('Conversation.ReportMessages'), openReportModal)
)}
{canDownloadMessages && (
renderButton('download', lang('lng_media_download'), handleDownload, hasProtectedMessage)
{canDownloadMessages && !hasProtectedMessage && (
renderButton('download', lang('lng_media_download'), handleDownload)
)}
{!hasProtectedMessage && (
renderButton('copy', lang('lng_context_copy_selected_items'), handleCopy)
)}
{canDeleteMessages && (
renderButton('delete', lang('EditAdminGroupDeleteMessages'), openDeleteModal, true)
)}
{renderButton('copy', lang('lng_context_copy_selected_items'), handleCopy, hasProtectedMessage)}
{renderButton('delete', lang('EditAdminGroupDeleteMessages'), openDeleteModal, !canDeleteMessages, true)}
</div>
)}
</div>
@ -182,6 +188,7 @@ export default memo(withGlobal<OwnProps>(
const canDownload = selectCanDownloadSelectedMessages(global);
const { messageIds: selectedMessageIds } = global.selectedMessages || {};
const hasProtectedMessage = chatId ? selectHasProtectedMessage(global, chatId, selectedMessageIds) : false;
const canForward = chatId ? selectCanForwardMessages(global, chatId, selectedMessageIds) : false;
const isForwardModalOpen = global.forwardMessages.isModalShown;
const isAnyModalOpen = Boolean(isForwardModalOpen || global.requestedDraft
|| global.requestedAttachBotInChat || global.requestedAttachBotInstall);
@ -192,6 +199,7 @@ export default memo(withGlobal<OwnProps>(
canDeleteMessages: canDelete,
canReportMessages: canReport,
canDownloadMessages: canDownload,
canForwardMessages: canForward,
selectedMessageIds,
hasProtectedMessage,
isAnyModalOpen,

View File

@ -13,20 +13,23 @@
width: 100%;
height: 100%;
--background-url: url('../../../assets/turbulence.png');
--background-url: url('../../../assets/turbulence_1x.png');
--background-size: 256px;
background: rgba(0, 0, 0, 0.3) var(--background-url);
background: rgba(0, 0, 0, 0.25) var(--background-url);
background-size: var(--background-size) var(--background-size);
z-index: 1;
@media (-webkit-min-device-pixel-ratio: 2) {
--background-url: url('../../../assets/turbulence_2x.png');
}
@media (-webkit-min-device-pixel-ratio: 3) {
--background-url: url('../../../assets/turbulence_3x.png');
}
--x-direction: var(--background-size);
--y-direction: 0;
animation: 10s linear infinite dots;
&.highres {
--background-url: url('../../../assets/turbulence_2x.png');
--background-size: 128px;
}
animation: 20s linear infinite dots;
&::before {
content: '';
@ -40,7 +43,7 @@
--x-direction: 0;
--y-direction: var(--background-size);
animation: 10s linear -4s infinite dots;
animation: 20s linear -7s infinite dots;
}
&::after {
@ -55,7 +58,7 @@
--x-direction: calc(-1 * var(--background-size));
--y-direction: calc(-1 * var(--background-size));
animation: 10s linear -8s infinite dots;
animation: 20s linear -14s infinite dots;
}
}
@ -85,16 +88,13 @@
left: 50%;
transform: translate(-50%, -50%);
padding: 0.375rem 0.625rem;
padding: 0.5rem 0.875rem;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgba(0, 0, 0, 0.75);
color: #FFFFFF;
border-radius: 1rem;
white-space: nowrap;
}
.lock {
margin-bottom: 1px;
line-height: 1rem;
}
.canvas {
@ -105,13 +105,8 @@
@keyframes dots {
0% {
background-position: 0 0;
opacity: 1;
}
50% {
opacity: 0.75;
}
100% {
background-position: var(--x-direction) var(--y-direction);
opacity: 1;
}
}

View File

@ -8,7 +8,6 @@ import { getMessageInvoice } from '../../../global/helpers';
import { formatCurrency } from '../../../util/formatCurrency';
import { formatMediaDuration } from '../../../util/dateFormat';
import buildClassName from '../../../util/buildClassName';
import { DPR } from '../../../util/environment';
import useLang from '../../../hooks/useLang';
import useCanvasBlur from '../../../hooks/useCanvasBlur';
@ -66,7 +65,7 @@ const InvoiceMediaPreview: FC<OwnProps> = ({
onClick={handleClick}
>
<canvas ref={canvasRef} className={styles.canvas} width={width} height={height} />
<div className={buildClassName(styles.dots, DPR > 1 && styles.highres)} />
<div className={styles.dots} />
{Boolean(duration) && <div className={styles.duration}>{formatMediaDuration(duration)}</div>}
<div className={styles.buy}>
<i className={buildClassName('icon-lock', styles.lock)} />

View File

@ -399,7 +399,7 @@ export function selectAllowedMessageActions(global: GlobalState, message: ApiMes
|| getServerTime(global.serverTimeOffset) - message.date < MESSAGE_EDIT_ALLOWED_TIME
) && !(
content.sticker || content.contact || content.poll || content.action || content.audio
|| (content.video?.isRound) || content.location
|| (content.video?.isRound) || content.location || content.invoice
)
&& !isForwardedMessage(message)
&& !message.viaBotId
@ -922,6 +922,20 @@ export function selectHasProtectedMessage(global: GlobalState, chatId: string, m
return messageIds.some((messageId) => messages[messageId]?.isProtected);
}
export function selectCanForwardMessages(global: GlobalState, chatId: string, messageIds?: number[]) {
if (selectChat(global, chatId)?.isProtected) {
return false;
}
if (!messageIds) {
return false;
}
const messages = selectChatMessages(global, chatId);
return messageIds.every((messageId) => messages[messageId]?.isForwardingAllowed);
}
export function selectSponsoredMessage(global: GlobalState, chatId: string) {
const chat = selectChat(global, chatId);
const message = chat && isChatChannel(chat) ? global.messages.sponsoredByChatId[chatId] : undefined;