diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 7e9500c499..ec41a56443 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8911,8 +8911,9 @@ Sorry for the inconvenience."; "ChatList.EmptyChatListWithArchive" = "All of your chats are archived."; -"Conversation.AudioRateTooltip15X" = "Audio will play at 1.5X speed."; +"Conversation.AudioRateTooltip15X" = "Audio will play at 1.5x speed."; "Conversation.AudioRateOptionsTooltip" = "Long tap for more speed values."; +"Conversation.AudioRateTooltipCustom" = "Audio will play at %@x speed."; "ImportStickerPack.EmojiCount_1" = "%@ Emoji"; "ImportStickerPack.EmojiCount_any" = "%@ Emojis"; @@ -8936,3 +8937,5 @@ Sorry for the inconvenience."; "ChatList.ReadAll" = "Read All"; "ChatList.ClearSavedMessagesConfirmation" = "Are you sure you want to delete all your saved messages?"; + +"Conversation.Translation.Settings" = "Settings"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index cc0cfc3c2b..0dde3eaf08 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -751,6 +751,7 @@ public protocol SharedAccountContext: AnyObject { var immediateExperimentalUISettings: ExperimentalUISettings { get } var currentInAppNotificationSettings: Atomic { get } var currentMediaInputSettings: Atomic { get } + var currentStickerSettings: Atomic { get } var energyUsageSettings: EnergyUsageSettings { get } diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 8be0947f5d..46b0050389 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -2715,7 +2715,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause)) } } - mediaAccessoryPanel.setRate = { [weak self] rate, fromMenu in + mediaAccessoryPanel.setRate = { [weak self] rate, changeType in guard let strongSelf = self else { return } @@ -2756,10 +2756,25 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp rate = 2.0 } else { - text = nil - rate = nil + let value = String(format: "%0.1f", baseRate.doubleValue) + text = presentationData.strings.Conversation_AudioRateTooltipCustom(value).string + if case let .sliderCommit(previousValue, newValue) = changeType { + if newValue > previousValue { + rate = .infinity + } else if newValue < previousValue { + rate = -.infinity + } else { + rate = nil + } + } else { + rate = nil + } } - if let rate, let text, !fromMenu { + var showTooltip = true + if case .sliderChange = changeType { + showTooltip = false + } + if let rate, let text, showTooltip { controller.present( UndoOverlayController( presentationData: presentationData, diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index fad7948100..f3094b361b 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -615,16 +615,8 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { func setFile(context: AccountContext, userLocation: MediaResourceUserLocation, fileReference: FileMediaReference) { if self.contextAndMedia == nil || !self.contextAndMedia!.1.media.isEqual(to: fileReference.media) { - if var largestSize = fileReference.media.dimensions { - var displaySize = largestSize.cgSize.dividedByScreenScale() - if let previewDimensions = largestImageRepresentation(fileReference.media.previewRepresentations)?.dimensions { - let previewAspect = CGFloat(previewDimensions.width) / CGFloat(previewDimensions.height) - let aspect = displaySize.width / displaySize.height - if abs(previewAspect - 1.0 / aspect) < 0.1 { - displaySize = CGSize(width: displaySize.height, height: displaySize.width) - largestSize = PixelDimensions(width: largestSize.height, height: largestSize.width) - } - } + if let largestSize = fileReference.media.dimensions { + let displaySize = largestSize.cgSize.dividedByScreenScale() self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))() /*if largestSize.width > 2600 || largestSize.height > 2600 { diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 2c4b223f40..b0d86bc067 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -1904,19 +1904,23 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta } - _ = (ApplicationSpecificNotice.getSetPublicChannelLink(accountManager: context.sharedContext.accountManager) |> deliverOnMainQueue).start(next: { showAlert in - if showAlert { - let text: String - if case .broadcast = peer.info { - text = presentationData.strings.Channel_Edit_PrivatePublicLinkAlert + if !updatedAddressNameValue.isEmpty { + _ = (ApplicationSpecificNotice.getSetPublicChannelLink(accountManager: context.sharedContext.accountManager) |> deliverOnMainQueue).start(next: { showAlert in + if showAlert { + let text: String + if case .broadcast = peer.info { + text = presentationData.strings.Channel_Edit_PrivatePublicLinkAlert + } else { + text = presentationData.strings.Group_Edit_PrivatePublicLinkAlert + } + presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: invokeAction)]), nil) } else { - text = presentationData.strings.Group_Edit_PrivatePublicLinkAlert + invokeAction() } - presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: invokeAction)]), nil) - } else { - invokeAction() - } - }) + }) + } else { + invokeAction() + } } else { switch mode { case .initialSetup: diff --git a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift index 92a77ffb9a..81d14a4568 100644 --- a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift +++ b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift @@ -465,8 +465,15 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { if let languages = translationSettings.ignoredLanguages { ignoredLanguages = languages } else { - if let activeLanguage = activeLanguageCode, supportedTranslationLanguages.contains(activeLanguage) { - ignoredLanguages = [activeLanguage] + + if var activeLanguage = activeLanguageCode { + let rawSuffix = "-raw" + if activeLanguage.hasSuffix(rawSuffix) { + activeLanguage = String(activeLanguage.dropLast(rawSuffix.count)) + } + if supportedTranslationLanguages.contains(activeLanguage) { + ignoredLanguages = [activeLanguage] + } } let systemLanguages = systemLanguageCodes() for systemLanguage in systemLanguages { diff --git a/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift b/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift index 0f418155d1..1736b737a0 100644 --- a/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift +++ b/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift @@ -77,13 +77,17 @@ private func translationSettingsControllerEntries(theme: PresentationTheme, stri if let ignoredLanguages = settings.ignoredLanguages { selectedLanguages = Set(ignoredLanguages) } else { - var langCode = strings.baseLanguageCode - if langCode == "nb" { - langCode = "no" - } else if langCode == "pt-br" { - langCode = "pt" + var activeLanguage = strings.baseLanguageCode + let rawSuffix = "-raw" + if activeLanguage.hasSuffix(rawSuffix) { + activeLanguage = String(activeLanguage.dropLast(rawSuffix.count)) } - selectedLanguages = Set([langCode]) + if activeLanguage == "nb" { + activeLanguage = "no" + } else if activeLanguage == "pt-br" { + activeLanguage = "pt" + } + selectedLanguages = Set([activeLanguage]) for language in systemLanguageCodes() { selectedLanguages.insert(language) } @@ -114,7 +118,11 @@ public func translationSettingsController(context: AccountContext) -> ViewContro let actionsDisposable = DisposableSet() let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let interfaceLanguageCode = presentationData.strings.baseLanguageCode + var interfaceLanguageCode = presentationData.strings.baseLanguageCode + let rawSuffix = "-raw" + if interfaceLanguageCode.hasSuffix(rawSuffix) { + interfaceLanguageCode = String(interfaceLanguageCode.dropLast(rawSuffix.count)) + } let arguments = TranslationSettingsControllerArguments(context: context, updateLanguageSelected: { code, value in let _ = updateTranslationSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in @@ -185,7 +193,12 @@ public func translationSettingsController(context: AccountContext) -> ViewContro if let ignoredLanguages = settings.ignoredLanguages { selectedLanguages = Set(ignoredLanguages) } else { - selectedLanguages = Set([presentationData.strings.baseLanguageCode]) + var activeLanguage = presentationData.strings.baseLanguageCode + let rawSuffix = "-raw" + if activeLanguage.hasSuffix(rawSuffix) { + activeLanguage = String(activeLanguage.dropLast(rawSuffix.count)) + } + selectedLanguages = Set([activeLanguage]) for language in systemLanguageCodes() { selectedLanguages.insert(language) } diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift index 69584f48fd..14130f8760 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift @@ -174,7 +174,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi public var tapAction: (() -> Void)? public var close: (() -> Void)? - public var setRate: ((AudioPlaybackRate, Bool) -> Void)? + public var setRate: ((AudioPlaybackRate, MediaNavigationAccessoryPanel.ChangeType) -> Void)? public var togglePlayPause: (() -> Void)? public var playPrevious: (() -> Void)? public var playNext: (() -> Void)? @@ -500,7 +500,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi } else { nextRate = .x2 } - self.setRate?(nextRate, false) + self.setRate?(nextRate, .preset) let frame = self.rateButton.view.convert(self.rateButton.bounds, to: nil) @@ -527,8 +527,10 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi private func contextMenuSpeedItems(dismiss: @escaping () -> Void) -> Signal<[ContextMenuItem], NoError> { var items: [ContextMenuItem] = [] - items.append(.custom(SliderContextItem(minValue: 0.5, maxValue: 2.5, value: self.playbackBaseRate?.doubleValue ?? 1.0, valueChanged: { [weak self] newValue, finished in - self?.setRate?(AudioPlaybackRate(newValue), true) + let previousValue = self.playbackBaseRate?.doubleValue ?? 1.0 + items.append(.custom(SliderContextItem(minValue: 0.5, maxValue: 2.5, value: previousValue, valueChanged: { [weak self] newValue, finished in + let type: MediaNavigationAccessoryPanel.ChangeType = finished ? .sliderCommit(previousValue, newValue) : .sliderChange + self?.setRate?(AudioPlaybackRate(newValue), type) if finished { dismiss() } @@ -547,7 +549,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi }, action: { [weak self] _, f in f(.default) - self?.setRate?(rate, true) + self?.setRate?(rate, .preset) }))) } diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryPanel.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryPanel.swift index c13c820f4d..696af04465 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryPanel.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryPanel.swift @@ -10,8 +10,14 @@ import TelegramPresentationData public final class MediaNavigationAccessoryPanel: ASDisplayNode { public let containerNode: MediaNavigationAccessoryContainerNode + public enum ChangeType { + case preset + case sliderChange + case sliderCommit(CGFloat, CGFloat) + } + public var close: (() -> Void)? - public var setRate: ((AudioPlaybackRate, Bool) -> Void)? + public var setRate: ((AudioPlaybackRate, ChangeType) -> Void)? public var togglePlayPause: (() -> Void)? public var tapAction: (() -> Void)? public var playPrevious: (() -> Void)? @@ -34,8 +40,8 @@ public final class MediaNavigationAccessoryPanel: ASDisplayNode { close() } } - self.containerNode.headerNode.setRate = { [weak self] rate, fromMenu in - self?.setRate?(rate, fromMenu) + self.containerNode.headerNode.setRate = { [weak self] rate, type in + self?.setRate?(rate, type) } self.containerNode.headerNode.togglePlayPause = { [weak self] in if let strongSelf = self, let togglePlayPause = strongSelf.togglePlayPause { diff --git a/submodules/TelegramBaseController/Sources/TelegramBaseController.swift b/submodules/TelegramBaseController/Sources/TelegramBaseController.swift index 787cb214bf..eb71cec93c 100644 --- a/submodules/TelegramBaseController/Sources/TelegramBaseController.swift +++ b/submodules/TelegramBaseController/Sources/TelegramBaseController.swift @@ -669,7 +669,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder { strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause)) } } - mediaAccessoryPanel.setRate = { [weak self] rate, fromMenu in + mediaAccessoryPanel.setRate = { [weak self] rate, changeType in guard let strongSelf = self else { return } @@ -709,10 +709,25 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder { text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp rate = 2.0 } else { - text = nil - rate = nil + let value = String(format: "%0.1f", baseRate.doubleValue) + text = presentationData.strings.Conversation_AudioRateTooltipCustom(value).string + if case let .sliderCommit(previousValue, newValue) = changeType { + if newValue > previousValue { + rate = .infinity + } else if newValue < previousValue { + rate = -.infinity + } else { + rate = nil + } + } else { + rate = nil + } } - if let rate, let text, !fromMenu { + var showTooltip = true + if case .sliderChange = changeType { + showTooltip = false + } + if let rate, let text, showTooltip { strongSelf.present( UndoOverlayController( presentationData: presentationData, diff --git a/submodules/TelegramPresentationData/Sources/PresentationData.swift b/submodules/TelegramPresentationData/Sources/PresentationData.swift index 17ea8d3028..69be2a5006 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationData.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationData.swift @@ -218,15 +218,17 @@ public final class InitialPresentationDataAndSettings { public let callListSettings: CallListSettings public let inAppNotificationSettings: InAppNotificationSettings public let mediaInputSettings: MediaInputSettings + public let stickerSettings: StickerSettings public let experimentalUISettings: ExperimentalUISettings - public init(presentationData: PresentationData, automaticMediaDownloadSettings: MediaAutoDownloadSettings, autodownloadSettings: AutodownloadSettings, callListSettings: CallListSettings, inAppNotificationSettings: InAppNotificationSettings, mediaInputSettings: MediaInputSettings, experimentalUISettings: ExperimentalUISettings) { + public init(presentationData: PresentationData, automaticMediaDownloadSettings: MediaAutoDownloadSettings, autodownloadSettings: AutodownloadSettings, callListSettings: CallListSettings, inAppNotificationSettings: InAppNotificationSettings, mediaInputSettings: MediaInputSettings, stickerSettings: StickerSettings, experimentalUISettings: ExperimentalUISettings) { self.presentationData = presentationData self.automaticMediaDownloadSettings = automaticMediaDownloadSettings self.autodownloadSettings = autodownloadSettings self.callListSettings = callListSettings self.inAppNotificationSettings = inAppNotificationSettings self.mediaInputSettings = mediaInputSettings + self.stickerSettings = stickerSettings self.experimentalUISettings = experimentalUISettings } } @@ -242,6 +244,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager deliverOn(Queue(name: "PresentationData-Load", qos: .userInteractive)) @@ -340,6 +347,13 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager deliverOnMainQueue).start(completed: { - Queue.mainQueue().after(0.2) { - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .mediaSaved(text: isVideo ? presentationData.strings.Gallery_VideoSaved : presentationData.strings.Gallery_ImageSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return true }), nil) - } - }) - f(.default) - }))) + } + + if resourceAvailable, !message.containsSecretMedia && !isCopyProtected { + var mediaReference: AnyMediaReference? + var isVideo = false + for media in message.media { + if let image = media as? TelegramMediaImage, let _ = largestImageRepresentation(image.representations) { + mediaReference = ImageMediaReference.standalone(media: image).abstract + break + } else if let file = media as? TelegramMediaFile, file.isVideo { + mediaReference = FileMediaReference.standalone(media: file).abstract + isVideo = true + break } } + if let mediaReference = mediaReference { + actions.append(.action(ContextMenuActionItem(text: isVideo ? chatPresentationInterfaceState.strings.Gallery_SaveVideo : chatPresentationInterfaceState.strings.Gallery_SaveImage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + let _ = (saveToCameraRoll(context: context, postbox: context.account.postbox, userLocation: .peer(message.id.peerId), mediaReference: mediaReference) + |> deliverOnMainQueue).start(completed: { + Queue.mainQueue().after(0.2) { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .mediaSaved(text: isVideo ? presentationData.strings.Gallery_VideoSaved : presentationData.strings.Gallery_ImageSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return true }), nil) + } + }) + f(.default) + }))) + } } var downloadableMediaResourceInfos: [String] = [] diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index b8d8ab6382..0c210961fd 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -1034,7 +1034,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() { - needsShareButton = false + if hasCommentButton(item: item) { + } else { + needsShareButton = false + } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 72bf5b31b8..64f44ec677 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -53,7 +53,7 @@ private final class ChatMessageBubbleClippingNode: ASDisplayNode { } } -private func hasCommentButton(item: ChatMessageItem) -> Bool { +func hasCommentButton(item: ChatMessageItem) -> Bool { let firstMessage = item.content.firstMessage var hasDiscussion = false @@ -4541,6 +4541,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode for contentNode in self.contentNodes { if let contentNode = contentNode as? ChatMessageFileBubbleContentNode { return contentNode.interactiveFileNode.hasExpandedAudioTranscription + } else if let contentNode = contentNode as? ChatMessageInstantVideoBubbleContentNode { + return contentNode.hasExpandedAudioTranscription } } return false diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift index d187dfaeff..516b4fd898 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift @@ -23,6 +23,14 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode { private var audioTranscriptionState: AudioTranscriptionButtonComponent.TranscriptionState = .collapsed + var hasExpandedAudioTranscription: Bool { + if case .expanded = self.audioTranscriptionState { + return true + } else { + return false + } + } + override var visibility: ListViewItemNodeVisibility { didSet { var wasVisible = false diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index bcf70a8601..a19b616c4d 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -505,7 +505,10 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() { - needsShareButton = false + if hasCommentButton(item: item) { + } else { + needsShareButton = false + } } } diff --git a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoListPaneNode.swift b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoListPaneNode.swift index f409765387..8a23dd1484 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoListPaneNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoListPaneNode.swift @@ -262,7 +262,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause)) } } - mediaAccessoryPanel.setRate = { [weak self] rate, fromMenu in + mediaAccessoryPanel.setRate = { [weak self] rate, changeType in guard let strongSelf = self else { return } @@ -289,7 +289,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { } return true }) - + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let text: String? let rate: CGFloat? @@ -303,10 +303,25 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp rate = 2.0 } else { - text = nil - rate = nil + let value = String(format: "%0.1f", baseRate.doubleValue) + text = presentationData.strings.Conversation_AudioRateTooltipCustom(value).string + if case let .sliderCommit(previousValue, newValue) = changeType { + if newValue > previousValue { + rate = .infinity + } else if newValue < previousValue { + rate = -.infinity + } else { + rate = nil + } + } else { + rate = nil + } } - if let rate, let text, !fromMenu { + var showTooltip = true + if case .sliderChange = changeType { + showTooltip = false + } + if let rate, let text, showTooltip { controller.present( UndoOverlayController( presentationData: presentationData, diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index d5f6328059..7fee2dd5cc 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1105,7 +1105,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese })) } - if user.botInfo != nil, !user.isVerified { + if user.botInfo != nil { items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 6, text: presentationData.strings.ReportPeer_Report, action: { interaction.openReport(.default) })) diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index d5d67f16ee..77b9b3dcf7 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -163,6 +163,9 @@ public final class SharedAccountContextImpl: SharedAccountContext { public let currentMediaInputSettings: Atomic private var mediaInputSettingsDisposable: Disposable? + public let currentStickerSettings: Atomic + private var stickerSettingsDisposable: Disposable? + private let automaticMediaDownloadSettingsDisposable = MetaDisposable() private var immediateExperimentalUISettingsValue = Atomic(value: ExperimentalUISettings.defaultSettings) @@ -237,6 +240,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { self.currentAutomaticMediaDownloadSettings = initialPresentationDataAndSettings.automaticMediaDownloadSettings self.currentAutodownloadSettings = Atomic(value: initialPresentationDataAndSettings.autodownloadSettings) self.currentMediaInputSettings = Atomic(value: initialPresentationDataAndSettings.mediaInputSettings) + self.currentStickerSettings = Atomic(value: initialPresentationDataAndSettings.stickerSettings) self.currentInAppNotificationSettings = Atomic(value: initialPresentationDataAndSettings.inAppNotificationSettings) let presentationData: Signal = .single(initialPresentationDataAndSettings.presentationData) @@ -348,6 +352,15 @@ public final class SharedAccountContextImpl: SharedAccountContext { } }) + self.stickerSettingsDisposable = (self.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) + |> deliverOnMainQueue).start(next: { [weak self] sharedData in + if let strongSelf = self { + if let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.stickerSettings]?.get(StickerSettings.self) { + let _ = strongSelf.currentStickerSettings.swap(settings) + } + } + }) + let immediateExperimentalUISettingsValue = self.immediateExperimentalUISettingsValue let _ = immediateExperimentalUISettingsValue.swap(initialPresentationDataAndSettings.experimentalUISettings) self.experimentalUISettingsDisposable = (self.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.experimentalUISettings]) diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index d8a51f8f73..776d2bb783 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -546,7 +546,11 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil let animationName: String - if rate == 1.5 { + if rate == .infinity { + animationName = "anim_voicefast" + } else if rate == -.infinity { + animationName = "anim_voiceslow" + } else if rate == 1.5 { animationName = "anim_voice1_5x" } else if rate == 2.0 { animationName = "anim_voice2x"