Merge commit 'c7faf7503295d52b5bebcda403b065b31f4982a4'

This commit is contained in:
Ali 2021-08-13 23:35:59 +02:00
commit 66a03ac134
26 changed files with 338 additions and 90 deletions

View File

@ -6585,3 +6585,26 @@ Sorry for the inconvenience.";
"Chat.NextChannelArchivedSwipeAction" = "Release to go to archived channels"; "Chat.NextChannelArchivedSwipeAction" = "Release to go to archived channels";
"Chat.NextChannelUnarchivedSwipeProgress" = "Swipe up to go to unarchived channels"; "Chat.NextChannelUnarchivedSwipeProgress" = "Swipe up to go to unarchived channels";
"Chat.NextChannelUnarchivedSwipeAction" = "Release to go to unarchived channels"; "Chat.NextChannelUnarchivedSwipeAction" = "Release to go to unarchived channels";
"Conversation.ForwardOptions.Text" = "What whould you like to do with %1$@ from %2$@?";
"Conversation.ForwardOptions.TextPersonal" = "What whould you like to do with %1$@ from your chat with %2$@?";
"Conversation.ForwardOptions.ForwardToAnotherChat" = "Forward to Another Chat";
"Conversation.ForwardOptions.CancelForwarding" = "Cancel Forwarding";
"Conversation.ForwardOptions.HideSendersNames" = "Hide Senders' Names";
"Conversation.ForwardOptions.ShowSendersNames" = "Show Senders' Names";
"Conversation.ForwardOptions.Title_1" = "%@ Message";
"Conversation.ForwardOptions.Title_2" = "%@ Messages";
"Conversation.ForwardOptions.Title_3_10" = "%@ Messages";
"Conversation.ForwardOptions.Title_any" = "%@ Messages";
"Conversation.ForwardOptions.Title_many" = "%@ Messages";
"Conversation.ForwardOptions.Title_0" = "%@ Messages";
"Conversation.ForwardOptions.Messages_1" = "%@ message";
"Conversation.ForwardOptions.Messages_2" = "%@ messages";
"Conversation.ForwardOptions.Messages_3_10" = "%@ messages";
"Conversation.ForwardOptions.Messages_any" = "%@ messages";
"Conversation.ForwardOptions.Messages_many" = "%@ messages";
"Conversation.ForwardOptions.Messages_0" = "%@ messages";
"Conversation.ForwardOptions.You" = "You (senders' names hidden)";

View File

@ -1,7 +1,8 @@
import Foundation import Foundation
import Display import Display
import Postbox
import SwiftSignalKit import SwiftSignalKit
import Postbox
import TelegramCore
public struct ChatListNodePeersFilter: OptionSet { public struct ChatListNodePeersFilter: OptionSet {
public var rawValue: Int32 public var rawValue: Int32
@ -40,9 +41,9 @@ public final class PeerSelectionControllerParams {
public let createNewGroup: (() -> Void)? public let createNewGroup: (() -> Void)?
public let pretendPresentedInModal: Bool public let pretendPresentedInModal: Bool
public let multipleSelection: Bool public let multipleSelection: Bool
public let forwardedMessagesCount: Int public let forwardedMessageIds: [EngineMessage.Id]
public init(context: AccountContext, filter: ChatListNodePeersFilter = [.onlyWriteable], hasChatListSelector: Bool = true, hasContactSelector: Bool = true, hasGlobalSearch: Bool = true, title: String? = nil, attemptSelection: ((Peer) -> Void)? = nil, createNewGroup: (() -> Void)? = nil, pretendPresentedInModal: Bool = false, multipleSelection: Bool = false, forwardedMessagesCount: Int = 0) { public init(context: AccountContext, filter: ChatListNodePeersFilter = [.onlyWriteable], hasChatListSelector: Bool = true, hasContactSelector: Bool = true, hasGlobalSearch: Bool = true, title: String? = nil, attemptSelection: ((Peer) -> Void)? = nil, createNewGroup: (() -> Void)? = nil, pretendPresentedInModal: Bool = false, multipleSelection: Bool = false, forwardedMessageIds: [EngineMessage.Id] = []) {
self.context = context self.context = context
self.filter = filter self.filter = filter
self.hasChatListSelector = hasChatListSelector self.hasChatListSelector = hasChatListSelector
@ -53,7 +54,7 @@ public final class PeerSelectionControllerParams {
self.createNewGroup = createNewGroup self.createNewGroup = createNewGroup
self.pretendPresentedInModal = pretendPresentedInModal self.pretendPresentedInModal = pretendPresentedInModal
self.multipleSelection = multipleSelection self.multipleSelection = multipleSelection
self.forwardedMessagesCount = forwardedMessagesCount self.forwardedMessageIds = forwardedMessageIds
} }
} }
@ -65,7 +66,7 @@ public enum PeerSelectionControllerSendMode {
public protocol PeerSelectionController: ViewController { public protocol PeerSelectionController: ViewController {
var peerSelected: ((Peer) -> Void)? { get set } var peerSelected: ((Peer) -> Void)? { get set }
var multiplePeersSelected: (([Peer], [PeerId: Peer], NSAttributedString, PeerSelectionControllerSendMode) -> Void)? { get set } var multiplePeersSelected: (([Peer], [PeerId: Peer], NSAttributedString, PeerSelectionControllerSendMode, Bool) -> Void)? { get set }
var inProgress: Bool { get set } var inProgress: Bool { get set }
var customDismiss: (() -> Void)? { get set } var customDismiss: (() -> Void)? { get set }
} }

View File

@ -264,6 +264,7 @@ public final class ChatInterfaceState: Codable, Equatable {
public let composeDisableUrlPreview: String? public let composeDisableUrlPreview: String?
public let replyMessageId: EngineMessage.Id? public let replyMessageId: EngineMessage.Id?
public let forwardMessageIds: [EngineMessage.Id]? public let forwardMessageIds: [EngineMessage.Id]?
public let forwardMessageHideSendersNames: Bool
public let editMessage: ChatEditMessageState? public let editMessage: ChatEditMessageState?
public let selectionState: ChatInterfaceSelectionState? public let selectionState: ChatInterfaceSelectionState?
public let messageActionsState: ChatInterfaceMessageActionsState public let messageActionsState: ChatInterfaceMessageActionsState
@ -306,6 +307,7 @@ public final class ChatInterfaceState: Codable, Equatable {
self.composeDisableUrlPreview = nil self.composeDisableUrlPreview = nil
self.replyMessageId = nil self.replyMessageId = nil
self.forwardMessageIds = nil self.forwardMessageIds = nil
self.forwardMessageHideSendersNames = false
self.editMessage = nil self.editMessage = nil
self.selectionState = nil self.selectionState = nil
self.messageActionsState = ChatInterfaceMessageActionsState() self.messageActionsState = ChatInterfaceMessageActionsState()
@ -315,12 +317,13 @@ public final class ChatInterfaceState: Codable, Equatable {
self.inputLanguage = nil self.inputLanguage = nil
} }
public init(timestamp: Int32, composeInputState: ChatTextInputState, composeDisableUrlPreview: String?, replyMessageId: EngineMessage.Id?, forwardMessageIds: [EngineMessage.Id]?, editMessage: ChatEditMessageState?, selectionState: ChatInterfaceSelectionState?, messageActionsState: ChatInterfaceMessageActionsState, historyScrollState: ChatInterfaceHistoryScrollState?, mediaRecordingMode: ChatTextInputMediaRecordingButtonMode, silentPosting: Bool, inputLanguage: String?) { public init(timestamp: Int32, composeInputState: ChatTextInputState, composeDisableUrlPreview: String?, replyMessageId: EngineMessage.Id?, forwardMessageIds: [EngineMessage.Id]?, forwardMessageHideSendersNames: Bool, editMessage: ChatEditMessageState?, selectionState: ChatInterfaceSelectionState?, messageActionsState: ChatInterfaceMessageActionsState, historyScrollState: ChatInterfaceHistoryScrollState?, mediaRecordingMode: ChatTextInputMediaRecordingButtonMode, silentPosting: Bool, inputLanguage: String?) {
self.timestamp = timestamp self.timestamp = timestamp
self.composeInputState = composeInputState self.composeInputState = composeInputState
self.composeDisableUrlPreview = composeDisableUrlPreview self.composeDisableUrlPreview = composeDisableUrlPreview
self.replyMessageId = replyMessageId self.replyMessageId = replyMessageId
self.forwardMessageIds = forwardMessageIds self.forwardMessageIds = forwardMessageIds
self.forwardMessageHideSendersNames = forwardMessageHideSendersNames
self.editMessage = editMessage self.editMessage = editMessage
self.selectionState = selectionState self.selectionState = selectionState
self.messageActionsState = messageActionsState self.messageActionsState = messageActionsState
@ -357,6 +360,7 @@ public final class ChatInterfaceState: Codable, Equatable {
} else { } else {
self.forwardMessageIds = nil self.forwardMessageIds = nil
} }
self.forwardMessageHideSendersNames = ((try? container.decode(Int32.self, forKey: "fhn")) ?? 0) != 0
if let editMessage = try? container.decodeIfPresent(ChatEditMessageState.self, forKey: "em") { if let editMessage = try? container.decodeIfPresent(ChatEditMessageState.self, forKey: "em") {
self.editMessage = editMessage self.editMessage = editMessage
} else { } else {
@ -406,6 +410,7 @@ public final class ChatInterfaceState: Codable, Equatable {
} else { } else {
try container.encodeNil(forKey: "fm") try container.encodeNil(forKey: "fm")
} }
try container.encode((self.forwardMessageHideSendersNames ? 1 : 0) as Int32, forKey: "fhn")
if let editMessage = self.editMessage { if let editMessage = self.editMessage {
try container.encode(editMessage, forKey: "em") try container.encode(editMessage, forKey: "em")
} else { } else {
@ -446,6 +451,9 @@ public final class ChatInterfaceState: Codable, Equatable {
} else if (lhs.forwardMessageIds != nil) != (rhs.forwardMessageIds != nil) { } else if (lhs.forwardMessageIds != nil) != (rhs.forwardMessageIds != nil) {
return false return false
} }
if lhs.forwardMessageHideSendersNames != rhs.forwardMessageHideSendersNames {
return false
}
if lhs.messageActionsState != rhs.messageActionsState { if lhs.messageActionsState != rhs.messageActionsState {
return false return false
} }
@ -467,11 +475,11 @@ public final class ChatInterfaceState: Codable, Equatable {
public func withUpdatedComposeInputState(_ inputState: ChatTextInputState) -> ChatInterfaceState { public func withUpdatedComposeInputState(_ inputState: ChatTextInputState) -> ChatInterfaceState {
let updatedComposeInputState = inputState let updatedComposeInputState = inputState
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: updatedComposeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: updatedComposeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedComposeDisableUrlPreview(_ disableUrlPreview: String?) -> ChatInterfaceState { public func withUpdatedComposeDisableUrlPreview(_ disableUrlPreview: String?) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: disableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: disableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedEffectiveInputState(_ inputState: ChatTextInputState) -> ChatInterfaceState { public func withUpdatedEffectiveInputState(_ inputState: ChatTextInputState) -> ChatInterfaceState {
@ -483,15 +491,19 @@ public final class ChatInterfaceState: Codable, Equatable {
updatedComposeInputState = inputState updatedComposeInputState = inputState
} }
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: updatedComposeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: updatedEditMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: updatedComposeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: updatedEditMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedReplyMessageId(_ replyMessageId: EngineMessage.Id?) -> ChatInterfaceState { public func withUpdatedReplyMessageId(_ replyMessageId: EngineMessage.Id?) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedForwardMessageIds(_ forwardMessageIds: [EngineMessage.Id]?) -> ChatInterfaceState { public func withUpdatedForwardMessageIds(_ forwardMessageIds: [EngineMessage.Id]?) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
}
public func withUpdatedForwardMessageHideSendersNames(_ forwardMessageHideSendersNames: Bool) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedSelectedMessages(_ messageIds: [EngineMessage.Id]) -> ChatInterfaceState { public func withUpdatedSelectedMessages(_ messageIds: [EngineMessage.Id]) -> ChatInterfaceState {
@ -502,7 +514,7 @@ public final class ChatInterfaceState: Codable, Equatable {
for messageId in messageIds { for messageId in messageIds {
selectedIds.insert(messageId) selectedIds.insert(messageId)
} }
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds), messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds), messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withToggledSelectedMessages(_ messageIds: [EngineMessage.Id], value: Bool) -> ChatInterfaceState { public func withToggledSelectedMessages(_ messageIds: [EngineMessage.Id], value: Bool) -> ChatInterfaceState {
@ -517,39 +529,39 @@ public final class ChatInterfaceState: Codable, Equatable {
selectedIds.remove(messageId) selectedIds.remove(messageId)
} }
} }
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds), messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds), messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withoutSelectionState() -> ChatInterfaceState { public func withoutSelectionState() -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: nil, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: nil, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedTimestamp(_ timestamp: Int32) -> ChatInterfaceState { public func withUpdatedTimestamp(_ timestamp: Int32) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedEditMessage(_ editMessage: ChatEditMessageState?) -> ChatInterfaceState { public func withUpdatedEditMessage(_ editMessage: ChatEditMessageState?) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedMessageActionsState(_ f: (ChatInterfaceMessageActionsState) -> ChatInterfaceMessageActionsState) -> ChatInterfaceState { public func withUpdatedMessageActionsState(_ f: (ChatInterfaceMessageActionsState) -> ChatInterfaceMessageActionsState) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: f(self.messageActionsState), historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: f(self.messageActionsState), historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedHistoryScrollState(_ historyScrollState: ChatInterfaceHistoryScrollState?) -> ChatInterfaceState { public func withUpdatedHistoryScrollState(_ historyScrollState: ChatInterfaceHistoryScrollState?) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedMediaRecordingMode(_ mediaRecordingMode: ChatTextInputMediaRecordingButtonMode) -> ChatInterfaceState { public func withUpdatedMediaRecordingMode(_ mediaRecordingMode: ChatTextInputMediaRecordingButtonMode) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedSilentPosting(_ silentPosting: Bool) -> ChatInterfaceState { public func withUpdatedSilentPosting(_ silentPosting: Bool) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: silentPosting, inputLanguage: self.inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: silentPosting, inputLanguage: self.inputLanguage)
} }
public func withUpdatedInputLanguage(_ inputLanguage: String?) -> ChatInterfaceState { public func withUpdatedInputLanguage(_ inputLanguage: String?) -> ChatInterfaceState {
return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: inputLanguage) return ChatInterfaceState(timestamp: self.timestamp, composeInputState: self.composeInputState, composeDisableUrlPreview: self.composeDisableUrlPreview, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, forwardMessageHideSendersNames: self.forwardMessageHideSendersNames, editMessage: self.editMessage, selectionState: self.selectionState, messageActionsState: self.messageActionsState, historyScrollState: self.historyScrollState, mediaRecordingMode: self.mediaRecordingMode, silentPosting: self.silentPosting, inputLanguage: inputLanguage)
} }
public static func parse(_ state: OpaqueChatInterfaceState) -> ChatInterfaceState { public static func parse(_ state: OpaqueChatInterfaceState) -> ChatInterfaceState {

View File

@ -891,7 +891,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
}).start() }).start()
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true)) let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true))
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, peerMap, messageText, mode in peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, peerMap, messageText, mode, hideSendersNames in
guard let strongSelf = self, let strongController = peerSelectionController else { guard let strongSelf = self, let strongController = peerSelectionController else {
return return
} }
@ -912,8 +912,13 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
} }
} }
var attributes: [MessageAttribute] = []
if hideSendersNames {
attributes.append(ForwardHideSendersNamesMessageAttribute())
}
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil) return .forward(source: messageId, grouping: .auto, attributes: attributes, correlationId: nil)
}) })
var displayPeers: [Peer] = [] var displayPeers: [Peer] = []

View File

@ -327,6 +327,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
private var reorderFeedbackDisposable: MetaDisposable? private var reorderFeedbackDisposable: MetaDisposable?
private var reorderInProgress: Bool = false private var reorderInProgress: Bool = false
private var reorderingItemsCompleted: (() -> Void)? private var reorderingItemsCompleted: (() -> Void)?
private var reorderScrollStartTimestamp: Double?
public var reorderedItemHasShadow = true public var reorderedItemHasShadow = true
private let waitingForNodesDisposable = MetaDisposable() private let waitingForNodesDisposable = MetaDisposable()
@ -3974,20 +3975,38 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
var offsetRanges = OffsetRanges() var offsetRanges = OffsetRanges()
var scrollingForReorder = false
if let reorderOffset = self.reorderNode?.currentOffset(), !self.itemNodes.isEmpty { if let reorderOffset = self.reorderNode?.currentOffset(), !self.itemNodes.isEmpty {
let effectiveInsets = self.visualInsets ?? self.insets let effectiveInsets = self.visualInsets ?? self.insets
var offset: CGFloat = 6.0
if let reorderScrollStartTimestamp = self.reorderScrollStartTimestamp, reorderScrollStartTimestamp + 2.0 < timestamp {
offset *= 2.0
}
if reorderOffset < effectiveInsets.top + 10.0 { if reorderOffset < effectiveInsets.top + 10.0 {
if self.itemNodes[0].apparentFrame.minY < effectiveInsets.top { if self.itemNodes[0].apparentFrame.minY < effectiveInsets.top {
continueAnimations = true continueAnimations = true
offsetRanges.offset(IndexRange(first: 0, last: Int.max), offset: 6.0) offsetRanges.offset(IndexRange(first: 0, last: Int.max), offset: offset)
scrollingForReorder = true
} }
} else if reorderOffset > self.visibleSize.height - effectiveInsets.bottom - 10.0 { } else if reorderOffset > self.visibleSize.height - effectiveInsets.bottom - 10.0 {
if self.itemNodes[self.itemNodes.count - 1].apparentFrame.maxY > self.visibleSize.height - effectiveInsets.bottom { if self.itemNodes[self.itemNodes.count - 1].apparentFrame.maxY > self.visibleSize.height - effectiveInsets.bottom {
continueAnimations = true continueAnimations = true
offsetRanges.offset(IndexRange(first: 0, last: Int.max), offset: -6.0) if self.reorderScrollStartTimestamp == nil {
self.reorderScrollStartTimestamp = timestamp
}
offsetRanges.offset(IndexRange(first: 0, last: Int.max), offset: -offset)
scrollingForReorder = true
} }
} }
} }
if scrollingForReorder {
if self.reorderScrollStartTimestamp == nil {
self.reorderScrollStartTimestamp = timestamp
}
} else {
self.reorderScrollStartTimestamp = nil
}
var requestUpdateVisibleItems = false var requestUpdateVisibleItems = false
var index = 0 var index = 0

View File

@ -19,6 +19,7 @@ import ContextUI
import SaveToCameraRoll import SaveToCameraRoll
import UndoUI import UndoUI
import TelegramUIPreferences import TelegramUIPreferences
import OpenInExternalAppUI
public enum UniversalVideoGalleryItemContentInfo { public enum UniversalVideoGalleryItemContentInfo {
case message(Message) case message(Message)
@ -2088,6 +2089,36 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
c.setItems(strongSelf.contextMenuSpeedItems()) c.setItems(strongSelf.contextMenuSpeedItems())
}))) })))
if let (message, _, _) = strongSelf.contentInfo() {
for media in message.media {
if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
let url = content.url
let item = OpenInItem.url(url: url)
let canOpenIn = availableOpenInOptions(context: strongSelf.context, item: item).count > 1
let openText = canOpenIn ? strongSelf.presentationData.strings.Conversation_FileOpenIn : strongSelf.presentationData.strings.Conversation_LinkDialogOpen
items.append(.action(ContextMenuActionItem(text: openText, textColor: .primary, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Share"), color: theme.contextMenu.primaryColor) }, action: { _, f in
f(.default)
if let strongSelf = self, let controller = strongSelf.galleryController() {
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
let actionSheet = OpenInActionSheetController(context: strongSelf.context, forceTheme: presentationData.theme, item: item, openUrl: { [weak self] url in
if let strongSelf = self {
strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: strongSelf.baseNavigationController(), dismissInput: {})
}
})
controller.present(actionSheet, in: .window(.root))
}
})))
break
}
}
}
if let (message, maybeFile, _) = strongSelf.contentInfo(), let file = maybeFile { if let (message, maybeFile, _) = strongSelf.contentInfo(), let file = maybeFile {
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Gallery_SaveVideo, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Download"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Gallery_SaveVideo, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Download"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in
f(.default) f(.default)

View File

@ -62,9 +62,20 @@ private func allOpenInOptions(context: AccountContext, item: OpenInItem) -> [Ope
var options: [OpenInOption] = [] var options: [OpenInOption] = []
switch item { switch item {
case let .url(url): case let .url(url):
options.append(OpenInOption(identifier: "safari", application: .safari, action: { var skipSafari = false
return .openUrl(url: url) if url.contains("youtube.com/") || url.contains("youtu.be/") {
})) let updatedUrl = url.replacingOccurrences(of: "https://", with: "youtube://").replacingOccurrences(of: "http://", with: "youtube://")
options.append(OpenInOption(identifier: "youtube", application: .other(title: "YouTube", identifier: 544007664, scheme: "youtube", store: nil), action: {
return .openUrl(url: updatedUrl)
}))
skipSafari = true
}
if !skipSafari {
options.append(OpenInOption(identifier: "safari", application: .safari, action: {
return .openUrl(url: url)
}))
}
options.append(OpenInOption(identifier: "chrome", application: .other(title: "Chrome", identifier: 535886823, scheme: "googlechrome", store: nil), action: { options.append(OpenInOption(identifier: "chrome", application: .other(title: "Chrome", identifier: 535886823, scheme: "googlechrome", store: nil), action: {
if let url = URL(string: url), var components = URLComponents(url: url, resolvingAgainstBaseURL: true) { if let url = URL(string: url), var components = URLComponents(url: url, resolvingAgainstBaseURL: true) {

View File

@ -373,6 +373,8 @@ public func chatMessageStickerPackThumbnail(postbox: Postbox, resource: MediaRes
} }
} }
addCorners(context, arguments: arguments)
return context return context
} }
} }

View File

@ -234,6 +234,7 @@ private var declaredEncodables: Void = {
declareEncodable(CachedDisplayAsPeers.self, f: { CachedDisplayAsPeers(decoder: $0) }) declareEncodable(CachedDisplayAsPeers.self, f: { CachedDisplayAsPeers(decoder: $0) })
declareEncodable(WallpapersState.self, f: { WallpapersState(decoder: $0) }) declareEncodable(WallpapersState.self, f: { WallpapersState(decoder: $0) })
declareEncodable(WallpaperDataResource.self, f: { WallpaperDataResource(decoder: $0) }) declareEncodable(WallpaperDataResource.self, f: { WallpaperDataResource(decoder: $0) })
declareEncodable(ForwardHideSendersNamesMessageAttribute.self, f: { ForwardHideSendersNamesMessageAttribute(decoder: $0) })
return return
}() }()

View File

@ -3,7 +3,6 @@ import Postbox
import TelegramApi import TelegramApi
import SwiftSignalKit import SwiftSignalKit
public enum EnqueueMessageGrouping { public enum EnqueueMessageGrouping {
case none case none
case auto case auto
@ -114,6 +113,8 @@ private func filterMessageAttributesForOutgoingMessage(_ attributes: [MessageAtt
return true return true
case _ as EmojiSearchQueryMessageAttribute: case _ as EmojiSearchQueryMessageAttribute:
return true return true
case _ as ForwardHideSendersNamesMessageAttribute:
return true
default: default:
return false return false
} }
@ -131,6 +132,8 @@ private func filterMessageAttributesForForwardedMessage(_ attributes: [MessageAt
return true return true
case _ as OutgoingScheduleInfoMessageAttribute: case _ as OutgoingScheduleInfoMessageAttribute:
return true return true
case _ as ForwardHideSendersNamesMessageAttribute:
return true
default: default:
return false return false
} }
@ -560,6 +563,14 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
var forwardInfo: StoreMessageForwardInfo? var forwardInfo: StoreMessageForwardInfo?
var hideSendersNames = false
for attribute in requestedAttributes {
if let _ = attribute as? ForwardHideSendersNamesMessageAttribute {
hideSendersNames = true
break
}
}
if sourceMessage.id.namespace == Namespaces.Message.Cloud && peerId.namespace != Namespaces.Peer.SecretChat { if sourceMessage.id.namespace == Namespaces.Message.Cloud && peerId.namespace != Namespaces.Peer.SecretChat {
attributes.append(ForwardSourceInfoAttribute(messageId: sourceMessage.id)) attributes.append(ForwardSourceInfoAttribute(messageId: sourceMessage.id))
@ -606,7 +617,9 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
} }
} }
if let sourceForwardInfo = sourceMessage.forwardInfo { if hideSendersNames {
} else if let sourceForwardInfo = sourceMessage.forwardInfo {
forwardInfo = StoreMessageForwardInfo(authorId: sourceForwardInfo.author?.id, sourceId: sourceForwardInfo.source?.id, sourceMessageId: sourceForwardInfo.sourceMessageId, date: sourceForwardInfo.date, authorSignature: sourceForwardInfo.authorSignature, psaType: nil, flags: []) forwardInfo = StoreMessageForwardInfo(authorId: sourceForwardInfo.author?.id, sourceId: sourceForwardInfo.source?.id, sourceMessageId: sourceForwardInfo.sourceMessageId, date: sourceForwardInfo.date, authorSignature: sourceForwardInfo.authorSignature, psaType: nil, flags: [])
} else { } else {
if sourceMessage.id.peerId != account.peerId { if sourceMessage.id.peerId != account.peerId {

View File

@ -697,6 +697,7 @@ public final class PendingMessageManager {
return .complete() return .complete()
} else if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { } else if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var isForward = false var isForward = false
var hideSendersNames = false
var replyMessageId: Int32? var replyMessageId: Int32?
var scheduleTime: Int32? var scheduleTime: Int32?
@ -714,6 +715,8 @@ public final class PendingMessageManager {
} else if let attribute = attribute as? OutgoingScheduleInfoMessageAttribute { } else if let attribute = attribute as? OutgoingScheduleInfoMessageAttribute {
flags |= Int32(1 << 10) flags |= Int32(1 << 10)
scheduleTime = attribute.scheduleTime scheduleTime = attribute.scheduleTime
} else if let _ = attribute as? ForwardHideSendersNamesMessageAttribute {
hideSendersNames = true
} }
} }
@ -722,6 +725,9 @@ public final class PendingMessageManager {
if messages.contains(where: { $0.0.groupingKey != nil }) { if messages.contains(where: { $0.0.groupingKey != nil }) {
flags |= (1 << 9) flags |= (1 << 9)
} }
if hideSendersNames {
flags |= (1 << 11)
}
var forwardIds: [(MessageId, Int64)] = [] var forwardIds: [(MessageId, Int64)] = []
for (message, content) in messages { for (message, content) in messages {

View File

@ -1,7 +1,6 @@
import Foundation import Foundation
import Postbox import Postbox
public class AuthorSignatureMessageAttribute: MessageAttribute { public class AuthorSignatureMessageAttribute: MessageAttribute {
public let signature: String public let signature: String

View File

@ -0,0 +1,13 @@
import Foundation
import Postbox
public class ForwardHideSendersNamesMessageAttribute: MessageAttribute {
public init() {
}
required public init(decoder: PostboxDecoder) {
}
public func encode(_ encoder: PostboxEncoder) {
}
}

View File

@ -5287,7 +5287,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let strongSelf = self { if let strongSelf = self {
strongSelf.commitPurposefulAction() strongSelf.commitPurposefulAction()
if let forwardMessageIds = strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds { if let forwardMessageIds = strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds {
strongSelf.forwardMessages(messageIds: forwardMessageIds, resetCurrent: true) strongSelf.forwardMessages(messageIds: forwardMessageIds, hideSendersNames: strongSelf.presentationInterfaceState.interfaceState.forwardMessageHideSendersNames, resetCurrent: true)
} }
} }
}, forwardMessages: { [weak self] messages in }, forwardMessages: { [weak self] messages in
@ -5296,6 +5296,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let forwardMessageIds = messages.map { $0.id }.sorted() let forwardMessageIds = messages.map { $0.id }.sorted()
strongSelf.forwardMessages(messageIds: forwardMessageIds) strongSelf.forwardMessages(messageIds: forwardMessageIds)
} }
}, updateForwardMessageHideSendersNames: { [weak self] value in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageHideSendersNames(value) }) })
}
}, shareSelectedMessages: { [weak self] in }, shareSelectedMessages: { [weak self] in
if let strongSelf = self, let selectedIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !selectedIds.isEmpty { if let strongSelf = self, let selectedIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !selectedIds.isEmpty {
strongSelf.commitPurposefulAction() strongSelf.commitPurposefulAction()
@ -11008,16 +11012,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
private func forwardMessages(messageIds: [MessageId], resetCurrent: Bool = false) { private func forwardMessages(messageIds: [MessageId], hideSendersNames: Bool = false, resetCurrent: Bool = false) {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in let _ = (self.context.account.postbox.transaction { transaction -> [Message] in
return messageIds.compactMap(transaction.getMessage) return messageIds.compactMap(transaction.getMessage)
} }
|> deliverOnMainQueue).start(next: { [weak self] messages in |> deliverOnMainQueue).start(next: { [weak self] messages in
self?.forwardMessages(messages: messages, resetCurrent: resetCurrent) self?.forwardMessages(messages: messages, hideSendersNames: hideSendersNames, resetCurrent: resetCurrent)
}) })
} }
private func forwardMessages(messages: [Message], resetCurrent: Bool) { private func forwardMessages(messages: [Message], hideSendersNames: Bool = false, resetCurrent: Bool) {
let _ = self.presentVoiceMessageDiscardAlert(action: { let _ = self.presentVoiceMessageDiscardAlert(action: {
var filter: ChatListNodePeersFilter = [.onlyWriteable, .includeSavedMessages, .excludeDisabled, .doNotSearchMessages] var filter: ChatListNodePeersFilter = [.onlyWriteable, .includeSavedMessages, .excludeDisabled, .doNotSearchMessages]
var hasPublicPolls = false var hasPublicPolls = false
@ -11037,7 +11041,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var attemptSelectionImpl: ((Peer) -> Void)? var attemptSelectionImpl: ((Peer) -> Void)?
let controller = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: filter, attemptSelection: { peer in let controller = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: filter, attemptSelection: { peer in
attemptSelectionImpl?(peer) attemptSelectionImpl?(peer)
}, multipleSelection: true, forwardedMessagesCount: messages.count)) }, multipleSelection: true, forwardedMessageIds: messages.map { $0.id }))
let context = self.context let context = self.context
attemptSelectionImpl = { [weak controller] peer in attemptSelectionImpl = { [weak controller] peer in
guard let controller = controller else { guard let controller = controller else {
@ -11052,7 +11056,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
controller.present(textAlertController(context: context, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) controller.present(textAlertController(context: context, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
} }
controller.multiplePeersSelected = { [weak self, weak controller] peers, peerMap, messageText, mode in controller.multiplePeersSelected = { [weak self, weak controller] peers, peerMap, messageText, mode, hideSendersNames in
guard let strongSelf = self, let strongController = controller else { guard let strongSelf = self, let strongController = controller else {
return return
} }
@ -11073,8 +11077,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
var attributes: [MessageAttribute] = []
if hideSendersNames {
attributes.append(ForwardHideSendersNamesMessageAttribute())
}
result.append(contentsOf: messages.map { message -> EnqueueMessage in result.append(contentsOf: messages.map { message -> EnqueueMessage in
return .forward(source: message.id, grouping: .auto, attributes: [], correlationId: nil) return .forward(source: message.id, grouping: .auto, attributes: attributes, correlationId: nil)
}) })
let commit: ([EnqueueMessage]) -> Void = { result in let commit: ([EnqueueMessage]) -> Void = { result in
@ -11162,7 +11171,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if resetCurrent { if resetCurrent {
strongSelf.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(nil) }) }) strongSelf.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(nil).withUpdatedForwardMessageHideSendersNames(false) }) })
} }
var isPinnedMessages = false var isPinnedMessages = false

View File

@ -988,7 +988,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if let _ = accessoryPanelNode as? ReplyAccessoryPanelNode { if let _ = accessoryPanelNode as? ReplyAccessoryPanelNode {
strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedReplyMessageId(nil) }) strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedReplyMessageId(nil) })
} else if let _ = accessoryPanelNode as? ForwardAccessoryPanelNode { } else if let _ = accessoryPanelNode as? ForwardAccessoryPanelNode {
strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedForwardMessageIds(nil) }) strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedForwardMessageIds(nil).withUpdatedForwardMessageHideSendersNames(false) })
} else if let _ = accessoryPanelNode as? EditAccessoryPanelNode { } else if let _ = accessoryPanelNode as? EditAccessoryPanelNode {
strongSelf.interfaceInteraction?.setupEditMessage(nil, { _ in }) strongSelf.interfaceInteraction?.setupEditMessage(nil, { _ in })
} else if let _ = accessoryPanelNode as? WebpagePreviewAccessoryPanelNode { } else if let _ = accessoryPanelNode as? WebpagePreviewAccessoryPanelNode {
@ -2352,8 +2352,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if !messages.isEmpty || self.chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil { if !messages.isEmpty || self.chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil {
if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds { if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
var attributes: [MessageAttribute] = []
if self.chatPresentationInterfaceState.interfaceState.forwardMessageHideSendersNames {
attributes.append(ForwardHideSendersNamesMessageAttribute())
}
for id in forwardMessageIds { for id in forwardMessageIds {
messages.append(.forward(source: id, grouping: .auto, attributes: [], correlationId: nil)) messages.append(.forward(source: id, grouping: .auto, attributes: attributes, correlationId: nil))
} }
} }
@ -2379,7 +2383,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if let strongSelf = self, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode { if let strongSelf = self, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode {
strongSelf.ignoreUpdateHeight = true strongSelf.ignoreUpdateHeight = true
textInputPanelNode.text = "" textInputPanelNode.text = ""
strongSelf.requestUpdateChatInterfaceState(.immediate, true, { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedComposeDisableUrlPreview(nil) }) strongSelf.requestUpdateChatInterfaceState(.immediate, true, { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardMessageHideSendersNames(false).withUpdatedComposeDisableUrlPreview(nil) })
strongSelf.ignoreUpdateHeight = false strongSelf.ignoreUpdateHeight = false
} }
}, usedCorrelationId) }, usedCorrelationId)

View File

@ -49,10 +49,10 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS
} else if let forwardMessageIds = chatPresentationInterfaceState.interfaceState.forwardMessageIds { } else if let forwardMessageIds = chatPresentationInterfaceState.interfaceState.forwardMessageIds {
if let forwardPanelNode = currentPanel as? ForwardAccessoryPanelNode, forwardPanelNode.messageIds == forwardMessageIds { if let forwardPanelNode = currentPanel as? ForwardAccessoryPanelNode, forwardPanelNode.messageIds == forwardMessageIds {
forwardPanelNode.interfaceInteraction = interfaceInteraction forwardPanelNode.interfaceInteraction = interfaceInteraction
forwardPanelNode.updateThemeAndStrings(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings) forwardPanelNode.updateThemeAndStrings(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, hideSendersNames: chatPresentationInterfaceState.interfaceState.forwardMessageHideSendersNames)
return forwardPanelNode return forwardPanelNode
} else { } else {
let panelNode = ForwardAccessoryPanelNode(context: context, messageIds: forwardMessageIds, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings) let panelNode = ForwardAccessoryPanelNode(context: context, messageIds: forwardMessageIds, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, hideSendersNames: chatPresentationInterfaceState.interfaceState.forwardMessageHideSendersNames)
panelNode.interfaceInteraction = interfaceInteraction panelNode.interfaceInteraction = interfaceInteraction
return panelNode return panelNode
} }

View File

@ -549,7 +549,7 @@ final class ChatMediaInputNode: ChatInputNode {
self.listView.useSingleDimensionTouchPoint = true self.listView.useSingleDimensionTouchPoint = true
self.listView.reorderedItemHasShadow = false self.listView.reorderedItemHasShadow = false
self.listView.transform = CATransform3DMakeRotation(-CGFloat(Double.pi / 2.0), 0.0, 0.0, 1.0) self.listView.transform = CATransform3DMakeRotation(-CGFloat(Double.pi / 2.0), 0.0, 0.0, 1.0)
self.listView.scroller.panGestureRecognizer.cancelsTouchesInView = false self.listView.scroller.panGestureRecognizer.cancelsTouchesInView = true
self.listView.accessibilityPageScrolledString = { row, count in self.listView.accessibilityPageScrolledString = { row, count in
return strings.VoiceOver_ScrollStatus(row, count).string return strings.VoiceOver_ScrollStatus(row, count).string
} }
@ -557,7 +557,7 @@ final class ChatMediaInputNode: ChatInputNode {
self.gifListView = ListView() self.gifListView = ListView()
self.gifListView.useSingleDimensionTouchPoint = true self.gifListView.useSingleDimensionTouchPoint = true
self.gifListView.transform = CATransform3DMakeRotation(-CGFloat(Double.pi / 2.0), 0.0, 0.0, 1.0) self.gifListView.transform = CATransform3DMakeRotation(-CGFloat(Double.pi / 2.0), 0.0, 0.0, 1.0)
self.gifListView.scroller.panGestureRecognizer.cancelsTouchesInView = false self.gifListView.scroller.panGestureRecognizer.cancelsTouchesInView = true
self.gifListView.accessibilityPageScrolledString = { row, count in self.gifListView.accessibilityPageScrolledString = { row, count in
return strings.VoiceOver_ScrollStatus(row, count).string return strings.VoiceOver_ScrollStatus(row, count).string
} }

View File

@ -216,7 +216,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
switch thumbnailItem { switch thumbnailItem {
case let .still(representation): case let .still(representation):
imageSize = representation.dimensions.cgSize.aspectFitted(boundingImageSize) imageSize = representation.dimensions.cgSize.aspectFitted(boundingImageSize)
let imageApply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingImageSize, intrinsicInsets: UIEdgeInsets())) let imageApply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(radius: 6.0), imageSize: imageSize, boundingSize: boundingImageSize, intrinsicInsets: UIEdgeInsets()))
imageApply() imageApply()
self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource, nilIfEmpty: true)) self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource, nilIfEmpty: true))
case let .animated(resource, _): case let .animated(resource, _):
@ -339,7 +339,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
imageSize = representation.dimensions.cgSize.aspectFitted(boundingImageSize) imageSize = representation.dimensions.cgSize.aspectFitted(boundingImageSize)
let imageNode = TransformImageNode() let imageNode = TransformImageNode()
let imageApply = imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingImageSize, intrinsicInsets: UIEdgeInsets())) let imageApply = imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(radius: 6.0), imageSize: imageSize, boundingSize: boundingImageSize, intrinsicInsets: UIEdgeInsets()))
imageApply() imageApply()
imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource, nilIfEmpty: true)) imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource, nilIfEmpty: true))
scalingNode.addSubnode(imageNode) scalingNode.addSubnode(imageNode)

View File

@ -28,7 +28,10 @@ private func fixGridScrolling(_ gridNode: GridNode) {
var scrollIndex: Int? var scrollIndex: Int?
if itemFrame.minY + itemFrame.height * 0.6 < contentInset { if itemFrame.minY + itemFrame.height * 0.6 < contentInset {
for i in 0 ..< gridNode.items.count { for i in 0 ..< gridNode.items.count {
if let _ = gridNode.items[i] as? ChatMediaInputStickerGridItem { if let _ = gridNode.items[i] as? StickerPaneTrendingListGridItem {
scrollIndex = i
break
} else if let _ = gridNode.items[i] as? ChatMediaInputStickerGridItem {
scrollIndex = i scrollIndex = i
break break
} }

View File

@ -60,6 +60,7 @@ final class ChatPanelInterfaceInteraction {
let forwardSelectedMessages: () -> Void let forwardSelectedMessages: () -> Void
let forwardCurrentForwardMessages: () -> Void let forwardCurrentForwardMessages: () -> Void
let forwardMessages: ([Message]) -> Void let forwardMessages: ([Message]) -> Void
let updateForwardMessageHideSendersNames: (Bool) -> Void
let shareSelectedMessages: () -> Void let shareSelectedMessages: () -> Void
let updateTextInputStateAndMode: (@escaping (ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void let updateTextInputStateAndMode: (@escaping (ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void
let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void
@ -144,6 +145,7 @@ final class ChatPanelInterfaceInteraction {
forwardSelectedMessages: @escaping () -> Void, forwardSelectedMessages: @escaping () -> Void,
forwardCurrentForwardMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void,
forwardMessages: @escaping ([Message]) -> Void, forwardMessages: @escaping ([Message]) -> Void,
updateForwardMessageHideSendersNames: @escaping (Bool) -> Void,
shareSelectedMessages: @escaping () -> Void, shareSelectedMessages: @escaping () -> Void,
updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void,
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void,
@ -227,6 +229,7 @@ final class ChatPanelInterfaceInteraction {
self.forwardSelectedMessages = forwardSelectedMessages self.forwardSelectedMessages = forwardSelectedMessages
self.forwardCurrentForwardMessages = forwardCurrentForwardMessages self.forwardCurrentForwardMessages = forwardCurrentForwardMessages
self.forwardMessages = forwardMessages self.forwardMessages = forwardMessages
self.updateForwardMessageHideSendersNames = updateForwardMessageHideSendersNames
self.shareSelectedMessages = shareSelectedMessages self.shareSelectedMessages = shareSelectedMessages
self.updateTextInputStateAndMode = updateTextInputStateAndMode self.updateTextInputStateAndMode = updateTextInputStateAndMode
self.updateInputModeAndDismissedButtonKeyboardMessageId = updateInputModeAndDismissedButtonKeyboardMessageId self.updateInputModeAndDismissedButtonKeyboardMessageId = updateInputModeAndDismissedButtonKeyboardMessageId

View File

@ -65,6 +65,7 @@ final class ChatRecentActionsController: TelegramBaseController {
}, forwardSelectedMessages: { }, forwardSelectedMessages: {
}, forwardCurrentForwardMessages: { }, forwardCurrentForwardMessages: {
}, forwardMessages: { _ in }, forwardMessages: { _ in
}, updateForwardMessageHideSendersNames: { _ in
}, shareSelectedMessages: { }, shareSelectedMessages: {
}, updateTextInputStateAndMode: { _ in }, updateTextInputStateAndMode: { _ in
}, updateInputModeAndDismissedButtonKeyboardMessageId: { _ in }, updateInputModeAndDismissedButtonKeyboardMessageId: { _ in

View File

@ -6,10 +6,13 @@ import Postbox
import SwiftSignalKit import SwiftSignalKit
import Display import Display
import TelegramPresentationData import TelegramPresentationData
import TelegramUIPreferences
import AccountContext import AccountContext
import LocalizedPeerData import LocalizedPeerData
import AlertUI import AlertUI
import PresentationDataUtils import PresentationDataUtils
import TextFormat
import Markdown
func textStringForForwardedMessage(_ message: Message, strings: PresentationStrings) -> (String, Bool) { func textStringForForwardedMessage(_ message: Message, strings: PresentationStrings) -> (String, Bool) {
for media in message.media { for media in message.media {
@ -76,6 +79,8 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri
final class ForwardAccessoryPanelNode: AccessoryPanelNode { final class ForwardAccessoryPanelNode: AccessoryPanelNode {
private let messageDisposable = MetaDisposable() private let messageDisposable = MetaDisposable()
let messageIds: [MessageId] let messageIds: [MessageId]
private var authors: String?
private var sourcePeer: (isPersonal: Bool, displayTitle: String)?
let closeButton: ASButtonNode let closeButton: ASButtonNode
let lineNode: ASImageNode let lineNode: ASImageNode
@ -87,14 +92,20 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
let context: AccountContext let context: AccountContext
var theme: PresentationTheme var theme: PresentationTheme
var strings: PresentationStrings var strings: PresentationStrings
var fontSize: PresentationFontSize
var nameDisplayOrder: PresentationPersonNameOrder
var hideSendersNames: Bool
private var validLayout: (size: CGSize, interfaceState: ChatPresentationInterfaceState)? private var validLayout: (size: CGSize, interfaceState: ChatPresentationInterfaceState)?
init(context: AccountContext, messageIds: [MessageId], theme: PresentationTheme, strings: PresentationStrings) { init(context: AccountContext, messageIds: [MessageId], theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, nameDisplayOrder: PresentationPersonNameOrder, hideSendersNames: Bool) {
self.context = context self.context = context
self.messageIds = messageIds self.messageIds = messageIds
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.fontSize = fontSize
self.nameDisplayOrder = nameDisplayOrder
self.hideSendersNames = hideSendersNames
self.closeButton = ASButtonNode() self.closeButton = ASButtonNode()
self.closeButton.accessibilityLabel = strings.VoiceOver_DiscardPreparedContent self.closeButton.accessibilityLabel = strings.VoiceOver_DiscardPreparedContent
@ -133,6 +144,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
var authors = "" var authors = ""
var uniquePeerIds = Set<PeerId>() var uniquePeerIds = Set<PeerId>()
var text = "" var text = ""
var sourcePeer: (Bool, String)?
for message in messages { for message in messages {
if let author = message.effectiveAuthor, !uniquePeerIds.contains(author.id) { if let author = message.effectiveAuthor, !uniquePeerIds.contains(author.id) {
uniquePeerIds.insert(author.id) uniquePeerIds.insert(author.id)
@ -141,6 +153,9 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
} }
authors.append(author.compactDisplayTitle) authors.append(author.compactDisplayTitle)
} }
if let peer = message.peers[message.id.peerId] {
sourcePeer = (peer.id.namespace == Namespaces.Peer.CloudUser, peer.displayTitle(strings: strongSelf.strings, displayOrder: strongSelf.nameDisplayOrder))
}
} }
if messages.count == 1 { if messages.count == 1 {
let (string, _) = textStringForForwardedMessage(messages[0], strings: strings) let (string, _) = textStringForForwardedMessage(messages[0], strings: strings)
@ -149,7 +164,15 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
text = strings.ForwardedMessages(Int32(messages.count)) text = strings.ForwardedMessages(Int32(messages.count))
} }
strongSelf.titleNode.attributedText = NSAttributedString(string: authors, font: Font.medium(15.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor) strongSelf.sourcePeer = sourcePeer
strongSelf.authors = authors
if strongSelf.hideSendersNames {
strongSelf.titleNode.attributedText = NSAttributedString(string: strongSelf.strings.Conversation_ForwardOptions_You, font: Font.medium(15.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor)
} else {
strongSelf.titleNode.attributedText = NSAttributedString(string: authors, font: Font.medium(15.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor)
}
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor) strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor)
let headerString: String let headerString: String
@ -178,20 +201,27 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
} }
override func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) { override func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
if self.theme !== theme || self.strings !== strings { self.updateThemeAndStrings(theme: theme, strings: strings, hideSendersNames: self.hideSendersNames)
}
func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings, hideSendersNames: Bool) {
if self.theme !== theme || self.strings !== strings || self.hideSendersNames != hideSendersNames {
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.hideSendersNames = hideSendersNames
self.closeButton.setImage(PresentationResourcesChat.chatInputPanelCloseIconImage(theme), for: []) self.closeButton.setImage(PresentationResourcesChat.chatInputPanelCloseIconImage(theme), for: [])
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme) self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
if let text = self.titleNode.attributedText?.string { if hideSendersNames {
self.titleNode.attributedText = NSAttributedString(string: text, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor) self.titleNode.attributedText = NSAttributedString(string: strings.Conversation_ForwardOptions_You, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor)
} else if let authors = self.authors {
self.titleNode.attributedText = NSAttributedString(string: authors, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor)
} }
if let text = self.textNode.attributedText?.string { if let text = self.textNode.attributedText?.string {
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: self.theme.chat.inputPanel.primaryTextColor) self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: self.theme.chat.inputPanel.secondaryTextColor)
} }
if let (size, interfaceState) = self.validLayout { if let (size, interfaceState) = self.validLayout {
@ -208,14 +238,16 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
self.validLayout = (size, interfaceState) self.validLayout = (size, interfaceState)
let bounds = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: 45.0)) let bounds = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: 45.0))
let leftInset: CGFloat = 55.0 let inset: CGFloat = interfaceState.renderedPeer == nil ? 19.0 : 55.0
let leftInset: CGFloat = inset
let rightInset: CGFloat = inset
let textLineInset: CGFloat = 10.0 let textLineInset: CGFloat = 10.0
let rightInset: CGFloat = 55.0
let textRightInset: CGFloat = 20.0 let textRightInset: CGFloat = 20.0
let closeButtonSize = CGSize(width: 44.0, height: bounds.height) let closeButtonSize = CGSize(width: 44.0, height: bounds.height)
let closeButtonFrame = CGRect(origin: CGPoint(x: bounds.width - rightInset - closeButtonSize.width + 12.0, y: 2.0), size: closeButtonSize) let closeButtonFrame = CGRect(origin: CGPoint(x: bounds.width - rightInset - closeButtonSize.width + 12.0, y: 2.0), size: closeButtonSize)
self.closeButton.frame = closeButtonFrame self.closeButton.frame = closeButtonFrame
self.closeButton.isHidden = interfaceState.renderedPeer == nil
self.actionArea.frame = CGRect(origin: CGPoint(x: leftInset, y: 2.0), size: CGSize(width: closeButtonFrame.minX - leftInset, height: bounds.height)) self.actionArea.frame = CGRect(origin: CGPoint(x: leftInset, y: 2.0), size: CGSize(width: closeButtonFrame.minX - leftInset, height: bounds.height))
@ -229,9 +261,28 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
} }
@objc func closePressed() { @objc func closePressed() {
let alertController = textAlertController(context: self.context, title: self.strings.Conversation_CancelForwardTitle, text: self.strings.Conversation_CancelForwardText, actions: [TextAlertAction(type: .genericAction, title: self.strings.Conversation_CancelForwardSelectChat, action: { [weak self] in guard let (isPersonal, peerDisplayTitle) = self.sourcePeer else {
return
}
let messageCount = Int32(self.messageIds.count)
let messages = self.strings.Conversation_ForwardOptions_Messages(messageCount)
let string = isPersonal ? self.strings.Conversation_ForwardOptions_TextPersonal(messages, peerDisplayTitle) : self.strings.Conversation_ForwardOptions_Text(messages, peerDisplayTitle)
let font = Font.regular(floor(self.fontSize.baseDisplaySize * 15.0 / 17.0))
let boldFont = Font.semibold(floor(self.fontSize.baseDisplaySize * 15.0 / 17.0))
let body = MarkdownAttributeSet(font: font, textColor: self.theme.actionSheet.secondaryTextColor)
let bold = MarkdownAttributeSet(font: boldFont, textColor: self.theme.actionSheet.secondaryTextColor)
let title = NSAttributedString(string: self.strings.Conversation_ForwardOptions_Title(messageCount), font: Font.semibold(floor(self.fontSize.baseDisplaySize)), textColor: self.theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
let text = addAttributesToStringWithRanges(string._tuple, body: body, argumentAttributes: [0: bold, 1: bold], textAlignment: .center)
let alertController = richTextAlertController(context: self.context, title: title, text: text, actions: [TextAlertAction(type: .genericAction, title: self.strings.Conversation_ForwardOptions_ForwardToAnotherChat, action: { [weak self] in
self?.interfaceInteraction?.forwardCurrentForwardMessages() self?.interfaceInteraction?.forwardCurrentForwardMessages()
}), TextAlertAction(type: .defaultAction, title: self.strings.Conversation_CancelForwardCancelForward, action: { [weak self] in }), TextAlertAction(type: .genericAction, title: self.hideSendersNames ? self.strings.Conversation_ForwardOptions_ShowSendersNames : self.strings.Conversation_ForwardOptions_HideSendersNames, action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateForwardMessageHideSendersNames(!strongSelf.hideSendersNames)
}
}), TextAlertAction(type: .destructiveAction, title: self.strings.Conversation_ForwardOptions_CancelForwarding, action: { [weak self] in
self?.dismiss?() self?.dismiss?()
})], actionLayout: .vertical) })], actionLayout: .vertical)
self.interfaceInteraction?.presentController(alertController, nil) self.interfaceInteraction?.presentController(alertController, nil)
@ -239,7 +290,11 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) { @objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state { if case .ended = recognizer.state {
self.interfaceInteraction?.forwardCurrentForwardMessages() if self.closeButton.isHidden {
self.interfaceInteraction?.updateForwardMessageHideSendersNames(!self.hideSendersNames)
} else {
self.closePressed()
}
} }
} }
} }

View File

@ -379,6 +379,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
forwardMessages() forwardMessages()
}, forwardCurrentForwardMessages: { }, forwardCurrentForwardMessages: {
}, forwardMessages: { _ in }, forwardMessages: { _ in
}, updateForwardMessageHideSendersNames: { _ in
}, shareSelectedMessages: { }, shareSelectedMessages: {
shareMessages() shareMessages()
}, updateTextInputStateAndMode: { _ in }, updateTextInputStateAndMode: { _ in
@ -5644,7 +5645,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
func forwardMessages(messageIds: Set<MessageId>?) { func forwardMessages(messageIds: Set<MessageId>?) {
if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty { if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty {
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true)) let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true))
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, peerMap, messageText, mode in peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, peerMap, messageText, mode, hideSendersNames in
guard let strongSelf = self, let strongController = peerSelectionController else { guard let strongSelf = self, let strongController = peerSelectionController else {
return return
} }
@ -5665,8 +5666,13 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
} }
} }
var attributes: [MessageAttribute] = []
if hideSendersNames {
attributes.append(ForwardHideSendersNamesMessageAttribute())
}
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil) return .forward(source: messageId, grouping: .auto, attributes: attributes, correlationId: nil)
}) })
var displayPeers: [Peer] = [] var displayPeers: [Peer] = []

View File

@ -19,7 +19,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
private var customTitle: String? private var customTitle: String?
public var peerSelected: ((Peer) -> Void)? public var peerSelected: ((Peer) -> Void)?
public var multiplePeersSelected: (([Peer], [PeerId: Peer], NSAttributedString, PeerSelectionControllerSendMode) -> Void)? public var multiplePeersSelected: (([Peer], [PeerId: Peer], NSAttributedString, PeerSelectionControllerSendMode, Bool) -> Void)?
private let filter: ChatListNodePeersFilter private let filter: ChatListNodePeersFilter
private let attemptSelection: ((Peer) -> Void)? private let attemptSelection: ((Peer) -> Void)?
@ -58,7 +58,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
private let hasContactSelector: Bool private let hasContactSelector: Bool
private let hasGlobalSearch: Bool private let hasGlobalSearch: Bool
private let pretendPresentedInModal: Bool private let pretendPresentedInModal: Bool
private let forwardedMessagesCount: Int private let forwardedMessageIds: [EngineMessage.Id]
override public var _presentedInModal: Bool { override public var _presentedInModal: Bool {
get { get {
@ -86,7 +86,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self.attemptSelection = params.attemptSelection self.attemptSelection = params.attemptSelection
self.createNewGroup = params.createNewGroup self.createNewGroup = params.createNewGroup
self.pretendPresentedInModal = params.pretendPresentedInModal self.pretendPresentedInModal = params.pretendPresentedInModal
self.forwardedMessagesCount = params.forwardedMessagesCount self.forwardedMessageIds = params.forwardedMessageIds
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
@ -150,7 +150,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
} }
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.displayNode = PeerSelectionControllerNode(context: self.context, filter: self.filter, hasChatListSelector: self.hasChatListSelector, hasContactSelector: self.hasContactSelector, hasGlobalSearch: self.hasGlobalSearch, forwardedMessagesCount: self.forwardedMessagesCount, createNewGroup: self.createNewGroup, present: { [weak self] c, a in self.displayNode = PeerSelectionControllerNode(context: self.context, filter: self.filter, hasChatListSelector: self.hasChatListSelector, hasContactSelector: self.hasContactSelector, hasGlobalSearch: self.hasGlobalSearch, forwardedMessageIds: self.forwardedMessageIds, createNewGroup: self.createNewGroup, present: { [weak self] c, a in
self?.present(c, in: .window(.root), with: a) self?.present(c, in: .window(.root), with: a)
}, presentInGlobalOverlay: { [weak self] c, a in }, presentInGlobalOverlay: { [weak self] c, a in
self?.presentInGlobalOverlay(c, with: a) self?.presentInGlobalOverlay(c, with: a)
@ -160,8 +160,8 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
self.peerSelectionNode.navigationBar = self.navigationBar self.peerSelectionNode.navigationBar = self.navigationBar
self.peerSelectionNode.requestSend = { [weak self] peers, peerMap, text, mode in self.peerSelectionNode.requestSend = { [weak self] peers, peerMap, text, mode, hideSendersNames in
self?.multiplePeersSelected?(peers, peerMap, text, mode) self?.multiplePeersSelected?(peers, peerMap, text, mode, hideSendersNames)
} }
self.peerSelectionNode.requestDeactivateSearch = { [weak self] in self.peerSelectionNode.requestDeactivateSearch = { [weak self] in

View File

@ -20,6 +20,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
private let dismiss: () -> Void private let dismiss: () -> Void
private let filter: ChatListNodePeersFilter private let filter: ChatListNodePeersFilter
private let hasGlobalSearch: Bool private let hasGlobalSearch: Bool
private let forwardedMessageIds: [EngineMessage.Id]
private var presentationInterfaceState: ChatPresentationInterfaceState private var presentationInterfaceState: ChatPresentationInterfaceState
private var interfaceInteraction: ChatPanelInterfaceInteraction? private var interfaceInteraction: ChatPanelInterfaceInteraction?
@ -37,6 +38,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
private let segmentedControlNode: SegmentedControlNode? private let segmentedControlNode: SegmentedControlNode?
private var textInputPanelNode: PeerSelectionTextInputPanelNode? private var textInputPanelNode: PeerSelectionTextInputPanelNode?
private var forwardAccessoryPanelNode: ForwardAccessoryPanelNode?
var contactListNode: ContactListNode? var contactListNode: ContactListNode?
let chatListNode: ChatListNode let chatListNode: ChatListNode
@ -56,7 +58,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
var requestOpenDisabledPeer: ((Peer) -> Void)? var requestOpenDisabledPeer: ((Peer) -> Void)?
var requestOpenPeerFromSearch: ((Peer) -> Void)? var requestOpenPeerFromSearch: ((Peer) -> Void)?
var requestOpenMessageFromSearch: ((Peer, MessageId) -> Void)? var requestOpenMessageFromSearch: ((Peer, MessageId) -> Void)?
var requestSend: (([Peer], [PeerId: Peer], NSAttributedString, PeerSelectionControllerSendMode) -> Void)? var requestSend: (([Peer], [PeerId: Peer], NSAttributedString, PeerSelectionControllerSendMode, Bool) -> Void)?
private var presentationData: PresentationData private var presentationData: PresentationData
private var presentationDataDisposable: Disposable? private var presentationDataDisposable: Disposable?
@ -66,28 +68,21 @@ final class PeerSelectionControllerNode: ASDisplayNode {
return self.readyValue.get() return self.readyValue.get()
} }
init(context: AccountContext, filter: ChatListNodePeersFilter, hasChatListSelector: Bool, hasContactSelector: Bool, hasGlobalSearch: Bool, forwardedMessagesCount: Int, createNewGroup: (() -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void) { init(context: AccountContext, filter: ChatListNodePeersFilter, hasChatListSelector: Bool, hasContactSelector: Bool, hasGlobalSearch: Bool, forwardedMessageIds: [EngineMessage.Id], createNewGroup: (() -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void) {
self.context = context self.context = context
self.present = present self.present = present
self.presentInGlobalOverlay = presentInGlobalOverlay self.presentInGlobalOverlay = presentInGlobalOverlay
self.dismiss = dismiss self.dismiss = dismiss
self.filter = filter self.filter = filter
self.hasGlobalSearch = hasGlobalSearch self.hasGlobalSearch = hasGlobalSearch
self.forwardedMessageIds = forwardedMessageIds
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.presentationData = presentationData self.presentationData = presentationData
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil) self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil)
var mockMessageIds: [MessageId]? self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds) }
if forwardedMessagesCount > 0 {
var messageIds: [MessageId] = []
for _ in 0 ..< forwardedMessagesCount {
messageIds.append(MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: Int32.random(in: 0 ..< Int32.max)))
}
mockMessageIds = messageIds
}
self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(mockMessageIds) }
if hasChatListSelector && hasContactSelector { if hasChatListSelector && hasContactSelector {
self.toolbarBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor) self.toolbarBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
@ -198,6 +193,10 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}, forwardSelectedMessages: { }, forwardSelectedMessages: {
}, forwardCurrentForwardMessages: { }, forwardCurrentForwardMessages: {
}, forwardMessages: { _ in }, forwardMessages: { _ in
}, updateForwardMessageHideSendersNames: { [weak self] value in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageHideSendersNames(value) }) })
}
}, shareSelectedMessages: { }, shareSelectedMessages: {
}, updateTextInputStateAndMode: { [weak self] f in }, updateTextInputStateAndMode: { [weak self] f in
if let strongSelf = self { if let strongSelf = self {
@ -335,6 +334,11 @@ final class PeerSelectionControllerNode: ASDisplayNode {
func beginSelection() { func beginSelection() {
if let _ = self.textInputPanelNode { if let _ = self.textInputPanelNode {
} else { } else {
let forwardAccessoryPanelNode = ForwardAccessoryPanelNode(context: self.context, messageIds: self.forwardedMessageIds, theme: self.presentationData.theme, strings: self.presentationData.strings, fontSize: self.presentationData.chatFontSize, nameDisplayOrder: self.presentationData.nameDisplayOrder, hideSendersNames: false)
forwardAccessoryPanelNode.interfaceInteraction = self.interfaceInteraction
self.addSubnode(forwardAccessoryPanelNode)
self.forwardAccessoryPanelNode = forwardAccessoryPanelNode
let textInputPanelNode = PeerSelectionTextInputPanelNode(presentationInterfaceState: self.presentationInterfaceState, presentController: { [weak self] c in self?.present(c, nil) }) let textInputPanelNode = PeerSelectionTextInputPanelNode(presentationInterfaceState: self.presentationInterfaceState, presentController: { [weak self] c in self?.present(c, nil) })
textInputPanelNode.interfaceInteraction = self.interfaceInteraction textInputPanelNode.interfaceInteraction = self.interfaceInteraction
textInputPanelNode.sendMessage = { [weak self] mode in textInputPanelNode.sendMessage = { [weak self] mode in
@ -342,10 +346,13 @@ final class PeerSelectionControllerNode: ASDisplayNode {
return return
} }
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
let hideSendersNames = strongSelf.presentationInterfaceState.interfaceState.forwardMessageHideSendersNames
if strongSelf.contactListActive { if strongSelf.contactListActive {
strongSelf.contactListNode?.multipleSelection = true strongSelf.contactListNode?.multipleSelection = true
let selectedContactPeers = strongSelf.contactListNode?.selectedPeers ?? [] let selectedContactPeers = strongSelf.contactListNode?.selectedPeers ?? []
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
var selectedPeers: [Peer] = [] var selectedPeers: [Peer] = []
var selectedPeerMap: [PeerId: Peer] = [:] var selectedPeerMap: [PeerId: Peer] = [:]
for contactPeer in selectedContactPeers { for contactPeer in selectedContactPeers {
@ -355,7 +362,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
} }
} }
if !selectedPeers.isEmpty { if !selectedPeers.isEmpty {
strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode) strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode, hideSendersNames)
} }
} else { } else {
var selectedPeerIds: [PeerId] = [] var selectedPeerIds: [PeerId] = []
@ -366,14 +373,13 @@ final class PeerSelectionControllerNode: ASDisplayNode {
return state return state
} }
if !selectedPeerIds.isEmpty { if !selectedPeerIds.isEmpty {
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
var selectedPeers: [Peer] = [] var selectedPeers: [Peer] = []
for peerId in selectedPeerIds { for peerId in selectedPeerIds {
if let peer = selectedPeerMap[peerId] { if let peer = selectedPeerMap[peerId] {
selectedPeers.append(peer) selectedPeers.append(peer)
} }
} }
strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode) strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode, hideSendersNames)
} }
} }
} }
@ -416,6 +422,12 @@ final class PeerSelectionControllerNode: ASDisplayNode {
var toolbarHeight: CGFloat = cleanInsets.bottom var toolbarHeight: CGFloat = cleanInsets.bottom
var textPanelHeight: CGFloat? var textPanelHeight: CGFloat?
var accessoryHeight: CGFloat = 0.0
if let forwardAccessoryPanelNode = self.forwardAccessoryPanelNode {
let size = forwardAccessoryPanelNode.calculateSizeThatFits(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right, height: layout.size.height))
accessoryHeight = size.height
}
if let textInputPanelNode = self.textInputPanelNode { if let textInputPanelNode = self.textInputPanelNode {
var panelTransition = transition var panelTransition = transition
@ -433,15 +445,30 @@ final class PeerSelectionControllerNode: ASDisplayNode {
let panelFrame = CGRect(x: 0.0, y: layout.size.height - panelHeight, width: layout.size.width, height: panelHeight) let panelFrame = CGRect(x: 0.0, y: layout.size.height - panelHeight, width: layout.size.width, height: panelHeight)
if textInputPanelNode.frame.width.isZero { if textInputPanelNode.frame.width.isZero {
var initialPanelFrame = panelFrame var initialPanelFrame = panelFrame
initialPanelFrame.origin.y = layout.size.height initialPanelFrame.origin.y = layout.size.height + accessoryHeight
textInputPanelNode.frame = initialPanelFrame textInputPanelNode.frame = initialPanelFrame
} }
transition.updateFrame(node: textInputPanelNode, frame: panelFrame) transition.updateFrame(node: textInputPanelNode, frame: panelFrame)
} }
if let forwardAccessoryPanelNode = self.forwardAccessoryPanelNode {
let size = forwardAccessoryPanelNode.calculateSizeThatFits(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right, height: layout.size.height))
forwardAccessoryPanelNode.updateState(size: size, interfaceState: self.presentationInterfaceState)
forwardAccessoryPanelNode.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings, hideSendersNames: self.presentationInterfaceState.interfaceState.forwardMessageHideSendersNames)
let panelFrame = CGRect(x: layout.safeInsets.left, y: layout.size.height - (textPanelHeight ?? 0.0) - size.height, width: size.width - layout.safeInsets.left - layout.safeInsets.right, height: size.height)
accessoryHeight = size.height
if forwardAccessoryPanelNode.frame.width.isZero {
var initialPanelFrame = panelFrame
initialPanelFrame.origin.y = layout.size.height
forwardAccessoryPanelNode.frame = initialPanelFrame
}
transition.updateFrame(node: forwardAccessoryPanelNode, frame: panelFrame)
}
if let segmentedControlNode = self.segmentedControlNode, let toolbarBackgroundNode = self.toolbarBackgroundNode, let toolbarSeparatorNode = self.toolbarSeparatorNode { if let segmentedControlNode = self.segmentedControlNode, let toolbarBackgroundNode = self.toolbarBackgroundNode, let toolbarSeparatorNode = self.toolbarSeparatorNode {
if let textPanelHeight = textPanelHeight { if let textPanelHeight = textPanelHeight {
toolbarHeight = textPanelHeight toolbarHeight = textPanelHeight + accessoryHeight
} else { } else {
toolbarHeight += 44.0 toolbarHeight += 44.0
} }

View File

@ -291,7 +291,7 @@ private final class FeaturedPackItemNode: ListViewItemNode {
} else { } else {
self.containerNode.addSubnode(animatedStickerNode) self.containerNode.addSubnode(animatedStickerNode)
} }
animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: account, resource: resource), width: 80, height: 80, mode: .direct(cachePathPrefix: nil)) animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: account, resource: resource), width: 128, height: 128, mode: .cached)
} }
animatedStickerNode.visibility = self.visibilityStatus && loopAnimatedStickers animatedStickerNode.visibility = self.visibilityStatus && loopAnimatedStickers
} }
@ -398,7 +398,7 @@ class StickerPaneTrendingListGridItemNode: GridItemNode {
override var isVisibleInGrid: Bool { override var isVisibleInGrid: Bool {
didSet { didSet {
self.updateVisibility()
} }
} }
@ -453,6 +453,10 @@ class StickerPaneTrendingListGridItemNode: GridItemNode {
self.setNeedsLayout() self.setNeedsLayout()
} }
func updateVisibility() {
}
override func layout() { override func layout() {
super.layout() super.layout()
guard let item = self.item else { guard let item = self.item else {