Various improvements

This commit is contained in:
Ilya Laktyushin 2023-02-25 18:00:45 +04:00
parent 96496aabd9
commit 441e102b0d
23 changed files with 215 additions and 94 deletions

View File

@ -8911,8 +8911,9 @@ Sorry for the inconvenience.";
"ChatList.EmptyChatListWithArchive" = "All of your chats are archived."; "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.AudioRateOptionsTooltip" = "Long tap for more speed values.";
"Conversation.AudioRateTooltipCustom" = "Audio will play at %@x speed.";
"ImportStickerPack.EmojiCount_1" = "%@ Emoji"; "ImportStickerPack.EmojiCount_1" = "%@ Emoji";
"ImportStickerPack.EmojiCount_any" = "%@ Emojis"; "ImportStickerPack.EmojiCount_any" = "%@ Emojis";
@ -8936,3 +8937,5 @@ Sorry for the inconvenience.";
"ChatList.ReadAll" = "Read All"; "ChatList.ReadAll" = "Read All";
"ChatList.ClearSavedMessagesConfirmation" = "Are you sure you want to delete all your saved messages?"; "ChatList.ClearSavedMessagesConfirmation" = "Are you sure you want to delete all your saved messages?";
"Conversation.Translation.Settings" = "Settings";

View File

@ -751,6 +751,7 @@ public protocol SharedAccountContext: AnyObject {
var immediateExperimentalUISettings: ExperimentalUISettings { get } var immediateExperimentalUISettings: ExperimentalUISettings { get }
var currentInAppNotificationSettings: Atomic<InAppNotificationSettings> { get } var currentInAppNotificationSettings: Atomic<InAppNotificationSettings> { get }
var currentMediaInputSettings: Atomic<MediaInputSettings> { get } var currentMediaInputSettings: Atomic<MediaInputSettings> { get }
var currentStickerSettings: Atomic<StickerSettings> { get }
var energyUsageSettings: EnergyUsageSettings { get } var energyUsageSettings: EnergyUsageSettings { get }

View File

@ -2715,7 +2715,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause)) 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 { guard let strongSelf = self else {
return return
} }
@ -2756,10 +2756,25 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp
rate = 2.0 rate = 2.0
} else { } else {
text = 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 rate = nil
} }
if let rate, let text, !fromMenu { } else {
rate = nil
}
}
var showTooltip = true
if case .sliderChange = changeType {
showTooltip = false
}
if let rate, let text, showTooltip {
controller.present( controller.present(
UndoOverlayController( UndoOverlayController(
presentationData: presentationData, presentationData: presentationData,

View File

@ -615,16 +615,8 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
func setFile(context: AccountContext, userLocation: MediaResourceUserLocation, fileReference: FileMediaReference) { func setFile(context: AccountContext, userLocation: MediaResourceUserLocation, fileReference: FileMediaReference) {
if self.contextAndMedia == nil || !self.contextAndMedia!.1.media.isEqual(to: fileReference.media) { if self.contextAndMedia == nil || !self.contextAndMedia!.1.media.isEqual(to: fileReference.media) {
if var largestSize = fileReference.media.dimensions { if let largestSize = fileReference.media.dimensions {
var displaySize = largestSize.cgSize.dividedByScreenScale() let 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)
}
}
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))() self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))()
/*if largestSize.width > 2600 || largestSize.height > 2600 { /*if largestSize.width > 2600 || largestSize.height > 2600 {

View File

@ -1904,6 +1904,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
} }
if !updatedAddressNameValue.isEmpty {
_ = (ApplicationSpecificNotice.getSetPublicChannelLink(accountManager: context.sharedContext.accountManager) |> deliverOnMainQueue).start(next: { showAlert in _ = (ApplicationSpecificNotice.getSetPublicChannelLink(accountManager: context.sharedContext.accountManager) |> deliverOnMainQueue).start(next: { showAlert in
if showAlert { if showAlert {
let text: String let text: String
@ -1917,6 +1918,9 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
invokeAction() invokeAction()
} }
}) })
} else {
invokeAction()
}
} else { } else {
switch mode { switch mode {
case .initialSetup: case .initialSetup:

View File

@ -465,9 +465,16 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
if let languages = translationSettings.ignoredLanguages { if let languages = translationSettings.ignoredLanguages {
ignoredLanguages = languages ignoredLanguages = languages
} else { } else {
if let activeLanguage = activeLanguageCode, supportedTranslationLanguages.contains(activeLanguage) {
if var activeLanguage = activeLanguageCode {
let rawSuffix = "-raw"
if activeLanguage.hasSuffix(rawSuffix) {
activeLanguage = String(activeLanguage.dropLast(rawSuffix.count))
}
if supportedTranslationLanguages.contains(activeLanguage) {
ignoredLanguages = [activeLanguage] ignoredLanguages = [activeLanguage]
} }
}
let systemLanguages = systemLanguageCodes() let systemLanguages = systemLanguageCodes()
for systemLanguage in systemLanguages { for systemLanguage in systemLanguages {
if !ignoredLanguages.contains(systemLanguage) { if !ignoredLanguages.contains(systemLanguage) {

View File

@ -77,13 +77,17 @@ private func translationSettingsControllerEntries(theme: PresentationTheme, stri
if let ignoredLanguages = settings.ignoredLanguages { if let ignoredLanguages = settings.ignoredLanguages {
selectedLanguages = Set(ignoredLanguages) selectedLanguages = Set(ignoredLanguages)
} else { } else {
var langCode = strings.baseLanguageCode var activeLanguage = strings.baseLanguageCode
if langCode == "nb" { let rawSuffix = "-raw"
langCode = "no" if activeLanguage.hasSuffix(rawSuffix) {
} else if langCode == "pt-br" { activeLanguage = String(activeLanguage.dropLast(rawSuffix.count))
langCode = "pt"
} }
selectedLanguages = Set([langCode]) if activeLanguage == "nb" {
activeLanguage = "no"
} else if activeLanguage == "pt-br" {
activeLanguage = "pt"
}
selectedLanguages = Set([activeLanguage])
for language in systemLanguageCodes() { for language in systemLanguageCodes() {
selectedLanguages.insert(language) selectedLanguages.insert(language)
} }
@ -114,7 +118,11 @@ public func translationSettingsController(context: AccountContext) -> ViewContro
let actionsDisposable = DisposableSet() let actionsDisposable = DisposableSet()
let presentationData = context.sharedContext.currentPresentationData.with { $0 } 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 arguments = TranslationSettingsControllerArguments(context: context, updateLanguageSelected: { code, value in
let _ = updateTranslationSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in let _ = updateTranslationSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
@ -185,7 +193,12 @@ public func translationSettingsController(context: AccountContext) -> ViewContro
if let ignoredLanguages = settings.ignoredLanguages { if let ignoredLanguages = settings.ignoredLanguages {
selectedLanguages = Set(ignoredLanguages) selectedLanguages = Set(ignoredLanguages)
} else { } 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() { for language in systemLanguageCodes() {
selectedLanguages.insert(language) selectedLanguages.insert(language)
} }

View File

@ -174,7 +174,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
public var tapAction: (() -> Void)? public var tapAction: (() -> Void)?
public var close: (() -> Void)? public var close: (() -> Void)?
public var setRate: ((AudioPlaybackRate, Bool) -> Void)? public var setRate: ((AudioPlaybackRate, MediaNavigationAccessoryPanel.ChangeType) -> Void)?
public var togglePlayPause: (() -> Void)? public var togglePlayPause: (() -> Void)?
public var playPrevious: (() -> Void)? public var playPrevious: (() -> Void)?
public var playNext: (() -> Void)? public var playNext: (() -> Void)?
@ -500,7 +500,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
} else { } else {
nextRate = .x2 nextRate = .x2
} }
self.setRate?(nextRate, false) self.setRate?(nextRate, .preset)
let frame = self.rateButton.view.convert(self.rateButton.bounds, to: nil) 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> { private func contextMenuSpeedItems(dismiss: @escaping () -> Void) -> Signal<[ContextMenuItem], NoError> {
var items: [ContextMenuItem] = [] 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 let previousValue = self.playbackBaseRate?.doubleValue ?? 1.0
self?.setRate?(AudioPlaybackRate(newValue), true) 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 { if finished {
dismiss() dismiss()
} }
@ -547,7 +549,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
}, action: { [weak self] _, f in }, action: { [weak self] _, f in
f(.default) f(.default)
self?.setRate?(rate, true) self?.setRate?(rate, .preset)
}))) })))
} }

View File

@ -10,8 +10,14 @@ import TelegramPresentationData
public final class MediaNavigationAccessoryPanel: ASDisplayNode { public final class MediaNavigationAccessoryPanel: ASDisplayNode {
public let containerNode: MediaNavigationAccessoryContainerNode public let containerNode: MediaNavigationAccessoryContainerNode
public enum ChangeType {
case preset
case sliderChange
case sliderCommit(CGFloat, CGFloat)
}
public var close: (() -> Void)? public var close: (() -> Void)?
public var setRate: ((AudioPlaybackRate, Bool) -> Void)? public var setRate: ((AudioPlaybackRate, ChangeType) -> Void)?
public var togglePlayPause: (() -> Void)? public var togglePlayPause: (() -> Void)?
public var tapAction: (() -> Void)? public var tapAction: (() -> Void)?
public var playPrevious: (() -> Void)? public var playPrevious: (() -> Void)?
@ -34,8 +40,8 @@ public final class MediaNavigationAccessoryPanel: ASDisplayNode {
close() close()
} }
} }
self.containerNode.headerNode.setRate = { [weak self] rate, fromMenu in self.containerNode.headerNode.setRate = { [weak self] rate, type in
self?.setRate?(rate, fromMenu) self?.setRate?(rate, type)
} }
self.containerNode.headerNode.togglePlayPause = { [weak self] in self.containerNode.headerNode.togglePlayPause = { [weak self] in
if let strongSelf = self, let togglePlayPause = strongSelf.togglePlayPause { if let strongSelf = self, let togglePlayPause = strongSelf.togglePlayPause {

View File

@ -669,7 +669,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause)) 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 { guard let strongSelf = self else {
return return
} }
@ -709,10 +709,25 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp
rate = 2.0 rate = 2.0
} else { } else {
text = 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 rate = nil
} }
if let rate, let text, !fromMenu { } else {
rate = nil
}
}
var showTooltip = true
if case .sliderChange = changeType {
showTooltip = false
}
if let rate, let text, showTooltip {
strongSelf.present( strongSelf.present(
UndoOverlayController( UndoOverlayController(
presentationData: presentationData, presentationData: presentationData,

View File

@ -218,15 +218,17 @@ public final class InitialPresentationDataAndSettings {
public let callListSettings: CallListSettings public let callListSettings: CallListSettings
public let inAppNotificationSettings: InAppNotificationSettings public let inAppNotificationSettings: InAppNotificationSettings
public let mediaInputSettings: MediaInputSettings public let mediaInputSettings: MediaInputSettings
public let stickerSettings: StickerSettings
public let experimentalUISettings: ExperimentalUISettings 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.presentationData = presentationData
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
self.autodownloadSettings = autodownloadSettings self.autodownloadSettings = autodownloadSettings
self.callListSettings = callListSettings self.callListSettings = callListSettings
self.inAppNotificationSettings = inAppNotificationSettings self.inAppNotificationSettings = inAppNotificationSettings
self.mediaInputSettings = mediaInputSettings self.mediaInputSettings = mediaInputSettings
self.stickerSettings = stickerSettings
self.experimentalUISettings = experimentalUISettings self.experimentalUISettings = experimentalUISettings
} }
} }
@ -242,6 +244,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
var mediaInputSettings: PreferencesEntry? var mediaInputSettings: PreferencesEntry?
var experimentalUISettings: PreferencesEntry? var experimentalUISettings: PreferencesEntry?
var contactSynchronizationSettings: PreferencesEntry? var contactSynchronizationSettings: PreferencesEntry?
var stickerSettings: PreferencesEntry?
init( init(
localizationSettings: PreferencesEntry?, localizationSettings: PreferencesEntry?,
@ -252,7 +255,8 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
inAppNotificationSettings: PreferencesEntry?, inAppNotificationSettings: PreferencesEntry?,
mediaInputSettings: PreferencesEntry?, mediaInputSettings: PreferencesEntry?,
experimentalUISettings: PreferencesEntry?, experimentalUISettings: PreferencesEntry?,
contactSynchronizationSettings: PreferencesEntry? contactSynchronizationSettings: PreferencesEntry?,
stickerSettings: PreferencesEntry?
) { ) {
self.localizationSettings = localizationSettings self.localizationSettings = localizationSettings
self.presentationThemeSettings = presentationThemeSettings self.presentationThemeSettings = presentationThemeSettings
@ -263,6 +267,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
self.mediaInputSettings = mediaInputSettings self.mediaInputSettings = mediaInputSettings
self.experimentalUISettings = experimentalUISettings self.experimentalUISettings = experimentalUISettings
self.contactSynchronizationSettings = contactSynchronizationSettings self.contactSynchronizationSettings = contactSynchronizationSettings
self.stickerSettings = stickerSettings
} }
} }
@ -276,6 +281,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
let mediaInputSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.mediaInputSettings) let mediaInputSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.mediaInputSettings)
let experimentalUISettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings) let experimentalUISettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings)
let contactSynchronizationSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.contactSynchronizationSettings) let contactSynchronizationSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.contactSynchronizationSettings)
let stickerSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.stickerSettings)
return InternalData( return InternalData(
localizationSettings: localizationSettings, localizationSettings: localizationSettings,
@ -286,7 +292,8 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
inAppNotificationSettings: inAppNotificationSettings, inAppNotificationSettings: inAppNotificationSettings,
mediaInputSettings: mediaInputSettings, mediaInputSettings: mediaInputSettings,
experimentalUISettings: experimentalUISettings, experimentalUISettings: experimentalUISettings,
contactSynchronizationSettings: contactSynchronizationSettings contactSynchronizationSettings: contactSynchronizationSettings,
stickerSettings: stickerSettings
) )
} }
|> deliverOn(Queue(name: "PresentationData-Load", qos: .userInteractive)) |> deliverOn(Queue(name: "PresentationData-Load", qos: .userInteractive))
@ -340,6 +347,13 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
mediaInputSettings = MediaInputSettings.defaultSettings mediaInputSettings = MediaInputSettings.defaultSettings
} }
let stickerSettings: StickerSettings
if let value = internalData.stickerSettings?.get(StickerSettings.self) {
stickerSettings = value
} else {
stickerSettings = StickerSettings.defaultSettings
}
let experimentalUISettings: ExperimentalUISettings = internalData.experimentalUISettings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings let experimentalUISettings: ExperimentalUISettings = internalData.experimentalUISettings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings
let contactSettings: ContactSynchronizationSettings = internalData.contactSynchronizationSettings?.get(ContactSynchronizationSettings.self) ?? ContactSynchronizationSettings.defaultSettings let contactSettings: ContactSynchronizationSettings = internalData.contactSynchronizationSettings?.get(ContactSynchronizationSettings.self) ?? ContactSynchronizationSettings.defaultSettings
@ -385,7 +399,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
let chatBubbleCorners = PresentationChatBubbleCorners(mainRadius: CGFloat(themeSettings.chatBubbleSettings.mainRadius), auxiliaryRadius: CGFloat(themeSettings.chatBubbleSettings.auxiliaryRadius), mergeBubbleCorners: themeSettings.chatBubbleSettings.mergeBubbleCorners) let chatBubbleCorners = PresentationChatBubbleCorners(mainRadius: CGFloat(themeSettings.chatBubbleSettings.mainRadius), auxiliaryRadius: CGFloat(themeSettings.chatBubbleSettings.auxiliaryRadius), mergeBubbleCorners: themeSettings.chatBubbleSettings.mergeBubbleCorners)
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, reduceMotion: themeSettings.reduceMotion, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings) return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, reduceMotion: themeSettings.reduceMotion, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, stickerSettings: stickerSettings, experimentalUISettings: experimentalUISettings)
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -604,7 +604,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.automaticMediaDownloadSettings = context.sharedContext.currentAutomaticMediaDownloadSettings self.automaticMediaDownloadSettings = context.sharedContext.currentAutomaticMediaDownloadSettings
self.stickerSettings = ChatInterfaceStickerSettings(loopAnimatedStickers: false) self.stickerSettings = ChatInterfaceStickerSettings(loopAnimatedStickers: context.sharedContext.currentStickerSettings.with { $0 }.loopAnimatedStickers)
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation, subject: subject, peerNearbyData: peerNearbyData, greetingData: context.prefetchManager?.preloadedGreetingSticker, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil) self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: mode, chatLocation: chatLocation, subject: subject, peerNearbyData: peerNearbyData, greetingData: context.prefetchManager?.preloadedGreetingSticker, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil)
self.presentationInterfaceStatePromise = ValuePromise(self.presentationInterfaceState) self.presentationInterfaceStatePromise = ValuePromise(self.presentationInterfaceState)
@ -10116,7 +10116,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let locale = Locale(identifier: languageCode) let locale = Locale(identifier: languageCode)
let fromLanguage: String = locale.localizedString(forLanguageCode: langCode) ?? "" let fromLanguage: String = locale.localizedString(forLanguageCode: langCode) ?? ""
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: .white)!, title: nil, text: presentationData.strings.Conversation_Translation_AddedToDoNotTranslateText(fromLanguage).string, round: false, undoText: "Settings"), elevatedLayout: false, animateInAsReplacement: false, action: { [weak self] action in strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: .white)!, title: nil, text: presentationData.strings.Conversation_Translation_AddedToDoNotTranslateText(fromLanguage).string, round: false, undoText: presentationData.strings.Conversation_Translation_Settings), elevatedLayout: false, animateInAsReplacement: false, action: { [weak self] action in
if case .undo = action, let strongSelf = self { if case .undo = action, let strongSelf = self {
let controller = translationSettingsController(context: strongSelf.context) let controller = translationSettingsController(context: strongSelf.context)
controller.navigationPresentation = .modal controller.navigationPresentation = .modal
@ -15632,7 +15632,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.dismiss() self.dismiss()
let navigateToLocation: NavigateToChatControllerParams.Location let navigateToLocation: NavigateToChatControllerParams.Location
if let threadId = messages.first?.threadId { if let message = messages.first, let threadId = message.threadId, threadId != 1 || (message.peers[message.id.peerId] as? TelegramChannel)?.flags.contains(.isForum) == true {
navigateToLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)) navigateToLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
} else { } else {
navigateToLocation = .peer(peer) navigateToLocation = .peer(peer)

View File

@ -1074,9 +1074,8 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
} }
} }
if !messageText.isEmpty || (resourceAvailable && isImage) || diceEmoji != nil {
let isCopyProtected = chatPresentationInterfaceState.copyProtectionEnabled || message.isCopyProtected() let isCopyProtected = chatPresentationInterfaceState.copyProtectionEnabled || message.isCopyProtected()
if !messageText.isEmpty || (resourceAvailable && isImage) || diceEmoji != nil {
if !isExpired { if !isExpired {
if !isPoll { if !isPoll {
if !isCopyProtected { if !isCopyProtected {
@ -1183,8 +1182,9 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}))) })))
} }
} }
}
if resourceAvailable, !message.containsSecretMedia, !chatPresentationInterfaceState.copyProtectionEnabled, !message.isCopyProtected() { if resourceAvailable, !message.containsSecretMedia && !isCopyProtected {
var mediaReference: AnyMediaReference? var mediaReference: AnyMediaReference?
var isVideo = false var isVideo = false
for media in message.media { for media in message.media {
@ -1212,7 +1212,6 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}))) })))
} }
} }
}
var downloadableMediaResourceInfos: [String] = [] var downloadableMediaResourceInfos: [String] = []
for media in message.media { for media in message.media {

View File

@ -1034,9 +1034,12 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
} }
if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() { if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() {
if hasCommentButton(item: item) {
} else {
needsShareButton = false needsShareButton = false
} }
} }
}
var isEmoji = false var isEmoji = false
if let _ = telegramDice { if let _ = telegramDice {

View File

@ -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 let firstMessage = item.content.firstMessage
var hasDiscussion = false var hasDiscussion = false
@ -4541,6 +4541,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
for contentNode in self.contentNodes { for contentNode in self.contentNodes {
if let contentNode = contentNode as? ChatMessageFileBubbleContentNode { if let contentNode = contentNode as? ChatMessageFileBubbleContentNode {
return contentNode.interactiveFileNode.hasExpandedAudioTranscription return contentNode.interactiveFileNode.hasExpandedAudioTranscription
} else if let contentNode = contentNode as? ChatMessageInstantVideoBubbleContentNode {
return contentNode.hasExpandedAudioTranscription
} }
} }
return false return false

View File

@ -23,6 +23,14 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
private var audioTranscriptionState: AudioTranscriptionButtonComponent.TranscriptionState = .collapsed private var audioTranscriptionState: AudioTranscriptionButtonComponent.TranscriptionState = .collapsed
var hasExpandedAudioTranscription: Bool {
if case .expanded = self.audioTranscriptionState {
return true
} else {
return false
}
}
override var visibility: ListViewItemNodeVisibility { override var visibility: ListViewItemNodeVisibility {
didSet { didSet {
var wasVisible = false var wasVisible = false

View File

@ -505,9 +505,12 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
} }
if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() { if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() {
if hasCommentButton(item: item) {
} else {
needsShareButton = false needsShareButton = false
} }
} }
}
var layoutInsets = UIEdgeInsets(top: mergedTop.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, left: 0.0, bottom: mergedBottom.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, right: 0.0) var layoutInsets = UIEdgeInsets(top: mergedTop.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, left: 0.0, bottom: mergedBottom.merged ? layoutConstants.bubble.mergedSpacing : layoutConstants.bubble.defaultSpacing, right: 0.0)
if dateHeaderAtBottom { if dateHeaderAtBottom {

View File

@ -262,7 +262,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
strongSelf.context.sharedContext.mediaManager.setPlaylist(nil, type: type, control: SharedMediaPlayerControlAction.playback(.pause)) 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 { guard let strongSelf = self else {
return return
} }
@ -303,10 +303,25 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp text = presentationData.strings.Conversation_AudioRateTooltipSpeedUp
rate = 2.0 rate = 2.0
} else { } else {
text = 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 rate = nil
} }
if let rate, let text, !fromMenu { } else {
rate = nil
}
}
var showTooltip = true
if case .sliderChange = changeType {
showTooltip = false
}
if let rate, let text, showTooltip {
controller.present( controller.present(
UndoOverlayController( UndoOverlayController(
presentationData: presentationData, presentationData: presentationData,

View File

@ -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: { items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 6, text: presentationData.strings.ReportPeer_Report, action: {
interaction.openReport(.default) interaction.openReport(.default)
})) }))

View File

@ -163,6 +163,9 @@ public final class SharedAccountContextImpl: SharedAccountContext {
public let currentMediaInputSettings: Atomic<MediaInputSettings> public let currentMediaInputSettings: Atomic<MediaInputSettings>
private var mediaInputSettingsDisposable: Disposable? private var mediaInputSettingsDisposable: Disposable?
public let currentStickerSettings: Atomic<StickerSettings>
private var stickerSettingsDisposable: Disposable?
private let automaticMediaDownloadSettingsDisposable = MetaDisposable() private let automaticMediaDownloadSettingsDisposable = MetaDisposable()
private var immediateExperimentalUISettingsValue = Atomic<ExperimentalUISettings>(value: ExperimentalUISettings.defaultSettings) private var immediateExperimentalUISettingsValue = Atomic<ExperimentalUISettings>(value: ExperimentalUISettings.defaultSettings)
@ -237,6 +240,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
self.currentAutomaticMediaDownloadSettings = initialPresentationDataAndSettings.automaticMediaDownloadSettings self.currentAutomaticMediaDownloadSettings = initialPresentationDataAndSettings.automaticMediaDownloadSettings
self.currentAutodownloadSettings = Atomic(value: initialPresentationDataAndSettings.autodownloadSettings) self.currentAutodownloadSettings = Atomic(value: initialPresentationDataAndSettings.autodownloadSettings)
self.currentMediaInputSettings = Atomic(value: initialPresentationDataAndSettings.mediaInputSettings) self.currentMediaInputSettings = Atomic(value: initialPresentationDataAndSettings.mediaInputSettings)
self.currentStickerSettings = Atomic(value: initialPresentationDataAndSettings.stickerSettings)
self.currentInAppNotificationSettings = Atomic(value: initialPresentationDataAndSettings.inAppNotificationSettings) self.currentInAppNotificationSettings = Atomic(value: initialPresentationDataAndSettings.inAppNotificationSettings)
let presentationData: Signal<PresentationData, NoError> = .single(initialPresentationDataAndSettings.presentationData) let presentationData: Signal<PresentationData, NoError> = .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 = self.immediateExperimentalUISettingsValue
let _ = immediateExperimentalUISettingsValue.swap(initialPresentationDataAndSettings.experimentalUISettings) let _ = immediateExperimentalUISettingsValue.swap(initialPresentationDataAndSettings.experimentalUISettings)
self.experimentalUISettingsDisposable = (self.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.experimentalUISettings]) self.experimentalUISettingsDisposable = (self.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.experimentalUISettings])

View File

@ -546,7 +546,11 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
self.iconCheckNode = nil self.iconCheckNode = nil
let animationName: String 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" animationName = "anim_voice1_5x"
} else if rate == 2.0 { } else if rate == 2.0 {
animationName = "anim_voice2x" animationName = "anim_voice2x"