mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
96496aabd9
commit
441e102b0d
@ -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";
|
||||
|
@ -751,6 +751,7 @@ public protocol SharedAccountContext: AnyObject {
|
||||
var immediateExperimentalUISettings: ExperimentalUISettings { get }
|
||||
var currentInAppNotificationSettings: Atomic<InAppNotificationSettings> { get }
|
||||
var currentMediaInputSettings: Atomic<MediaInputSettings> { get }
|
||||
var currentStickerSettings: Atomic<StickerSettings> { get }
|
||||
|
||||
var energyUsageSettings: EnergyUsageSettings { get }
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
})))
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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<Te
|
||||
var mediaInputSettings: PreferencesEntry?
|
||||
var experimentalUISettings: PreferencesEntry?
|
||||
var contactSynchronizationSettings: PreferencesEntry?
|
||||
var stickerSettings: PreferencesEntry?
|
||||
|
||||
init(
|
||||
localizationSettings: PreferencesEntry?,
|
||||
@ -252,7 +255,8 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
inAppNotificationSettings: PreferencesEntry?,
|
||||
mediaInputSettings: PreferencesEntry?,
|
||||
experimentalUISettings: PreferencesEntry?,
|
||||
contactSynchronizationSettings: PreferencesEntry?
|
||||
contactSynchronizationSettings: PreferencesEntry?,
|
||||
stickerSettings: PreferencesEntry?
|
||||
) {
|
||||
self.localizationSettings = localizationSettings
|
||||
self.presentationThemeSettings = presentationThemeSettings
|
||||
@ -263,6 +267,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
self.mediaInputSettings = mediaInputSettings
|
||||
self.experimentalUISettings = experimentalUISettings
|
||||
self.contactSynchronizationSettings = contactSynchronizationSettings
|
||||
self.stickerSettings = stickerSettings
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,6 +281,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
let mediaInputSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.mediaInputSettings)
|
||||
let experimentalUISettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings)
|
||||
let contactSynchronizationSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.contactSynchronizationSettings)
|
||||
let stickerSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.stickerSettings)
|
||||
|
||||
return InternalData(
|
||||
localizationSettings: localizationSettings,
|
||||
@ -286,7 +292,8 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
inAppNotificationSettings: inAppNotificationSettings,
|
||||
mediaInputSettings: mediaInputSettings,
|
||||
experimentalUISettings: experimentalUISettings,
|
||||
contactSynchronizationSettings: contactSynchronizationSettings
|
||||
contactSynchronizationSettings: contactSynchronizationSettings,
|
||||
stickerSettings: stickerSettings
|
||||
)
|
||||
}
|
||||
|> deliverOn(Queue(name: "PresentationData-Load", qos: .userInteractive))
|
||||
@ -340,6 +347,13 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
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 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)
|
||||
|
||||
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
@ -604,7 +604,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
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.presentationInterfaceStatePromise = ValuePromise(self.presentationInterfaceState)
|
||||
@ -10116,7 +10116,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let locale = Locale(identifier: languageCode)
|
||||
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 {
|
||||
let controller = translationSettingsController(context: strongSelf.context)
|
||||
controller.navigationPresentation = .modal
|
||||
@ -15632,7 +15632,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.dismiss()
|
||||
|
||||
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))
|
||||
} else {
|
||||
navigateToLocation = .peer(peer)
|
||||
|
@ -1074,9 +1074,8 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
}
|
||||
}
|
||||
|
||||
let isCopyProtected = chatPresentationInterfaceState.copyProtectionEnabled || message.isCopyProtected()
|
||||
if !messageText.isEmpty || (resourceAvailable && isImage) || diceEmoji != nil {
|
||||
let isCopyProtected = chatPresentationInterfaceState.copyProtectionEnabled || message.isCopyProtected()
|
||||
|
||||
if !isExpired {
|
||||
if !isPoll {
|
||||
if !isCopyProtected {
|
||||
@ -1183,35 +1182,35 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
if resourceAvailable, !message.containsSecretMedia, !chatPresentationInterfaceState.copyProtectionEnabled, !message.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)
|
||||
})))
|
||||
}
|
||||
|
||||
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] = []
|
||||
|
@ -1034,7 +1034,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
|
||||
if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() {
|
||||
needsShareButton = false
|
||||
if hasCommentButton(item: item) {
|
||||
} else {
|
||||
needsShareButton = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -505,7 +505,10 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
|
||||
if item.associatedData.isCopyProtectionEnabled || item.message.isCopyProtected() {
|
||||
needsShareButton = false
|
||||
if hasCommentButton(item: item) {
|
||||
} else {
|
||||
needsShareButton = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}))
|
||||
|
@ -163,6 +163,9 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
public let currentMediaInputSettings: Atomic<MediaInputSettings>
|
||||
private var mediaInputSettingsDisposable: Disposable?
|
||||
|
||||
public let currentStickerSettings: Atomic<StickerSettings>
|
||||
private var stickerSettingsDisposable: Disposable?
|
||||
|
||||
private let automaticMediaDownloadSettingsDisposable = MetaDisposable()
|
||||
|
||||
private var immediateExperimentalUISettingsValue = Atomic<ExperimentalUISettings>(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<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.swap(initialPresentationDataAndSettings.experimentalUISettings)
|
||||
self.experimentalUISettingsDisposable = (self.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.experimentalUISettings])
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user