mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
Merge commit 'c7faf7503295d52b5bebcda403b065b31f4982a4'
This commit is contained in:
commit
66a03ac134
@ -6585,3 +6585,26 @@ Sorry for the inconvenience.";
|
||||
"Chat.NextChannelArchivedSwipeAction" = "Release to go to archived channels";
|
||||
"Chat.NextChannelUnarchivedSwipeProgress" = "Swipe up 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)";
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import Foundation
|
||||
import Display
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
|
||||
public struct ChatListNodePeersFilter: OptionSet {
|
||||
public var rawValue: Int32
|
||||
@ -40,9 +41,9 @@ public final class PeerSelectionControllerParams {
|
||||
public let createNewGroup: (() -> Void)?
|
||||
public let pretendPresentedInModal: 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.filter = filter
|
||||
self.hasChatListSelector = hasChatListSelector
|
||||
@ -53,7 +54,7 @@ public final class PeerSelectionControllerParams {
|
||||
self.createNewGroup = createNewGroup
|
||||
self.pretendPresentedInModal = pretendPresentedInModal
|
||||
self.multipleSelection = multipleSelection
|
||||
self.forwardedMessagesCount = forwardedMessagesCount
|
||||
self.forwardedMessageIds = forwardedMessageIds
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +66,7 @@ public enum PeerSelectionControllerSendMode {
|
||||
|
||||
public protocol PeerSelectionController: ViewController {
|
||||
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 customDismiss: (() -> Void)? { get set }
|
||||
}
|
||||
|
||||
@ -264,6 +264,7 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
public let composeDisableUrlPreview: String?
|
||||
public let replyMessageId: EngineMessage.Id?
|
||||
public let forwardMessageIds: [EngineMessage.Id]?
|
||||
public let forwardMessageHideSendersNames: Bool
|
||||
public let editMessage: ChatEditMessageState?
|
||||
public let selectionState: ChatInterfaceSelectionState?
|
||||
public let messageActionsState: ChatInterfaceMessageActionsState
|
||||
@ -306,6 +307,7 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
self.composeDisableUrlPreview = nil
|
||||
self.replyMessageId = nil
|
||||
self.forwardMessageIds = nil
|
||||
self.forwardMessageHideSendersNames = false
|
||||
self.editMessage = nil
|
||||
self.selectionState = nil
|
||||
self.messageActionsState = ChatInterfaceMessageActionsState()
|
||||
@ -315,12 +317,13 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
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.composeInputState = composeInputState
|
||||
self.composeDisableUrlPreview = composeDisableUrlPreview
|
||||
self.replyMessageId = replyMessageId
|
||||
self.forwardMessageIds = forwardMessageIds
|
||||
self.forwardMessageHideSendersNames = forwardMessageHideSendersNames
|
||||
self.editMessage = editMessage
|
||||
self.selectionState = selectionState
|
||||
self.messageActionsState = messageActionsState
|
||||
@ -357,6 +360,7 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
} else {
|
||||
self.forwardMessageIds = nil
|
||||
}
|
||||
self.forwardMessageHideSendersNames = ((try? container.decode(Int32.self, forKey: "fhn")) ?? 0) != 0
|
||||
if let editMessage = try? container.decodeIfPresent(ChatEditMessageState.self, forKey: "em") {
|
||||
self.editMessage = editMessage
|
||||
} else {
|
||||
@ -406,6 +410,7 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
} else {
|
||||
try container.encodeNil(forKey: "fm")
|
||||
}
|
||||
try container.encode((self.forwardMessageHideSendersNames ? 1 : 0) as Int32, forKey: "fhn")
|
||||
if let editMessage = self.editMessage {
|
||||
try container.encode(editMessage, forKey: "em")
|
||||
} else {
|
||||
@ -446,6 +451,9 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
} else if (lhs.forwardMessageIds != nil) != (rhs.forwardMessageIds != nil) {
|
||||
return false
|
||||
}
|
||||
if lhs.forwardMessageHideSendersNames != rhs.forwardMessageHideSendersNames {
|
||||
return false
|
||||
}
|
||||
if lhs.messageActionsState != rhs.messageActionsState {
|
||||
return false
|
||||
}
|
||||
@ -467,11 +475,11 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
public func withUpdatedComposeInputState(_ inputState: ChatTextInputState) -> ChatInterfaceState {
|
||||
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 {
|
||||
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 {
|
||||
@ -483,15 +491,19 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
@ -502,7 +514,7 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
for messageId in messageIds {
|
||||
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 {
|
||||
@ -517,39 +529,39 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
|
||||
@ -891,12 +891,12 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
}).start()
|
||||
|
||||
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 {
|
||||
return
|
||||
}
|
||||
strongController.dismiss()
|
||||
|
||||
|
||||
var result: [EnqueueMessage] = []
|
||||
if messageText.string.count > 0 {
|
||||
let inputText = convertMarkdownToAttributes(messageText)
|
||||
@ -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
|
||||
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
|
||||
return .forward(source: messageId, grouping: .auto, attributes: attributes, correlationId: nil)
|
||||
})
|
||||
|
||||
var displayPeers: [Peer] = []
|
||||
|
||||
@ -327,6 +327,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
private var reorderFeedbackDisposable: MetaDisposable?
|
||||
private var reorderInProgress: Bool = false
|
||||
private var reorderingItemsCompleted: (() -> Void)?
|
||||
private var reorderScrollStartTimestamp: Double?
|
||||
public var reorderedItemHasShadow = true
|
||||
|
||||
private let waitingForNodesDisposable = MetaDisposable()
|
||||
@ -3974,20 +3975,38 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
var offsetRanges = OffsetRanges()
|
||||
|
||||
var scrollingForReorder = false
|
||||
if let reorderOffset = self.reorderNode?.currentOffset(), !self.itemNodes.isEmpty {
|
||||
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 self.itemNodes[0].apparentFrame.minY < effectiveInsets.top {
|
||||
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 {
|
||||
if self.itemNodes[self.itemNodes.count - 1].apparentFrame.maxY > self.visibleSize.height - effectiveInsets.bottom {
|
||||
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 index = 0
|
||||
|
||||
@ -19,6 +19,7 @@ import ContextUI
|
||||
import SaveToCameraRoll
|
||||
import UndoUI
|
||||
import TelegramUIPreferences
|
||||
import OpenInExternalAppUI
|
||||
|
||||
public enum UniversalVideoGalleryItemContentInfo {
|
||||
case message(Message)
|
||||
@ -2088,6 +2089,36 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
|
||||
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 {
|
||||
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)
|
||||
|
||||
@ -62,9 +62,20 @@ private func allOpenInOptions(context: AccountContext, item: OpenInItem) -> [Ope
|
||||
var options: [OpenInOption] = []
|
||||
switch item {
|
||||
case let .url(url):
|
||||
options.append(OpenInOption(identifier: "safari", application: .safari, action: {
|
||||
return .openUrl(url: url)
|
||||
}))
|
||||
var skipSafari = false
|
||||
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: {
|
||||
if let url = URL(string: url), var components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
|
||||
|
||||
@ -373,6 +373,8 @@ public func chatMessageStickerPackThumbnail(postbox: Postbox, resource: MediaRes
|
||||
}
|
||||
}
|
||||
|
||||
addCorners(context, arguments: arguments)
|
||||
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,6 +234,7 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(CachedDisplayAsPeers.self, f: { CachedDisplayAsPeers(decoder: $0) })
|
||||
declareEncodable(WallpapersState.self, f: { WallpapersState(decoder: $0) })
|
||||
declareEncodable(WallpaperDataResource.self, f: { WallpaperDataResource(decoder: $0) })
|
||||
declareEncodable(ForwardHideSendersNamesMessageAttribute.self, f: { ForwardHideSendersNamesMessageAttribute(decoder: $0) })
|
||||
|
||||
return
|
||||
}()
|
||||
|
||||
@ -3,7 +3,6 @@ import Postbox
|
||||
import TelegramApi
|
||||
import SwiftSignalKit
|
||||
|
||||
|
||||
public enum EnqueueMessageGrouping {
|
||||
case none
|
||||
case auto
|
||||
@ -114,6 +113,8 @@ private func filterMessageAttributesForOutgoingMessage(_ attributes: [MessageAtt
|
||||
return true
|
||||
case _ as EmojiSearchQueryMessageAttribute:
|
||||
return true
|
||||
case _ as ForwardHideSendersNamesMessageAttribute:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@ -131,6 +132,8 @@ private func filterMessageAttributesForForwardedMessage(_ attributes: [MessageAt
|
||||
return true
|
||||
case _ as OutgoingScheduleInfoMessageAttribute:
|
||||
return true
|
||||
case _ as ForwardHideSendersNamesMessageAttribute:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@ -560,6 +563,14 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
|
||||
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 {
|
||||
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: [])
|
||||
} else {
|
||||
if sourceMessage.id.peerId != account.peerId {
|
||||
|
||||
@ -697,6 +697,7 @@ public final class PendingMessageManager {
|
||||
return .complete()
|
||||
} else if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
var isForward = false
|
||||
var hideSendersNames = false
|
||||
var replyMessageId: Int32?
|
||||
var scheduleTime: Int32?
|
||||
|
||||
@ -714,6 +715,8 @@ public final class PendingMessageManager {
|
||||
} else if let attribute = attribute as? OutgoingScheduleInfoMessageAttribute {
|
||||
flags |= Int32(1 << 10)
|
||||
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 }) {
|
||||
flags |= (1 << 9)
|
||||
}
|
||||
if hideSendersNames {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
|
||||
var forwardIds: [(MessageId, Int64)] = []
|
||||
for (message, content) in messages {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
|
||||
|
||||
public class AuthorSignatureMessageAttribute: MessageAttribute {
|
||||
public let signature: String
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
|
||||
public class ForwardHideSendersNamesMessageAttribute: MessageAttribute {
|
||||
public init() {
|
||||
}
|
||||
|
||||
required public init(decoder: PostboxDecoder) {
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
}
|
||||
}
|
||||
@ -5287,7 +5287,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let strongSelf = self {
|
||||
strongSelf.commitPurposefulAction()
|
||||
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
|
||||
@ -5296,6 +5296,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let forwardMessageIds = messages.map { $0.id }.sorted()
|
||||
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
|
||||
if let strongSelf = self, let selectedIds = strongSelf.presentationInterfaceState.interfaceState.selectionState?.selectedIds, !selectedIds.isEmpty {
|
||||
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
|
||||
return messageIds.compactMap(transaction.getMessage)
|
||||
}
|
||||
|> 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: {
|
||||
var filter: ChatListNodePeersFilter = [.onlyWriteable, .includeSavedMessages, .excludeDisabled, .doNotSearchMessages]
|
||||
var hasPublicPolls = false
|
||||
@ -11037,7 +11041,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
var attemptSelectionImpl: ((Peer) -> Void)?
|
||||
let controller = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: filter, attemptSelection: { peer in
|
||||
attemptSelectionImpl?(peer)
|
||||
}, multipleSelection: true, forwardedMessagesCount: messages.count))
|
||||
}, multipleSelection: true, forwardedMessageIds: messages.map { $0.id }))
|
||||
let context = self.context
|
||||
attemptSelectionImpl = { [weak controller] peer in
|
||||
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.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 {
|
||||
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
|
||||
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
|
||||
@ -11162,7 +11171,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@ -988,7 +988,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
if let _ = accessoryPanelNode as? ReplyAccessoryPanelNode {
|
||||
strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedReplyMessageId(nil) })
|
||||
} 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 {
|
||||
strongSelf.interfaceInteraction?.setupEditMessage(nil, { _ in })
|
||||
} else if let _ = accessoryPanelNode as? WebpagePreviewAccessoryPanelNode {
|
||||
@ -2352,8 +2352,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
if !messages.isEmpty || self.chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil {
|
||||
if let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
|
||||
var attributes: [MessageAttribute] = []
|
||||
if self.chatPresentationInterfaceState.interfaceState.forwardMessageHideSendersNames {
|
||||
attributes.append(ForwardHideSendersNamesMessageAttribute())
|
||||
}
|
||||
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 {
|
||||
strongSelf.ignoreUpdateHeight = true
|
||||
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
|
||||
}
|
||||
}, usedCorrelationId)
|
||||
|
||||
@ -49,10 +49,10 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS
|
||||
} else if let forwardMessageIds = chatPresentationInterfaceState.interfaceState.forwardMessageIds {
|
||||
if let forwardPanelNode = currentPanel as? ForwardAccessoryPanelNode, forwardPanelNode.messageIds == forwardMessageIds {
|
||||
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
|
||||
} 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
|
||||
return panelNode
|
||||
}
|
||||
|
||||
@ -549,7 +549,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
self.listView.useSingleDimensionTouchPoint = true
|
||||
self.listView.reorderedItemHasShadow = false
|
||||
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
|
||||
return strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
@ -557,7 +557,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
self.gifListView = ListView()
|
||||
self.gifListView.useSingleDimensionTouchPoint = true
|
||||
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
|
||||
return strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
||||
switch thumbnailItem {
|
||||
case let .still(representation):
|
||||
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()
|
||||
self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource, nilIfEmpty: true))
|
||||
case let .animated(resource, _):
|
||||
@ -339,7 +339,7 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
||||
imageSize = representation.dimensions.cgSize.aspectFitted(boundingImageSize)
|
||||
|
||||
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()
|
||||
imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource, nilIfEmpty: true))
|
||||
scalingNode.addSubnode(imageNode)
|
||||
|
||||
@ -28,7 +28,10 @@ private func fixGridScrolling(_ gridNode: GridNode) {
|
||||
var scrollIndex: Int?
|
||||
if itemFrame.minY + itemFrame.height * 0.6 < contentInset {
|
||||
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
|
||||
break
|
||||
}
|
||||
|
||||
@ -60,6 +60,7 @@ final class ChatPanelInterfaceInteraction {
|
||||
let forwardSelectedMessages: () -> Void
|
||||
let forwardCurrentForwardMessages: () -> Void
|
||||
let forwardMessages: ([Message]) -> Void
|
||||
let updateForwardMessageHideSendersNames: (Bool) -> Void
|
||||
let shareSelectedMessages: () -> Void
|
||||
let updateTextInputStateAndMode: (@escaping (ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void
|
||||
let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void
|
||||
@ -144,6 +145,7 @@ final class ChatPanelInterfaceInteraction {
|
||||
forwardSelectedMessages: @escaping () -> Void,
|
||||
forwardCurrentForwardMessages: @escaping () -> Void,
|
||||
forwardMessages: @escaping ([Message]) -> Void,
|
||||
updateForwardMessageHideSendersNames: @escaping (Bool) -> Void,
|
||||
shareSelectedMessages: @escaping () -> Void,
|
||||
updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void,
|
||||
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void,
|
||||
@ -227,6 +229,7 @@ final class ChatPanelInterfaceInteraction {
|
||||
self.forwardSelectedMessages = forwardSelectedMessages
|
||||
self.forwardCurrentForwardMessages = forwardCurrentForwardMessages
|
||||
self.forwardMessages = forwardMessages
|
||||
self.updateForwardMessageHideSendersNames = updateForwardMessageHideSendersNames
|
||||
self.shareSelectedMessages = shareSelectedMessages
|
||||
self.updateTextInputStateAndMode = updateTextInputStateAndMode
|
||||
self.updateInputModeAndDismissedButtonKeyboardMessageId = updateInputModeAndDismissedButtonKeyboardMessageId
|
||||
|
||||
@ -65,6 +65,7 @@ final class ChatRecentActionsController: TelegramBaseController {
|
||||
}, forwardSelectedMessages: {
|
||||
}, forwardCurrentForwardMessages: {
|
||||
}, forwardMessages: { _ in
|
||||
}, updateForwardMessageHideSendersNames: { _ in
|
||||
}, shareSelectedMessages: {
|
||||
}, updateTextInputStateAndMode: { _ in
|
||||
}, updateInputModeAndDismissedButtonKeyboardMessageId: { _ in
|
||||
|
||||
@ -6,10 +6,13 @@ import Postbox
|
||||
import SwiftSignalKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import AccountContext
|
||||
import LocalizedPeerData
|
||||
import AlertUI
|
||||
import PresentationDataUtils
|
||||
import TextFormat
|
||||
import Markdown
|
||||
|
||||
func textStringForForwardedMessage(_ message: Message, strings: PresentationStrings) -> (String, Bool) {
|
||||
for media in message.media {
|
||||
@ -76,6 +79,8 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri
|
||||
final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
private let messageDisposable = MetaDisposable()
|
||||
let messageIds: [MessageId]
|
||||
private var authors: String?
|
||||
private var sourcePeer: (isPersonal: Bool, displayTitle: String)?
|
||||
|
||||
let closeButton: ASButtonNode
|
||||
let lineNode: ASImageNode
|
||||
@ -87,14 +92,20 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
let context: AccountContext
|
||||
var theme: PresentationTheme
|
||||
var strings: PresentationStrings
|
||||
|
||||
var fontSize: PresentationFontSize
|
||||
var nameDisplayOrder: PresentationPersonNameOrder
|
||||
var hideSendersNames: Bool
|
||||
|
||||
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.messageIds = messageIds
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.fontSize = fontSize
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
self.hideSendersNames = hideSendersNames
|
||||
|
||||
self.closeButton = ASButtonNode()
|
||||
self.closeButton.accessibilityLabel = strings.VoiceOver_DiscardPreparedContent
|
||||
@ -133,6 +144,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
var authors = ""
|
||||
var uniquePeerIds = Set<PeerId>()
|
||||
var text = ""
|
||||
var sourcePeer: (Bool, String)?
|
||||
for message in messages {
|
||||
if let author = message.effectiveAuthor, !uniquePeerIds.contains(author.id) {
|
||||
uniquePeerIds.insert(author.id)
|
||||
@ -141,6 +153,9 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
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 {
|
||||
let (string, _) = textStringForForwardedMessage(messages[0], strings: strings)
|
||||
@ -149,7 +164,15 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
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)
|
||||
|
||||
let headerString: String
|
||||
@ -178,20 +201,27 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
|
||||
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.strings = strings
|
||||
self.hideSendersNames = hideSendersNames
|
||||
|
||||
self.closeButton.setImage(PresentationResourcesChat.chatInputPanelCloseIconImage(theme), for: [])
|
||||
|
||||
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
||||
|
||||
if let text = self.titleNode.attributedText?.string {
|
||||
self.titleNode.attributedText = NSAttributedString(string: text, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor)
|
||||
if hideSendersNames {
|
||||
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 {
|
||||
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 {
|
||||
@ -208,14 +238,16 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
self.validLayout = (size, interfaceState)
|
||||
|
||||
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 rightInset: CGFloat = 55.0
|
||||
let textRightInset: CGFloat = 20.0
|
||||
|
||||
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)
|
||||
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))
|
||||
|
||||
@ -229,9 +261,28 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
|
||||
@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()
|
||||
}), 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?()
|
||||
})], actionLayout: .vertical)
|
||||
self.interfaceInteraction?.presentController(alertController, nil)
|
||||
@ -239,7 +290,11 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
|
||||
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
self.interfaceInteraction?.forwardCurrentForwardMessages()
|
||||
if self.closeButton.isHidden {
|
||||
self.interfaceInteraction?.updateForwardMessageHideSendersNames(!self.hideSendersNames)
|
||||
} else {
|
||||
self.closePressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,6 +379,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
forwardMessages()
|
||||
}, forwardCurrentForwardMessages: {
|
||||
}, forwardMessages: { _ in
|
||||
}, updateForwardMessageHideSendersNames: { _ in
|
||||
}, shareSelectedMessages: {
|
||||
shareMessages()
|
||||
}, updateTextInputStateAndMode: { _ in
|
||||
@ -5644,7 +5645,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
func forwardMessages(messageIds: Set<MessageId>?) {
|
||||
if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty {
|
||||
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 {
|
||||
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
|
||||
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
|
||||
return .forward(source: messageId, grouping: .auto, attributes: attributes, correlationId: nil)
|
||||
})
|
||||
|
||||
var displayPeers: [Peer] = []
|
||||
|
||||
@ -19,7 +19,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
|
||||
private var customTitle: String?
|
||||
|
||||
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 attemptSelection: ((Peer) -> Void)?
|
||||
@ -58,7 +58,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
|
||||
private let hasContactSelector: Bool
|
||||
private let hasGlobalSearch: Bool
|
||||
private let pretendPresentedInModal: Bool
|
||||
private let forwardedMessagesCount: Int
|
||||
private let forwardedMessageIds: [EngineMessage.Id]
|
||||
|
||||
override public var _presentedInModal: Bool {
|
||||
get {
|
||||
@ -86,7 +86,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
|
||||
self.attemptSelection = params.attemptSelection
|
||||
self.createNewGroup = params.createNewGroup
|
||||
self.pretendPresentedInModal = params.pretendPresentedInModal
|
||||
self.forwardedMessagesCount = params.forwardedMessagesCount
|
||||
self.forwardedMessageIds = params.forwardedMessageIds
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))
|
||||
|
||||
@ -150,7 +150,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
|
||||
}
|
||||
|
||||
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)
|
||||
}, presentInGlobalOverlay: { [weak self] c, a in
|
||||
self?.presentInGlobalOverlay(c, with: a)
|
||||
@ -160,8 +160,8 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
|
||||
|
||||
self.peerSelectionNode.navigationBar = self.navigationBar
|
||||
|
||||
self.peerSelectionNode.requestSend = { [weak self] peers, peerMap, text, mode in
|
||||
self?.multiplePeersSelected?(peers, peerMap, text, mode)
|
||||
self.peerSelectionNode.requestSend = { [weak self] peers, peerMap, text, mode, hideSendersNames in
|
||||
self?.multiplePeersSelected?(peers, peerMap, text, mode, hideSendersNames)
|
||||
}
|
||||
|
||||
self.peerSelectionNode.requestDeactivateSearch = { [weak self] in
|
||||
|
||||
@ -20,6 +20,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
private let dismiss: () -> Void
|
||||
private let filter: ChatListNodePeersFilter
|
||||
private let hasGlobalSearch: Bool
|
||||
private let forwardedMessageIds: [EngineMessage.Id]
|
||||
|
||||
private var presentationInterfaceState: ChatPresentationInterfaceState
|
||||
private var interfaceInteraction: ChatPanelInterfaceInteraction?
|
||||
@ -37,6 +38,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
private let segmentedControlNode: SegmentedControlNode?
|
||||
|
||||
private var textInputPanelNode: PeerSelectionTextInputPanelNode?
|
||||
private var forwardAccessoryPanelNode: ForwardAccessoryPanelNode?
|
||||
|
||||
var contactListNode: ContactListNode?
|
||||
let chatListNode: ChatListNode
|
||||
@ -56,7 +58,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
var requestOpenDisabledPeer: ((Peer) -> Void)?
|
||||
var requestOpenPeerFromSearch: ((Peer) -> 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 presentationDataDisposable: Disposable?
|
||||
@ -66,28 +68,21 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
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.present = present
|
||||
self.presentInGlobalOverlay = presentInGlobalOverlay
|
||||
self.dismiss = dismiss
|
||||
self.filter = filter
|
||||
self.hasGlobalSearch = hasGlobalSearch
|
||||
self.forwardedMessageIds = forwardedMessageIds
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
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)
|
||||
|
||||
var mockMessageIds: [MessageId]?
|
||||
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) }
|
||||
self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds) }
|
||||
|
||||
if hasChatListSelector && hasContactSelector {
|
||||
self.toolbarBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
|
||||
@ -198,6 +193,10 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
}, forwardSelectedMessages: {
|
||||
}, forwardCurrentForwardMessages: {
|
||||
}, forwardMessages: { _ in
|
||||
}, updateForwardMessageHideSendersNames: { [weak self] value in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageHideSendersNames(value) }) })
|
||||
}
|
||||
}, shareSelectedMessages: {
|
||||
}, updateTextInputStateAndMode: { [weak self] f in
|
||||
if let strongSelf = self {
|
||||
@ -335,6 +334,11 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
func beginSelection() {
|
||||
if let _ = self.textInputPanelNode {
|
||||
} 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) })
|
||||
textInputPanelNode.interfaceInteraction = self.interfaceInteraction
|
||||
textInputPanelNode.sendMessage = { [weak self] mode in
|
||||
@ -342,10 +346,13 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
|
||||
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
|
||||
let hideSendersNames = strongSelf.presentationInterfaceState.interfaceState.forwardMessageHideSendersNames
|
||||
|
||||
if strongSelf.contactListActive {
|
||||
strongSelf.contactListNode?.multipleSelection = true
|
||||
let selectedContactPeers = strongSelf.contactListNode?.selectedPeers ?? []
|
||||
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
|
||||
|
||||
var selectedPeers: [Peer] = []
|
||||
var selectedPeerMap: [PeerId: Peer] = [:]
|
||||
for contactPeer in selectedContactPeers {
|
||||
@ -355,7 +362,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
if !selectedPeers.isEmpty {
|
||||
strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode)
|
||||
strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode, hideSendersNames)
|
||||
}
|
||||
} else {
|
||||
var selectedPeerIds: [PeerId] = []
|
||||
@ -366,14 +373,13 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
return state
|
||||
}
|
||||
if !selectedPeerIds.isEmpty {
|
||||
let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText
|
||||
var selectedPeers: [Peer] = []
|
||||
for peerId in selectedPeerIds {
|
||||
if let peer = selectedPeerMap[peerId] {
|
||||
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 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 {
|
||||
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)
|
||||
if textInputPanelNode.frame.width.isZero {
|
||||
var initialPanelFrame = panelFrame
|
||||
initialPanelFrame.origin.y = layout.size.height
|
||||
initialPanelFrame.origin.y = layout.size.height + accessoryHeight
|
||||
textInputPanelNode.frame = initialPanelFrame
|
||||
}
|
||||
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 textPanelHeight = textPanelHeight {
|
||||
toolbarHeight = textPanelHeight
|
||||
toolbarHeight = textPanelHeight + accessoryHeight
|
||||
} else {
|
||||
toolbarHeight += 44.0
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ private final class FeaturedPackItemNode: ListViewItemNode {
|
||||
self.visibilityStatus = self.visibility != .none
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var visibilityStatus: Bool = false {
|
||||
didSet {
|
||||
if self.visibilityStatus != oldValue {
|
||||
@ -291,7 +291,7 @@ private final class FeaturedPackItemNode: ListViewItemNode {
|
||||
} else {
|
||||
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
|
||||
}
|
||||
@ -398,7 +398,7 @@ class StickerPaneTrendingListGridItemNode: GridItemNode {
|
||||
|
||||
override var isVisibleInGrid: Bool {
|
||||
didSet {
|
||||
|
||||
self.updateVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
@ -453,6 +453,10 @@ class StickerPaneTrendingListGridItemNode: GridItemNode {
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
func updateVisibility() {
|
||||
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
guard let item = self.item else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user