Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2021-08-30 17:22:33 +03:00
commit 5180ffab4a
15 changed files with 351 additions and 72 deletions

View File

@ -2480,11 +2480,15 @@ Unused sets are archived when you add more.";
"Call.CallInProgressTitle" = "Call in Progress";
"Call.CallInProgressMessage" = "Finish call with %1$@ and start a new one with %2$@?";
"Call.CallInProgressVoiceChatMessage" = "Finish call with %1$@ and start a voice chat with %2$@?";
"Call.CallInProgressLiveStreamMessage" = "Finish call with %1$@ and start a live stream with %2$@?";
"Call.ExternalCallInProgressMessage" = "Please finish the current call first.";
"Call.VoiceChatInProgressTitle" = "Voice Chat in Progress";
"Call.LiveStreamInProgressTitle" = "Live Stream in Progress";
"Call.VoiceChatInProgressMessage" = "Leave voice chat in %1$@ and start a new one with %2$@?";
"Call.LiveStreamInProgressMessage" = "Leave live stream in %1$@ and start a new one with %2$@?";
"Call.VoiceChatInProgressCallMessage" = "Leave voice chat in %1$@ and start a call with %2$@?";
"Call.LiveStreamInProgressCallMessage" = "Leave live stream in %1$@ and start a call with %2$@?";
"Call.Message" = "Message";
@ -2618,6 +2622,7 @@ Unused sets are archived when you add more.";
"Channel.AdminLog.CanBeAnonymous" = "Remain Anonymous";
"Channel.AdminLog.CanEditMessages" = "Edit Messages";
"Channel.AdminLog.CanManageCalls" = "Manage Voice Chats";
"Channel.AdminLog.CanManageLiveStreams" = "Manage Live Streams";
"Channel.AdminLog.MessageToggleInvitesOn" = "%@ enabled group invites";
"Channel.AdminLog.MessageToggleInvitesOff" = "%@ disabled group invites";
@ -2676,6 +2681,7 @@ Unused sets are archived when you add more.";
"Channel.AdminLogFilter.EventsPinned" = "Pinned Messages";
"Channel.AdminLogFilter.EventsLeaving" = "Members Removed";
"Channel.AdminLogFilter.EventsCalls" = "Voice Chats";
"Channel.AdminLogFilter.EventsLiveStreams" = "Live Streams";
"Channel.AdminLogFilter.EventsInviteLinks" = "Invite Links";
"Channel.AdminLogFilter.AdminsTitle" = "ADMINS";
"Channel.AdminLogFilter.AdminsAll" = "All Admins";
@ -5708,6 +5714,7 @@ Sorry for the inconvenience.";
"VoiceChat.SpeakPermissionAdmin" = "New paricipants are muted";
"VoiceChat.Share" = "Share Invite Link";
"VoiceChat.EndVoiceChat" = "End Voice Chat";
"VoiceChat.EndLiveStream" = "End Live Stream";
"VoiceChat.CopyInviteLink" = "Copy Invite Link";
"VoiceChat.InviteLinkCopiedText" = "Invite link copied to clipboard";
@ -5723,16 +5730,17 @@ Sorry for the inconvenience.";
"VoiceChatChannel.Title" = "Live Stream";
"VoiceChat.InviteMember" = "Invite Member";
"VoiceChat.UserInvited" = "You invited **%@** to the voice chat";
"Notification.VoiceChatInvitation" = "%1$@ invited %2$@ to the voice chat";
"Notification.VoiceChatInvitationForYou" = "%1$@ invited you to the voice chat";
"VoiceChat.InvitedPeerText" = "You invited %@ to the voice chat";
"LiveStream.InvitedPeerText" = "You invited %@ to the live stream";
"VoiceChat.RemovedPeerText" = "You removed %@ from this group";
"Notification.VoiceChatStarted" = "%1$@ started a voice chat";
"Notification.VoiceChatEnded" = "Voice chat ended (%@)";
"Notification.LiveStreamEnded" = "Live stream ended (%@)";
"Notification.VoiceChatEndedGroup" = "%1$@ ended the voice chat (%2$@)";
"VoiceChat.Panel.TapToJoin" = "Tap to join";
@ -5752,12 +5760,17 @@ Sorry for the inconvenience.";
"VoiceChat.Status.MembersFormat" = "%1$@ %2$@";
"ChannelInfo.CreateVoiceChat" = "Start Voice Chat";
"ChannelInfo.CreateLiveStream" = "Start Live Stream";
"VoiceChat.AnonymousDisabledAlertText" = "Sorry, you can't join voice chat as an anonymous admin.";
"LiveStream.AnonymousDisabledAlertText" = "Sorry, you can't join live stream as an anonymous admin.";
"VoiceChat.ChatFullAlertText" = "Sorry, this voice chat has too many participants at the moment.";
"LiveStream.ChatFullAlertText" = "Sorry, this live stream has too many participants at the moment.";
"VoiceChat.EndConfirmationTitle" = "End voice chat";
"LiveStream.EndConfirmationTitle" = "End live stream";
"VoiceChat.EndConfirmationText" = "Are you sure you want to end this voice chat?";
"LiveStream.EndConfirmationText" = "Are you sure you want to end this live stream?";
"VoiceChat.EndConfirmationEnd" = "End";
"VoiceChat.InviteMemberToGroupFirstText" = "%1$@ isn't a member of \"%2$@\" yet. Add them to the group?";
@ -5765,6 +5778,7 @@ Sorry for the inconvenience.";
"VoiceChat.InviteMemberToGroupFirstAdd" = "Add";
"VoiceChat.CreateNewVoiceChatText" = "Voice chat ended. Start a new one?";
"LiveStream.CreateNewVoiceChatText" = "Live stream ended. Start a new one?";
"VoiceChat.CreateNewVoiceChatStart" = "Start";
"VoiceChat.CreateNewVoiceChatStartNow" = "Start Now";
"VoiceChat.CreateNewVoiceChatSchedule" = "Schedule";
@ -5774,8 +5788,10 @@ Sorry for the inconvenience.";
"PUSH_CHAT_VOICECHAT_INVITE_YOU" = "%2$@|%1$@ invited you to the voice chat";
"PUSH_CHAT_VOICECHAT_END" = "%2$@|%1$@ has ended the voice chat";
"Call.VoiceChatInProgressTitle" = "Voice Chat in Progress";
"Call.VoiceChatInProgressMessageCall" = "Leave voice chat in %1$@ and start a call with %2$@?";
"PUSH_CHAT_LIVESTREAM_START" = "%2$@|%1$@ started a live stream";
"PUSH_CHAT_LIVESTREAM_INVITE" = "%2$@|%1$@ invited %3$@ to the live stream";
"PUSH_CHAT_LIVESTREAM_INVITE_YOU" = "%2$@|%1$@ invited you to the live stream";
"PUSH_CHAT_LIVESTREAM_END" = "%2$@|%1$@ has ended the live stream";
"Conversation.Dice.u1F3B3" = "Send a bowling emoji to try your luck.";
@ -5791,7 +5807,9 @@ Sorry for the inconvenience.";
"VoiceOver.Chat.MessagesSelected_any" = "%@ messages selected";
"Channel.AdminLog.StartedVoiceChat" = "%1$@ started voice chat";
"Channel.AdminLog.StartedLiveStream" = "%1$@ started live stream";
"Channel.AdminLog.EndedVoiceChat" = "%1$@ ended voice chat";
"Channel.AdminLog.EndedLiveStream" = "%1$@ ended live stream";
"Channel.AdminLog.MutedParticipant" = "%1$@ muted %2$@";
"Channel.AdminLog.UnmutedMutedParticipant" = "%1$@ unmuted %2$@";
"Channel.AdminLog.AllowedNewMembersToSpeak" = "%1$@ allowed new members to speak";
@ -5800,22 +5818,29 @@ Sorry for the inconvenience.";
"Group.GroupMembersHeader" = "GROUP MEMBERS";
"Conversation.VoiceChatMediaRecordingRestricted" = "You can't record voice and video messages during a voice chat.";
"Conversation.LiveStreamMediaRecordingRestricted" = "You can't record voice and video messages during a live stream.";
"CallList.ActiveVoiceChatsHeader" = "ACTIVE VOICE CHATS";
"CallList.RecentCallsHeader" = "RECENT CALLS";
"VoiceChat.PeerJoinedText" = "%@ joined the voice chat";
"LiveStream.PeerJoinedText" = "%@ joined the live stream";
"VoiceChat.StartRecording" = "Start Recording";
"LiveStream.StartRecording" = "Start Recording";
"VoiceChat.StopRecording" = "Stop Recording";
"VoiceChat.StartRecordingTitle" = "Start Recording";
"LiveStream.StartRecordingTitle" = "Start Recording";
"VoiceChat.StartRecordingText" = "Do you want to start recording this chat and save the result into an audio file?\n\nOther members will see that the chat is being recorded.";
"LiveStream.StartRecordingText" = "Do you want to start recording this live stream and save the result into an audio file?\n\nOther members will see that the chat is being recorded.";
"VoiceChat.StartRecordingStart" = "Start";
"VoiceChat.RecordingTitlePlaceholder" = "Audio Title (Optional)";
"VoiceChat.RecordingStarted" = "Voice chat recording started";
"LiveStream.RecordingStarted" = "Live stream recording started";
"VoiceChat.RecordingInProgress" = "Voice chat is being recorded";
"LiveStream.RecordingInProgress" = "Live stream is being recorded";
"VoiceChat.StopRecordingTitle" = "Stop Recording?";
"VoiceChat.StopRecordingStop" = "Stop";
@ -5840,6 +5865,7 @@ Sorry for the inconvenience.";
"VoiceChat.MuteForMe" = "Mute for Me";
"PeerInfo.ButtonVoiceChat" = "Voice Chat";
"PeerInfo.ButtonLiveStream" = "Live Stream";
"VoiceChat.OpenChat" = "Open Chat";
"GroupInfo.InviteLinks" = "Invite Links";
@ -6187,16 +6213,20 @@ Sorry for the inconvenience.";
"VoiceChat.DisplayAsInfo" = "Choose whether you want to be displayed as your personal account or as your channel.";
"VoiceChat.DisplayAsInfoGroup" = "Choose whether you want to be displayed as your personal account, this group, or one of your channels.";
"VoiceChat.DisplayAsSuccess" = "Members of this voice chat will now see your as **%@**.";
"LiveStream.DisplayAsSuccess" = "Members of this live stream will now see your as **%@**.";
"VoiceChat.PersonalAccount" = "personal account";
"VoiceChat.EditTitle" = "Edit Voice Chat Title";
"LiveStream.EditTitle" = "Edit Live Stream Title";
"VoiceChat.EditPermissions" = "Edit Permissions";
"VoiceChat.OpenChannel" = "Open Channel";
"VoiceChat.EditTitleTitle" = "Voice Chat Title";
"VoiceChat.EditTitleText" = "Edit a title of this voice chat.";
"LiveStream.EditTitleText" = "Edit a title of this live stream.";
"VoiceChat.EditTitleSuccess" = "Voice chat title changed to **%@**.";
"LiveStream.EditTitleSuccess" = "Live stream title changed to **%@**.";
"VoiceChat.EditTitleRemoveSuccess" = "Voice chat title removed.";
"LiveStream.EditTitleRemoveSuccess" = "Live Stream title removed.";
"VoiceChat.InviteLink.Speaker" = "Speaker";
"VoiceChat.InviteLink.Listener" = "Listener";
@ -6217,8 +6247,6 @@ Sorry for the inconvenience.";
"VoiceChat.InviteLink.InviteListeners_many" = "[%@] Invite Listeners";
"VoiceChat.InviteLink.InviteListeners_any" = "[%@] Invite Listeners";
"Conversation.JoinVoiceChat" = "JOIN VOICE CHAT";
"Conversation.CancelForwardTitle" = "Cancel Forwarding";
"Conversation.CancelForwardText" = "Do you want to cancel forwarding or send messages to a different chat?";
"Conversation.CancelForwardCancelForward" = "Cancel Forwarding";
@ -6260,8 +6288,10 @@ Sorry for the inconvenience.";
"VoiceChat.RemovePeerConfirmationChannel" = "Are you sure you want to remove %@ from the channel?";
"VoiceChat.RemoveAndBanPeerConfirmation" = "Do you want to remove %1$@ from the voice chat and ban them in %2$@?";
"LiveStream.RemoveAndBanPeerConfirmation" = "Do you want to remove %1$@ from the live stream and ban them in %2$@?";
"Notification.VoiceChatStartedChannel" = "Voice chat started";
"Notification.LiveStreamStarted" = "Live stream started";
"Conversation.MessageCopied" = "Message copied to clipboard";
"Conversation.LinkCopied" = "Link copied to clipboard";
@ -6280,14 +6310,19 @@ Sorry for the inconvenience.";
"Conversation.DeletedFromContacts" = "**%@** deleted from your contacts";
"Conversation.VoiceChat" = "Voice Chat";
"Conversation.LiveStream" = "Live Stream";
"Conversation.JoinVoiceChatAsSpeaker" = "JOIN AS SPEAKER";
"Conversation.JoinVoiceChatAsListener" = "JOIN AS LISTENER";
"VoiceChat.LeaveConfirmation" = "Are you sure you want to leave this voice chat?";
"LiveStream.LeaveConfirmation" = "Are you sure you want to leave this live stream?";
"VoiceChat.LeaveVoiceChat" = "Leave Voice Chat";
"LiveStream.LeaveVoiceChat" = "Leave Live Stream";
"VoiceChat.LeaveAndEndVoiceChat" = "End Voice Chat";
"LiveStream.LeaveAndEndVoiceChat" = "End Live Stream";
"VoiceChat.LeaveAndCancelVoiceChat" = "Abort Voice Chat";
"LiveStream.LeaveAndCancelVoiceChat" = "Abort Live Stream";
"VoiceChat.ForwardTooltip.Chat" = "Invite link forwarded to **%@**";
"VoiceChat.ForwardTooltip.TwoChats" = "Invite link forwarded to **%@** and **%@**";
@ -6341,12 +6376,15 @@ Sorry for the inconvenience.";
"VoiceChat.UnpinVideo" = "Unpin Video";
"Notification.VoiceChatScheduledChannel" = "Voice chat scheduled for %@";
"Notification.LiveStreamScheduled" = "Live stream scheduled for %@";
"Notification.VoiceChatScheduled" = "%1$@ scheduled a voice chat for %2$@";
"Notification.VoiceChatScheduledTodayChannel" = "Voice chat scheduled for today at %@";
"Notification.LiveStreamScheduledToday" = "Live stream scheduled for today at %@";
"Notification.VoiceChatScheduledToday" = "%1$@ scheduled a voice chat for today at %2$@";
"Notification.VoiceChatScheduledTomorrowChannel" = "Voice chat scheduled for tomorrow at %@";
"Notification.LiveStreamScheduledTomorrow" = "Live stream scheduled for tomorrow at %@";
"Notification.VoiceChatScheduledTomorrow" = "%1$@ scheduled a voice chat for tomorrow at %2$@";
"VoiceChat.StartsIn" = "Starts in";
@ -6365,28 +6403,36 @@ Sorry for the inconvenience.";
"VoiceChat.TapToEditTitle" = "Tap to edit title";
"ChannelInfo.ScheduleVoiceChat" = "Schedule Voice Chat";
"ChannelInfo.ScheduleLiveStream" = "Schedule Live Stream";
"ScheduleVoiceChat.Title" = "Schedule Voice Chat";
"ScheduleVoiceChatChannel.Title" = "Schedule Voice Chat";
"ScheduleLiveStream.Title" = "Schedule Live Stream";
"ScheduleVoiceChat.GroupText" = "The members of the group will be notified that the voice chat will start in %@.";
"ScheduleVoiceChat.ChannelText" = "The members of the channel will be notified that the voice chat will start in %@.";
"ScheduleLiveStream.ChannelText" = "The members of the channel will be notified that the live stream will start in %@.";
"ScheduleVoiceChat.ScheduleToday" = "Start today at %@";
"ScheduleVoiceChat.ScheduleTomorrow" = "Start tomorrow at %@";
"ScheduleVoiceChat.ScheduleOn" = "Start on %@ at %@";
"Conversation.ScheduledVoiceChat" = "Scheduled Voice Chat";
"Conversation.ScheduledLiveStream" = "Scheduled Live Stream";
"Conversation.ScheduledVoiceChatStartsOn" = "Voice chat starts on %@";
"Conversation.ScheduledLiveStreamStartsOn" = "Live stream starts on %@";
"Conversation.ScheduledVoiceChatStartsOnShort" = "Starts on %@";
"Conversation.ScheduledVoiceChatStartsToday" = "Voice chat starts today at %@";
"Conversation.ScheduledLiveStreamStartsToday" = "Live stream starts today at %@";
"Conversation.ScheduledVoiceChatStartsTodayShort" = "Starts today at %@";
"Conversation.ScheduledVoiceChatStartsTomorrow" = "Voice chat starts tomorrow at %@";
"Conversation.ScheduledLiveStreamStartsTomorrow" = "Live stream starts tomorrow at %@";
"Conversation.ScheduledVoiceChatStartsTomorrowShort" = "Starts tomorrow at %@";
"VoiceChat.CancelVoiceChat" = "Abort Voice Chat";
"VoiceChat.CancelLiveStream" = "Abort Live Stream";
"VoiceChat.CancelConfirmationTitle" = "Abort Voice Chat";
"LiveStream.CancelConfirmationTitle" = "Abort Live Stream";
"VoiceChat.CancelConfirmationText" = "Do you want to abort the scheduled voice chat?";
"LiveStream.CancelConfirmationText" = "Do you want to abort the scheduled live stream?";
"VoiceChat.CancelConfirmationEnd" = "Abort";
"ScheduledIn.Seconds_1" = "%@ second";

View File

@ -142,7 +142,11 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
}
}
case .removeFromGroup:
text = strings.VoiceChat_RemoveAndBanPeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder), chatPeer.displayTitle(strings: strings, displayOrder: nameOrder))
if case let .channel(channel) = chatPeer, case .broadcast = channel.info {
text = strings.LiveStream_RemoveAndBanPeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder), chatPeer.displayTitle(strings: strings, displayOrder: nameOrder))
} else {
text = strings.VoiceChat_RemoveAndBanPeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder), chatPeer.displayTitle(strings: strings, displayOrder: nameOrder))
}
case .removeFromChannel:
text = strings.VoiceChat_RemovePeerConfirmationChannel(peer.displayTitle(strings: strings, displayOrder: nameOrder))
default:

View File

@ -379,7 +379,7 @@ private struct ChannelAdminControllerState: Equatable {
}
}
private func stringForRight(strings: PresentationStrings, right: TelegramChatAdminRightsFlags, isGroup: Bool, defaultBannedRights: TelegramChatBannedRights?) -> String {
private func stringForRight(strings: PresentationStrings, right: TelegramChatAdminRightsFlags, isGroup: Bool, isChannel: Bool, defaultBannedRights: TelegramChatBannedRights?) -> String {
if right.contains(.canChangeInfo) {
return isGroup ? strings.Group_EditAdmin_PermissionChangeInfo : strings.Channel_EditAdmin_PermissionChangeInfo
} else if right.contains(.canPostMessages) {
@ -407,7 +407,11 @@ private func stringForRight(strings: PresentationStrings, right: TelegramChatAdm
} else if right.contains(.canBeAnonymous) {
return strings.Channel_AdminLog_CanBeAnonymous
} else if right.contains(.canManageCalls) {
return strings.Channel_AdminLog_CanManageCalls
if isChannel {
return strings.Channel_AdminLog_CanManageLiveStreams
} else {
return strings.Channel_AdminLog_CanManageCalls
}
} else {
return ""
}
@ -498,6 +502,11 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
if let channel = channelView.peers[channelView.peerId] as? TelegramChannel, let admin = adminView.peers[adminView.peerId] {
entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, admin, adminView.peerPresences[admin.id] as? TelegramUserPresence))
var isChannel = false
if case .broadcast = channel.info {
isChannel = true
}
var isCreator = false
if let initialParticipant = initialParticipant, case .creator = initialParticipant {
@ -566,7 +575,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
var index = 0
for right in rightsOrder {
if accountUserRightsFlags.contains(right) {
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, defaultBannedRights: channel.defaultBannedRights), right, currentRightsFlags, currentRightsFlags.contains(right), right == .canBeAnonymous))
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, isChannel: isChannel, defaultBannedRights: channel.defaultBannedRights), right, currentRightsFlags, currentRightsFlags.contains(right), right == .canBeAnonymous))
index += 1
}
}
@ -596,7 +605,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
var index = 0
for right in rightsOrder {
if accountUserRightsFlags.contains(right) {
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, defaultBannedRights: channel.defaultBannedRights), right, currentRightsFlags, currentRightsFlags.contains(right), !state.updating && admin.id != accountPeerId && !rightEnabledByDefault(channelPeer: channel, right: right)))
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, isChannel: isChannel, defaultBannedRights: channel.defaultBannedRights), right, currentRightsFlags, currentRightsFlags.contains(right), !state.updating && admin.id != accountPeerId && !rightEnabledByDefault(channelPeer: channel, right: right)))
index += 1
}
}
@ -628,7 +637,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
} else if let initialParticipant = initialParticipant, case let .member(_, _, maybeAdminInfo, _, _) = initialParticipant, let adminInfo = maybeAdminInfo {
var index = 0
for right in rightsOrder {
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, defaultBannedRights: channel.defaultBannedRights), right, adminInfo.rights.rights, adminInfo.rights.rights.contains(right), false))
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, isChannel: isChannel, defaultBannedRights: channel.defaultBannedRights), right, adminInfo.rights.rights, adminInfo.rights.rights.contains(right), false))
index += 1
}
}
@ -683,6 +692,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
entries.append(.rightsTitle(presentationData.theme, presentationData.strings.Channel_EditAdmin_PermissionsHeader))
let isGroup = true
let isChannel = false
let maskRightsFlags: TelegramChatAdminRightsFlags = .groupSpecific
let rightsOrder: [TelegramChatAdminRightsFlags] = [
.canChangeInfo,
@ -714,7 +724,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
var index = 0
for right in rightsOrder {
if accountUserRightsFlags.contains(right) {
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, defaultBannedRights: group.defaultBannedRights), right, currentRightsFlags, currentRightsFlags.contains(right), !state.updating && accountIsCreator))
entries.append(.rightItem(presentationData.theme, index, stringForRight(strings: presentationData.strings, right: right, isGroup: isGroup, isChannel: isChannel, defaultBannedRights: group.defaultBannedRights), right, currentRightsFlags, currentRightsFlags.contains(right), !state.updating && accountIsCreator))
index += 1
}
}

View File

@ -526,8 +526,10 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
var joinText = self.strings.VoiceChat_PanelJoin
var title = self.strings.VoiceChat_Title
var isChannel = false
if let currentData = self.currentData, currentData.isChannel {
title = self.strings.VoiceChatChannel_Title
isChannel = true
}
var text = self.currentText
var isScheduled = false
@ -536,9 +538,9 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
isScheduled = true
if let voiceChatTitle = self.currentData?.info.title {
title = voiceChatTitle
text = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, alwaysShowTime: true, format: HumanReadableStringFormat(dateFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsOn($0) }, tomorrowFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTomorrow($0) }, todayFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsToday($0) })).string
text = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, alwaysShowTime: true, format: HumanReadableStringFormat(dateFormatString: { isChannel ? self.strings.Conversation_ScheduledLiveStreamStartsOn($0) : self.strings.Conversation_ScheduledVoiceChatStartsOn($0) }, tomorrowFormatString: { isChannel ? self.strings.Conversation_ScheduledLiveStreamStartsTomorrow($0) : self.strings.Conversation_ScheduledVoiceChatStartsTomorrow($0) }, todayFormatString: { isChannel ? self.strings.Conversation_ScheduledLiveStreamStartsToday($0) : self.strings.Conversation_ScheduledVoiceChatStartsToday($0) })).string
} else {
title = self.strings.Conversation_ScheduledVoiceChat
title = isChannel ? self.strings.Conversation_ScheduledLiveStream : self.strings.Conversation_ScheduledVoiceChat
text = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, alwaysShowTime: true, format: HumanReadableStringFormat(dateFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsOnShort($0) }, tomorrowFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTomorrowShort($0) }, todayFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTodayShort($0) })).string
}

View File

@ -398,6 +398,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
private var initialCall: EngineGroupCallDescription?
public let internalId: CallSessionInternalId
public let peerId: PeerId
private let isChannel: Bool
private var invite: String?
private var joinAsPeerId: PeerId
private var ignorePreviousJoinAsPeerId: (PeerId, UInt32)?
@ -650,6 +651,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
self.initialCall = initialCall
self.internalId = internalId
self.peerId = peerId
self.isChannel = isChannel
self.invite = invite
self.joinAsPeerId = joinAsPeerId ?? accountContext.account.peerId
self.schedulePending = initialCall == nil
@ -1524,12 +1526,12 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
}
if case .anonymousNotAllowed = error {
let presentationData = strongSelf.accountContext.sharedContext.currentPresentationData.with { $0 }
strongSelf.accountContext.sharedContext.mainWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.VoiceChat_AnonymousDisabledAlertText, actions: [
strongSelf.accountContext.sharedContext.mainWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: strongSelf.isChannel ? presentationData.strings.LiveStream_AnonymousDisabledAlertText : presentationData.strings.VoiceChat_AnonymousDisabledAlertText, actions: [
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
]), on: .root, blockInteraction: false, completion: {})
} else if case .tooManyParticipants = error {
let presentationData = strongSelf.accountContext.sharedContext.currentPresentationData.with { $0 }
strongSelf.accountContext.sharedContext.mainWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.VoiceChat_ChatFullAlertText, actions: [
strongSelf.accountContext.sharedContext.mainWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: strongSelf.isChannel ? presentationData.strings.LiveStream_ChatFullAlertText : presentationData.strings.VoiceChat_ChatFullAlertText, actions: [
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
]), on: .root, blockInteraction: false, completion: {})
} else if case .invalidJoinAsPeer = error {

View File

@ -1238,7 +1238,13 @@ public final class VoiceChatController: ViewController {
dismissController?()
if strongSelf.call.invitePeer(participant.peer.id) {
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: participant.peer, text: strongSelf.presentationData.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return false })
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
} else {
text = strongSelf.presentationData.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
}
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: participant.peer, text: text), action: { _ in return false })
}
} else {
if let groupPeer = groupPeer as? TelegramChannel, let listenerLink = inviteLinks?.listenerLink, !groupPeer.hasPermission(.inviteMembers) {
@ -1338,7 +1344,13 @@ public final class VoiceChatController: ViewController {
dismissController?()
if strongSelf.call.invitePeer(peer.id) {
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: strongSelf.presentationData.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return false })
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
} else {
text = strongSelf.presentationData.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
}
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: text), action: { _ in return false })
}
}))
} else if let groupPeer = groupPeer as? TelegramGroup {
@ -1400,7 +1412,13 @@ public final class VoiceChatController: ViewController {
dismissController?()
if strongSelf.call.invitePeer(peer.id) {
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: strongSelf.presentationData.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return false })
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
} else {
text = strongSelf.presentationData.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
}
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: text), action: { _ in return false })
}
}))
}
@ -2193,7 +2211,13 @@ public final class VoiceChatController: ViewController {
return
}
if event.joined {
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: event.peer, text: strongSelf.presentationData.strings.VoiceChat_PeerJoinedText(event.peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return false })
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_PeerJoinedText(event.peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
} else {
text = strongSelf.presentationData.strings.VoiceChat_PeerJoinedText(event.peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
}
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: event.peer, text: text), action: { _ in return false })
}
}))
@ -2202,7 +2226,13 @@ public final class VoiceChatController: ViewController {
guard let strongSelf = self else {
return
}
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: strongSelf.presentationData.strings.VoiceChat_DisplayAsSuccess(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return false })
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_DisplayAsSuccess(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
} else {
text = strongSelf.presentationData.strings.VoiceChat_DisplayAsSuccess(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
}
strongSelf.presentUndoOverlay(content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: text), action: { _ in return false })
}))
self.stateVersionDisposable.set((self.call.stateVersion
@ -2228,7 +2258,13 @@ public final class VoiceChatController: ViewController {
}
if !hasTooltipAlready {
let location = strongSelf.titleNode.recordingIconNode.convert(strongSelf.titleNode.recordingIconNode.bounds, to: nil)
strongSelf.controller?.present(TooltipScreen(text: presentationData.strings.VoiceChat_RecordingInProgress, icon: nil, location: .point(location.offsetBy(dx: 1.0, dy: 0.0), .top), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = presentationData.strings.LiveStream_RecordingInProgress
} else {
text = presentationData.strings.VoiceChat_RecordingInProgress
}
strongSelf.controller?.present(TooltipScreen(text: text, icon: nil, location: .point(location.offsetBy(dx: 1.0, dy: 0.0), .top), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
return .dismiss(consume: true)
}), in: .window(.root))
}
@ -2475,7 +2511,13 @@ public final class VoiceChatController: ViewController {
}
if canManageCall {
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_EditTitle, icon: { theme -> UIImage? in
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_EditTitle
} else {
text = strongSelf.presentationData.strings.VoiceChat_EditTitle
}
items.append(.action(ContextMenuActionItem(text: text, icon: { theme -> UIImage? in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Pencil"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
f(.default)
@ -2589,8 +2631,14 @@ public final class VoiceChatController: ViewController {
self?.controller?.present(alertController, in: .window(.root))
}), false))
} else {
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_StartRecording
} else {
text = strongSelf.presentationData.strings.VoiceChat_StartRecording
}
if strongSelf.callState?.scheduleTimestamp == nil {
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_StartRecording, icon: { theme -> UIImage? in
items.append(.action(ContextMenuActionItem(text: text, icon: { theme -> UIImage? in
return generateStartRecordingIcon(color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
f(.dismissWithoutContent)
@ -2603,15 +2651,33 @@ public final class VoiceChatController: ViewController {
// if let strongSelf = self {
// strongSelf.call.setShouldBeRecording(true, title: "", videoOrientation: videoOrientation)
//
// strongSelf.presentUndoOverlay(content: .voiceChatRecording(text: strongSelf.presentationData.strings.VoiceChat_RecordingStarted), action: { _ in return false })
// strongSelf.presentUndoOverlay(content: .voiceChatRecording(text: text), action: { _ in return false })
// strongSelf.call.playTone(.recordingStarted)
// }
// })
let controller = voiceChatTitleEditController(sharedContext: strongSelf.context.sharedContext, account: strongSelf.context.account, forceTheme: strongSelf.darkTheme, title: strongSelf.presentationData.strings.VoiceChat_StartRecordingTitle, text: strongSelf.presentationData.strings.VoiceChat_StartRecordingText, placeholder: strongSelf.presentationData.strings.VoiceChat_RecordingTitlePlaceholder, value: nil, maxLength: 40, apply: { title in
let title: String
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
title = strongSelf.presentationData.strings.LiveStream_StartRecordingTitle
text = strongSelf.presentationData.strings.LiveStream_StartRecordingText
} else {
title = strongSelf.presentationData.strings.VoiceChat_StartRecordingTitle
text = strongSelf.presentationData.strings.VoiceChat_StartRecordingText
}
let controller = voiceChatTitleEditController(sharedContext: strongSelf.context.sharedContext, account: strongSelf.context.account, forceTheme: strongSelf.darkTheme, title: title, text: text, placeholder: strongSelf.presentationData.strings.VoiceChat_RecordingTitlePlaceholder, value: nil, maxLength: 40, apply: { title in
if let strongSelf = self, let title = title {
strongSelf.call.setShouldBeRecording(true, title: title, videoOrientation: nil)
strongSelf.presentUndoOverlay(content: .voiceChatRecording(text: strongSelf.presentationData.strings.VoiceChat_RecordingStarted), action: { _ in return false })
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_RecordingStarted
} else {
text = strongSelf.presentationData.strings.VoiceChat_RecordingStarted
}
strongSelf.presentUndoOverlay(content: .voiceChatRecording(text: text), action: { _ in return false })
strongSelf.call.playTone(.recordingStarted)
}
})
@ -2622,7 +2688,13 @@ public final class VoiceChatController: ViewController {
}
if canManageCall {
items.append(.action(ContextMenuActionItem(text: isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelVoiceChat : strongSelf.presentationData.strings.VoiceChat_EndVoiceChat, textColor: .destructive, icon: { theme in
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelLiveStream : strongSelf.presentationData.strings.VoiceChat_EndLiveStream
} else {
text = isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelVoiceChat : strongSelf.presentationData.strings.VoiceChat_EndVoiceChat
}
items.append(.action(ContextMenuActionItem(text: text, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.destructiveActionTextColor)
}, action: { _, f in
f(.dismissWithoutContent)
@ -2644,13 +2716,29 @@ public final class VoiceChatController: ViewController {
})
}
let alertController = textAlertController(context: strongSelf.context, forceTheme: strongSelf.darkTheme, title: isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationTitle : strongSelf.presentationData.strings.VoiceChat_EndConfirmationTitle, text: isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationText : strongSelf.presentationData.strings.VoiceChat_EndConfirmationText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationEnd : strongSelf.presentationData.strings.VoiceChat_EndConfirmationEnd, action: {
let title: String
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
title = isScheduled ? strongSelf.presentationData.strings.LiveStream_CancelConfirmationTitle : strongSelf.presentationData.strings.LiveStream_EndConfirmationTitle
text = isScheduled ? strongSelf.presentationData.strings.LiveStream_CancelConfirmationText : strongSelf.presentationData.strings.LiveStream_EndConfirmationText
} else {
title = isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationTitle : strongSelf.presentationData.strings.VoiceChat_EndConfirmationTitle
text = isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationText : strongSelf.presentationData.strings.VoiceChat_EndConfirmationText
}
let alertController = textAlertController(context: strongSelf.context, forceTheme: strongSelf.darkTheme, title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationEnd : strongSelf.presentationData.strings.VoiceChat_EndConfirmationEnd, action: {
action()
})])
strongSelf.controller?.present(alertController, in: .window(.root))
})))
} else {
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.VoiceChat_LeaveVoiceChat, textColor: .destructive, icon: { theme in
let leaveText: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
leaveText = strongSelf.presentationData.strings.LiveStream_LeaveVoiceChat
} else {
leaveText = strongSelf.presentationData.strings.VoiceChat_LeaveVoiceChat
}
items.append(.action(ContextMenuActionItem(text: leaveText, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.destructiveActionTextColor)
}, action: { _, f in
f(.dismissWithoutContent)
@ -2967,7 +3055,7 @@ public final class VoiceChatController: ViewController {
isGroup = false
}
let intervalString = scheduledTimeIntervalString(strings: self.presentationData.strings, value: max(60, delta))
self.scheduleTextNode.attributedText = NSAttributedString(string: isGroup ? self.presentationData.strings.ScheduleVoiceChat_GroupText(intervalString).string : self.presentationData.strings.ScheduleVoiceChat_ChannelText(intervalString).string, font: Font.regular(14.0), textColor: UIColor(rgb: 0x8e8e93))
self.scheduleTextNode.attributedText = NSAttributedString(string: isGroup ? self.presentationData.strings.ScheduleVoiceChat_GroupText(intervalString).string : self.presentationData.strings.ScheduleLiveStream_ChannelText(intervalString).string, font: Font.regular(14.0), textColor: UIColor(rgb: 0x8e8e93))
if let (layout, navigationHeight) = self.validLayout {
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .spring))
@ -3108,14 +3196,35 @@ public final class VoiceChatController: ViewController {
let actionSheet = ActionSheetController(presentationData: self.presentationData.withUpdated(theme: self.darkTheme))
var items: [ActionSheetItem] = []
let leaveTitle: String
let leaveAndCancelTitle: String
if let channel = self.peer as? TelegramChannel, case .broadcast = channel.info {
leaveTitle = self.presentationData.strings.LiveStream_LeaveConfirmation
leaveAndCancelTitle = self.isScheduled ? self.presentationData.strings.LiveStream_LeaveAndCancelVoiceChat : self.presentationData.strings.LiveStream_LeaveAndEndVoiceChat
} else {
leaveTitle = self.presentationData.strings.VoiceChat_LeaveConfirmation
leaveAndCancelTitle = self.isScheduled ? self.presentationData.strings.VoiceChat_LeaveAndCancelVoiceChat : self.presentationData.strings.VoiceChat_LeaveAndEndVoiceChat
}
items.append(ActionSheetTextItem(title: self.presentationData.strings.VoiceChat_LeaveConfirmation))
items.append(ActionSheetButtonItem(title: self.isScheduled ? self.presentationData.strings.VoiceChat_LeaveAndCancelVoiceChat : self.presentationData.strings.VoiceChat_LeaveAndEndVoiceChat, color: .destructive, action: { [weak self, weak actionSheet] in
items.append(ActionSheetTextItem(title: leaveTitle))
items.append(ActionSheetButtonItem(title: leaveAndCancelTitle, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
if let strongSelf = self {
let title: String
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
title = strongSelf.isScheduled ? strongSelf.presentationData.strings.LiveStream_CancelConfirmationTitle : strongSelf.presentationData.strings.LiveStream_EndConfirmationTitle
text = strongSelf.isScheduled ? strongSelf.presentationData.strings.LiveStream_CancelConfirmationText : strongSelf.presentationData.strings.LiveStream_EndConfirmationText
} else {
title = strongSelf.isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationTitle : strongSelf.presentationData.strings.VoiceChat_EndConfirmationTitle
text = strongSelf.isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationText : strongSelf.presentationData.strings.VoiceChat_EndConfirmationText
}
if let (members, _) = strongSelf.currentCallMembers, members.count >= 10 || true {
let alertController = textAlertController(context: strongSelf.context, forceTheme: strongSelf.darkTheme, title: strongSelf.isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationTitle : strongSelf.presentationData.strings.VoiceChat_EndConfirmationTitle, text: strongSelf.isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationText : strongSelf.presentationData.strings.VoiceChat_EndConfirmationText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: strongSelf.isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationEnd : strongSelf.presentationData.strings.VoiceChat_EndConfirmationEnd, action: {
let alertController = textAlertController(context: strongSelf.context, forceTheme: strongSelf.darkTheme, title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: strongSelf.isScheduled ? strongSelf.presentationData.strings.VoiceChat_CancelConfirmationEnd : strongSelf.presentationData.strings.VoiceChat_EndConfirmationEnd, action: {
action()
})])
strongSelf.controller?.present(alertController, in: .window(.root))
@ -3124,7 +3233,15 @@ public final class VoiceChatController: ViewController {
}
}
}))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.VoiceChat_LeaveVoiceChat, color: .accent, action: { [weak self, weak actionSheet] in
let leaveText: String
if let channel = self.peer as? TelegramChannel, case .broadcast = channel.info {
leaveText = self.presentationData.strings.LiveStream_LeaveVoiceChat
} else {
leaveText = self.presentationData.strings.VoiceChat_LeaveVoiceChat
}
items.append(ActionSheetButtonItem(title: leaveText, color: .accent, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
guard let strongSelf = self else {
@ -3939,7 +4056,7 @@ public final class VoiceChatController: ViewController {
var title = self.currentTitle
if self.isScheduling {
if let peer = self.peer as? TelegramChannel, case .broadcast = peer.info {
title = self.presentationData.strings.ScheduleVoiceChatChannel_Title
title = self.presentationData.strings.ScheduleLiveStream_Title
} else {
title = self.presentationData.strings.ScheduleVoiceChat_Title
}
@ -5882,11 +5999,29 @@ public final class VoiceChatController: ViewController {
}
let initialTitle = strongSelf.callState?.title ?? ""
let controller = voiceChatTitleEditController(sharedContext: strongSelf.context.sharedContext, account: strongSelf.context.account, forceTheme: strongSelf.darkTheme, title: strongSelf.presentationData.strings.VoiceChat_EditTitleTitle, text: strongSelf.presentationData.strings.VoiceChat_EditTitleText, placeholder: chatPeer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), value: initialTitle, maxLength: 40, apply: { title in
let title: String
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
title = strongSelf.presentationData.strings.LiveStream_EditTitle
text = strongSelf.presentationData.strings.LiveStream_EditTitleText
} else {
title = strongSelf.presentationData.strings.VoiceChat_EditTitle
text = strongSelf.presentationData.strings.VoiceChat_EditTitleText
}
let controller = voiceChatTitleEditController(sharedContext: strongSelf.context.sharedContext, account: strongSelf.context.account, forceTheme: strongSelf.darkTheme, title: title, text: text, placeholder: chatPeer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), value: initialTitle, maxLength: 40, apply: { title in
if let strongSelf = self, let title = title, title != initialTitle {
strongSelf.call.updateTitle(title)
strongSelf.presentUndoOverlay(content: .voiceChatFlag(text: title.isEmpty ? strongSelf.presentationData.strings.VoiceChat_EditTitleRemoveSuccess : strongSelf.presentationData.strings.VoiceChat_EditTitleSuccess(title).string), action: { _ in return false })
let text: String
if let channel = strongSelf.peer as? TelegramChannel, case .broadcast = channel.info {
text = title.isEmpty ? strongSelf.presentationData.strings.LiveStream_EditTitleRemoveSuccess : strongSelf.presentationData.strings.LiveStream_EditTitleSuccess(title).string
} else {
text = title.isEmpty ? strongSelf.presentationData.strings.VoiceChat_EditTitleRemoveSuccess : strongSelf.presentationData.strings.VoiceChat_EditTitleSuccess(title).string
}
strongSelf.presentUndoOverlay(content: .voiceChatFlag(text: text), action: { _ in return false })
}
})
strongSelf.controller?.present(controller, in: .window(.root))

View File

@ -440,7 +440,12 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
case let .groupPhoneCall(_, _, scheduleDate, duration):
if let scheduleDate = scheduleDate {
if message.author?.id.namespace == Namespaces.Peer.CloudChannel {
let titleString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate, alwaysShowTime: true, allowYesterday: false, format: HumanReadableStringFormat(dateFormatString: { strings.Notification_VoiceChatScheduledChannel($0) }, tomorrowFormatString: { strings.Notification_VoiceChatScheduledTomorrowChannel($0) }, todayFormatString: { strings.Notification_VoiceChatScheduledTodayChannel($0) }))
let titleString: PresentationStrings.FormattedString
if let channel = message.author as? TelegramChannel, case .broadcast = channel.info {
titleString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate, alwaysShowTime: true, allowYesterday: false, format: HumanReadableStringFormat(dateFormatString: { strings.Notification_LiveStreamScheduled($0) }, tomorrowFormatString: { strings.Notification_LiveStreamScheduledTomorrow($0) }, todayFormatString: { strings.Notification_LiveStreamScheduledToday($0) }))
} else {
titleString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate, alwaysShowTime: true, allowYesterday: false, format: HumanReadableStringFormat(dateFormatString: { strings.Notification_VoiceChatScheduledChannel($0) }, tomorrowFormatString: { strings.Notification_VoiceChatScheduledTomorrowChannel($0) }, todayFormatString: { strings.Notification_VoiceChatScheduledTodayChannel($0) }))
}
attributedString = NSAttributedString(string: titleString.string, font: titleFont, textColor: primaryTextColor)
} else {
let titleString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate, alwaysShowTime: true, allowYesterday: false, format: HumanReadableStringFormat(dateFormatString: { strings.Notification_VoiceChatScheduled(authorName, $0) }, tomorrowFormatString: { strings.Notification_VoiceChatScheduledTomorrow(authorName, $0) }, todayFormatString: { strings.Notification_VoiceChatScheduledToday(authorName, $0) }))
@ -449,7 +454,12 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
}
} else if let duration = duration {
if message.author?.id.namespace == Namespaces.Peer.CloudChannel {
let titleString = strings.Notification_VoiceChatEnded(callDurationString(strings: strings, value: duration)).string
let titleString: String
if let channel = message.author as? TelegramChannel, case .broadcast = channel.info {
titleString = strings.Notification_LiveStreamEnded(callDurationString(strings: strings, value: duration)).string
} else {
titleString = strings.Notification_VoiceChatEnded(callDurationString(strings: strings, value: duration)).string
}
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
} else {
let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)]
@ -458,8 +468,13 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
}
} else {
if message.author?.id.namespace == Namespaces.Peer.CloudChannel {
let titleString = strings.Notification_VoiceChatStartedChannel
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
let titleString: String
if let channel = message.author as? TelegramChannel, case .broadcast = channel.info {
titleString = strings.Notification_LiveStreamStarted
} else {
titleString = strings.Notification_VoiceChatStartedChannel
}
attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor)
} else {
let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)]
let titleString = strings.Notification_VoiceChatStarted(authorName)

View File

@ -346,14 +346,30 @@ public final class AccountContextImpl: AccountContext {
let presentationData = strongSelf.sharedContext.currentPresentationData.with { $0 }
if let current = current {
if current is TelegramChannel || current is TelegramGroup {
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: presentationData.strings.Call_VoiceChatInProgressTitle, text: presentationData.strings.Call_VoiceChatInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
let title: String
let text: String
if let channel = current as? TelegramChannel, case .broadcast = channel.info {
title = presentationData.strings.Call_LiveStreamInProgressTitle
text = presentationData.strings.Call_LiveStreamInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string
} else {
title = presentationData.strings.Call_VoiceChatInProgressTitle
text = presentationData.strings.Call_VoiceChatInProgressMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string
}
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
guard let strongSelf = self else {
return
}
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, invite: invite, requestJoinAsPeerId: requestJoinAsPeerId, initialCall: activeCall, endCurrentIfAny: true)
})]), on: .root)
} else {
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressVoiceChatMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
let text: String
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
text = presentationData.strings.Call_CallInProgressLiveStreamMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string
} else {
text = presentationData.strings.Call_CallInProgressVoiceChatMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string
}
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: presentationData.strings.Call_CallInProgressTitle, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
guard let strongSelf = self else {
return
}
@ -392,7 +408,13 @@ public final class AccountContextImpl: AccountContext {
let presentationData = strongSelf.sharedContext.currentPresentationData.with { $0 }
if let current = current {
if current is TelegramChannel || current is TelegramGroup {
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: presentationData.strings.Call_VoiceChatInProgressTitle, text: presentationData.strings.Call_VoiceChatInProgressCallMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
let text: String
if let channel = current as? TelegramChannel, case .broadcast = channel.info {
text = presentationData.strings.Call_LiveStreamInProgressCallMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string
} else {
text = presentationData.strings.Call_VoiceChatInProgressCallMessage(current.compactDisplayTitle, peer.compactDisplayTitle).string
}
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: presentationData.strings.Call_VoiceChatInProgressTitle, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
guard let strongSelf = self else {
return
}

View File

@ -637,7 +637,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
if canManageGroupCalls {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatStartNow, action: {
let text: String
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_CreateNewVoiceChatText
} else {
text = strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatText
}
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatStartNow, action: {
if let strongSelf = self {
var dismissStatus: (() -> Void)?
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: {
@ -666,7 +672,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
case .generic, .scheduledTooLate:
text = strongSelf.presentationData.strings.Login_UnknownError
case .anonymousNotAllowed:
text = strongSelf.presentationData.strings.VoiceChat_AnonymousDisabledAlertText
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_AnonymousDisabledAlertText
} else {
text = strongSelf.presentationData.strings.VoiceChat_AnonymousDisabledAlertText
}
}
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, completed: {
@ -6189,7 +6199,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let rect = strongSelf.chatDisplayNode.frameForInputActionButton()
if let rect = rect {
strongSelf.mediaRestrictedTooltipController?.dismiss()
let tooltipController = TooltipController(content: .text(strongSelf.presentationInterfaceState.strings.Conversation_VoiceChatMediaRecordingRestricted), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize)
let text: String
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationInterfaceState.strings.Conversation_LiveStreamMediaRecordingRestricted
} else {
text = strongSelf.presentationInterfaceState.strings.Conversation_VoiceChatMediaRecordingRestricted
}
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize)
strongSelf.mediaRestrictedTooltipController = tooltipController
strongSelf.mediaRestrictedTooltipControllerMode = false
tooltipController.dismissed = { [weak tooltipController] _ in

View File

@ -1303,9 +1303,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
overscrollView = current
} else {
overscrollView = ComponentHostView<Empty>()
overscrollView.layer.sublayerTransform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0)
self.overscrollView = overscrollView
self.view.addSubview(overscrollView)
self.view.superview?.insertSubview(overscrollView, aboveSubview: self.view)
}
let expandDistance = max(-offset - 12.0, 0.0)
@ -1379,7 +1378,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
environment: {},
containerSize: CGSize(width: self.bounds.width, height: 200.0)
)
overscrollView.frame = overscrollFrame
overscrollView.frame = self.view.convert(overscrollFrame, to: self.view.superview!)
} else if let overscrollView = self.overscrollView {
self.overscrollView = nil
overscrollView.removeFromSuperview()
@ -2582,14 +2581,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
}
}
let overscrollView = self.overscrollView
self.overscrollView = nil
if let overscrollView = overscrollView {
self.view.superview?.insertSubview(overscrollView, aboveSubview: self.view)
}
let snapshotView = self.view.snapshotView(afterScreenUpdates: true)!
let snapshotView = self.view.snapshotView(afterScreenUpdates: false)!
snapshotView.frame = self.view.bounds
if let sublayers = self.layer.sublayers {
@ -2599,9 +2591,14 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
}
self.view.addSubview(snapshotView)
let overscrollView = self.overscrollView
if let overscrollView = overscrollView {
overscrollView.alpha = 1.0
self.overscrollView = nil
overscrollView.frame = overscrollView.convert(overscrollView.bounds, to: self.view)
snapshotView.addSubview(overscrollView)
overscrollView.layer.sublayerTransform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0)
}
return SnapshotState(

View File

@ -290,7 +290,11 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
case "telegram_message":
actionTitle = item.presentationData.strings.Conversation_ViewMessage
case "telegram_voicechat":
title = item.presentationData.strings.Conversation_VoiceChat
if let channel = item.message.peers[item.message.id.peerId] as? TelegramChannel, case let .broadcast = channel.info {
title = item.presentationData.strings.Conversation_LiveStream
} else {
title = item.presentationData.strings.Conversation_VoiceChat
}
if webpage.url.contains("voicechat=") {
actionTitle = item.presentationData.strings.Conversation_JoinVoiceChatAsSpeaker
} else {

View File

@ -279,7 +279,7 @@ private func channelRecentActionsFilterControllerEntries(presentationData: Prese
([.editMessages], presentationData.strings.Channel_AdminLogFilter_EventsEditedMessages),
([.pinnedMessages], presentationData.strings.Channel_AdminLogFilter_EventsPinned),
([.leave], presentationData.strings.Channel_AdminLogFilter_EventsLeaving),
([.calls], presentationData.strings.Channel_AdminLogFilter_EventsCalls)
([.calls], presentationData.strings.Channel_AdminLogFilter_EventsLiveStreams)
]
}

View File

@ -714,7 +714,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
(.canInviteUsers, self.presentationData.strings.Channel_AdminLog_CanInviteUsersViaLink),
(.canPinMessages, self.presentationData.strings.Channel_AdminLog_CanPinMessages),
(.canAddAdmins, self.presentationData.strings.Channel_AdminLog_CanAddAdmins),
(.canManageCalls, self.presentationData.strings.Channel_AdminLog_CanManageCalls)
(.canManageCalls, self.presentationData.strings.Channel_AdminLog_CanManageLiveStreams)
]
prevFlags = prevFlags.intersection(TelegramChatAdminRightsFlags.broadcastSpecific)
newFlags = newFlags.intersection(TelegramChatAdminRightsFlags.broadcastSpecific)
@ -1122,9 +1122,17 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let rawText: PresentationStrings.FormattedString
if case .startGroupCall = self.entry.event.action {
rawText = self.presentationData.strings.Channel_AdminLog_StartedVoiceChat(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
rawText = self.presentationData.strings.Channel_AdminLog_StartedLiveStream(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
} else {
rawText = self.presentationData.strings.Channel_AdminLog_StartedVoiceChat(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
}
} else {
rawText = self.presentationData.strings.Channel_AdminLog_EndedVoiceChat(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
rawText = self.presentationData.strings.Channel_AdminLog_EndedLiveStream(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
} else {
rawText = self.presentationData.strings.Channel_AdminLog_EndedVoiceChat(author?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
}
}
appendAttributedText(text: rawText, generateEntities: { index in

View File

@ -2429,7 +2429,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
buttonText = presentationData.strings.PeerInfo_ButtonVideoCall
buttonIcon = .videoCall
case .voiceChat:
buttonText = presentationData.strings.PeerInfo_ButtonVoiceChat
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
buttonText = presentationData.strings.PeerInfo_ButtonLiveStream
} else {
buttonText = presentationData.strings.PeerInfo_ButtonVoiceChat
}
buttonIcon = .voiceChat
case .mute:
if let notificationSettings = notificationSettings, case .muted = notificationSettings.muteState {

View File

@ -4060,7 +4060,11 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
case .generic, .scheduledTooLate:
text = strongSelf.presentationData.strings.Login_UnknownError
case .anonymousNotAllowed:
text = strongSelf.presentationData.strings.VoiceChat_AnonymousDisabledAlertText
if let channel = strongSelf.data?.peer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_AnonymousDisabledAlertText
} else {
text = strongSelf.presentationData.strings.VoiceChat_AnonymousDisabledAlertText
}
}
strongSelf.controller?.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}))
@ -4404,14 +4408,24 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
items.append(.separator)
}
}
let createVoiceChatTitle: String
let scheduleVoiceChatTitle: String
if let channel = strongSelf.data?.peer as? TelegramChannel, case .broadcast = channel.info {
createVoiceChatTitle = strongSelf.presentationData.strings.ChannelInfo_CreateLiveStream
scheduleVoiceChatTitle = strongSelf.presentationData.strings.ChannelInfo_ScheduleLiveStream
} else {
createVoiceChatTitle = strongSelf.presentationData.strings.ChannelInfo_CreateVoiceChat
scheduleVoiceChatTitle = strongSelf.presentationData.strings.ChannelInfo_ScheduleVoiceChat
}
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.ChannelInfo_CreateVoiceChat, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/VoiceChat"), color: theme.contextMenu.primaryColor) }, action: { _, f in
items.append(.action(ContextMenuActionItem(text: createVoiceChatTitle, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/VoiceChat"), color: theme.contextMenu.primaryColor) }, action: { _, f in
f(.dismissWithoutContent)
self?.createAndJoinGroupCall(peerId: peerId, joinAsPeerId: defaultJoinAsPeerId)
})))
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.ChannelInfo_ScheduleVoiceChat, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Schedule"), color: theme.contextMenu.primaryColor) }, action: { _, f in
items.append(.action(ContextMenuActionItem(text: scheduleVoiceChatTitle, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Schedule"), color: theme.contextMenu.primaryColor) }, action: { _, f in
f(.dismissWithoutContent)
self?.scheduleGroupCall()