Voice Chats: Indicators and service messages (#1134)
This commit is contained in:
parent
6f9b6ba3df
commit
23529106b3
@ -40,6 +40,8 @@ function buildApiChatFieldsFromPeerEntity(
|
|||||||
&& { username: peerEntity.username }
|
&& { username: peerEntity.username }
|
||||||
),
|
),
|
||||||
...(('verified' in peerEntity) && { isVerified: peerEntity.verified }),
|
...(('verified' in peerEntity) && { isVerified: peerEntity.verified }),
|
||||||
|
...(('callActive' in peerEntity) && { isCallActive: peerEntity.callActive }),
|
||||||
|
...(('callNotEmpty' in peerEntity) && { isCallNotEmpty: peerEntity.callNotEmpty }),
|
||||||
...((peerEntity instanceof GramJs.Chat || peerEntity instanceof GramJs.Channel) && {
|
...((peerEntity instanceof GramJs.Chat || peerEntity instanceof GramJs.Channel) && {
|
||||||
...(peerEntity.participantsCount && { membersCount: peerEntity.participantsCount }),
|
...(peerEntity.participantsCount && { membersCount: peerEntity.participantsCount }),
|
||||||
joinDate: peerEntity.date,
|
joinDate: peerEntity.date,
|
||||||
|
|||||||
@ -599,6 +599,13 @@ function buildAction(
|
|||||||
const currencySign = getCurrencySign(action.currency);
|
const currencySign = getCurrencySign(action.currency);
|
||||||
const amount = (Number(action.totalAmount) / 100).toFixed(2);
|
const amount = (Number(action.totalAmount) / 100).toFixed(2);
|
||||||
text = `You successfully transferred ${currencySign}${amount} to shop for %product%`;
|
text = `You successfully transferred ${currencySign}${amount} to shop for %product%`;
|
||||||
|
} else if (action instanceof GramJs.MessageActionGroupCall) {
|
||||||
|
if (action.duration) {
|
||||||
|
const mins = Math.max(Math.round(action.duration / 60), 1);
|
||||||
|
text = `Voice chat ended (${mins} min${mins > 1 ? 's' : ''})`;
|
||||||
|
} else {
|
||||||
|
text = 'Voice chat started';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
text = '%ACTION_NOT_IMPLEMENTED%';
|
text = '%ACTION_NOT_IMPLEMENTED%';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -355,6 +355,7 @@ async function getFullChannelInfo(
|
|||||||
canViewParticipants,
|
canViewParticipants,
|
||||||
linkedChatId,
|
linkedChatId,
|
||||||
hiddenPrehistory,
|
hiddenPrehistory,
|
||||||
|
call,
|
||||||
} = result.fullChat;
|
} = result.fullChat;
|
||||||
|
|
||||||
const inviteLink = exportedInvite instanceof GramJs.ChatInviteExported
|
const inviteLink = exportedInvite instanceof GramJs.ChatInviteExported
|
||||||
@ -387,6 +388,7 @@ async function getFullChannelInfo(
|
|||||||
members,
|
members,
|
||||||
kickedMembers,
|
kickedMembers,
|
||||||
adminMembers,
|
adminMembers,
|
||||||
|
groupCallId: call ? call.id.toString() : undefined,
|
||||||
linkedChatId: linkedChatId ? getApiChatIdFromMtpPeer({ chatId: linkedChatId } as GramJs.TypePeer) : undefined,
|
linkedChatId: linkedChatId ? getApiChatIdFromMtpPeer({ chatId: linkedChatId } as GramJs.TypePeer) : undefined,
|
||||||
},
|
},
|
||||||
users: [...(users || []), ...(bannedUsers || []), ...(adminUsers || [])],
|
users: [...(users || []), ...(bannedUsers || []), ...(adminUsers || [])],
|
||||||
|
|||||||
@ -30,6 +30,10 @@ export interface ApiChat {
|
|||||||
isSupport?: boolean;
|
isSupport?: boolean;
|
||||||
photos?: ApiPhoto[];
|
photos?: ApiPhoto[];
|
||||||
|
|
||||||
|
// Calls
|
||||||
|
isCallActive?: boolean;
|
||||||
|
isCallNotEmpty?: boolean;
|
||||||
|
|
||||||
// Current user permissions
|
// Current user permissions
|
||||||
isNotJoined?: boolean;
|
isNotJoined?: boolean;
|
||||||
isCreator?: boolean;
|
isCreator?: boolean;
|
||||||
@ -56,6 +60,21 @@ export interface ApiTypingStatus {
|
|||||||
timestamp: number;
|
timestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiTypeGroupCall {
|
||||||
|
joinMuted?: true;
|
||||||
|
canChangeJoinMuted?: true;
|
||||||
|
joinDateAsc?: true;
|
||||||
|
scheduleStartSubscribed?: true;
|
||||||
|
id: number;
|
||||||
|
participantsCount: number;
|
||||||
|
params?: any;
|
||||||
|
title?: string;
|
||||||
|
streamDcId?: number;
|
||||||
|
recordStartDate?: number;
|
||||||
|
scheduleDate?: number;
|
||||||
|
version: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ApiChatFullInfo {
|
export interface ApiChatFullInfo {
|
||||||
about?: string;
|
about?: string;
|
||||||
onlineCount?: number;
|
onlineCount?: number;
|
||||||
@ -65,6 +84,7 @@ export interface ApiChatFullInfo {
|
|||||||
canViewMembers?: boolean;
|
canViewMembers?: boolean;
|
||||||
isPreHistoryHidden?: boolean;
|
isPreHistoryHidden?: boolean;
|
||||||
inviteLink?: string;
|
inviteLink?: string;
|
||||||
|
groupCallId?: string;
|
||||||
slowMode?: {
|
slowMode?: {
|
||||||
seconds: number;
|
seconds: number;
|
||||||
nextSendDate?: number;
|
nextSendDate?: number;
|
||||||
|
|||||||
@ -52,6 +52,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
.title, .subtitle {
|
.title, .subtitle {
|
||||||
padding-right: .125rem;
|
padding-right: .125rem;
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import useEnsureMessage from '../../../hooks/useEnsureMessage';
|
|||||||
import useChatContextActions from '../../../hooks/useChatContextActions';
|
import useChatContextActions from '../../../hooks/useChatContextActions';
|
||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import useMedia from '../../../hooks/useMedia';
|
import useMedia from '../../../hooks/useMedia';
|
||||||
|
import ChatCallStatus from './ChatCallStatus';
|
||||||
import { ChatAnimationTypes } from './hooks';
|
import { ChatAnimationTypes } from './hooks';
|
||||||
|
|
||||||
import Avatar from '../../common/Avatar';
|
import Avatar from '../../common/Avatar';
|
||||||
@ -248,13 +249,18 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
contextActions={contextActions}
|
contextActions={contextActions}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
>
|
>
|
||||||
<Avatar
|
<div className="status">
|
||||||
chat={chat}
|
<Avatar
|
||||||
user={privateChatUser}
|
chat={chat}
|
||||||
withOnlineStatus
|
user={privateChatUser}
|
||||||
isSavedMessages={privateChatUser && privateChatUser.isSelf}
|
withOnlineStatus
|
||||||
lastSyncTime={lastSyncTime}
|
isSavedMessages={privateChatUser && privateChatUser.isSelf}
|
||||||
/>
|
lastSyncTime={lastSyncTime}
|
||||||
|
/>
|
||||||
|
{chat.isCallActive && (
|
||||||
|
<ChatCallStatus isSelected={isSelected} isActive={animationLevel !== 0} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h3>{renderText(getChatTitle(lang, chat, privateChatUser))}</h3>
|
<h3>{renderText(getChatTitle(lang, chat, privateChatUser))}</h3>
|
||||||
|
|||||||
80
src/components/left/main/ChatCallStatus.scss
Normal file
80
src/components/left/main/ChatCallStatus.scss
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
@keyframes bar-animation-transform-1 {
|
||||||
|
0% { transform: scaleY(0.33); }
|
||||||
|
12.5% { transform: scaleY(1.66); }
|
||||||
|
25% { transform: scaleY(0.33); }
|
||||||
|
37.5% { transform: scaleY(1); }
|
||||||
|
50% { transform: scaleY(0.33); }
|
||||||
|
62.5% { transform: scaleY(1.66); }
|
||||||
|
75% { transform: scaleY(0.33); }
|
||||||
|
87.5% { transform: scaleY(1.66); }
|
||||||
|
100% { transform: scaleY(0.33); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bar-animation-transform-2 {
|
||||||
|
0% { transform: scaleY(1); }
|
||||||
|
12.5% { transform: scaleY(0.33); }
|
||||||
|
25% { transform: scaleY(1.66); }
|
||||||
|
37.5% { transform: scaleY(0.33); }
|
||||||
|
50% { transform: scaleY(1); }
|
||||||
|
62.5% { transform: scaleY(0.33); }
|
||||||
|
75% { transform: scaleY(1.66); }
|
||||||
|
87.5% { transform: scaleY(0.33); }
|
||||||
|
100% { transform: scaleY(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.ChatCallStatus {
|
||||||
|
position: absolute;
|
||||||
|
right: 6px;
|
||||||
|
bottom: 0;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #0ac630;
|
||||||
|
border: 2px solid var(--color-background);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
& > div {
|
||||||
|
width: 2px;
|
||||||
|
height: 6px;
|
||||||
|
background: var(--color-background);
|
||||||
|
border-radius: 1px;
|
||||||
|
margin: 1px;
|
||||||
|
will-change: transform;
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
& > div:nth-child(odd) {
|
||||||
|
transform: scaleY(0.8);
|
||||||
|
}
|
||||||
|
& > div:nth-child(even) {
|
||||||
|
transform: scaleY(1.33);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: var(--color-white);
|
||||||
|
border-color: var(--color-chat-active);
|
||||||
|
.indicator div{
|
||||||
|
background-color: var(--color-chat-active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active .indicator {
|
||||||
|
div:nth-child(odd) {
|
||||||
|
animation: bar-animation-transform-2 3.2s normal infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:nth-child(even) {
|
||||||
|
animation: bar-animation-transform-1 3.2s normal infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
26
src/components/left/main/ChatCallStatus.tsx
Normal file
26
src/components/left/main/ChatCallStatus.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import React, { FC, memo } from '../../../lib/teact/teact';
|
||||||
|
import buildClassName from '../../../util/buildClassName';
|
||||||
|
|
||||||
|
import './ChatCallStatus.scss';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
isSelected?: boolean;
|
||||||
|
isActive?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ChatCallStatus: FC<OwnProps> = ({
|
||||||
|
isSelected,
|
||||||
|
isActive,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className={buildClassName('ChatCallStatus', isActive && 'active', isSelected && 'selected')}>
|
||||||
|
<div className="indicator">
|
||||||
|
<div />
|
||||||
|
<div />
|
||||||
|
<div />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ChatCallStatus);
|
||||||
6
src/lib/gramjs/tl/api.d.ts
vendored
6
src/lib/gramjs/tl/api.d.ts
vendored
@ -285,7 +285,7 @@ namespace Api {
|
|||||||
export type TypeAccessPointRule = AccessPointRule;
|
export type TypeAccessPointRule = AccessPointRule;
|
||||||
export type TypeTlsClientHello = TlsClientHello;
|
export type TypeTlsClientHello = TlsClientHello;
|
||||||
export type TypeTlsBlock = TlsBlockString | TlsBlockRandom | TlsBlockZero | TlsBlockDomain | TlsBlockGrease | TlsBlockScope;
|
export type TypeTlsBlock = TlsBlockString | TlsBlockRandom | TlsBlockZero | TlsBlockDomain | TlsBlockGrease | TlsBlockScope;
|
||||||
|
|
||||||
|
|
||||||
export namespace storage {
|
export namespace storage {
|
||||||
export type TypeFileType = storage.FileUnknown | storage.FilePartial | storage.FileJpeg | storage.FileGif | storage.FilePng | storage.FilePdf | storage.FileMp3 | storage.FileMov | storage.FileMp4 | storage.FileWebp;
|
export type TypeFileType = storage.FileUnknown | storage.FilePartial | storage.FileJpeg | storage.FileGif | storage.FilePng | storage.FilePdf | storage.FileMp3 | storage.FileMov | storage.FileMp4 | storage.FileWebp;
|
||||||
@ -7001,7 +7001,7 @@ namespace Api {
|
|||||||
}> {
|
}> {
|
||||||
entries: Api.TypeTlsBlock[];
|
entries: Api.TypeTlsBlock[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export namespace storage {
|
export namespace storage {
|
||||||
export class FileUnknown extends VirtualClass<void> {};
|
export class FileUnknown extends VirtualClass<void> {};
|
||||||
@ -8500,7 +8500,7 @@ namespace Api {
|
|||||||
}>, Api.TypeDestroySessionRes> {
|
}>, Api.TypeDestroySessionRes> {
|
||||||
sessionId: long;
|
sessionId: long;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export namespace auth {
|
export namespace auth {
|
||||||
export class SendCode extends Request<Partial<{
|
export class SendCode extends Request<Partial<{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user