diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 73d9a81a03..194ad5b28d 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -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,11 +5818,13 @@ 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"; "VoiceChat.StopRecording" = "Stop Recording"; @@ -5815,7 +5835,9 @@ Sorry for the inconvenience."; "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 +5862,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 +6210,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 +6244,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 +6285,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 +6307,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 +6373,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 +6400,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"; diff --git a/submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.swift b/submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.swift index 32e6f49319..6fa0341561 100644 --- a/submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.swift +++ b/submodules/DeleteChatPeerActionSheetItem/Sources/DeleteChatPeerActionSheetItem.swift @@ -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: diff --git a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift index 05c6b82ead..9f91716540 100644 --- a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift @@ -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 } } diff --git a/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift b/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift index 617d4505db..67333e7fcf 100644 --- a/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift +++ b/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift @@ -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 } diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 1b3b041458..d3ecb1d38c 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -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 { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index f55535c18d..753043c1fc 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1236,7 +1236,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) { @@ -1336,7 +1342,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 { @@ -1398,7 +1410,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 }) } })) } @@ -2175,7 +2193,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 }) } })) @@ -2184,7 +2208,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 @@ -2210,7 +2240,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)) } @@ -2457,7 +2493,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) @@ -2585,15 +2627,29 @@ 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 }) + 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) } }) // let controller = voiceChatTitleEditController(sharedContext: strongSelf.context.sharedContext, account: strongSelf.context.account, forceTheme: strongSelf.darkTheme, title: presentationData.strings.VoiceChat_StartRecordingTitle, text: presentationData.strings.VoiceChat_StartRecordingText, placeholder: presentationData.strings.VoiceChat_RecordingTitlePlaceholder, value: nil, maxLength: 40, apply: { title in // if let strongSelf = self, let title = title { // strongSelf.call.setShouldBeRecording(true, title: title) + +// 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: strongSelf.presentationData.strings.VoiceChat_RecordingStarted), action: { _ in return false }) +// strongSelf.presentUndoOverlay(content: .voiceChatRecording(text: text), action: { _ in return false }) // strongSelf.call.playTone(.recordingStarted) // } // }) @@ -2604,7 +2660,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) @@ -2626,13 +2688,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) @@ -2949,7 +3027,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)) @@ -3090,14 +3168,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)) @@ -3106,7 +3205,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 { @@ -3921,7 +4028,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 } @@ -5857,11 +5964,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)) diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 58cf89ea86..38f10a80b6 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -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) diff --git a/submodules/TelegramUI/Sources/AccountContext.swift b/submodules/TelegramUI/Sources/AccountContext.swift index 9d400eda65..af60f54420 100644 --- a/submodules/TelegramUI/Sources/AccountContext.swift +++ b/submodules/TelegramUI/Sources/AccountContext.swift @@ -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 } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 7798d1a711..07c318b576 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift index 140e3b074a..d851547ee1 100644 --- a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -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 { diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsFilterController.swift b/submodules/TelegramUI/Sources/ChatRecentActionsFilterController.swift index 4318cfcf24..1c5a4da42f 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsFilterController.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsFilterController.swift @@ -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) ] } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift index c86f900f60..3b92d64542 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index e7d06100a9..f4d788d26a 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -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 { diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index f3a76fa9b6..929456c3eb 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -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()