From 0575fc6e0052b9d950d71fb32003c48302c52367 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Mon, 29 Nov 2021 18:26:02 +0100 Subject: [PATCH] Calls: Add peer-to-peer calls with fallback to group calls --- src/api/gramjs/methods/chats.ts | 51 +++++--- src/api/gramjs/methods/management.ts | 16 ++- src/assets/call-fallback-avatar.png | Bin 0 -> 18478 bytes src/bundles/calls.ts | 1 + .../calls/CallFallbackConfirm.async.tsx | 15 +++ src/components/calls/CallFallbackConfirm.tsx | 68 +++++++++++ src/components/main/Main.tsx | 5 + src/components/middle/HeaderActions.tsx | 35 ++++-- src/components/middle/HeaderMenuContainer.tsx | 19 ++- .../right/hooks/useProfileViewportIds.ts | 8 +- src/components/ui/ConfirmDialog.tsx | 4 +- src/global/cache.ts | 12 ++ src/global/types.ts | 11 +- src/lib/teact/teact.ts | 4 +- src/modules/actions/api/calls.async.ts | 114 ++++++++++++++++-- src/modules/actions/ui/calls.ts | 26 +++- src/modules/selectors/calls.ts | 9 +- 17 files changed, 346 insertions(+), 52 deletions(-) create mode 100644 src/assets/call-fallback-avatar.png create mode 100644 src/components/calls/CallFallbackConfirm.async.tsx create mode 100644 src/components/calls/CallFallbackConfirm.tsx diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index 5932da779..f5aa4148e 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -495,10 +495,10 @@ export async function updateChatMutedState({ } export async function createChannel({ - title, about, users, + title, about = '', users, }: { - title: string; about?: string; users: ApiUser[]; -}): Promise { + title: string; about?: string; users?: ApiUser[]; +}, noErrorUpdate = false): Promise { const result = await invokeRequest(new GramJs.channels.CreateChannel({ broadcast: true, title, @@ -527,10 +527,16 @@ export async function createChannel({ const channel = buildApiChatFromPreview(newChannel)!; - await invokeRequest(new GramJs.channels.InviteToChannel({ - channel: buildInputEntity(channel.id, channel.accessHash) as GramJs.InputChannel, - users: users.map(({ id, accessHash }) => buildInputEntity(id, accessHash)) as GramJs.InputUser[], - })); + if (users?.length) { + try { + await invokeRequest(new GramJs.channels.InviteToChannel({ + channel: buildInputEntity(channel.id, channel.accessHash) as GramJs.InputChannel, + users: users.map(({ id, accessHash }) => buildInputEntity(id, accessHash)) as GramJs.InputUser[], + }), true, noErrorUpdate); + } catch (err) { + // `noErrorUpdate` will cause an exception which we don't want either + } + } return channel; } @@ -1027,20 +1033,25 @@ export async function openChatByInvite(hash: string) { return { chatId: chat.id }; } -export function addChatMembers(chat: ApiChat, users: ApiUser[]) { - if (chat.type === 'chatTypeChannel' || chat.type === 'chatTypeSuperGroup') { - return invokeRequest(new GramJs.channels.InviteToChannel({ - channel: buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel, - users: users.map((user) => buildInputEntity(user.id, user.accessHash)) as GramJs.InputUser[], - }), true); - } +export function addChatMembers(chat: ApiChat, users: ApiUser[], noErrorUpdate = false) { + try { + if (chat.type === 'chatTypeChannel' || chat.type === 'chatTypeSuperGroup') { + return invokeRequest(new GramJs.channels.InviteToChannel({ + channel: buildInputEntity(chat.id, chat.accessHash) as GramJs.InputChannel, + users: users.map((user) => buildInputEntity(user.id, user.accessHash)) as GramJs.InputUser[], + }), true, noErrorUpdate); + } - return Promise.all(users.map((user) => { - return invokeRequest(new GramJs.messages.AddChatUser({ - chatId: buildInputEntity(chat.id) as BigInt.BigInteger, - userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, - }), true); - })); + return Promise.all(users.map((user) => { + return invokeRequest(new GramJs.messages.AddChatUser({ + chatId: buildInputEntity(chat.id) as BigInt.BigInteger, + userId: buildInputEntity(user.id, user.accessHash) as GramJs.InputUser, + }), true, noErrorUpdate); + })); + } catch (err) { + // `noErrorUpdate` will cause an exception which we don't want either + return undefined; + } } export function deleteChatMember(chat: ApiChat, user: ApiUser) { diff --git a/src/api/gramjs/methods/management.ts b/src/api/gramjs/methods/management.ts index af93f0ebf..73c98a485 100644 --- a/src/api/gramjs/methods/management.ts +++ b/src/api/gramjs/methods/management.ts @@ -42,15 +42,19 @@ export async function setChatUsername( } } -export async function updatePrivateLink( - { chat }: { chat: ApiChat }, -) { +export async function updatePrivateLink({ + chat, usageLimit, expireDate, +}: { + chat: ApiChat; usageLimit?: number; expireDate?: number; +}) { const result = await invokeRequest(new GramJs.messages.ExportChatInvite({ peer: buildInputPeer(chat.id, chat.accessHash), + usageLimit, + expireDate, })); - if (!result || !(result instanceof GramJs.ChatInviteExported)) { - return; + if (!result) { + return undefined; } onUpdate({ @@ -60,4 +64,6 @@ export async function updatePrivateLink( inviteLink: result.link, }, }); + + return result.link; } diff --git a/src/assets/call-fallback-avatar.png b/src/assets/call-fallback-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..3a850f2ee00e6bd32841e1a89e55fd3490aaa87f GIT binary patch literal 18478 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 M07*qoM6N<$f{zOeQ~&?~ literal 0 HcmV?d00001 diff --git a/src/bundles/calls.ts b/src/bundles/calls.ts index cc2f86d7f..a33bd663f 100644 --- a/src/bundles/calls.ts +++ b/src/bundles/calls.ts @@ -1,2 +1,3 @@ export { default as GroupCall } from '../components/calls/group/GroupCall'; export { default as ActiveCallHeader } from '../components/calls/ActiveCallHeader'; +export { default as CallFallbackConfirm } from '../components/calls/CallFallbackConfirm'; diff --git a/src/components/calls/CallFallbackConfirm.async.tsx b/src/components/calls/CallFallbackConfirm.async.tsx new file mode 100644 index 000000000..c106cd23f --- /dev/null +++ b/src/components/calls/CallFallbackConfirm.async.tsx @@ -0,0 +1,15 @@ +import React, { FC, memo } from '../../lib/teact/teact'; +import useModuleLoader from '../../hooks/useModuleLoader'; +import { Bundles } from '../../util/moduleLoader'; + +type OwnProps = { + isOpen: boolean; +}; + +const CallFallbackConfirmAsync: FC = ({ isOpen }) => { + const CallFallbackConfirm = useModuleLoader(Bundles.Calls, 'CallFallbackConfirm', !isOpen); + + return CallFallbackConfirm ? : undefined; +}; + +export default memo(CallFallbackConfirmAsync); diff --git a/src/components/calls/CallFallbackConfirm.tsx b/src/components/calls/CallFallbackConfirm.tsx new file mode 100644 index 000000000..18e2c5f9a --- /dev/null +++ b/src/components/calls/CallFallbackConfirm.tsx @@ -0,0 +1,68 @@ +import React, { FC, memo, useState } from '../../lib/teact/teact'; +import { withGlobal } from '../../lib/teact/teactn'; + +import { GlobalActions } from '../../global/types'; + +import { pick } from '../../util/iteratees'; + +import ConfirmDialog from '../ui/ConfirmDialog'; +import Checkbox from '../ui/Checkbox'; +import { selectCallFallbackChannelTitle } from '../../modules/selectors/calls'; +import { getUserFullName } from '../../modules/helpers'; +import { selectCurrentMessageList, selectUser } from '../../modules/selectors'; +import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; + +export type OwnProps = { + isOpen: boolean; +}; + +interface StateProps { + userFullName?: string; + channelTitle: string; +} + +type DispatchProps = Pick; + +const CallFallbackConfirm: FC = ({ + isOpen, + channelTitle, + userFullName, + closeCallFallbackConfirm, + inviteToCallFallback, +}) => { + const [shouldRemove, setShouldRemove] = useState(true); + const renderingUserFullName = useCurrentOrPrev(userFullName, true); + + return ( + { + inviteToCallFallback({ shouldRemove }); + }} + onClose={closeCallFallbackConfirm} + > +

The call will be started in a private channel {channelTitle}.

+ +
+ ); +}; + +export default memo(withGlobal( + (global): StateProps => { + const { chatId } = selectCurrentMessageList(global) || {}; + const user = chatId ? selectUser(global, chatId) : undefined; + + return { + userFullName: user ? getUserFullName(user) : undefined, + channelTitle: selectCallFallbackChannelTitle(global), + }; + }, + (setGlobal, actions): DispatchProps => pick(actions, [ + 'closeCallFallbackConfirm', 'inviteToCallFallback', + ]), +)(CallFallbackConfirm)); diff --git a/src/components/main/Main.tsx b/src/components/main/Main.tsx index 821b70e25..9be9e1e9f 100644 --- a/src/components/main/Main.tsx +++ b/src/components/main/Main.tsx @@ -46,6 +46,7 @@ import HistoryCalendar from './HistoryCalendar.async'; import StickerSetModal from '../common/StickerSetModal.async'; import GroupCall from '../calls/group/GroupCall.async'; import ActiveCallHeader from '../calls/ActiveCallHeader.async'; +import CallFallbackConfirm from '../calls/CallFallbackConfirm.async'; import './Main.scss'; @@ -67,6 +68,7 @@ type StateProps = { animationLevel: number; language?: LangCode; wasTimeFormatSetManually?: boolean; + isCallFallbackConfirmOpen: boolean; }; type DispatchProps = Pick = ({ animationLevel, language, wasTimeFormatSetManually, + isCallFallbackConfirmOpen, loadAnimatedEmojis, loadNotificationSettings, loadNotificationExceptions, @@ -282,6 +285,7 @@ const Main: FC = ({ )} + ); }; @@ -333,6 +337,7 @@ export default memo(withGlobal( animationLevel, language, wasTimeFormatSetManually, + isCallFallbackConfirmOpen: Boolean(global.groupCalls.isFallbackConfirmOpen), }; }, (setGlobal, actions): DispatchProps => pick(actions, [ diff --git a/src/components/middle/HeaderActions.tsx b/src/components/middle/HeaderActions.tsx index 3e98b28d3..6acf904b5 100644 --- a/src/components/middle/HeaderActions.tsx +++ b/src/components/middle/HeaderActions.tsx @@ -13,7 +13,9 @@ import { IAnchorPosition } from '../../types'; import { ARE_CALLS_SUPPORTED, IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment'; import { pick } from '../../util/iteratees'; -import { isChatBasicGroup, isChatChannel, isChatSuperGroup } from '../../modules/helpers'; +import { + isChatBasicGroup, isChatChannel, isChatSuperGroup, isUserId, +} from '../../modules/helpers'; import { selectChat, selectChatBot, @@ -43,13 +45,16 @@ interface StateProps { canRestartBot?: boolean; canSubscribe?: boolean; canSearch?: boolean; + canCall?: boolean; canMute?: boolean; canLeave?: boolean; canEnterVoiceChat?: boolean; canCreateVoiceChat?: boolean; } -type DispatchProps = Pick; +type DispatchProps = Pick; // Chrome breaks layout when focusing input during transition const SEARCH_FOCUS_DELAY_MS = 400; @@ -63,6 +68,7 @@ const HeaderActions: FC = ({ canRestartBot, canSubscribe, canSearch, + canCall, canMute, canLeave, canEnterVoiceChat, @@ -73,6 +79,7 @@ const HeaderActions: FC = ({ sendBotCommand, openLocalTextSearch, restartBot, + openCallFallbackConfirm, }) => { // eslint-disable-next-line no-null/no-null const menuButtonRef = useRef(null); @@ -170,6 +177,17 @@ const HeaderActions: FC = ({ )} + {canCall && ( + + )} )}