mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
no message
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
D06879571DB8F22200424BBD /* FetchCachedRepresentations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06879561DB8F22200424BBD /* FetchCachedRepresentations.swift */; };
|
||||
D073CE631DCBBE5D007511FD /* MessageSent.caf in Resources */ = {isa = PBXBuildFile; fileRef = D073CE621DCBBE5D007511FD /* MessageSent.caf */; };
|
||||
D073CE651DCBC26B007511FD /* ServiceSoundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE641DCBC26B007511FD /* ServiceSoundManager.swift */; };
|
||||
D073CE711DCBF23F007511FD /* DeclareEncodables.swift in Sources */ = {isa = PBXBuildFile; fileRef = D073CE701DCBF23F007511FD /* DeclareEncodables.swift */; };
|
||||
D07A7DA31D957671005BCD27 /* ListMessageSnippetItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07A7DA21D957671005BCD27 /* ListMessageSnippetItemNode.swift */; };
|
||||
D07A7DA51D95783C005BCD27 /* ListMessageNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07A7DA41D95783C005BCD27 /* ListMessageNode.swift */; };
|
||||
D07CFF741DCA207200761F81 /* PeerSelectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07CFF731DCA207200761F81 /* PeerSelectionController.swift */; };
|
||||
@@ -256,6 +257,7 @@
|
||||
D06879561DB8F22200424BBD /* FetchCachedRepresentations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchCachedRepresentations.swift; sourceTree = "<group>"; };
|
||||
D073CE621DCBBE5D007511FD /* MessageSent.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = MessageSent.caf; path = TelegramUI/Sounds/MessageSent.caf; sourceTree = "<group>"; };
|
||||
D073CE641DCBC26B007511FD /* ServiceSoundManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceSoundManager.swift; sourceTree = "<group>"; };
|
||||
D073CE701DCBF23F007511FD /* DeclareEncodables.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeclareEncodables.swift; sourceTree = "<group>"; };
|
||||
D07A7DA21D957671005BCD27 /* ListMessageSnippetItemNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListMessageSnippetItemNode.swift; sourceTree = "<group>"; };
|
||||
D07A7DA41D95783C005BCD27 /* ListMessageNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListMessageNode.swift; sourceTree = "<group>"; };
|
||||
D07CFF731DCA207200761F81 /* PeerSelectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerSelectionController.swift; sourceTree = "<group>"; };
|
||||
@@ -1106,6 +1108,7 @@
|
||||
D0B844571DAC44E8005F29E1 /* PeerPresenceStatusManager.swift */,
|
||||
D0ED5D4A1DC806D7007CBB15 /* ApplicationSpecificData.swift */,
|
||||
D073CE641DCBC26B007511FD /* ServiceSoundManager.swift */,
|
||||
D073CE701DCBF23F007511FD /* DeclareEncodables.swift */,
|
||||
);
|
||||
name = Utils;
|
||||
sourceTree = "<group>";
|
||||
@@ -1432,6 +1435,7 @@
|
||||
D0F69DFF1D6B8A880046BCD6 /* ChatListController.swift in Sources */,
|
||||
D0E7A1C11D8C258D00C37A6F /* ChatHistoryEntriesForView.swift in Sources */,
|
||||
D0F69DF11D6B8A6C0046BCD6 /* AuthorizationController.swift in Sources */,
|
||||
D073CE711DCBF23F007511FD /* DeclareEncodables.swift in Sources */,
|
||||
D0E7A1BF1D8C24B900C37A6F /* ChatHistoryViewForLocation.swift in Sources */,
|
||||
D0F69E891D6B8C850046BCD6 /* FastBlur.m in Sources */,
|
||||
D07CFF761DCA224100761F81 /* PeerSelectionControllerNode.swift in Sources */,
|
||||
|
||||
@@ -4,10 +4,4 @@ import AsyncDisplayKit
|
||||
class AccessoryPanelNode: ASDisplayNode {
|
||||
var dismiss: (() -> Void)?
|
||||
var interfaceInteraction: ChatPanelInterfaceInteraction?
|
||||
|
||||
var insets = UIEdgeInsets() {
|
||||
didSet {
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,7 +453,8 @@ public class ChatController: ViewController {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
let peerId = self.peerId
|
||||
let interfaceState = self.presentationInterfaceState.interfaceState
|
||||
let timestamp = Int32(Date().timeIntervalSince1970)
|
||||
let interfaceState = self.presentationInterfaceState.interfaceState.withUpdatedTimestamp(timestamp)
|
||||
self.account.postbox.modify({ modifier -> Void in
|
||||
modifier.updatePeerChatInterfaceState(peerId, update: { _ in
|
||||
return interfaceState
|
||||
|
||||
@@ -144,6 +144,10 @@ class ChatControllerNode: ASDisplayNode {
|
||||
if let inputNode = self.inputNode {
|
||||
previousInputHeight = inputNode.bounds.size.height
|
||||
}
|
||||
var previousInputPanelOrigin = CGPoint(x: 0.0, y: layout.size.height - previousInputHeight)
|
||||
if let inputPanelNode = self.inputPanelNode {
|
||||
previousInputPanelOrigin.y -= inputPanelNode.bounds.size.height
|
||||
}
|
||||
self.containerLayoutAndNavigationBarHeight = (layout, navigationBarHeight)
|
||||
|
||||
var dismissedInputNode: ChatInputNode?
|
||||
@@ -261,7 +265,6 @@ class ChatControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
immediatelyLayoutAccessoryPanelAndAnimateAppearance = true
|
||||
accessoryPanelNode.insets = UIEdgeInsets(top: 0.0, left: 45.0, bottom: 0.0, right: 54.0)
|
||||
}
|
||||
} else if let accessoryPanelNode = self.accessoryPanelNode {
|
||||
dismissedAccessoryPanelNode = self.accessoryPanelNode
|
||||
@@ -322,7 +325,9 @@ class ChatControllerNode: ASDisplayNode {
|
||||
|
||||
if let accessoryPanelNode = self.accessoryPanelNode, let accessoryPanelFrame = accessoryPanelFrame, !accessoryPanelNode.frame.equalTo(accessoryPanelFrame) {
|
||||
if immediatelyLayoutAccessoryPanelAndAnimateAppearance {
|
||||
accessoryPanelNode.frame = accessoryPanelFrame.offsetBy(dx: 0.0, dy: accessoryPanelFrame.size.height)
|
||||
var startAccessoryPanelFrame = accessoryPanelFrame
|
||||
startAccessoryPanelFrame.origin.y = previousInputPanelOrigin.y
|
||||
accessoryPanelNode.frame = startAccessoryPanelFrame
|
||||
accessoryPanelNode.alpha = 0.0
|
||||
}
|
||||
|
||||
|
||||
@@ -57,24 +57,59 @@ struct ChatTextInputState: Coding, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatEmbeddedInterfaceState: PeerChatListEmbeddedInterfaceState {
|
||||
let timestamp: Int32
|
||||
let text: String
|
||||
|
||||
init(timestamp: Int32, text: String) {
|
||||
self.timestamp = timestamp
|
||||
self.text = text
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.timestamp = decoder.decodeInt32ForKey("d")
|
||||
self.text = decoder.decodeStringForKey("t")
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
encoder.encodeInt32(self.timestamp, forKey: "d")
|
||||
encoder.encodeString(self.text, forKey: "t")
|
||||
}
|
||||
|
||||
public func isEqual(to: PeerChatListEmbeddedInterfaceState) -> Bool {
|
||||
if let to = to as? ChatEmbeddedInterfaceState {
|
||||
return self.timestamp == to.timestamp && self.text == to.text
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatInterfaceState: PeerChatInterfaceState, Equatable {
|
||||
let timestamp: Int32
|
||||
let inputState: ChatTextInputState
|
||||
let replyMessageId: MessageId?
|
||||
let forwardMessageIds: [MessageId]?
|
||||
let selectionState: ChatInterfaceSelectionState?
|
||||
|
||||
var chatListEmbeddedState: PeerChatListEmbeddedInterfaceState? {
|
||||
if !self.inputState.inputText.isEmpty && self.timestamp != 0 {
|
||||
return ChatEmbeddedInterfaceState(timestamp: self.timestamp, text: self.inputState.inputText)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
self.timestamp = 0
|
||||
self.inputState = ChatTextInputState()
|
||||
self.replyMessageId = nil
|
||||
self.forwardMessageIds = nil
|
||||
self.selectionState = nil
|
||||
}
|
||||
|
||||
init(inputState: ChatTextInputState, replyMessageId: MessageId?, forwardMessageIds: [MessageId]?, selectionState: ChatInterfaceSelectionState?) {
|
||||
init(timestamp: Int32, inputState: ChatTextInputState, replyMessageId: MessageId?, forwardMessageIds: [MessageId]?, selectionState: ChatInterfaceSelectionState?) {
|
||||
self.timestamp = timestamp
|
||||
self.inputState = inputState
|
||||
self.replyMessageId = replyMessageId
|
||||
self.forwardMessageIds = forwardMessageIds
|
||||
@@ -82,6 +117,7 @@ final class ChatInterfaceState: PeerChatInterfaceState, Equatable {
|
||||
}
|
||||
|
||||
init(decoder: Decoder) {
|
||||
self.timestamp = decoder.decodeInt32ForKey("ts")
|
||||
if let inputState = decoder.decodeObjectForKey("is", decoder: { return ChatTextInputState(decoder: $0) }) as? ChatTextInputState {
|
||||
self.inputState = inputState
|
||||
} else {
|
||||
@@ -108,6 +144,7 @@ final class ChatInterfaceState: PeerChatInterfaceState, Equatable {
|
||||
}
|
||||
|
||||
func encode(_ encoder: Encoder) {
|
||||
encoder.encodeInt32(self.timestamp, forKey: "ts")
|
||||
encoder.encodeObject(self.inputState, forKey: "is")
|
||||
if let replyMessageId = self.replyMessageId {
|
||||
encoder.encodeInt64(replyMessageId.peerId.toInt64(), forKey: "r.p")
|
||||
@@ -152,15 +189,15 @@ final class ChatInterfaceState: PeerChatInterfaceState, Equatable {
|
||||
}
|
||||
|
||||
func withUpdatedInputState(_ inputState: ChatTextInputState) -> ChatInterfaceState {
|
||||
return ChatInterfaceState(inputState: inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: self.selectionState)
|
||||
return ChatInterfaceState(timestamp: self.timestamp, inputState: inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: self.selectionState)
|
||||
}
|
||||
|
||||
func withUpdatedReplyMessageId(_ replyMessageId: MessageId?) -> ChatInterfaceState {
|
||||
return ChatInterfaceState(inputState: self.inputState, replyMessageId: replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: self.selectionState)
|
||||
return ChatInterfaceState(timestamp: self.timestamp, inputState: self.inputState, replyMessageId: replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: self.selectionState)
|
||||
}
|
||||
|
||||
func withUpdatedForwardMessageIds(_ forwardMessageIds: [MessageId]?) -> ChatInterfaceState {
|
||||
return ChatInterfaceState(inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: forwardMessageIds, selectionState: self.selectionState)
|
||||
return ChatInterfaceState(timestamp: self.timestamp, inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: forwardMessageIds, selectionState: self.selectionState)
|
||||
}
|
||||
|
||||
func withUpdatedSelectedMessage(_ messageId: MessageId) -> ChatInterfaceState {
|
||||
@@ -169,7 +206,7 @@ final class ChatInterfaceState: PeerChatInterfaceState, Equatable {
|
||||
selectedIds.formUnion(selectionState.selectedIds)
|
||||
}
|
||||
selectedIds.insert(messageId)
|
||||
return ChatInterfaceState(inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds))
|
||||
return ChatInterfaceState(timestamp: self.timestamp, inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds))
|
||||
}
|
||||
|
||||
func withToggledSelectedMessage(_ messageId: MessageId) -> ChatInterfaceState {
|
||||
@@ -182,10 +219,14 @@ final class ChatInterfaceState: PeerChatInterfaceState, Equatable {
|
||||
} else {
|
||||
selectedIds.insert(messageId)
|
||||
}
|
||||
return ChatInterfaceState(inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds))
|
||||
return ChatInterfaceState(timestamp: self.timestamp, inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: ChatInterfaceSelectionState(selectedIds: selectedIds))
|
||||
}
|
||||
|
||||
func withoutSelectionState() -> ChatInterfaceState {
|
||||
return ChatInterfaceState(inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: nil)
|
||||
return ChatInterfaceState(timestamp: self.timestamp, inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: nil)
|
||||
}
|
||||
|
||||
func withUpdatedTimestamp(_ timestamp: Int32) -> ChatInterfaceState {
|
||||
return ChatInterfaceState(timestamp: timestamp, inputState: self.inputState, replyMessageId: self.replyMessageId, forwardMessageIds: self.forwardMessageIds, selectionState: self.selectionState)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,22 +11,24 @@ class ChatListItem: ListViewItem {
|
||||
let message: Message
|
||||
let combinedReadState: CombinedPeerReadState?
|
||||
let notificationSettings: PeerNotificationSettings?
|
||||
let embeddedState: PeerChatListEmbeddedInterfaceState?
|
||||
let action: (Message) -> Void
|
||||
|
||||
let selectable: Bool = true
|
||||
|
||||
init(account: Account, message: Message, combinedReadState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, action: @escaping (Message) -> Void) {
|
||||
init(account: Account, message: Message, combinedReadState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, embeddedState: PeerChatListEmbeddedInterfaceState?, action: @escaping (Message) -> Void) {
|
||||
self.account = account
|
||||
self.message = message
|
||||
self.combinedReadState = combinedReadState
|
||||
self.notificationSettings = notificationSettings
|
||||
self.embeddedState = embeddedState
|
||||
self.action = action
|
||||
}
|
||||
|
||||
func nodeConfiguredForWidth(async: @escaping (@escaping () -> Void) -> Void, width: CGFloat, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> Void) -> Void) {
|
||||
async {
|
||||
let node = ChatListItemNode()
|
||||
node.setupItem(account: self.account, message: self.message, combinedReadState: self.combinedReadState, notificationSettings: self.notificationSettings)
|
||||
node.setupItem(account: self.account, message: self.message, combinedReadState: self.combinedReadState, notificationSettings: self.notificationSettings, embeddedState: self.embeddedState)
|
||||
node.relativePosition = (first: previousItem == nil, last: nextItem == nil)
|
||||
node.insets = ChatListItemNode.insets(first: node.relativePosition.first, last: node.relativePosition.last)
|
||||
node.layoutForWidth(width, item: self, previousItem: previousItem, nextItem: nextItem)
|
||||
@@ -38,7 +40,7 @@ class ChatListItem: ListViewItem {
|
||||
assert(node is ChatListItemNode)
|
||||
if let node = node as? ChatListItemNode {
|
||||
Queue.mainQueue().async {
|
||||
node.setupItem(account: self.account, message: self.message, combinedReadState: self.combinedReadState, notificationSettings: self.notificationSettings)
|
||||
node.setupItem(account: self.account, message: self.message, combinedReadState: self.combinedReadState, notificationSettings: self.notificationSettings, embeddedState: self.embeddedState)
|
||||
let layout = node.asyncLayout()
|
||||
async {
|
||||
let first = previousItem == nil
|
||||
@@ -115,6 +117,7 @@ class ChatListItemNode: ListViewItemNode {
|
||||
var message: Message?
|
||||
var combinedReadState: CombinedPeerReadState?
|
||||
var notificationSettings: PeerNotificationSettings?
|
||||
var embeddedState: PeerChatListEmbeddedInterfaceState?
|
||||
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let highlightedBackgroundNode: ASDisplayNode
|
||||
@@ -205,11 +208,12 @@ class ChatListItemNode: ListViewItemNode {
|
||||
self.contentNode.addSubnode(self.mutedIconNode)
|
||||
}
|
||||
|
||||
func setupItem(account: Account, message: Message, combinedReadState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?) {
|
||||
func setupItem(account: Account, message: Message, combinedReadState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, embeddedState: PeerChatListEmbeddedInterfaceState?) {
|
||||
self.account = account
|
||||
self.message = message
|
||||
self.combinedReadState = combinedReadState
|
||||
self.notificationSettings = notificationSettings
|
||||
self.embeddedState = embeddedState
|
||||
|
||||
let peer = message.peers[message.id.peerId]
|
||||
if let peer = peer {
|
||||
@@ -280,6 +284,7 @@ class ChatListItemNode: ListViewItemNode {
|
||||
let message = self.message
|
||||
let combinedReadState = self.combinedReadState
|
||||
let notificationSettings = self.notificationSettings
|
||||
let embeddedState = self.embeddedState
|
||||
|
||||
return { account, width, first, last in
|
||||
var textAttributedString: NSAttributedString?
|
||||
@@ -317,7 +322,12 @@ class ChatListItemNode: ListViewItemNode {
|
||||
}
|
||||
|
||||
let attributedText: NSAttributedString
|
||||
if let author = message.author as? TelegramUser, let peer = peer, peer as? TelegramUser == nil {
|
||||
if let embeddedState = embeddedState as? ChatEmbeddedInterfaceState {
|
||||
let mutableAttributedText = NSMutableAttributedString()
|
||||
mutableAttributedText.append(NSAttributedString(string: "Draft: ", font: textFont, textColor: UIColor(0xdd4b39)))
|
||||
mutableAttributedText.append(NSAttributedString(string: embeddedState.text, font: textFont, textColor: UIColor.black))
|
||||
attributedText = mutableAttributedText;
|
||||
} else if let author = message.author as? TelegramUser, let peer = peer, peer as? TelegramUser == nil {
|
||||
let peerText: NSString = (author.id == account?.peerId ? "You: " : author.compactDisplayTitle + ": ") as NSString
|
||||
|
||||
let mutableAttributedText = NSMutableAttributedString(string: peerText.appending(messageText as String), attributes: [kCTFontAttributeName as String: textFont])
|
||||
|
||||
@@ -37,10 +37,10 @@ private func mappedInsertEntries(account: Account, nodeInteraction: ChatListNode
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(placeholder: "Search for messages or users", activate: {
|
||||
nodeInteraction.activateSearch()
|
||||
}), directionHint: entry.directionHint)
|
||||
case let .MessageEntry(message, combinedReadState, notificationSettings):
|
||||
case let .MessageEntry(_, message, combinedReadState, notificationSettings, embeddedState):
|
||||
switch mode {
|
||||
case .chatList:
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(account: account, message: message, combinedReadState: combinedReadState, notificationSettings: notificationSettings, action: { _ in
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(account: account, message: message, combinedReadState: combinedReadState, notificationSettings: notificationSettings, embeddedState: embeddedState, action: { _ in
|
||||
nodeInteraction.peerSelected(message.id.peerId)
|
||||
}), directionHint: entry.directionHint)
|
||||
case .peers:
|
||||
@@ -63,10 +63,10 @@ private func mappedUpdateEntries(account: Account, nodeInteraction: ChatListNode
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(placeholder: "Search for messages or users", activate: {
|
||||
nodeInteraction.activateSearch()
|
||||
}), directionHint: entry.directionHint)
|
||||
case let .MessageEntry(message, combinedReadState, notificationSettings):
|
||||
case let .MessageEntry(_, message, combinedReadState, notificationSettings, embeddedState):
|
||||
switch mode {
|
||||
case .chatList:
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(account: account, message: message, combinedReadState: combinedReadState, notificationSettings: notificationSettings, action: { _ in
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(account: account, message: message, combinedReadState: combinedReadState, notificationSettings: notificationSettings, embeddedState: embeddedState, action: { _ in
|
||||
nodeInteraction.peerSelected(message.id.peerId)
|
||||
}), directionHint: entry.directionHint)
|
||||
case .peers:
|
||||
|
||||
@@ -62,7 +62,7 @@ enum ChatListNodeEntryId: Hashable, CustomStringConvertible {
|
||||
|
||||
enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
case SearchEntry
|
||||
case MessageEntry(Message, CombinedPeerReadState?, PeerNotificationSettings?)
|
||||
case MessageEntry(MessageIndex, Message, CombinedPeerReadState?, PeerNotificationSettings?, PeerChatListEmbeddedInterfaceState?)
|
||||
case HoleEntry(ChatListHole)
|
||||
case Nothing(MessageIndex)
|
||||
|
||||
@@ -70,8 +70,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
switch self {
|
||||
case .SearchEntry:
|
||||
return MessageIndex.absoluteUpperBound()
|
||||
case let .MessageEntry(message, _, _):
|
||||
return MessageIndex(message)
|
||||
case let .MessageEntry(index, _, _, _, _):
|
||||
return index
|
||||
case let .HoleEntry(hole):
|
||||
return hole.index
|
||||
case let .Nothing(index):
|
||||
@@ -83,8 +83,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
switch self {
|
||||
case .SearchEntry:
|
||||
return .Search
|
||||
case let .MessageEntry(message, _, _):
|
||||
return .PeerId(message.id.peerId.toInt64())
|
||||
case let .MessageEntry(index, _, _, _, _):
|
||||
return .PeerId(index.id.peerId.toInt64())
|
||||
case let .HoleEntry(hole):
|
||||
return .Hole(Int64(hole.index.id.id))
|
||||
case let .Nothing(index):
|
||||
@@ -105,9 +105,12 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case let .MessageEntry(lhsMessage, lhsUnreadCount, lhsNotificationSettings):
|
||||
case let .MessageEntry(lhsIndex, lhsMessage, lhsUnreadCount, lhsNotificationSettings, lhsEmbeddedState):
|
||||
switch rhs {
|
||||
case let .MessageEntry(rhsMessage, rhsUnreadCount, rhsNotificationSettings):
|
||||
case let .MessageEntry(rhsIndex, rhsMessage, rhsUnreadCount, rhsNotificationSettings, rhsEmbeddedState):
|
||||
if lhsIndex != rhsIndex {
|
||||
return false
|
||||
}
|
||||
if lhsMessage.id != rhsMessage.id || lhsMessage.flags != rhsMessage.flags || lhsUnreadCount != rhsUnreadCount {
|
||||
return false
|
||||
}
|
||||
@@ -118,6 +121,13 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
} else if (lhsNotificationSettings != nil) != (rhsNotificationSettings != nil) {
|
||||
return false
|
||||
}
|
||||
if let lhsEmbeddedState = lhsEmbeddedState, let rhsEmbeddedState = rhsEmbeddedState {
|
||||
if !lhsEmbeddedState.isEqual(to: rhsEmbeddedState) {
|
||||
return false
|
||||
}
|
||||
} else if (lhsEmbeddedState != nil) != (rhsEmbeddedState != nil) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
default:
|
||||
break
|
||||
@@ -145,8 +155,8 @@ func chatListNodeEntriesForView(_ view: ChatListView) -> [ChatListNodeEntry] {
|
||||
var result: [ChatListNodeEntry] = []
|
||||
for entry in view.entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(message, combinedReadState, notificationSettings):
|
||||
result.append(.MessageEntry(message, combinedReadState, notificationSettings))
|
||||
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState):
|
||||
result.append(.MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState))
|
||||
case let .HoleEntry(hole):
|
||||
result.append(.HoleEntry(hole))
|
||||
case let .Nothing(index):
|
||||
|
||||
@@ -59,7 +59,7 @@ final class ChatListSearchContainerNode: SearchDisplayControllerContentNode {
|
||||
for item in items {
|
||||
switch item {
|
||||
case let .message(message):
|
||||
listItems.append(ChatListItem(account: account, message: message, combinedReadState: nil, notificationSettings: nil, action: { [weak strongSelf] _ in
|
||||
listItems.append(ChatListItem(account: account, message: message, combinedReadState: nil, notificationSettings: nil, embeddedState: nil, action: { [weak strongSelf] _ in
|
||||
if let strongSelf = strongSelf, let peer = message.peers[message.id.peerId] {
|
||||
strongSelf.listNode.clearHighlightAnimated(true)
|
||||
strongSelf.openMessage(peer, message.id)
|
||||
|
||||
@@ -391,19 +391,23 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
if self.sendButton.alpha.isZero {
|
||||
self.sendButton.alpha = 1.0
|
||||
self.micButton.alpha = 0.0
|
||||
if animated {
|
||||
self.sendButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||
self.sendButton.layer.animateSpring(from: NSNumber(value: Float(0.1)), to: NSNumber(value: Float(1.0)), keyPath: "transform.scale", duration: 0.6)
|
||||
self.micButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.micButton.alpha.isZero {
|
||||
self.micButton.alpha = 1.0
|
||||
self.sendButton.alpha = 0.0
|
||||
if animated {
|
||||
self.micButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||
self.micButton.layer.animateSpring(from: NSNumber(value: Float(0.1)), to: NSNumber(value: Float(1.0)), keyPath: "transform.scale", duration: 0.6)
|
||||
self.sendButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (accessoryButtonsWidth, textFieldHeight) = self.calculateTextFieldMetrics(width: self.bounds.size.width)
|
||||
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight)
|
||||
|
||||
11
TelegramUI/DeclareEncodables.swift
Normal file
11
TelegramUI/DeclareEncodables.swift
Normal file
@@ -0,0 +1,11 @@
|
||||
import Postbox
|
||||
|
||||
private var telegramUIDeclaredEncodables: Void = {
|
||||
declareEncodable(ChatInterfaceState.self, f: { ChatInterfaceState(decoder: $0) })
|
||||
declareEncodable(ChatEmbeddedInterfaceState.self, f: { ChatEmbeddedInterfaceState(decoder: $0) })
|
||||
return
|
||||
}()
|
||||
|
||||
public func telegramUIDeclareEncodables() {
|
||||
let _ = telegramUIDeclaredEncodables
|
||||
}
|
||||
@@ -5,12 +5,26 @@ import Postbox
|
||||
import SwiftSignalKit
|
||||
import Display
|
||||
|
||||
private let lineImage = generateVerticallyStretchableFilledCircleImage(radius: 1.0, color: UIColor(0x007ee5))
|
||||
private let closeButtonImage = generateImage(CGSize(width: 12.0, height: 12.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setStrokeColor(UIColor(0x9099A2).cgColor)
|
||||
context.setLineWidth(2.0)
|
||||
context.setLineCap(.round)
|
||||
context.move(to: CGPoint(x: 1.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: size.width - 1.0, y: size.height - 1.0))
|
||||
context.strokePath()
|
||||
context.move(to: CGPoint(x: size.width - 1.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: 1.0, y: size.height - 1.0))
|
||||
context.strokePath()
|
||||
})
|
||||
|
||||
final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
private let messageDisposable = MetaDisposable()
|
||||
let messageIds: [MessageId]
|
||||
|
||||
let closeButton: ASButtonNode
|
||||
let lineNode: ASDisplayNode
|
||||
let lineNode: ASImageNode
|
||||
let titleNode: ASTextNode
|
||||
let textNode: ASTextNode
|
||||
|
||||
@@ -18,12 +32,14 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
self.messageIds = messageIds
|
||||
|
||||
self.closeButton = ASButtonNode()
|
||||
self.closeButton.setImage(UIImage(bundleImageName: "Chat/Input/Acessory Panels/CloseButton")?.precomposed(), for: [])
|
||||
self.closeButton.setImage(closeButtonImage, for: [])
|
||||
self.closeButton.hitTestSlop = UIEdgeInsetsMake(-8.0, -8.0, -8.0, -8.0)
|
||||
self.closeButton.displaysAsynchronously = false
|
||||
|
||||
self.lineNode = ASDisplayNode()
|
||||
self.lineNode.backgroundColor = UIColor(0x007ee5)
|
||||
self.lineNode = ASImageNode()
|
||||
self.lineNode.displayWithoutProcessing = true
|
||||
self.lineNode.displaysAsynchronously = false
|
||||
self.lineNode.image = lineImage
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.truncationMode = .byTruncatingTail
|
||||
@@ -65,8 +81,8 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
text = "\(messages.count) messages"
|
||||
}
|
||||
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: authors, font: Font.regular(14.5), textColor: UIColor(0x007ee5))
|
||||
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.5), textColor: UIColor.black)
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: authors, font: Font.medium(15.0), textColor: UIColor(0x007ee5))
|
||||
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: UIColor.black)
|
||||
|
||||
strongSelf.setNeedsLayout()
|
||||
}
|
||||
@@ -78,24 +94,28 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
|
||||
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
return CGSize(width: constrainedSize.width, height: 40.0)
|
||||
return CGSize(width: constrainedSize.width, height: 45.0)
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
|
||||
let bounds = self.bounds
|
||||
let leftInset: CGFloat = 55.0
|
||||
let textLineInset: CGFloat = 10.0
|
||||
let rightInset: CGFloat = 55.0
|
||||
let textRightInset: CGFloat = 20.0
|
||||
|
||||
let closeButtonSize = self.closeButton.measure(CGSize(width: 100.0, height: 100.0))
|
||||
self.closeButton.frame = CGRect(origin: CGPoint(x: bounds.size.width - self.insets.right - closeButtonSize.width, y: 12.0), size: closeButtonSize)
|
||||
self.closeButton.frame = CGRect(origin: CGPoint(x: bounds.size.width - rightInset - closeButtonSize.width, y: 19.0), size: closeButtonSize)
|
||||
|
||||
self.lineNode.frame = CGRect(origin: CGPoint(x: self.insets.left, y: 8.0), size: CGSize(width: 2.0, height: bounds.size.height - 5.0))
|
||||
self.lineNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 8.0), size: CGSize(width: 2.0, height: bounds.size.height - 10.0))
|
||||
|
||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - 11.0 - insets.left - insets.right - 14.0, height: bounds.size.height))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: self.insets.left + 11.0, y: 7.0), size: titleSize)
|
||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 7.0), size: titleSize)
|
||||
|
||||
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - 11.0 - insets.left - insets.right - 14.0, height: bounds.size.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: self.insets.left + 11.0, y: 25.0), size: textSize)
|
||||
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 25.0), size: textSize)
|
||||
}
|
||||
|
||||
@objc func closePressed() {
|
||||
|
||||
@@ -5,12 +5,26 @@ import Postbox
|
||||
import SwiftSignalKit
|
||||
import Display
|
||||
|
||||
private let lineImage = generateVerticallyStretchableFilledCircleImage(radius: 1.0, color: UIColor(0x007ee5))
|
||||
private let closeButtonImage = generateImage(CGSize(width: 12.0, height: 12.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setStrokeColor(UIColor(0x9099A2).cgColor)
|
||||
context.setLineWidth(2.0)
|
||||
context.setLineCap(.round)
|
||||
context.move(to: CGPoint(x: 1.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: size.width - 1.0, y: size.height - 1.0))
|
||||
context.strokePath()
|
||||
context.move(to: CGPoint(x: size.width - 1.0, y: 1.0))
|
||||
context.addLine(to: CGPoint(x: 1.0, y: size.height - 1.0))
|
||||
context.strokePath()
|
||||
})
|
||||
|
||||
final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
private let messageDisposable = MetaDisposable()
|
||||
let messageId: MessageId
|
||||
|
||||
let closeButton: ASButtonNode
|
||||
let lineNode: ASDisplayNode
|
||||
let lineNode: ASImageNode
|
||||
let titleNode: ASTextNode
|
||||
let textNode: ASTextNode
|
||||
|
||||
@@ -18,12 +32,14 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
self.messageId = messageId
|
||||
|
||||
self.closeButton = ASButtonNode()
|
||||
self.closeButton.setImage(UIImage(bundleImageName: "Chat/Input/Acessory Panels/CloseButton")?.precomposed(), for: [])
|
||||
self.closeButton.setImage(closeButtonImage, for: [])
|
||||
self.closeButton.hitTestSlop = UIEdgeInsetsMake(-8.0, -8.0, -8.0, -8.0)
|
||||
self.closeButton.displaysAsynchronously = false
|
||||
|
||||
self.lineNode = ASDisplayNode()
|
||||
self.lineNode.backgroundColor = UIColor(0x007ee5)
|
||||
self.lineNode = ASImageNode()
|
||||
self.lineNode.displayWithoutProcessing = true
|
||||
self.lineNode.displaysAsynchronously = false
|
||||
self.lineNode.image = lineImage
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.truncationMode = .byTruncatingTail
|
||||
@@ -56,8 +72,8 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
text = messageText
|
||||
}
|
||||
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: authorName, font: Font.regular(14.5), textColor: UIColor(0x007ee5))
|
||||
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.5), textColor: UIColor.black)
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: authorName, font: Font.medium(15.0), textColor: UIColor(0x007ee5))
|
||||
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: UIColor.black)
|
||||
|
||||
strongSelf.setNeedsLayout()
|
||||
}
|
||||
@@ -69,24 +85,28 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
|
||||
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
||||
return CGSize(width: constrainedSize.width, height: 40.0)
|
||||
return CGSize(width: constrainedSize.width, height: 45.0)
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
|
||||
let bounds = self.bounds
|
||||
let leftInset: CGFloat = 55.0
|
||||
let textLineInset: CGFloat = 10.0
|
||||
let rightInset: CGFloat = 55.0
|
||||
let textRightInset: CGFloat = 20.0
|
||||
|
||||
let closeButtonSize = self.closeButton.measure(CGSize(width: 100.0, height: 100.0))
|
||||
self.closeButton.frame = CGRect(origin: CGPoint(x: bounds.size.width - self.insets.right - closeButtonSize.width, y: 12.0), size: closeButtonSize)
|
||||
self.closeButton.frame = CGRect(origin: CGPoint(x: bounds.size.width - rightInset - closeButtonSize.width, y: 19.0), size: closeButtonSize)
|
||||
|
||||
self.lineNode.frame = CGRect(origin: CGPoint(x: self.insets.left, y: 8.0), size: CGSize(width: 2.0, height: bounds.size.height - 5.0))
|
||||
self.lineNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 8.0), size: CGSize(width: 2.0, height: bounds.size.height - 10.0))
|
||||
|
||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - 11.0 - insets.left - insets.right - 14.0, height: bounds.size.height))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: self.insets.left + 11.0, y: 7.0), size: titleSize)
|
||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 7.0), size: titleSize)
|
||||
|
||||
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - 11.0 - insets.left - insets.right - 14.0, height: bounds.size.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: self.insets.left + 11.0, y: 25.0), size: textSize)
|
||||
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 25.0), size: textSize)
|
||||
}
|
||||
|
||||
@objc func closePressed() {
|
||||
|
||||
Reference in New Issue
Block a user