From df505a7b621d78ad83c1250c75440c6865dddfb3 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 22 Oct 2023 13:52:38 +0400 Subject: [PATCH] Various improvements --- .../FolderInviteLinkListController.swift | 6 +- .../Sources/NotificationSoundSelection.swift | 4 +- .../Sources/ChannelAdminsController.swift | 2 +- .../Sources/ReplaceBoostScreen.swift | 2 +- .../Sources/DeleteAccountDataController.swift | 2 +- .../DataPrivacySettingsController.swift | 6 +- .../PrivacyAndSecurityController.swift | 2 +- .../Sources/ChannelStatsController.swift | 15 +- .../Sources/VoiceChatController.swift | 4 +- .../SyncCore/SyncCore_CachedUserData.swift | 1 + .../Sources/PeerNameColor.swift | 2 + ...ChatMessageGiveawayBubbleContentNode.swift | 5 +- .../ChatRecentActionsControllerNode.swift | 1 + .../Sources/ChatControllerInteraction.swift | 3 + .../Sources/MediaEditorScreen.swift | 3 +- .../Sources/PeerInfoStoryGridScreen.swift | 6 +- .../CountriesMultiselectionScreen.swift | 2 +- .../Sources/ShareWithPeersScreen.swift | 4 +- .../Sources/StorageUsageScreen.swift | 2 +- .../StoryItemSetContainerComponent.swift | 14 +- .../TelegramUI/Sources/ChatController.swift | 394 ++++++++++-------- .../ChatInterfaceStateContextMenus.swift | 6 +- .../TelegramUI/Sources/OpenResolvedUrl.swift | 52 +-- .../OverlayAudioPlayerControllerNode.swift | 1 + .../Sources/PeerInfo/PeerInfoScreen.swift | 5 +- .../Sources/SharedAccountContext.swift | 1 + .../Sources/UndoOverlayController.swift | 4 +- .../Sources/UndoOverlayControllerNode.swift | 18 +- 28 files changed, 292 insertions(+), 275 deletions(-) diff --git a/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift b/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift index 3b0e437cf6..f2e72ec1f9 100644 --- a/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift +++ b/submodules/InviteLinksUI/Sources/FolderInviteLinkListController.swift @@ -492,7 +492,7 @@ public func folderInviteLinkListController(context: AccountContext, updatedPrese didDisplayAddPeerNotice = true dismissTooltipsImpl?() - displayTooltipImpl?(.info(title: nil, text: presentationData.strings.FolderLinkScreen_ToastNewChatAdded, timeout: 8), true) + displayTooltipImpl?(.info(title: nil, text: presentationData.strings.FolderLinkScreen_ToastNewChatAdded, timeout: 8, customUndoText: nil), true) } } else { let text: String @@ -592,11 +592,11 @@ public func folderInviteLinkListController(context: AccountContext, updatedPrese dismissTooltipsImpl?() let presentationData = context.sharedContext.currentPresentationData.with { $0 } - presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.FolderLinkScreen_SaveUnknownError, timeout: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) + presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.FolderLinkScreen_SaveUnknownError, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) }, completed: { let presentationData = context.sharedContext.currentPresentationData.with { $0 } linkUpdated(ExportedChatFolderLink(title: state.title ?? "", link: currentLink.link, peerIds: Array(state.selectedPeerIds), isRevoked: false)) - displayTooltipImpl?(.info(title: nil, text: presentationData.strings.FolderLinkScreen_ToastLinkUpdated, timeout: 3), false) + displayTooltipImpl?(.info(title: nil, text: presentationData.strings.FolderLinkScreen_ToastLinkUpdated, timeout: 3, customUndoText: nil), false) dismissImpl?() })) diff --git a/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift b/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift index 1953ba14d4..5d0aab4433 100644 --- a/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift +++ b/submodules/NotificationSoundSelectionUI/Sources/NotificationSoundSelection.swift @@ -540,7 +540,7 @@ public func presentCustomNotificationSoundFilePicker(context: AccountContext, co let data = try Data(contentsOf: url) if data.count > settings.maxSize { - presentUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLarge_Title, text: presentationData.strings.Notifications_UploadError_TooLarge_Text(dataSizeString(Int64(settings.maxSize), formatting: DataSizeStringFormatting(presentationData: presentationData))).string, timeout: nil)) + presentUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLarge_Title, text: presentationData.strings.Notifications_UploadError_TooLarge_Text(dataSizeString(Int64(settings.maxSize), formatting: DataSizeStringFormatting(presentationData: presentationData))).string, timeout: nil, customUndoText: nil)) souceUrl.stopAccessingSecurityScopedResource() EngineTempBox.shared.dispose(tempFile) @@ -593,7 +593,7 @@ public func presentCustomNotificationSoundFilePicker(context: AccountContext, co if duration > Double(settings.maxDuration) { souceUrl.stopAccessingSecurityScopedResource() - presentUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLong_Title(fileName).string, text: presentationData.strings.Notifications_UploadError_TooLong_Text(stringForDuration(Int32(settings.maxDuration))).string, timeout: nil)) + presentUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLong_Title(fileName).string, text: presentationData.strings.Notifications_UploadError_TooLong_Text(stringForDuration(Int32(settings.maxDuration))).string, timeout: nil, customUndoText: nil)) } else { Logger.shared.log("NotificationSoundSelection", "Uploading sound") diff --git a/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift b/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift index afc2bb66c6..2a230594ff 100644 --- a/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift @@ -581,7 +581,7 @@ public func channelAdminsController(context: AccountContext, updatedPresentation guard let peer = peer, let user = user else { return } - presentControllerImpl?(UndoOverlayController(presentationData: context.sharedContext.currentPresentationData.with { $0 }, content: .succeed(text: presentationData.strings.Channel_OwnershipTransfer_TransferCompleted(user.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string, timeout: nil), elevatedLayout: false, action: { _ in return false }), nil) + presentControllerImpl?(UndoOverlayController(presentationData: context.sharedContext.currentPresentationData.with { $0 }, content: .succeed(text: presentationData.strings.Channel_OwnershipTransfer_TransferCompleted(user.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false }), nil) }) } diff --git a/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift b/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift index c826152697..7a3ba67ad7 100644 --- a/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift +++ b/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift @@ -232,7 +232,7 @@ private final class ReplaceBoostScreenComponent: CombinedComponent { selectedSlotsUpdated(state.selectedSlots) } else { let presentationData = accountContext.sharedContext.currentPresentationData.with { $0 } - let undoController = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "Wait until the boost is available or get **3** more boosts by gifting a **Telegram Premium** subscription.", timeout: nil), elevatedLayout: false, position: .top, action: { _ in return true }) + let undoController = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "Wait until the boost is available or get **3** more boosts by gifting a **Telegram Premium** subscription.", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, action: { _ in return true }) presentController(undoController) } }) diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index 6631833d34..a423c640a1 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -466,7 +466,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let presentGlobalController = context.sharedContext.presentGlobalController let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: false).start(completed: { Queue.mainQueue().after(0.1) { - presentGlobalController(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.DeleteAccount_Success, timeout: nil), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), nil) + presentGlobalController(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.DeleteAccount_Success, timeout: nil, customUndoText: nil), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), nil) } }) }) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift b/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift index 855d3bfc45..f5ad980054 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/DataPrivacySettingsController.swift @@ -377,7 +377,7 @@ public func dataPrivacyController(context: AccountContext) -> ViewController { text = nil } if let text = text { - presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: text, timeout: nil), elevatedLayout: false, action: { _ in return false })) + presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: text, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false })) } })) } @@ -426,7 +426,7 @@ public func dataPrivacyController(context: AccountContext) -> ViewController { return state } let presentationData = context.sharedContext.currentPresentationData.with { $0 } - presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.Privacy_ContactsReset_ContactsDeleted, timeout: nil), elevatedLayout: false, action: { _ in return false })) + presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.Privacy_ContactsReset_ContactsDeleted, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false })) })) }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {})])) } @@ -476,7 +476,7 @@ public func dataPrivacyController(context: AccountContext) -> ViewController { return state } let presentationData = context.sharedContext.currentPresentationData.with { $0 } - presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.Privacy_DeleteDrafts_DraftsDeleted, timeout: nil), elevatedLayout: false, action: { _ in return false })) + presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.Privacy_DeleteDrafts_DraftsDeleted, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false })) })) } dismissAction() diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 188374b830..3c686730ab 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -951,7 +951,7 @@ public func privacyAndSecurityController( hapticFeedback.impact() var alreadyPresented = false - presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Privacy_VoiceMessages_Tooltip, timeout: nil), elevatedLayout: false, animateInAsReplacement: false, action: { action in + presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Privacy_VoiceMessages_Tooltip, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { action in if action == .info { if !alreadyPresented { let controller = PremiumIntroScreen(context: context, source: .settings) diff --git a/submodules/StatisticsUI/Sources/ChannelStatsController.swift b/submodules/StatisticsUI/Sources/ChannelStatsController.swift index f34fac7743..d155a4a864 100644 --- a/submodules/StatisticsUI/Sources/ChannelStatsController.swift +++ b/submodules/StatisticsUI/Sources/ChannelStatsController.swift @@ -786,10 +786,17 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p entries.append(.boosterTabs(presentationData.theme, "\(boostsCount) Boosts", "\(giftsCount) Gifts", state.giftsSelected)) } - if let boostersState { + let selectedState: ChannelBoostersContext.State? + if state.giftsSelected { + selectedState = giftsState + } else { + selectedState = boostersState + } + + if let selectedState { var boosterIndex: Int32 = 0 - var boosters: [ChannelBoostersContext.State.Boost] = boostersState.boosts + var boosters: [ChannelBoostersContext.State.Boost] = selectedState.boosts var effectiveExpanded = state.boostersExpanded if boosters.count > maxUsersDisplayedLimit && !state.boostersExpanded { boosters = Array(boosters.prefix(Int(maxUsersDisplayedLimit))) @@ -803,7 +810,7 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p } if !effectiveExpanded { - entries.append(.boostersExpand(presentationData.theme, presentationData.strings.PeopleNearby_ShowMorePeople(Int32(boostersState.count) - maxUsersDisplayedLimit))) + entries.append(.boostersExpand(presentationData.theme, presentationData.strings.PeopleNearby_ShowMorePeople(Int32(selectedState.count) - maxUsersDisplayedLimit))) } } @@ -939,7 +946,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD pushImpl?(controller) }, updateGiftsSelected: { selected in - updateState { $0.withUpdatedGiftsSelected(selected) } + updateState { $0.withUpdatedGiftsSelected(selected).withUpdatedBoostersExpanded(false) } }) let messageView = context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId: peerId, threadId: nil), index: .upperBound, anchorIndex: .upperBound, count: 100, fixedCombinedReadStates: nil) diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index f00ffed5b5..6a4ee3a0c0 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1572,7 +1572,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController }).start() } - strongSelf.presentUndoOverlay(content: .info(title: nil, text: strongSelf.presentationData.strings.VoiceChat_EditBioSuccess, timeout: nil), action: { _ in return false }) + strongSelf.presentUndoOverlay(content: .info(title: nil, text: strongSelf.presentationData.strings.VoiceChat_EditBioSuccess, timeout: nil, customUndoText: nil), action: { _ in return false }) } }) self?.controller?.present(controller, in: .window(.root)) @@ -1593,7 +1593,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController if let strongSelf = self, let (firstName, lastName) = firstAndLastName { let _ = context.engine.accountData.updateAccountPeerName(firstName: firstName, lastName: lastName).start() - strongSelf.presentUndoOverlay(content: .info(title: nil, text: strongSelf.presentationData.strings.VoiceChat_EditNameSuccess, timeout: nil), action: { _ in return false }) + strongSelf.presentUndoOverlay(content: .info(title: nil, text: strongSelf.presentationData.strings.VoiceChat_EditNameSuccess, timeout: nil, customUndoText: nil), action: { _ in return false }) } }) self?.controller?.present(controller, in: .window(.root)) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index 4ea1ac7aa9..040951dec9 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -128,6 +128,7 @@ public enum PeerNameColor: Int32, CaseIterable { case greenDash case cyanDash case blueDash + case pinkDash } public struct PeerEmojiStatus: Equatable, Codable { diff --git a/submodules/TelegramPresentationData/Sources/PeerNameColor.swift b/submodules/TelegramPresentationData/Sources/PeerNameColor.swift index aa13a83bf4..8c3ca8e668 100644 --- a/submodules/TelegramPresentationData/Sources/PeerNameColor.swift +++ b/submodules/TelegramPresentationData/Sources/PeerNameColor.swift @@ -35,6 +35,8 @@ public extension PeerNameColor { return (UIColor(rgb: 0x27ACCE), UIColor(rgb: 0x82E8D6)) case .blueDash: return (UIColor(rgb: 0x3391D4), UIColor(rgb: 0x7DD3F0)) + case .pinkDash: + return (UIColor(rgb: 0xdd4371), UIColor(rgb: 0xffbe9f)) } } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift index a35000fd8c..ead629e841 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift @@ -158,10 +158,7 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode guard let item = self.item else { return } - - let presentationData = item.context.sharedContext.currentPresentationData.with { $0 } - let controller = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can't participate in this giveaway.", timeout: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }) - item.controllerInteraction.presentControllerInCurrent(controller, nil) + item.controllerInteraction.displayGiveawayParticipationStatus(item.message.id) } private func removePlaceholder(animated: Bool) { diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift index e45b0b5295..40988aefb5 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift @@ -566,6 +566,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, openRequestedPeerSelection: { _, _, _ in }, saveMediaToFiles: { _ in }, openNoAdsDemo: { + }, displayGiveawayParticipationStatus: { _ in }, requestMessageUpdate: { _, _ in }, cancelInteractiveKeyboardGestures: { }, dismissTextInput: { diff --git a/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift index 1b5e74a0bc..85db04b490 100644 --- a/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift @@ -197,6 +197,7 @@ public final class ChatControllerInteraction { public let openRequestedPeerSelection: (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32) -> Void public let saveMediaToFiles: (EngineMessage.Id) -> Void public let openNoAdsDemo: () -> Void + public let displayGiveawayParticipationStatus: (EngineMessage.Id) -> Void public let requestMessageUpdate: (MessageId, Bool) -> Void public let cancelInteractiveKeyboardGestures: () -> Void @@ -312,6 +313,7 @@ public final class ChatControllerInteraction { openRequestedPeerSelection: @escaping (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32) -> Void, saveMediaToFiles: @escaping (EngineMessage.Id) -> Void, openNoAdsDemo: @escaping () -> Void, + displayGiveawayParticipationStatus: @escaping (EngineMessage.Id) -> Void, requestMessageUpdate: @escaping (MessageId, Bool) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, dismissTextInput: @escaping () -> Void, @@ -409,6 +411,7 @@ public final class ChatControllerInteraction { self.openRequestedPeerSelection = openRequestedPeerSelection self.saveMediaToFiles = saveMediaToFiles self.openNoAdsDemo = openNoAdsDemo + self.displayGiveawayParticipationStatus = displayGiveawayParticipationStatus self.requestMessageUpdate = requestMessageUpdate self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures self.dismissTextInput = dismissTextInput diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index bc63703219..a6a98368f6 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -4248,7 +4248,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate content = .info( title: presentationData.strings.Story_Editor_TooltipReachedReactionLimitTitle, text: presentationData.strings.Story_Editor_TooltipReachedReactionLimitText(value).string, - timeout: nil + timeout: nil, + customUndoText: nil ) } else { let value = presentationData.strings.Story_Editor_TooltipPremiumReactionLimitValue(premiumLimits.maxStoriesSuggestedReactions) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift index ea1d32e799..b1b19c9605 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift @@ -117,7 +117,7 @@ final class PeerInfoStoryGridScreenComponent: Component { environment.controller()?.present(UndoOverlayController( presentationData: presentationData, - content: .info(title: nil, text: text, timeout: nil), + content: .info(title: nil, text: text, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false } @@ -361,7 +361,7 @@ final class PeerInfoStoryGridScreenComponent: Component { let title: String = presentationData.strings.StoryList_TooltipStoriesSavedToProfile(Int32(selectedCount)) environment.controller()?.present(UndoOverlayController( presentationData: presentationData, - content: .info(title: nil, text: title, timeout: nil), + content: .info(title: nil, text: title, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false } @@ -384,7 +384,7 @@ final class PeerInfoStoryGridScreenComponent: Component { environment.controller()?.present(UndoOverlayController( presentationData: presentationData, - content: .info(title: title, text: text, timeout: nil), + content: .info(title: title, text: text, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false } diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/CountriesMultiselectionScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/CountriesMultiselectionScreen.swift index e3b6f4b196..a4d93ce24f 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/CountriesMultiselectionScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/CountriesMultiselectionScreen.swift @@ -468,7 +468,7 @@ final class CountriesMultiselectionScreenComponent: Component { self.hapticFeedback.error() let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } - controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum \(limit) countries.", timeout: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) + controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum \(limit) countries.", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) return } toggleCountry() diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift index 562039d92f..28e88fc1a7 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift @@ -1444,7 +1444,7 @@ final class ShareWithPeersScreenComponent: Component { self.hapticFeedback.error() let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } - controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum \(component.context.userLimits.maxGiveawayChannelsCount) channels.", timeout: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) + controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum \(component.context.userLimits.maxGiveawayChannelsCount) channels.", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) return } if case .channels = component.stateContext.subject { @@ -1474,7 +1474,7 @@ final class ShareWithPeersScreenComponent: Component { self.hapticFeedback.error() let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } - controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum 10 subscribers.", timeout: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) + controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum 10 subscribers.", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current) return } togglePeer() diff --git a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift index f97c9df860..3236d75c72 100644 --- a/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift +++ b/submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift @@ -2276,7 +2276,7 @@ final class StorageUsageScreenComponent: Component { } let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } - controller.present(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(size, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).string, timeout: nil), elevatedLayout: false, action: { _ in return false }), in: .current) + controller.present(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(size, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).string, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false }), in: .current) } private func reloadStats(firstTime: Bool, completion: @escaping () -> Void) { diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 7cb6dbc8f1..4eb2be2d52 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -3324,7 +3324,7 @@ public final class StoryItemSetContainerComponent: Component { let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme) self.component?.presentController(UndoOverlayController( presentationData: presentationData, - content: .info(title: nil, text: component.strings.Story_ToastShowStoriesTo(peer.compactDisplayTitle).string, timeout: nil), + content: .info(title: nil, text: component.strings.Story_ToastShowStoriesTo(peer.compactDisplayTitle).string, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, animateInAsReplacement: false, @@ -3345,7 +3345,7 @@ public final class StoryItemSetContainerComponent: Component { let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme) self.component?.presentController(UndoOverlayController( presentationData: presentationData, - content: .info(title: nil, text: component.strings.Story_ToastHideStoriesFrom(peer.compactDisplayTitle).string, timeout: nil), + content: .info(title: nil, text: component.strings.Story_ToastHideStoriesFrom(peer.compactDisplayTitle).string, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, animateInAsReplacement: false, @@ -4787,7 +4787,7 @@ public final class StoryItemSetContainerComponent: Component { let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } let controller = UndoOverlayController( presentationData: presentationData, - content: .info(title: nil, text: text, timeout: nil), + content: .info(title: nil, text: text, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, blurred: true, @@ -5778,7 +5778,7 @@ public final class StoryItemSetContainerComponent: Component { if component.slice.item.storyItem.isPinned { self.component?.presentController(UndoOverlayController( presentationData: presentationData, - content: .info(title: nil, text: component.strings.Story_ToastRemovedFromProfileText, timeout: nil), + content: .info(title: nil, text: component.strings.Story_ToastRemovedFromProfileText, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, blurred: true, @@ -5787,7 +5787,7 @@ public final class StoryItemSetContainerComponent: Component { } else { self.component?.presentController(UndoOverlayController( presentationData: presentationData, - content: .info(title: component.strings.Story_ToastSavedToProfileTitle, text: component.strings.Story_ToastSavedToProfileText, timeout: nil), + content: .info(title: component.strings.Story_ToastSavedToProfileTitle, text: component.strings.Story_ToastSavedToProfileText, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, blurred: true, @@ -5929,7 +5929,7 @@ public final class StoryItemSetContainerComponent: Component { if component.slice.item.storyItem.isPinned { self.scheduledStoryUnpinnedUndoOverlay = UndoOverlayController( presentationData: presentationData, - content: .info(title: nil, text: presentationData.strings.Story_ToastRemovedFromChannelText, timeout: nil), + content: .info(title: nil, text: presentationData.strings.Story_ToastRemovedFromChannelText, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, blurred: true, @@ -5938,7 +5938,7 @@ public final class StoryItemSetContainerComponent: Component { } else { self.component?.presentController(UndoOverlayController( presentationData: presentationData, - content: .info(title: presentationData.strings.Story_ToastSavedToChannelTitle, text: presentationData.strings.Story_ToastSavedToChannelText, timeout: nil), + content: .info(title: presentationData.strings.Story_ToastSavedToChannelTitle, text: presentationData.strings.Story_ToastSavedToChannelText, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, blurred: true, diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 21fb06b88e..16463ef115 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -297,6 +297,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var preloadAttachBotIconsDisposables: DisposableSet? var keepMessageCountersSyncrhonizedDisposable: Disposable? var saveMediaDisposable: MetaDisposable? + var giveawayStatusDisposable: MetaDisposable? let editingMessage = ValuePromise(nil, ignoreRepeated: true) let startingBot = ValuePromise(false, ignoreRepeated: true) @@ -733,34 +734,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G case .full: break } - } else if let giveaway = media as? TelegramMediaGiveaway { -//TODO:localize - var peerName = "" - if let peerId = giveaway.channelPeerIds.first, let peer = message.peers[peerId] { - peerName = EnginePeer(peer).compactDisplayTitle - } - + } else if let _ = media as? TelegramMediaGiveaway { var signal = strongSelf.context.engine.payments.premiumGiveawayInfo(peerId: message.id.peerId, messageId: message.id) let disposable: MetaDisposable - if let current = strongSelf.bankCardDisposable { + if let current = strongSelf.giveawayStatusDisposable { disposable = current } else { disposable = MetaDisposable() - strongSelf.bankCardDisposable = disposable + strongSelf.giveawayStatusDisposable = disposable } -// var cancelImpl: (() -> Void)? -// let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let progressSignal = Signal { subscriber in -// let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { -// cancelImpl?() -// })) -// strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) -// return ActionDisposable { [weak controller] in -// Queue.mainQueue().async() { -// controller?.dismiss() -// } -// } return EmptyDisposable } |> runOn(Queue.mainQueue()) @@ -773,149 +757,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G progressDisposable.dispose() } } -// cancelImpl = { -// disposable.set(nil) -// } disposable.set((signal |> deliverOnMainQueue).startStrict(next: { [weak self] info in - if let strongSelf = self, let info = info { - let untilDate = stringForDate(timestamp: giveaway.untilDate, strings: strongSelf.presentationData.strings) - - let title: String - let text: String - var warning: String? - - var dismissImpl: (() -> Void)? - - var actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { - dismissImpl?() - })] - - switch info { - case let .ongoing(start, status): - let startDate = stringForDate(timestamp: start, strings: strongSelf.presentationData.strings) - - title = "About This Giveaway" - - let intro: String - if case .almostOver = status { - intro = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers." - } else { - intro = "The giveaway is sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers." - } - - let ending: String - if giveaway.flags.contains(.onlyNewSubscribers) { - if giveaway.channelPeerIds.count > 1 { - ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels after **\(startDate)**." - } else { - ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**." - } - } else { - if giveaway.channelPeerIds.count > 1 { - ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels." - } else { - ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)**." - } - } - - var participation: String - switch status { - case .notQualified: - if giveaway.channelPeerIds.count > 1 { - participation = "To take part in this giveaway please join the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels) before **\(untilDate)**." - } else { - participation = "To take part in this giveaway please join the channel **\(peerName)** before **\(untilDate)**." - } - case let .notAllowed(reason): - switch reason { - case let .joinedTooEarly(joinedOn): - let joinDate = stringForDate(timestamp: joinedOn, strings: strongSelf.presentationData.strings) - participation = "You are not eligible to participate in this giveaway, because you joined this channel on **\(joinDate)**, which is before the contest started." - case let .channelAdmin(adminId): - let _ = adminId - participation = "You are not eligible to participate in this giveaway, because you are an admin of participating channel (**\(peerName)**)." - case let .disallowedCountry(countryCode): - let _ = countryCode - participation = "You are not eligible to participate in this giveaway, because your country is not included in the terms of the giveaway." - } - case .participating: - if giveaway.channelPeerIds.count > 1 { - participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels)." - } else { - participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)**." - } - case .almostOver: - participation = "The giveaway is over, preparing results." - } - - if !participation.isEmpty { - participation = "\n\n\(participation)" - } - - text = "\(intro)\n\n\(ending)\(participation)" - case let .finished(status, start, finish, _, activatedCount): - let startDate = stringForDate(timestamp: start, strings: strongSelf.presentationData.strings) - let finishDate = stringForDate(timestamp: finish, strings: strongSelf.presentationData.strings) - title = "Giveaway Ended" - - let intro = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers." - - var ending: String - if giveaway.flags.contains(.onlyNewSubscribers) { - if giveaway.channelPeerIds.count > 1 { - ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** and other listed channels after **\(startDate)**." - } else { - ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**." - } - } else { - if giveaway.channelPeerIds.count > 1 { - ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)** and other listed channels." - } else { - ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)**." - } - } - - if activatedCount > 0 { - ending += " \(activatedCount) of the winners already used their gift links." - } - - var result: String - switch status { - case .refunded: - result = "" - warning = "The channel cancelled the prizes by reversing the payment for them." - actions = [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Close, action: { - dismissImpl?() - })] - case .notWon: - result = "\n\nYou didn't win a prize in this giveaway." - case let .won(slug): - result = "\n\nYou won a prize in this giveaway. 🏆" - let _ = slug - actions = [TextAlertAction(type: .defaultAction, title: "View My Prize", action: { - dismissImpl?() - }), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { - dismissImpl?() - })] - } - - text = "\(intro)\n\n\(ending)\(result)" - } - - let alertController = giveawayInfoAlertController( - context: strongSelf.context, - updatedPresentationData: strongSelf.updatedPresentationData, - title: title, - text: text, - warning: warning, - actions: actions - ) - strongSelf.present(alertController, in: .window(.root)) - - dismissImpl = { [weak alertController] in - alertController?.dismissAnimated() - } + if let strongSelf = self, let info { + strongSelf.displayGiveawayStatusInfo(messageId: message.id, giveawayInfo: info) } })) @@ -4894,6 +4739,49 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G controller?.replace(with: c) } self.push(controller) + }, displayGiveawayParticipationStatus: { [weak self] messageId in + guard let self else { + return + } + let disposable: MetaDisposable + if let current = self.giveawayStatusDisposable { + disposable = current + } else { + disposable = MetaDisposable() + self.giveawayStatusDisposable = disposable + } + disposable.set((self.context.engine.payments.premiumGiveawayInfo(peerId: messageId.peerId, messageId: messageId) + |> deliverOnMainQueue).start(next: { [weak self] info in + guard let self, let info else { + return + } + let content: UndoOverlayContent + switch info { + case let .ongoing(_, status): + switch status { + case .notAllowed: + content = .info(title: nil, text: "You can't participate in this giveaway.", timeout: nil, customUndoText: "Learn More") + case .participating: + content = .succeed(text: "You are participating in this giveaway.", timeout: nil, customUndoText: "Learn More") + case .notQualified: + content = .info(title: nil, text: "You are not qualified for this giveaway yet.", timeout: nil, customUndoText: "Learn More") + case .almostOver: + content = .info(title: nil, text: "The giveaway is almost over.", timeout: nil, customUndoText: "Learn More") + } + case let .finished(status, _, _, _, _): + let _ = status + content = .info(title: nil, text: "The giveaway is ended.", timeout: nil, customUndoText: "Learn More") + } + let controller = UndoOverlayController(presentationData: self.presentationData, content: content, elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { [weak self] action in + if case .undo = action, let self { + self.displayGiveawayStatusInfo(messageId: messageId, giveawayInfo: info) + return true + } + return false + }) + self.present(controller, in: .current) + + })) }, requestMessageUpdate: { [weak self] id, scroll in if let self { self.chatDisplayNode.historyNode.requestMessageUpdate(id, andScrollToItem: scroll) @@ -6843,6 +6731,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.premiumGiftSuggestionDisposable?.dispose() self.powerSavingMonitoringDisposable?.dispose() self.saveMediaDisposable?.dispose() + self.giveawayStatusDisposable?.dispose() self.choosingStickerActivityDisposable?.dispose() self.automaticMediaDownloadSettingsDisposable?.dispose() self.stickerSettingsDisposable?.dispose() @@ -8061,7 +7950,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self, case let .message(index) = toSubject.index { if case let .message(messageSubject, _, _) = strongSelf.subject, initial, case let .id(messageId) = messageSubject, messageId != index.id { if messageId.peerId == index.id.peerId { - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.Conversation_MessageDoesntExist, timeout: nil), elevatedLayout: false, action: { _ in return true }), in: .current) + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.Conversation_MessageDoesntExist, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return true }), in: .current) } } else if let controllerInteraction = strongSelf.controllerInteraction { if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(index.id) { @@ -8076,7 +7965,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G hasQuote = true } else { //TODO:localize - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: "Quote not found", timeout: nil), elevatedLayout: false, action: { _ in return true }), in: .current) + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: "Quote not found", timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return true }), in: .current) } } @@ -9404,12 +9293,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G bannedMediaInput = true } else if channel.hasBannedPermission(.banSendVoice) != nil { if !isVideo { - strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil)) + strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil, customUndoText: nil)) return } } else if channel.hasBannedPermission(.banSendInstantVideos) != nil { if isVideo { - strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil)) + strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil, customUndoText: nil)) return } } @@ -9418,12 +9307,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G bannedMediaInput = true } else if group.hasBannedPermission(.banSendVoice) { if !isVideo { - strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil)) + strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil, customUndoText: nil)) return } } else if group.hasBannedPermission(.banSendInstantVideos) { if isVideo { - strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil)) + strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.restrictedSendingContentsText(), timeout: nil, customUndoText: nil)) return } } @@ -10654,7 +10543,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } unarchiveAutomaticallyArchivedPeer(account: strongSelf.context.account, peerId: peerId) - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .succeed(text: strongSelf.presentationData.strings.Conversation_UnarchiveDone, timeout: nil), elevatedLayout: false, action: { _ in return false }), in: .current) + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .succeed(text: strongSelf.presentationData.strings.Conversation_UnarchiveDone, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false }), in: .current) }, scrollToTop: { [weak self] in guard let strongSelf = self else { return @@ -10747,7 +10636,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G presentAddMembersImpl(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, parentController: strongSelf, groupPeer: peer, selectAddMemberDisposable: strongSelf.selectAddMemberDisposable, addMemberDisposable: strongSelf.addMemberDisposable) }, presentGigagroupHelp: { [weak self] in if let strongSelf = self { - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.Conversation_GigagroupDescription, timeout: nil), elevatedLayout: false, action: { _ in return true }), in: .current) + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.Conversation_GigagroupDescription, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return true }), in: .current) } }, editMessageMedia: { [weak self] messageId, draw in if let strongSelf = self { @@ -11841,7 +11730,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in return nil }), textAlignment: .center) let controller = richTextAlertController(context: strongSelf.context, title: attributedTitle, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.BroadcastGroups_LimitAlert_SettingsTip, timeout: nil), elevatedLayout: false, action: { _ in return false }), in: .current) + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.BroadcastGroups_LimitAlert_SettingsTip, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false }), in: .current) }), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.BroadcastGroups_LimitAlert_LearnMore, action: { let context = strongSelf.context @@ -13180,7 +13069,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G disposable.set((signal |> deliverOnMainQueue).startStrict(completed: { [weak self] in if let strongSelf = self, let _ = strongSelf.validLayout { - strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(selectedSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).string, timeout: nil), elevatedLayout: false, action: { _ in return false }), in: .current) + strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(selectedSize, formatting: DataSizeStringFormatting(presentationData: presentationData)))", stringForDeviceType()).string, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false }), in: .current) } })) @@ -13459,7 +13348,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if justInstalled { let content: UndoOverlayContent // if bot.flags.contains(.showInSettings) { - content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(botPeer.compactDisplayTitle).string, timeout: 5.0) + content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(botPeer.compactDisplayTitle).string, timeout: 5.0, customUndoText: nil) // } else { // content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsAdded(bot.shortName).string, timeout: 5.0) // } @@ -13702,12 +13591,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let content: UndoOverlayContent if botJustInstalled { if bot.flags.contains(.showInSettings) { - content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(bot.shortName).string, timeout: 5.0) + content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(bot.shortName).string, timeout: 5.0, customUndoText: nil) } else { - content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsAdded(bot.shortName).string, timeout: 5.0) + content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsAdded(bot.shortName).string, timeout: 5.0, customUndoText: nil) } } else { - content = .info(title: nil, text: strongSelf.presentationData.strings.WebApp_AddToAttachmentAlreadyAddedError, timeout: nil) + content = .info(title: nil, text: strongSelf.presentationData.strings.WebApp_AddToAttachmentAlreadyAddedError, timeout: nil, customUndoText: nil) } strongSelf.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, position: .top, action: { _ in return false }), in: .current) } else { @@ -14083,9 +13972,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G Queue.mainQueue().after(0.3) { let content: UndoOverlayContent if bot.flags.contains(.showInSettings) { - content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(bot.shortName).string, timeout: 5.0) + content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsSettingsAdded(bot.shortName).string, timeout: 5.0, customUndoText: nil) } else { - content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsAdded(bot.shortName).string, timeout: 5.0) + content = .succeed(text: strongSelf.presentationData.strings.WebApp_ShortcutsAdded(bot.shortName).string, timeout: 5.0, customUndoText: nil) } attachmentController.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, position: .top, action: { _ in return false }), in: .current) } @@ -19652,6 +19541,157 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G func updateNextChannelToReadVisibility() { self.chatDisplayNode.historyNode.offerNextChannelToRead = self.offerNextChannelToRead && self.presentationInterfaceState.interfaceState.selectionState == nil } + + func displayGiveawayStatusInfo(messageId: EngineMessage.Id, giveawayInfo: PremiumGiveawayInfo) { + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId)) + |> deliverOnMainQueue).startStandalone(next: { [weak self] message in + guard let self, let message, let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway else { + return + } + var peerName = "" + if let peerId = giveaway.channelPeerIds.first, let peer = message.peers[peerId] { + peerName = EnginePeer(peer).compactDisplayTitle + } + + let untilDate = stringForDate(timestamp: giveaway.untilDate, strings: self.presentationData.strings) + + let title: String + let text: String + var warning: String? + + var dismissImpl: (() -> Void)? + + var actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { + dismissImpl?() + })] + + switch giveawayInfo { + case let .ongoing(start, status): + let startDate = stringForDate(timestamp: start, strings: self.presentationData.strings) + + title = "About This Giveaway" + + let intro: String + if case .almostOver = status { + intro = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers." + } else { + intro = "The giveaway is sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers." + } + + let ending: String + if giveaway.flags.contains(.onlyNewSubscribers) { + if giveaway.channelPeerIds.count > 1 { + ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels after **\(startDate)**." + } else { + ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**." + } + } else { + if giveaway.channelPeerIds.count > 1 { + ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels." + } else { + ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)**." + } + } + + var participation: String + switch status { + case .notQualified: + if giveaway.channelPeerIds.count > 1 { + participation = "To take part in this giveaway please join the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels) before **\(untilDate)**." + } else { + participation = "To take part in this giveaway please join the channel **\(peerName)** before **\(untilDate)**." + } + case let .notAllowed(reason): + switch reason { + case let .joinedTooEarly(joinedOn): + let joinDate = stringForDate(timestamp: joinedOn, strings: self.presentationData.strings) + participation = "You are not eligible to participate in this giveaway, because you joined this channel on **\(joinDate)**, which is before the contest started." + case let .channelAdmin(adminId): + let _ = adminId + participation = "You are not eligible to participate in this giveaway, because you are an admin of participating channel (**\(peerName)**)." + case let .disallowedCountry(countryCode): + let _ = countryCode + participation = "You are not eligible to participate in this giveaway, because your country is not included in the terms of the giveaway." + } + case .participating: + if giveaway.channelPeerIds.count > 1 { + participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels)." + } else { + participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)**." + } + case .almostOver: + participation = "The giveaway is over, preparing results." + } + + if !participation.isEmpty { + participation = "\n\n\(participation)" + } + + text = "\(intro)\n\n\(ending)\(participation)" + case let .finished(status, start, finish, _, activatedCount): + let startDate = stringForDate(timestamp: start, strings: self.presentationData.strings) + let finishDate = stringForDate(timestamp: finish, strings: self.presentationData.strings) + title = "Giveaway Ended" + + let intro = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers." + + var ending: String + if giveaway.flags.contains(.onlyNewSubscribers) { + if giveaway.channelPeerIds.count > 1 { + ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** and other listed channels after **\(startDate)**." + } else { + ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**." + } + } else { + if giveaway.channelPeerIds.count > 1 { + ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)** and other listed channels." + } else { + ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)**." + } + } + + if activatedCount > 0 { + ending += " \(activatedCount) of the winners already used their gift links." + } + + var result: String + switch status { + case .refunded: + result = "" + warning = "The channel cancelled the prizes by reversing the payment for them." + actions = [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Close, action: { + dismissImpl?() + })] + case .notWon: + result = "\n\nYou didn't win a prize in this giveaway." + case let .won(slug): + result = "\n\nYou won a prize in this giveaway. 🏆" + let _ = slug + actions = [TextAlertAction(type: .defaultAction, title: "View My Prize", action: { + dismissImpl?() + }), TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: { + dismissImpl?() + })] + } + + text = "\(intro)\n\n\(ending)\(result)" + } + + let alertController = giveawayInfoAlertController( + context: self.context, + updatedPresentationData: self.updatedPresentationData, + title: title, + text: text, + warning: warning, + actions: actions + ) + self.present(alertController, in: .window(.root)) + + dismissImpl = { [weak alertController] in + alertController?.dismissAnimated() + } + }) + } } final class ChatContextControllerContentSourceImpl: ContextControllerContentSource { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 21b559877b..be2b92ec2d 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -861,7 +861,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState let _ = context.engine.messages.rateAudioTranscription(messageId: message.id, id: audioTranscription.id, isGood: value).startStandalone() let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let content: UndoOverlayContent = .info(title: nil, text: presentationData.strings.Chat_AudioTranscriptionFeedbackTip, timeout: nil) + let content: UndoOverlayContent = .info(title: nil, text: presentationData.strings.Chat_AudioTranscriptionFeedbackTip, timeout: nil, customUndoText: nil) controllerInteraction.displayUndo(content) }), false), at: 0) actions.insert(.separator, at: 1) @@ -888,9 +888,9 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState let settings = NotificationSoundSettings.extract(from: context.currentAppConfiguration.with({ $0 })) if size > settings.maxSize { - controllerInteraction.displayUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLarge_Title, text: presentationData.strings.Notifications_UploadError_TooLarge_Text(dataSizeString(Int64(settings.maxSize), formatting: DataSizeStringFormatting(presentationData: presentationData))).string, timeout: nil)) + controllerInteraction.displayUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLarge_Title, text: presentationData.strings.Notifications_UploadError_TooLarge_Text(dataSizeString(Int64(settings.maxSize), formatting: DataSizeStringFormatting(presentationData: presentationData))).string, timeout: nil, customUndoText: nil)) } else if Double(duration) > Double(settings.maxDuration) { - controllerInteraction.displayUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLong_Title(fileName).string, text: presentationData.strings.Notifications_UploadError_TooLong_Text(stringForDuration(Int32(settings.maxDuration))).string, timeout: nil)) + controllerInteraction.displayUndo(.info(title: presentationData.strings.Notifications_UploadError_TooLong_Title(fileName).string, text: presentationData.strings.Notifications_UploadError_TooLong_Text(stringForDuration(Int32(settings.maxDuration))).string, timeout: nil, customUndoText: nil)) } else { let _ = (context.engine.peers.saveNotificationSound(file: .message(message: MessageReference(message), media: file)) |> deliverOnMainQueue).startStandalone(completed: { diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 3372203cab..996985a855 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -601,7 +601,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur } case let .startAttach(peerId, payload, choose): let presentError: (String) -> Void = { errorText in - present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: errorText, timeout: nil), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: errorText, timeout: nil, customUndoText: nil), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return true }), nil) } @@ -894,54 +894,6 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur let controller = PremiumLimitScreen(context: context, subject: subject, count: Int32(status.boosts), forceDark: forceDark, action: { let dismiss = false updateImpl?() - -// switch canApplyStatus { -// case .ok: -// updateImpl?() -// case let .replace(previousPeer): -// let controller = replaceBoostConfirmationController(context: context, fromPeers: [previousPeer], toPeer: peer, commit: { -// updateImpl?() -// }) -// present(controller, nil) -// case let .error(error): -// let title: String? -// let text: String -// -// var actions: [TextAlertAction] = [ -// TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}) -// ] -// -// switch error { -// case .generic: -// title = nil -// text = presentationData.strings.Login_UnknownError -// case let .floodWait(timeout): -// title = presentationData.strings.ChannelBoost_Error_BoostTooOftenTitle -// let valueText = timeIntervalString(strings: presentationData.strings, value: timeout, usage: .afterTime, preferLowerValue: false) -// text = presentationData.strings.ChannelBoost_Error_BoostTooOftenText(valueText).string -// dismiss = true -// case .premiumRequired: -// title = presentationData.strings.ChannelBoost_Error_PremiumNeededTitle -// text = presentationData.strings.ChannelBoost_Error_PremiumNeededText -// actions = [ -// TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), -// TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: { -// dismissImpl?() -// let controller = context.sharedContext.makePremiumIntroController(context: context, source: .channelBoost(peerId), forceDark: false, dismissed: nil) -// navigationController?.pushViewController(controller) -// }) -// ] -// case .giftedPremiumNotAllowed: -// title = presentationData.strings.ChannelBoost_Error_GiftedPremiumNotAllowedTitle -// text = presentationData.strings.ChannelBoost_Error_GiftedPremiumNotAllowedText -// dismiss = true -// case .peerBoostAlreadyActive: -// return true -// } -// -// let controller = textAlertController(sharedContext: context.sharedContext, updatedPresentationData: updatedPresentationData, title: title, text: text, actions: actions, parseMarkdown: true) -// present(controller, nil) -// } return dismiss }, openPeer: { peer in @@ -971,7 +923,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur let _ = context.engine.peers.applyChannelBoost(peerId: peerId, slots: slots).startStandalone() let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let undoController = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "\(slots.count) boosts are reassigned from 1 other channel.", timeout: nil), elevatedLayout: true, position: .bottom, action: { _ in return true }) + let undoController = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "\(slots.count) boosts are reassigned from 1 other channel.", timeout: nil, customUndoText: nil), elevatedLayout: true, position: .bottom, action: { _ in return true }) (navigationController?.viewControllers.last as? ViewController)?.present(undoController, in: .window(.root)) }) dismissImpl?() diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 40056dac9b..3f80155d6b 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -167,6 +167,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, openRequestedPeerSelection: { _, _, _ in }, saveMediaToFiles: { _ in }, openNoAdsDemo: { + }, displayGiveawayParticipationStatus: { _ in }, requestMessageUpdate: { _, _ in }, cancelInteractiveKeyboardGestures: { }, dismissTextInput: { diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 17fd1eb03c..6e7a508d67 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -2918,6 +2918,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro }, openRequestedPeerSelection: { _, _, _ in }, saveMediaToFiles: { _ in }, openNoAdsDemo: { + }, displayGiveawayParticipationStatus: { _ in }, requestMessageUpdate: { _, _ in }, cancelInteractiveKeyboardGestures: { }, dismissTextInput: { @@ -4739,7 +4740,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro text = presentationData.strings.WebApp_ShortcutsAdded(bot.peer.compactDisplayTitle).string } controller.present( - UndoOverlayController(presentationData: presentationData, content: .succeed(text: text, timeout: 5.0), elevatedLayout: false, position: .top, action: { _ in return false }), + UndoOverlayController(presentationData: presentationData, content: .succeed(text: text, timeout: 5.0, customUndoText: nil), elevatedLayout: false, position: .top, action: { _ in return false }), in: .current ) }) @@ -6552,7 +6553,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro |> deliverOnMainQueue).startStrict(completed: { [weak self] in if let strongSelf = self, let peer = strongSelf.data?.peer { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let controller = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Conversation_DeletedFromContacts(EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string, timeout: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }) + let controller = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Conversation_DeletedFromContacts(EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string, timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }) controller.keepOnParentDismissal = true strongSelf.controller?.present(controller, in: .window(.root)) diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index fa2493f7a8..30011d92ac 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1556,6 +1556,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { }, openRequestedPeerSelection: { _, _, _ in }, saveMediaToFiles: { _ in }, openNoAdsDemo: { + }, displayGiveawayParticipationStatus: { _ in }, requestMessageUpdate: { _, _ in }, cancelInteractiveKeyboardGestures: { }, dismissTextInput: { diff --git a/submodules/UndoUI/Sources/UndoOverlayController.swift b/submodules/UndoUI/Sources/UndoOverlayController.swift index 5be099fc8e..a5775b1008 100644 --- a/submodules/UndoUI/Sources/UndoOverlayController.swift +++ b/submodules/UndoUI/Sources/UndoOverlayController.swift @@ -11,8 +11,8 @@ public enum UndoOverlayContent { case archivedChat(peerId: Int64, title: String, text: String, undo: Bool) case hidArchive(title: String, text: String, undo: Bool) case revealedArchive(title: String, text: String, undo: Bool) - case succeed(text: String, timeout: Double?) - case info(title: String?, text: String, timeout: Double?) + case succeed(text: String, timeout: Double?, customUndoText: String?) + case info(title: String?, text: String, timeout: Double?, customUndoText: String?) case emoji(name: String, text: String) case swipeToReply(title: String, text: String) case actionSucceeded(title: String, text: String, cancel: String, destructive: Bool) diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index 5b67c73eb6..52b58ab703 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -191,7 +191,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { if text.contains("](") { isUserInteractionEnabled = true } - case let .succeed(text, timeout): + case let .succeed(text, timeout, customUndoText): self.avatarNode = nil self.iconNode = nil self.iconCheckNode = nil @@ -203,9 +203,14 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in return nil }), textAlignment: .natural) self.textNode.attributedText = attributedText self.textNode.maximumNumberOfLines = 5 - displayUndo = false + if let customUndoText { + undoText = customUndoText + displayUndo = true + } else { + displayUndo = false + } self.originalRemainingSeconds = timeout ?? 3 - case let .info(title, text, timeout): + case let .info(title, text, timeout, customUndoText): self.avatarNode = nil self.iconNode = nil self.iconCheckNode = nil @@ -224,7 +229,12 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { }), textAlignment: .natural) self.textNode.attributedText = attributedText self.textNode.maximumNumberOfLines = 10 - displayUndo = false + if let customUndoText { + undoText = customUndoText + displayUndo = true + } else { + displayUndo = false + } if let timeout { self.originalRemainingSeconds = timeout } else {