Merge branch 'beta'

This commit is contained in:
Ali 2019-12-13 14:51:17 +04:00
commit 8568e31dda
62 changed files with 2735 additions and 2113 deletions

View file

@ -37,7 +37,7 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> {
|> mapToSignal { view -> Signal<[INMessage], NoError> in
var signals: [Signal<[INMessage], NoError>] = []
for entry in view.0.entries {
if case let .MessageEntry(index, _, readState, notificationSettings, _, _, _, _) = entry {
if case let .MessageEntry(index, _, readState, notificationSettings, _, _, _, _, _) = entry {
if index.messageIndex.id.peerId.namespace != Namespaces.Peer.CloudUser {
continue
}

View file

@ -5185,3 +5185,5 @@ Any member of this group will be able to see messages in the channel.";
"Theme.Colors.Proceed" = "Proceed";
"AuthSessions.AddDevice.UrlLoginHint" = "This code can be used to allow someone to log in to your Telegram account.\n\nTo confirm Telegram login, please go to Settings > Devices > Scan QR and scan the code.";
"ChatContextMenu.TextSelectionTip" = "Hold a word, then move cursor to select more| text to copy.";

View file

@ -1053,7 +1053,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
var sourceRect = selectedNode.view.superview!.convert(selectedNode.frame, to: sourceView)
sourceRect.size.height -= UIScreenPixel
switch item.content {
case let .peer(_, peer, _, _, _, _, _, _, _, _, _):
case let .peer(_, peer, _, _, _, _, _, _, _, _, _, _):
if peer.peerId.namespace != Namespaces.Peer.SecretChat {
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(peer.peerId), subject: nil, botStart: nil, mode: .standard(previewing: true))
chatController.canReadHistory.set(false)

View file

@ -472,7 +472,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
}
})
case let .message(message, peer, readState, presentationData):
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: enableHeaders ? ChatListSearchItemHeader(type: .messages, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: enableHeaders ? ChatListSearchItemHeader(type: .messages, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
case let .addContact(phoneNumber, theme, strings):
return ContactsAddItem(theme: theme, strings: strings, phoneNumber: phoneNumber, header: ChatListSearchItemHeader(type: .phoneNumber, theme: theme, strings: strings, actionTitle: nil, action: nil), action: {
interaction.addContact(phoneNumber)
@ -1332,7 +1332,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
bounds = selectedItemNode.bounds
}
switch item.content {
case let .peer(message, peer, _, _, _, _, _, _, _, _, _):
case let .peer(message, peer, _, _, _, _, _, _, _, _, _, _):
return (selectedItemNode.view, bounds, message?.id ?? peer.peerId)
case let .groupReference(groupId, _, _, _, _):
return (selectedItemNode.view, bounds, groupId)

View file

@ -20,12 +20,12 @@ import ChatListSearchItemNode
import ContextUI
public enum ChatListItemContent {
case peer(message: Message?, peer: RenderedPeer, combinedReadState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, embeddedState: PeerChatListEmbeddedInterfaceState?, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool, ignoreUnreadBadge: Bool, displayAsMessage: Bool)
case peer(message: Message?, peer: RenderedPeer, combinedReadState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, embeddedState: PeerChatListEmbeddedInterfaceState?, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool, ignoreUnreadBadge: Bool, displayAsMessage: Bool, hasFailedMessages: Bool)
case groupReference(groupId: PeerGroupId, peers: [ChatListGroupReferencePeer], message: Message?, unreadState: PeerGroupUnreadCountersCombinedSummary, hiddenByDefault: Bool)
public var chatLocation: ChatLocation? {
switch self {
case let .peer(_, peer, _, _, _, _, _, _, _, _, _):
case let .peer(_, peer, _, _, _, _, _, _, _, _, _, _):
return .peer(peer.peerId)
case .groupReference:
return nil
@ -38,7 +38,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
let context: AccountContext
let peerGroupId: PeerGroupId
let index: ChatListIndex
let content: ChatListItemContent
public let content: ChatListItemContent
let editing: Bool
let hasActiveRevealControls: Bool
let selected: Bool
@ -122,7 +122,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
public func selected(listView: ListView) {
switch self.content {
case let .peer(message, peer, _, _, _, _, _, _, isAd, _, _):
case let .peer(message, peer, _, _, _, _, _, _, isAd, _, _, _):
if let message = message, let peer = peer.peer {
self.interaction.messageSelected(peer, message, isAd)
} else if let peer = peer.peer {
@ -522,7 +522,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
var displayAsMessage = false
var enablePreview = true
switch item.content {
case let .peer(message, peerValue, _, _, _, _, _, _, _, _, displayAsMessageValue):
case let .peer(message, peerValue, _, _, _, _, _, _, _, _, displayAsMessageValue, _):
displayAsMessage = displayAsMessageValue
if displayAsMessage, let author = message?.author as? TelegramUser {
peer = author
@ -673,11 +673,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let isPeerGroup: Bool
let isAd: Bool
let displayAsMessage: Bool
let hasFailedMessages: Bool
var groupHiddenByDefault = false
switch item.content {
case let .peer(messageValue, peerValue, combinedReadStateValue, notificationSettingsValue, peerPresenceValue, summaryInfoValue, embeddedStateValue, inputActivitiesValue, isAdValue, ignoreUnreadBadge, displayAsMessageValue):
case let .peer(messageValue, peerValue, combinedReadStateValue, notificationSettingsValue, peerPresenceValue, summaryInfoValue, embeddedStateValue, inputActivitiesValue, isAdValue, ignoreUnreadBadge, displayAsMessageValue, hasFailedMessagesValue):
message = messageValue
contentPeer = .chat(peerValue)
combinedReadState = combinedReadStateValue
@ -698,6 +699,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
isPeerGroup = false
isAd = isAdValue
displayAsMessage = displayAsMessageValue
hasFailedMessages = hasFailedMessagesValue
case let .groupReference(_, peers, messageValue, unreadState, hiddenByDefault):
if let _ = messageValue, !peers.isEmpty {
contentPeer = .chat(peers[0].peer)
@ -717,6 +719,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
peerPresence = nil
isAd = false
displayAsMessage = false
hasFailedMessages = false
}
if let messageValue = message {
@ -975,7 +978,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
if message.flags.isSending && !message.isSentOrAcknowledged {
statusState = .clock(PresentationResourcesChatList.clockFrameImage(item.presentationData.theme), PresentationResourcesChatList.clockMinImage(item.presentationData.theme))
} else if message.id.peerId != account.peerId {
if message.flags.contains(.Failed) {
if hasFailedMessages {
statusState = .failed(item.presentationData.theme.chatList.failedFillColor, item.presentationData.theme.chatList.failedForegroundColor)
} else {
if let combinedReadState = combinedReadState, combinedReadState.isOutgoingMessageIndexRead(message.index) {
@ -1061,7 +1064,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
var credibilityIconOffset: CGFloat = 0.0
if displayAsMessage {
switch item.content {
case let .peer(message, _, _, _, _, _, _, _, _, _, _):
case let .peer(message, _, _, _, _, _, _, _, _, _, _, _):
if let peer = message?.author {
if peer.isScam {
currentCredibilityIconImage = PresentationResourcesChatList.scamIcon(item.presentationData.theme, type: .regular)
@ -1153,7 +1156,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let peerRevealOptions: [ItemListRevealOption]
let peerLeftRevealOptions: [ItemListRevealOption]
switch item.content {
case let .peer(_, renderedPeer, _, _, presence, _ ,_ ,_, _, _, displayAsMessage):
case let .peer(_, renderedPeer, _, _, presence, _ ,_ ,_, _, _, displayAsMessage, _):
if !displayAsMessage, let peer = renderedPeer.peer as? TelegramUser, let presence = presence as? TelegramUserPresence, !isServicePeer(peer) && !peer.flags.contains(.isSupport) && peer.id != item.context.account.peerId {
let relativeStatus = relativeUserPresenceStatus(presence, relativeTo: timestamp)
if case .online = relativeStatus {

View file

@ -141,10 +141,10 @@ public struct ChatListNodeState: Equatable {
private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatListNodeInteraction, peerGroupId: PeerGroupId, mode: ChatListNodeMode, entries: [ChatListNodeViewTransitionInsertEntry]) -> [ListViewInsertItem] {
return entries.map { entry -> ListViewInsertItem in
switch entry.entry {
case let .PeerEntry(index, presentationData, message, combinedReadState, notificationSettings, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd):
case let .PeerEntry(index, presentationData, message, combinedReadState, notificationSettings, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd, hasFailedMessages):
switch mode {
case .chatList:
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, notificationSettings: notificationSettings, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, notificationSettings: notificationSettings, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: hasFailedMessages), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
case let .peers(filter):
let itemPeer = peer.chatMainPeer
var chatPeer: Peer?
@ -222,10 +222,10 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatListNodeInteraction, peerGroupId: PeerGroupId, mode: ChatListNodeMode, entries: [ChatListNodeViewTransitionUpdateEntry]) -> [ListViewUpdateItem] {
return entries.map { entry -> ListViewUpdateItem in
switch entry.entry {
case let .PeerEntry(index, presentationData, message, combinedReadState, notificationSettings, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd):
case let .PeerEntry(index, presentationData, message, combinedReadState, notificationSettings, embeddedState, peer, presence, summaryInfo, editing, hasActiveRevealControls, selected, inputActivities, isAd, hasFailedMessages):
switch mode {
case .chatList:
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, notificationSettings: notificationSettings, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListItem(presentationData: presentationData, context: context, peerGroupId: peerGroupId, index: index, content: .peer(message: message, peer: peer, combinedReadState: combinedReadState, notificationSettings: notificationSettings, presence: presence, summaryInfo: summaryInfo, embeddedState: embeddedState, inputActivities: inputActivities, isAd: isAd, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: hasFailedMessages), editing: editing, hasActiveRevealControls: hasActiveRevealControls, selected: selected, header: nil, enableContextActions: true, hiddenOffset: false, interaction: nodeInteraction), directionHint: entry.directionHint)
case let .peers(filter):
let itemPeer = peer.chatMainPeer
var chatPeer: Peer?
@ -549,7 +549,7 @@ public final class ChatListNode: ListView {
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.view, state: state, savedMessagesPeer: savedMessagesPeer, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, mode: mode)
let entries = rawEntries.filter { entry in
switch entry {
case let .PeerEntry(_, _, _, _, _, _, peer, _, _, _, _, _, _, _):
case let .PeerEntry(_, _, _, _, _, _, peer, _, _, _, _, _, _, _, _):
switch mode {
case .chatList:
return true
@ -654,7 +654,7 @@ public final class ChatListNode: ListView {
var didIncludeHiddenByDefaultArchive = false
if let previous = previousView {
for entry in previous.filteredEntries {
if case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _) = entry {
if case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = entry {
if index.pinningIndex != nil {
previousPinnedChats.append(index.messageIndex.id.peerId)
}
@ -670,11 +670,11 @@ public final class ChatListNode: ListView {
var doesIncludeArchive = false
var doesIncludeHiddenByDefaultArchive = false
for entry in processedView.filteredEntries {
if case let .PeerEntry(index, _, _, _, _, _, _, _, _ , _, _, _, _, _) = entry {
if index.pinningIndex != nil {
updatedPinnedChats.append(index.messageIndex.id.peerId)
if case let .PeerEntry(peerEntry) = entry {
if peerEntry.index.pinningIndex != nil {
updatedPinnedChats.append(peerEntry.index.messageIndex.id.peerId)
}
if index.messageIndex.id.peerId == removingPeerId {
if peerEntry.index.messageIndex.id.peerId == removingPeerId {
doesIncludeRemovingPeerId = true
}
} else if case let .GroupReferenceEntry(entry) = entry {
@ -749,7 +749,7 @@ public final class ChatListNode: ListView {
continue
}
switch chatListView.filteredEntries[entryCount - i - 1] {
case let .PeerEntry(_, _, _, readState, notificationSettings, _, _, _, _, _, _, _, _, _):
case let .PeerEntry(_, _, _, readState, notificationSettings, _, _, _, _, _, _, _, _, _, _):
if let readState = readState {
let count = readState.count
rawUnreadCount += count
@ -895,7 +895,7 @@ public final class ChatListNode: ListView {
var referenceId: PinnedItemId?
var beforeAll = false
switch toEntry {
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, isAd):
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, isAd, _):
if isAd {
beforeAll = true
} else {
@ -913,7 +913,7 @@ public final class ChatListNode: ListView {
var itemId: PinnedItemId?
switch fromEntry {
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
itemId = .peer(index.messageIndex.id.peerId)
/*case let .GroupReferenceEntry(_, _, groupId, _, _, _, _):
itemId = .group(groupId)*/
@ -1338,7 +1338,7 @@ public final class ChatListNode: ListView {
continue
}
switch chatListView.filteredEntries[entryCount - i - 1] {
case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _):
case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _, _):
if interaction.highlightedChatLocation?.location == ChatLocation.peer(peer.peerId) {
current = (index, peer.peerId, entryCount - i - 1)
break outer
@ -1371,10 +1371,10 @@ public final class ChatListNode: ListView {
case .previous(unread: false), .next(unread: false):
var target: (ChatListIndex, PeerId)? = nil
if let current = current, entryCount > 1 {
if current.2 > 0, case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _) = chatListView.filteredEntries[current.2 - 1] {
if current.2 > 0, case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _, _) = chatListView.filteredEntries[current.2 - 1] {
next = (index, peer.peerId)
}
if current.2 <= entryCount - 2, case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _) = chatListView.filteredEntries[current.2 + 1] {
if current.2 <= entryCount - 2, case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _, _) = chatListView.filteredEntries[current.2 + 1] {
previous = (index, peer.peerId)
}
if case .previous = option {
@ -1383,7 +1383,7 @@ public final class ChatListNode: ListView {
target = next
}
} else if entryCount > 0 {
if case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _) = chatListView.filteredEntries[entryCount - 1] {
if case let .PeerEntry(index, _, _, _, _, _, peer, _, _, _, _, _, _, _, _) = chatListView.filteredEntries[entryCount - 1] {
target = (index, peer.peerId)
}
}
@ -1402,7 +1402,7 @@ public final class ChatListNode: ListView {
|> take(1)
|> deliverOnMainQueue).start(next: { update in
let entries = update.view.entries
if entries.count > index, case let .MessageEntry(index, _, _, _, _, renderedPeer, _, _) = entries[10 - index - 1] {
if entries.count > index, case let .MessageEntry(index, _, _, _, _, renderedPeer, _, _, _) = entries[10 - index - 1] {
let location: ChatListNodeLocation = .scroll(index: index, sourceIndex: .absoluteLowerBound, scrollPosition: .center(.top), animated: true)
self.setChatListLocation(location)
self.peerSelected?(renderedPeer.peerId, false, false)
@ -1445,7 +1445,7 @@ public final class ChatListNode: ListView {
continue
}
switch chatListView.filteredEntries[entryCount - i - 1] {
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
return index
default:
break

View file

@ -13,14 +13,14 @@ enum ChatListNodeEntryId: Hashable {
}
enum ChatListNodeEntry: Comparable, Identifiable {
case PeerEntry(index: ChatListIndex, presentationData: ChatListPresentationData, message: Message?, readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, peer: RenderedPeer, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool)
case PeerEntry(index: ChatListIndex, presentationData: ChatListPresentationData, message: Message?, readState: CombinedPeerReadState?, notificationSettings: PeerNotificationSettings?, embeddedInterfaceState: PeerChatListEmbeddedInterfaceState?, peer: RenderedPeer, presence: PeerPresence?, summaryInfo: ChatListMessageTagSummaryInfo, editing: Bool, hasActiveRevealControls: Bool, selected: Bool, inputActivities: [(Peer, PeerInputActivity)]?, isAd: Bool, hasFailedMessages: Bool)
case HoleEntry(ChatListHole, theme: PresentationTheme)
case GroupReferenceEntry(index: ChatListIndex, presentationData: ChatListPresentationData, groupId: PeerGroupId, peers: [ChatListGroupReferencePeer], message: Message?, editing: Bool, unreadState: PeerGroupUnreadCountersCombinedSummary, revealed: Bool, hiddenByDefault: Bool)
case ArchiveIntro(presentationData: ChatListPresentationData)
var sortIndex: ChatListIndex {
switch self {
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
return index
case let .HoleEntry(hole, _):
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
@ -33,7 +33,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
var stableId: ChatListNodeEntryId {
switch self {
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .PeerEntry(index, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
return .PeerId(index.messageIndex.id.peerId.toInt64())
case let .HoleEntry(hole, _):
return .Hole(Int64(hole.index.id.id))
@ -50,9 +50,9 @@ enum ChatListNodeEntry: Comparable, Identifiable {
static func ==(lhs: ChatListNodeEntry, rhs: ChatListNodeEntry) -> Bool {
switch lhs {
case let .PeerEntry(lhsIndex, lhsPresentationData, lhsMessage, lhsUnreadCount, lhsNotificationSettings, lhsEmbeddedState, lhsPeer, lhsPresence, lhsSummaryInfo, lhsEditing, lhsHasRevealControls, lhsSelected, lhsInputActivities, lhsAd):
case let .PeerEntry(lhsIndex, lhsPresentationData, lhsMessage, lhsUnreadCount, lhsNotificationSettings, lhsEmbeddedState, lhsPeer, lhsPresence, lhsSummaryInfo, lhsEditing, lhsHasRevealControls, lhsSelected, lhsInputActivities, lhsAd, lhsHasFailedMessages):
switch rhs {
case let .PeerEntry(rhsIndex, rhsPresentationData, rhsMessage, rhsUnreadCount, rhsNotificationSettings, rhsEmbeddedState, rhsPeer, rhsPresence, rhsSummaryInfo, rhsEditing, rhsHasRevealControls, rhsSelected, rhsInputActivities, rhsAd):
case let .PeerEntry(rhsIndex, rhsPresentationData, rhsMessage, rhsUnreadCount, rhsNotificationSettings, rhsEmbeddedState, rhsPeer, rhsPresence, rhsSummaryInfo, rhsEditing, rhsHasRevealControls, rhsSelected, rhsInputActivities, rhsAd, rhsHasFailedMessages):
if lhsIndex != rhsIndex {
return false
}
@ -119,7 +119,9 @@ enum ChatListNodeEntry: Comparable, Identifiable {
if lhsAd != rhsAd {
return false
}
if lhsHasFailedMessages != rhsHasFailedMessages {
return false
}
return true
default:
return false
@ -203,7 +205,7 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
}
loop: for entry in view.entries {
switch entry {
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo):
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed):
if let savedMessagesPeer = savedMessagesPeer, savedMessagesPeer.id == index.messageIndex.id.peerId {
continue loop
}
@ -216,7 +218,7 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
updatedMessage = nil
updatedCombinedReadState = nil
}
result.append(.PeerEntry(index: offsetPinnedIndex(index, offset: pinnedIndexOffset), presentationData: state.presentationData, message: updatedMessage, readState: updatedCombinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: false))
result.append(.PeerEntry(index: offsetPinnedIndex(index, offset: pinnedIndexOffset), presentationData: state.presentationData, message: updatedMessage, readState: updatedCombinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: false, hasFailedMessages: hasFailed))
case let .HoleEntry(hole):
if hole.index.timestamp == Int32.max - 1 {
return ([], true)
@ -228,13 +230,13 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
var pinningIndex: UInt16 = UInt16(pinnedIndexOffset == 0 ? 0 : (pinnedIndexOffset - 1))
if let savedMessagesPeer = savedMessagesPeer {
result.append(.PeerEntry(index: ChatListIndex.absoluteUpperBound.predecessor, presentationData: state.presentationData, message: nil, readState: nil, notificationSettings: nil, embeddedInterfaceState: nil, peer: RenderedPeer(peerId: savedMessagesPeer.id, peers: SimpleDictionary([savedMessagesPeer.id: savedMessagesPeer])), presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), editing: state.editing, hasActiveRevealControls: false, selected: false, inputActivities: nil, isAd: false))
result.append(.PeerEntry(index: ChatListIndex.absoluteUpperBound.predecessor, presentationData: state.presentationData, message: nil, readState: nil, notificationSettings: nil, embeddedInterfaceState: nil, peer: RenderedPeer(peerId: savedMessagesPeer.id, peers: SimpleDictionary([savedMessagesPeer.id: savedMessagesPeer])), presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), editing: state.editing, hasActiveRevealControls: false, selected: false, inputActivities: nil, isAd: false, hasFailedMessages: false))
} else {
if !view.additionalItemEntries.isEmpty {
for entry in view.additionalItemEntries.reversed() {
switch entry {
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo):
result.append(.PeerEntry(index: ChatListIndex(pinningIndex: pinningIndex, messageIndex: index.messageIndex), presentationData: state.presentationData, message: message, readState: combinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: true))
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed):
result.append(.PeerEntry(index: ChatListIndex(pinningIndex: pinningIndex, messageIndex: index.messageIndex), presentationData: state.presentationData, message: message, readState: combinedReadState, notificationSettings: notificationSettings, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: true, hasFailedMessages: hasFailed))
if pinningIndex != 0 {
pinningIndex -= 1
}

View file

@ -12,6 +12,7 @@ static_library(
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/TextSelectionNode:TextSelectionNode",
"//submodules/ReactionSelectionNode:ReactionSelectionNode",
"//submodules/AppBundle:AppBundle",
],
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",

View file

@ -2,6 +2,8 @@ import Foundation
import AsyncDisplayKit
import Display
import TelegramPresentationData
import TextSelectionNode
import AppBundle
private final class ContextActionsSelectionGestureRecognizer: UIPanGestureRecognizer {
var updateLocation: ((CGPoint, Bool) -> Void)?
@ -38,7 +40,7 @@ private enum ContextItemNode {
case separator(ASDisplayNode)
}
final class ContextActionsContainerNode: ASDisplayNode {
private final class InnerActionsContainerNode: ASDisplayNode {
private let presentationData: PresentationData
private var effectView: UIVisualEffectView?
private var itemNodes: [ContextItemNode]
@ -242,3 +244,179 @@ final class ContextActionsContainerNode: ASDisplayNode {
return nil
}
}
private final class InnerTextSelectionTipContainerNode: ASDisplayNode {
private let presentationData: PresentationData
private var effectView: UIVisualEffectView?
private let textNode: TextNode
private var textSelectionNode: TextSelectionNode?
private let iconNode: ASImageNode
private let text: String
private let targetSelectionIndex: Int
init(presentationData: PresentationData) {
self.presentationData = presentationData
self.textNode = TextNode()
var rawText = self.presentationData.strings.ChatContextMenu_TextSelectionTip
if let range = rawText.range(of: "|") {
rawText.removeSubrange(range)
self.text = rawText
self.targetSelectionIndex = NSRange(range, in: rawText).lowerBound
} else {
self.text = rawText
self.targetSelectionIndex = 1
}
self.iconNode = ASImageNode()
self.iconNode.displaysAsynchronously = false
self.iconNode.displayWithoutProcessing = true
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Tip"), color: presentationData.theme.contextMenu.primaryColor)
super.init()
self.clipsToBounds = true
self.cornerRadius = 14.0
self.backgroundColor = presentationData.theme.contextMenu.backgroundColor
let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: presentationData.theme.contextMenu.primaryColor.withAlphaComponent(0.15), knob: presentationData.theme.contextMenu.primaryColor, knobDiameter: 8.0), strings: presentationData.strings, textNode: self.textNode, updateIsActive: { _ in
}, present: { _, _ in
}, rootNode: self, performAction: { _, _ in
})
self.textSelectionNode = textSelectionNode
self.addSubnode(self.textNode)
self.addSubnode(self.iconNode)
self.textSelectionNode.flatMap(self.addSubnode)
self.addSubnode(textSelectionNode.highlightAreaNode)
}
func updateLayout(widthClass: ContainerViewLayoutSizeClass, width: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize {
switch widthClass {
case .compact:
if let effectView = self.effectView {
self.effectView = nil
effectView.removeFromSuperview()
}
case .regular:
if self.effectView == nil {
let effectView: UIVisualEffectView
if #available(iOS 13.0, *) {
if self.presentationData.theme.overallDarkAppearance {
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialDark))
} else {
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemMaterialLight))
}
} else if #available(iOS 10.0, *) {
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
} else {
effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
}
self.effectView = effectView
self.view.insertSubview(effectView, at: 0)
}
}
let verticalInset: CGFloat = 10.0
let horizontalInset: CGFloat = 16.0
let standardIconWidth: CGFloat = 32.0
let iconSideInset: CGFloat = 12.0
let textFont = Font.regular(floor(presentationData.fontSize.baseDisplaySize * 14.0 / 17.0))
let iconSize = self.iconNode.image?.size ?? CGSize(width: 16.0, height: 16.0)
let makeTextLayout = TextNode.asyncLayout(self.textNode)
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: self.text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor), backgroundColor: nil, minimumNumberOfLines: 0, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - horizontalInset * 2.0 - iconSize.width - 8.0, height: .greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets(), lineColor: nil, textShadowColor: nil, textStroke: nil))
let _ = textApply()
let textFrame = CGRect(origin: CGPoint(x: horizontalInset, y: verticalInset), size: textLayout.size)
transition.updateFrame(node: self.textNode, frame: textFrame)
let size = CGSize(width: width, height: textLayout.size.height + verticalInset * 2.0)
let iconFrame = CGRect(origin: CGPoint(x: size.width - standardIconWidth - iconSideInset + floor((standardIconWidth - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize)
transition.updateFrame(node: self.iconNode, frame: iconFrame)
if let textSelectionNode = self.textSelectionNode {
transition.updateFrame(node: textSelectionNode, frame: textFrame)
textSelectionNode.highlightAreaNode.frame = textFrame
}
if let effectView = self.effectView {
transition.updateFrame(view: effectView, frame: CGRect(origin: CGPoint(), size: size))
}
return size
}
func updateTheme(presentationData: PresentationData) {
self.backgroundColor = presentationData.theme.contextMenu.backgroundColor
}
func animateIn() {
if let textSelectionNode = self.textSelectionNode {
textSelectionNode.pretendInitiateSelection()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5, execute: { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.textSelectionNode?.pretendExtendSelection(to: strongSelf.targetSelectionIndex)
})
}
}
}
final class ContextActionsContainerNode: ASDisplayNode {
private let actionsNode: InnerActionsContainerNode
private let textSelectionTipNode: InnerTextSelectionTipContainerNode?
init(presentationData: PresentationData, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void, feedbackTap: @escaping () -> Void, displayTextSelectionTip: Bool) {
self.actionsNode = InnerActionsContainerNode(presentationData: presentationData, items: items, getController: getController, actionSelected: actionSelected, feedbackTap: feedbackTap)
if displayTextSelectionTip {
let textSelectionTipNode = InnerTextSelectionTipContainerNode(presentationData: presentationData)
textSelectionTipNode.isUserInteractionEnabled = false
self.textSelectionTipNode = textSelectionTipNode
} else {
self.textSelectionTipNode = nil
}
super.init()
self.addSubnode(self.actionsNode)
self.textSelectionTipNode.flatMap(self.addSubnode)
}
func updateLayout(widthClass: ContainerViewLayoutSizeClass, constrainedWidth: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize {
let actionsSize = self.actionsNode.updateLayout(widthClass: widthClass, constrainedWidth: constrainedWidth, transition: transition)
var contentSize = actionsSize
transition.updateFrame(node: self.actionsNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: actionsSize))
if let textSelectionTipNode = self.textSelectionTipNode {
contentSize.height += 8.0
let textSelectionTipSize = textSelectionTipNode.updateLayout(widthClass: widthClass, width: actionsSize.width, transition: transition)
transition.updateFrame(node: textSelectionTipNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentSize.height), size: textSelectionTipSize))
contentSize.height += textSelectionTipSize.height
}
return contentSize
}
func actionNode(at point: CGPoint) -> ContextActionNode? {
return self.actionsNode.actionNode(at: self.view.convert(point, to: self.actionsNode.view))
}
func updateTheme(presentationData: PresentationData) {
self.actionsNode.updateTheme(presentationData: presentationData)
self.textSelectionTipNode?.updateTheme(presentationData: presentationData)
}
func animateIn() {
self.textSelectionTipNode?.animateIn()
}
}

View file

@ -69,6 +69,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
private let attemptTransitionControllerIntoNavigation: () -> Void
private let getController: () -> ContextController?
private weak var gesture: ContextGesture?
private var displayTextSelectionTip: Bool
private var didSetItemsReady = false
let itemsReady = Promise<Bool>()
@ -107,7 +108,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
private let itemsDisposable = MetaDisposable()
init(account: Account, controller: ContextController, presentationData: PresentationData, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], beginDismiss: @escaping (ContextMenuActionResult) -> Void, recognizer: TapLongTapOrDoubleTapGestureRecognizer?, gesture: ContextGesture?, reactionSelected: @escaping (String) -> Void, beganAnimatingOut: @escaping () -> Void, attemptTransitionControllerIntoNavigation: @escaping () -> Void) {
init(account: Account, controller: ContextController, presentationData: PresentationData, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], beginDismiss: @escaping (ContextMenuActionResult) -> Void, recognizer: TapLongTapOrDoubleTapGestureRecognizer?, gesture: ContextGesture?, reactionSelected: @escaping (String) -> Void, beganAnimatingOut: @escaping () -> Void, attemptTransitionControllerIntoNavigation: @escaping () -> Void, displayTextSelectionTip: Bool) {
self.presentationData = presentationData
self.source = source
self.items = items
@ -116,6 +117,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
self.beganAnimatingOut = beganAnimatingOut
self.attemptTransitionControllerIntoNavigation = attemptTransitionControllerIntoNavigation
self.gesture = gesture
self.displayTextSelectionTip = displayTextSelectionTip
self.getController = { [weak controller] in
return controller
@ -163,7 +165,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
beginDismiss(result)
}, feedbackTap: {
feedbackTap?()
})
}, displayTextSelectionTip: self.displayTextSelectionTip)
if !reactionItems.isEmpty {
let reactionContextNode = ReactionContextNode(account: account, theme: presentationData.theme, items: reactionItems)
@ -528,6 +530,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
}, completion: { [weak self] in
self?.didCompleteAnimationIn = true
self?.hapticFeedback.prepareTap()
self?.actionsContainerNode.animateIn()
})
}
} else {
@ -535,6 +538,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
self.effectView.effect = makeCustomZoomBlurEffect()
}, completion: { [weak self] _ in
self?.didCompleteAnimationIn = true
self?.actionsContainerNode.animateIn()
})
}
@ -970,7 +974,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
self?.beginDismiss(result)
}, feedbackTap: { [weak self] in
self?.hapticFeedback.tap()
})
}, displayTextSelectionTip: self.displayTextSelectionTip)
self.scrollNode.insertSubnode(self.actionsContainerNode, aboveSubnode: previousActionsContainerNode)
if let layout = self.validLayout {
@ -982,6 +986,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
if !self.didSetItemsReady {
self.didSetItemsReady = true
self.displayTextSelectionTip = false
self.itemsReady.set(.single(true))
}
}
@ -1374,6 +1379,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
private weak var recognizer: TapLongTapOrDoubleTapGestureRecognizer?
private weak var gesture: ContextGesture?
private let displayTextSelectionTip: Bool
private var animatedDidAppear = false
private var wasDismissed = false
@ -1384,7 +1390,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
public var reactionSelected: ((String) -> Void)?
public init(account: Account, presentationData: PresentationData, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil) {
public init(account: Account, presentationData: PresentationData, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil, displayTextSelectionTip: Bool = false) {
self.account = account
self.presentationData = presentationData
self.source = source
@ -1392,6 +1398,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
self.reactionItems = reactionItems
self.recognizer = recognizer
self.gesture = gesture
self.displayTextSelectionTip = displayTextSelectionTip
super.init(navigationBarPresentationData: nil)
@ -1425,7 +1432,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
default:
break
}
})
}, displayTextSelectionTip: self.displayTextSelectionTip)
self.displayNodeDidLoad()

View file

@ -440,7 +440,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
case let .phoneNumberShareViaExceptionInfo(_, theme, text):
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
case let .editingPhoneNumber(_, theme, strings, id, title, label, value, hasActiveRevealControls):
return UserInfoEditingPhoneItem(theme: theme, strings: strings, id: id, label: title, value: value, editing: UserInfoEditingPhoneItemEditing(editable: true, hasActiveRevealControls: hasActiveRevealControls), sectionId: self.section, setPhoneIdWithRevealedOptions: { lhs, rhs in
return UserInfoEditingPhoneItem(presentationData: presentationData, id: id, label: title, value: value, editing: UserInfoEditingPhoneItemEditing(editable: true, hasActiveRevealControls: hasActiveRevealControls), sectionId: self.section, setPhoneIdWithRevealedOptions: { lhs, rhs in
arguments.setPhoneIdWithRevealedOptions(lhs, rhs)
}, updated: { value in
arguments.updatePhone(id, value)
@ -450,7 +450,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
arguments.deletePhone(id)
}, tag: DeviceContactInfoEntryTag.editingPhone(id))
case let .addPhoneNumber(_, theme, title):
return UserInfoEditingPhoneActionItem(theme: theme, title: title, sectionId: self.section, action: {
return UserInfoEditingPhoneActionItem(presentationData: presentationData, title: title, sectionId: self.section, action: {
arguments.addPhoneNumber()
})
case let .email(_, index, theme, title, label, value, selected):

View file

@ -634,7 +634,7 @@ private func userInfoEntries(account: Account, presentationData: PresentationDat
}
}
if !found {
entries.append(UserInfoEntry.phoneNumber(presentationData.theme, index, "home", formattedNumber, false))
entries.append(UserInfoEntry.phoneNumber(presentationData.theme, index, presentationData.strings.ContactInfo_PhoneLabelMobile, formattedNumber, false))
index += 1
} else {
for (label, number, isMain) in phoneNumbers {

View file

@ -8,13 +8,13 @@ import ItemListUI
import PresentationDataUtils
class UserInfoEditingPhoneActionItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let presentationData: ItemListPresentationData
let title: String
let sectionId: ItemListSectionId
let action: () -> Void
init(theme: PresentationTheme, title: String, sectionId: ItemListSectionId, action: @escaping () -> Void, tag: Any? = nil) {
self.theme = theme
init(presentationData: ItemListPresentationData, title: String, sectionId: ItemListSectionId, action: @escaping () -> Void, tag: Any? = nil) {
self.presentationData = presentationData
self.title = title
self.sectionId = sectionId
self.action = action
@ -61,8 +61,6 @@ class UserInfoEditingPhoneActionItem: ListViewItem, ItemListItem {
}
}
private let titleFont = Font.regular(15.0)
class UserInfoEditingPhoneActionItemNode: ListViewItemNode {
private let backgroundNode: ASDisplayNode
private let topStripeNode: ASDisplayNode
@ -114,15 +112,17 @@ class UserInfoEditingPhoneActionItemNode: ListViewItemNode {
let currentItem = self.item
return { item, params, neighbors in
let titleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
var updatedTheme: PresentationTheme?
if currentItem?.theme !== item.theme {
updatedTheme = item.theme
if currentItem?.presentationData.theme !== item.presentationData.theme {
updatedTheme = item.presentationData.theme
}
let textColor = item.theme.list.itemAccentColor
let textColor = item.presentationData.theme.list.itemAccentColor
let iconImage = PresentationResourcesItemList.addPhoneIcon(item.theme)
let iconImage = PresentationResourcesItemList.addPhoneIcon(item.presentationData.theme)
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: textColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@ -133,9 +133,9 @@ class UserInfoEditingPhoneActionItemNode: ListViewItemNode {
let itemBackgroundColor: UIColor
let itemSeparatorColor: UIColor
itemBackgroundColor = item.theme.list.plainBackgroundColor
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
contentSize = CGSize(width: params.width, height: 44.0)
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
contentSize = CGSize(width: params.width, height: 22.0 + titleLayout.size.height)
insets = itemListNeighborsPlainInsets(neighbors)
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
@ -148,7 +148,7 @@ class UserInfoEditingPhoneActionItemNode: ListViewItemNode {
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
}
strongSelf.iconNode.image = iconImage

View file

@ -19,8 +19,7 @@ struct UserInfoEditingPhoneItemEditing {
}
class UserInfoEditingPhoneItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let strings: PresentationStrings
let presentationData: ItemListPresentationData
let id: Int64
let label: String
let value: String
@ -32,9 +31,8 @@ class UserInfoEditingPhoneItem: ListViewItem, ItemListItem {
let delete: () -> Void
let tag: ItemListItemTag?
init(theme: PresentationTheme, strings: PresentationStrings, id: Int64, label: String, value: String, editing: UserInfoEditingPhoneItemEditing, sectionId: ItemListSectionId, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, updated: @escaping (String) -> Void, selectLabel: (() -> Void)?, delete: @escaping () -> Void, tag: ItemListItemTag?) {
self.theme = theme
self.strings = strings
init(presentationData: ItemListPresentationData, id: Int64, label: String, value: String, editing: UserInfoEditingPhoneItemEditing, sectionId: ItemListSectionId, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, updated: @escaping (String) -> Void, selectLabel: (() -> Void)?, delete: @escaping () -> Void, tag: ItemListItemTag?) {
self.presentationData = presentationData
self.id = id
self.label = label
self.value = value
@ -83,8 +81,6 @@ class UserInfoEditingPhoneItem: ListViewItem, ItemListItem {
var selectable: Bool = false
}
private let titleFont = Font.regular(15.0)
class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, ItemListItemFocusableNode {
private let backgroundNode: ASDisplayNode
private let topStripeNode: ASDisplayNode
@ -184,9 +180,11 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
super.didLoad()
if let item = self.item {
self.phoneNode.numberField?.textField.textColor = item.theme.list.itemPrimaryTextColor
self.phoneNode.numberField?.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
self.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
self.phoneNode.numberField?.textField.textColor = item.presentationData.theme.list.itemPrimaryTextColor
self.phoneNode.numberField?.textField.keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
self.phoneNode.numberField?.textField.tintColor = item.presentationData.theme.list.itemAccentColor
let titleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
self.phoneNode.numberField?.textField.font = titleFont
}
}
@ -197,15 +195,17 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
let currentItem = self.item
return { item, params, neighbors in
let titleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
var updatedTheme: PresentationTheme?
if currentItem?.theme !== item.theme {
updatedTheme = item.theme
if currentItem?.presentationData.theme !== item.presentationData.theme {
updatedTheme = item.presentationData.theme
}
let controlSizeAndApply = editableControlLayout(item.theme, false)
let controlSizeAndApply = editableControlLayout(item.presentationData.theme, false)
let textColor = item.theme.list.itemAccentColor
let textColor = item.presentationData.theme.list.itemAccentColor
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label, font: titleFont, textColor: textColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@ -216,9 +216,9 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
let itemBackgroundColor: UIColor
let itemSeparatorColor: UIColor
itemBackgroundColor = item.theme.list.plainBackgroundColor
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
contentSize = CGSize(width: params.width, height: 44.0)
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
contentSize = CGSize(width: params.width, height: 22.0 + labelLayout.size.height)
insets = itemListNeighborsPlainInsets(neighbors)
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
@ -236,7 +236,8 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
strongSelf.phoneNode.numberField?.textField.textColor = updatedTheme.list.itemPrimaryTextColor
strongSelf.phoneNode.numberField?.textField.keyboardAppearance = updatedTheme.rootController.keyboardColor.keyboardAppearance
strongSelf.phoneNode.numberField?.textField.tintColor = item.theme.list.itemAccentColor
strongSelf.phoneNode.numberField?.textField.tintColor = item.presentationData.theme.list.itemAccentColor
strongSelf.phoneNode.numberField?.textField.font = titleFont
strongSelf.clearButton.setImage(generateClearIcon(color: updatedTheme.list.inputClearButtonColor), for: [])
}
@ -283,7 +284,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.strings.Common_Delete, icon: .none, color: item.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
}
})
}

View file

@ -88,12 +88,12 @@ public struct ChatListGroupReferenceEntry: Equatable {
}
public enum ChatListEntry: Comparable {
case MessageEntry(ChatListIndex, Message?, CombinedPeerReadState?, PeerNotificationSettings?, PeerChatListEmbeddedInterfaceState?, RenderedPeer, PeerPresence?, ChatListMessageTagSummaryInfo)
case MessageEntry(ChatListIndex, Message?, CombinedPeerReadState?, PeerNotificationSettings?, PeerChatListEmbeddedInterfaceState?, RenderedPeer, PeerPresence?, ChatListMessageTagSummaryInfo, Bool)
case HoleEntry(ChatListHole)
public var index: ChatListIndex {
switch self {
case let .MessageEntry(index, _, _, _, _, _, _, _):
case let .MessageEntry(index, _, _, _, _, _, _, _, _):
return index
case let .HoleEntry(hole):
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
@ -102,9 +102,9 @@ public enum ChatListEntry: Comparable {
public static func ==(lhs: ChatListEntry, rhs: ChatListEntry) -> Bool {
switch lhs {
case let .MessageEntry(lhsIndex, lhsMessage, lhsReadState, lhsSettings, lhsEmbeddedState, lhsPeer, lhsPresence, lhsInfo):
case let .MessageEntry(lhsIndex, lhsMessage, lhsReadState, lhsSettings, lhsEmbeddedState, lhsPeer, lhsPresence, lhsInfo, lhsHasFailed):
switch rhs {
case let .MessageEntry(rhsIndex, rhsMessage, rhsReadState, rhsSettings, rhsEmbeddedState, rhsPeer, rhsPresence, rhsInfo):
case let .MessageEntry(rhsIndex, rhsMessage, rhsReadState, rhsSettings, rhsEmbeddedState, rhsPeer, rhsPresence, rhsInfo, rhsHasFailed):
if lhsIndex != rhsIndex {
return false
}
@ -141,6 +141,9 @@ public enum ChatListEntry: Comparable {
if lhsInfo != rhsInfo {
return false
}
if lhsHasFailed != rhsHasFailed {
return false
}
return true
default:
return false
@ -178,7 +181,7 @@ private func processedChatListEntry(_ entry: MutableChatListEntry, cachedDataTab
enum MutableChatListEntry: Equatable {
case IntermediateMessageEntry(ChatListIndex, IntermediateMessage?, CombinedPeerReadState?, PeerChatListEmbeddedInterfaceState?)
case MessageEntry(ChatListIndex, Message?, CombinedPeerReadState?, PeerNotificationSettings?, PeerChatListEmbeddedInterfaceState?, RenderedPeer, PeerPresence?, ChatListMessageTagSummaryInfo)
case MessageEntry(ChatListIndex, Message?, CombinedPeerReadState?, PeerNotificationSettings?, PeerChatListEmbeddedInterfaceState?, RenderedPeer, PeerPresence?, ChatListMessageTagSummaryInfo, Bool)
case HoleEntry(ChatListHole)
init(_ intermediateEntry: ChatListIntermediateEntry, cachedDataTable: CachedPeerDataTable, readStateTable: MessageHistoryReadStateTable, messageHistoryTable: MessageHistoryTable) {
@ -194,7 +197,7 @@ enum MutableChatListEntry: Equatable {
switch self {
case let .IntermediateMessageEntry(index, _, _, _):
return index
case let .MessageEntry(index, _, _, _, _, _, _, _):
case let .MessageEntry(index, _, _, _, _, _, _, _, _):
return index
case let .HoleEntry(hole):
return ChatListIndex(pinningIndex: nil, messageIndex: hole.index)
@ -488,13 +491,13 @@ final class MutableChatListView {
if !updatedPeerNotificationSettings.isEmpty {
for i in 0 ..< self.entries.count {
switch self.entries[i] {
case let .MessageEntry(index, message, readState, _, embeddedState, peer, peerPresence, summaryInfo):
case let .MessageEntry(index, message, readState, _, embeddedState, peer, peerPresence, summaryInfo, hasFailed):
var notificationSettingsPeerId = peer.peerId
if let peer = peer.peers[peer.peerId], let associatedPeerId = peer.associatedPeerId {
notificationSettingsPeerId = associatedPeerId
}
if let settings = updatedPeerNotificationSettings[notificationSettingsPeerId] {
self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo)
self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo, hasFailed)
hasChanges = true
}
default:
@ -502,17 +505,35 @@ final class MutableChatListView {
}
}
}
if !transaction.updatedFailedMessagePeerIds.isEmpty {
for i in 0 ..< self.entries.count {
switch self.entries[i] {
case let .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo, previousHasFailed):
if transaction.updatedFailedMessagePeerIds.contains(index.messageIndex.id.peerId) {
let hasFailed = postbox.messageHistoryFailedTable.contains(peerId: index.messageIndex.id.peerId)
if previousHasFailed != hasFailed {
self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo, hasFailed)
hasChanges = true
}
}
default:
continue
}
}
}
if !updatedPeers.isEmpty {
for i in 0 ..< self.entries.count {
switch self.entries[i] {
case let .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo):
case let .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo, hasFailed):
var updatedMessage: Message?
if let message = message {
updatedMessage = updateMessagePeers(message, updatedPeers: updatedPeers)
}
let updatedPeer = updatedRenderedPeer(peer, updatedPeers: updatedPeers)
if updatedMessage != nil || updatedPeer != nil {
self.entries[i] = .MessageEntry(index, updatedMessage ?? message, readState, settings, embeddedState, updatedPeer ?? peer, peerPresence, summaryInfo)
self.entries[i] = .MessageEntry(index, updatedMessage ?? message, readState, settings, embeddedState, updatedPeer ?? peer, peerPresence, summaryInfo, hasFailed)
hasChanges = true
}
default:
@ -523,13 +544,13 @@ final class MutableChatListView {
if !updatedPeerPresences.isEmpty {
for i in 0 ..< self.entries.count {
switch self.entries[i] {
case let .MessageEntry(index, message, readState, settings, embeddedState, peer, _, summaryInfo):
case let .MessageEntry(index, message, readState, settings, embeddedState, peer, _, summaryInfo, hasFailed):
var presencePeerId = peer.peerId
if let peer = peer.peers[peer.peerId], let associatedPeerId = peer.associatedPeerId {
presencePeerId = associatedPeerId
}
if let presence = updatedPeerPresences[presencePeerId] {
self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, presence, summaryInfo)
self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, presence, summaryInfo, hasFailed)
hasChanges = true
}
default:
@ -540,7 +561,7 @@ final class MutableChatListView {
if !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageActionsSummaries.isEmpty {
for i in 0 ..< self.entries.count {
switch self.entries[i] {
case let .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, currentSummary):
case let .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, currentSummary, hasFailed):
var updatedTagSummaryCount: Int32?
var updatedActionsSummaryCount: Int32?
@ -561,7 +582,7 @@ final class MutableChatListView {
if updatedTagSummaryCount != nil || updatedActionsSummaryCount != nil {
let summaryInfo = ChatListMessageTagSummaryInfo(tagSummaryCount: updatedTagSummaryCount ?? currentSummary.tagSummaryCount, actionsSummaryCount: updatedActionsSummaryCount ?? currentSummary.actionsSummaryCount)
self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo)
self.entries[i] = .MessageEntry(index, message, readState, settings, embeddedState, peer, peerPresence, summaryInfo, hasFailed)
hasChanges = true
}
default:
@ -816,51 +837,48 @@ final class MutableChatListView {
private func renderEntry(_ entry: MutableChatListEntry, postbox: Postbox, renderMessage: (IntermediateMessage) -> Message, getPeer: (PeerId) -> Peer?, getPeerNotificationSettings: (PeerId) -> PeerNotificationSettings?, getPeerPresence: (PeerId) -> PeerPresence?) -> MutableChatListEntry? {
switch entry {
case let .IntermediateMessageEntry(index, message, combinedReadState, embeddedState):
let renderedMessage: Message?
if let message = message {
renderedMessage = renderMessage(message)
case let .IntermediateMessageEntry(index, message, combinedReadState, embeddedState):
let renderedMessage: Message?
if let message = message {
renderedMessage = renderMessage(message)
} else {
renderedMessage = nil
}
var peers = SimpleDictionary<PeerId, Peer>()
var notificationSettings: PeerNotificationSettings?
var presence: PeerPresence?
if let peer = getPeer(index.messageIndex.id.peerId) {
peers[peer.id] = peer
if let associatedPeerId = peer.associatedPeerId {
if let associatedPeer = getPeer(associatedPeerId) {
peers[associatedPeer.id] = associatedPeer
}
notificationSettings = getPeerNotificationSettings(associatedPeerId)
presence = getPeerPresence(associatedPeerId)
} else {
renderedMessage = nil
notificationSettings = getPeerNotificationSettings(index.messageIndex.id.peerId)
presence = getPeerPresence(index.messageIndex.id.peerId)
}
var peers = SimpleDictionary<PeerId, Peer>()
var notificationSettings: PeerNotificationSettings?
var presence: PeerPresence?
if let peer = getPeer(index.messageIndex.id.peerId) {
peers[peer.id] = peer
if let associatedPeerId = peer.associatedPeerId {
if let associatedPeer = getPeer(associatedPeerId) {
peers[associatedPeer.id] = associatedPeer
}
notificationSettings = getPeerNotificationSettings(associatedPeerId)
presence = getPeerPresence(associatedPeerId)
} else {
notificationSettings = getPeerNotificationSettings(index.messageIndex.id.peerId)
presence = getPeerPresence(index.messageIndex.id.peerId)
}
}
var tagSummaryCount: Int32?
var actionsSummaryCount: Int32?
if let tagSummary = self.summaryComponents.tagSummary {
let key = MessageHistoryTagsSummaryKey(tag: tagSummary.tag, peerId: index.messageIndex.id.peerId, namespace: tagSummary.namespace)
if let summary = postbox.messageHistoryTagsSummaryTable.get(key) {
tagSummaryCount = summary.count
}
var tagSummaryCount: Int32?
var actionsSummaryCount: Int32?
if let tagSummary = self.summaryComponents.tagSummary {
let key = MessageHistoryTagsSummaryKey(tag: tagSummary.tag, peerId: index.messageIndex.id.peerId, namespace: tagSummary.namespace)
if let summary = postbox.messageHistoryTagsSummaryTable.get(key) {
tagSummaryCount = summary.count
}
}
if let actionsSummary = self.summaryComponents.actionsSummary {
let key = PendingMessageActionsSummaryKey(type: actionsSummary.type, peerId: index.messageIndex.id.peerId, namespace: actionsSummary.namespace)
actionsSummaryCount = postbox.pendingMessageActionsMetadataTable.getCount(.peerNamespaceAction(key.peerId, key.namespace, key.type))
}
return .MessageEntry(index, renderedMessage, combinedReadState, notificationSettings, embeddedState, RenderedPeer(peerId: index.messageIndex.id.peerId, peers: peers), presence, ChatListMessageTagSummaryInfo(tagSummaryCount: tagSummaryCount, actionsSummaryCount: actionsSummaryCount))
/*case let .IntermediateGroupReferenceEntry(groupId, index, counters):
let message = postbox.messageHistoryTable.getMessage(index.messageIndex).flatMap(postbox.renderIntermediateMessage)
return .GroupReferenceEntry(groupId, index, message, ChatListGroupReferenceTopPeers(postbox: postbox, groupId: groupId), counters ?? ChatListGroupReferenceUnreadCounters(postbox: postbox, groupId: groupId))*/
default:
return nil
}
if let actionsSummary = self.summaryComponents.actionsSummary {
let key = PendingMessageActionsSummaryKey(type: actionsSummary.type, peerId: index.messageIndex.id.peerId, namespace: actionsSummary.namespace)
actionsSummaryCount = postbox.pendingMessageActionsMetadataTable.getCount(.peerNamespaceAction(key.peerId, key.namespace, key.type))
}
return .MessageEntry(index, renderedMessage, combinedReadState, notificationSettings, embeddedState, RenderedPeer(peerId: index.messageIndex.id.peerId, peers: peers), presence, ChatListMessageTagSummaryInfo(tagSummaryCount: tagSummaryCount, actionsSummaryCount: actionsSummaryCount), postbox.messageHistoryFailedTable.contains(peerId: index.messageIndex.id.peerId))
default:
return nil
}
}
@ -892,8 +910,8 @@ public final class ChatListView {
var entries: [ChatListEntry] = []
for entry in mutableView.entries {
switch entry {
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo):
entries.append(.MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo))
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed):
entries.append(.MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed))
case let .HoleEntry(hole):
entries.append(.HoleEntry(hole))
/*case let .GroupReferenceEntry(groupId, index, message, topPeers, counters):
@ -912,8 +930,8 @@ public final class ChatListView {
var additionalItemEntries: [ChatListEntry] = []
for entry in mutableView.additionalItemEntries {
switch entry {
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo):
additionalItemEntries.append(.MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo))
case let .MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed):
additionalItemEntries.append(.MessageEntry(index, message, combinedReadState, notificationSettings, embeddedState, peer, peerPresence, summaryInfo, hasFailed))
case .HoleEntry:
assertionFailure()
/*case .GroupReferenceEntry:

View file

@ -0,0 +1,55 @@
import Foundation
final class MessageHistoryFailedTable: Table {
static func tableSpec(_ id: Int32) -> ValueBoxTable {
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: true)
}
private let sharedKey = ValueBoxKey(length: 8 + 4 + 4)
private(set) var updatedPeerIds = Set<PeerId>()
private func key(_ id: MessageId) -> ValueBoxKey {
self.sharedKey.setInt64(0, value: id.peerId.toInt64())
self.sharedKey.setInt32(8, value: id.namespace)
self.sharedKey.setInt32(8 + 4, value: id.id)
return self.sharedKey
}
private func lowerBound(peerId: PeerId) -> ValueBoxKey {
let key = ValueBoxKey(length: 8)
key.setInt64(0, value: peerId.toInt64())
return key
}
private func upperBound(peerId: PeerId) -> ValueBoxKey {
let key = ValueBoxKey(length: 8)
key.setInt64(0, value: peerId.toInt64())
return key.successor
}
func add(_ id: MessageId) {
self.valueBox.set(self.table, key: self.key(id), value: MemoryBuffer())
self.updatedPeerIds.insert(id.peerId)
}
func remove(_ id: MessageId) {
self.valueBox.remove(self.table, key: self.key(id), secure: false)
self.updatedPeerIds.insert(id.peerId)
}
func contains(peerId: PeerId) -> Bool {
var result = false
self.valueBox.range(self.table, start: self.lowerBound(peerId: peerId), end: self.upperBound(peerId: peerId), keys: { _ in
result = true
return false
}, limit: 1)
return result
}
override func beforeCommit() {
self.updatedPeerIds.removeAll()
}
}

View file

@ -69,6 +69,7 @@ final class MessageHistoryTable: Table {
let historyMetadataTable: MessageHistoryMetadataTable
let globallyUniqueMessageIdsTable: MessageGloballyUniqueIdTable
let unsentTable: MessageHistoryUnsentTable
let failedTable: MessageHistoryFailedTable
let tagsTable: MessageHistoryTagsTable
let globalTagsTable: GlobalMessageHistoryTagsTable
let localTagsTable: LocalMessageHistoryTagsTable
@ -78,7 +79,7 @@ final class MessageHistoryTable: Table {
let summaryTable: MessageHistoryTagsSummaryTable
let pendingActionsTable: PendingMessageActionsTable
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration, messageHistoryIndexTable: MessageHistoryIndexTable, messageHistoryHoleIndexTable: MessageHistoryHoleIndexTable, messageMediaTable: MessageMediaTable, historyMetadataTable: MessageHistoryMetadataTable, globallyUniqueMessageIdsTable: MessageGloballyUniqueIdTable, unsentTable: MessageHistoryUnsentTable, tagsTable: MessageHistoryTagsTable, globalTagsTable: GlobalMessageHistoryTagsTable, localTagsTable: LocalMessageHistoryTagsTable, readStateTable: MessageHistoryReadStateTable, synchronizeReadStateTable: MessageHistorySynchronizeReadStateTable, textIndexTable: MessageHistoryTextIndexTable, summaryTable: MessageHistoryTagsSummaryTable, pendingActionsTable: PendingMessageActionsTable) {
init(valueBox: ValueBox, table: ValueBoxTable, seedConfiguration: SeedConfiguration, messageHistoryIndexTable: MessageHistoryIndexTable, messageHistoryHoleIndexTable: MessageHistoryHoleIndexTable, messageMediaTable: MessageMediaTable, historyMetadataTable: MessageHistoryMetadataTable, globallyUniqueMessageIdsTable: MessageGloballyUniqueIdTable, unsentTable: MessageHistoryUnsentTable, failedTable: MessageHistoryFailedTable, tagsTable: MessageHistoryTagsTable, globalTagsTable: GlobalMessageHistoryTagsTable, localTagsTable: LocalMessageHistoryTagsTable, readStateTable: MessageHistoryReadStateTable, synchronizeReadStateTable: MessageHistorySynchronizeReadStateTable, textIndexTable: MessageHistoryTextIndexTable, summaryTable: MessageHistoryTagsSummaryTable, pendingActionsTable: PendingMessageActionsTable) {
self.seedConfiguration = seedConfiguration
self.messageHistoryIndexTable = messageHistoryIndexTable
self.messageHistoryHoleIndexTable = messageHistoryHoleIndexTable
@ -86,6 +87,7 @@ final class MessageHistoryTable: Table {
self.historyMetadataTable = historyMetadataTable
self.globallyUniqueMessageIdsTable = globallyUniqueMessageIdsTable
self.unsentTable = unsentTable
self.failedTable = failedTable
self.tagsTable = tagsTable
self.globalTagsTable = globalTagsTable
self.localTagsTable = localTagsTable
@ -249,6 +251,9 @@ final class MessageHistoryTable: Table {
if message.flags.contains(.Unsent) && !message.flags.contains(.Failed) {
self.unsentTable.add(message.id, operations: &unsentMessageOperations)
}
if message.flags.contains(.Failed) {
self.failedTable.add(message.id)
}
let tags = message.tags.rawValue
if tags != 0 {
for i in 0 ..< 32 {
@ -1194,6 +1199,9 @@ final class MessageHistoryTable: Table {
if message.flags.contains(.Unsent) && !message.flags.contains(.Failed) {
self.unsentTable.remove(index.id, operations: &unsentMessageOperations)
}
if message.flags.contains(.Failed) {
self.failedTable.remove(message.id)
}
if let globallyUniqueId = message.globallyUniqueId {
self.globallyUniqueMessageIdsTable.remove(peerId: message.id.peerId, globallyUniqueId: globallyUniqueId)
@ -1447,6 +1455,23 @@ final class MessageHistoryTable: Table {
break
}
if previousMessage.id != message.id {
if previousMessage.flags.contains(.Failed) {
self.failedTable.remove(previousMessage.id)
}
if message.flags.contains(.Failed) {
self.failedTable.add(message.id)
}
} else {
if previousMessage.flags.contains(.Failed) != message.flags.contains(.Failed) {
if previousMessage.flags.contains(.Failed) {
self.failedTable.remove(previousMessage.id)
} else {
self.failedTable.add(message.id)
}
}
}
if self.seedConfiguration.peerNamespacesRequiringMessageTextIndex.contains(message.id.peerId.namespace) {
if previousMessage.id != message.id || previousMessage.text != message.text || previousMessage.tags != message.tags {
self.textIndexTable.remove(messageId: previousMessage.id)

View file

@ -1134,6 +1134,7 @@ public final class Postbox {
let additionalChatListItemsTable: AdditionalChatListItemsTable
let messageHistoryMetadataTable: MessageHistoryMetadataTable
let messageHistoryUnsentTable: MessageHistoryUnsentTable
let messageHistoryFailedTable: MessageHistoryFailedTable
let messageHistoryTagsTable: MessageHistoryTagsTable
let globalMessageHistoryTagsTable: GlobalMessageHistoryTagsTable
let localMessageHistoryTagsTable: LocalMessageHistoryTagsTable
@ -1211,6 +1212,7 @@ public final class Postbox {
self.messageHistoryMetadataTable = MessageHistoryMetadataTable(valueBox: self.valueBox, table: MessageHistoryMetadataTable.tableSpec(10))
self.messageHistoryHoleIndexTable = MessageHistoryHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryHoleIndexTable.tableSpec(56), metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
self.messageHistoryUnsentTable = MessageHistoryUnsentTable(valueBox: self.valueBox, table: MessageHistoryUnsentTable.tableSpec(11))
self.messageHistoryFailedTable = MessageHistoryFailedTable(valueBox: self.valueBox, table: MessageHistoryFailedTable.tableSpec(49))
self.invalidatedMessageHistoryTagsSummaryTable = InvalidatedMessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: InvalidatedMessageHistoryTagsSummaryTable.tableSpec(47))
self.messageHistoryTagsSummaryTable = MessageHistoryTagsSummaryTable(valueBox: self.valueBox, table: MessageHistoryTagsSummaryTable.tableSpec(44), invalidateTable: self.invalidatedMessageHistoryTagsSummaryTable)
self.pendingMessageActionsMetadataTable = PendingMessageActionsMetadataTable(valueBox: self.valueBox, table: PendingMessageActionsMetadataTable.tableSpec(45))
@ -1227,7 +1229,7 @@ public final class Postbox {
self.timestampBasedMessageAttributesTable = TimestampBasedMessageAttributesTable(valueBox: self.valueBox, table: TimestampBasedMessageAttributesTable.tableSpec(34), indexTable: self.timestampBasedMessageAttributesIndexTable)
self.textIndexTable = MessageHistoryTextIndexTable(valueBox: self.valueBox, table: MessageHistoryTextIndexTable.tableSpec(41))
self.additionalChatListItemsTable = AdditionalChatListItemsTable(valueBox: self.valueBox, table: AdditionalChatListItemsTable.tableSpec(55))
self.messageHistoryTable = MessageHistoryTable(valueBox: self.valueBox, table: MessageHistoryTable.tableSpec(7), seedConfiguration: seedConfiguration, messageHistoryIndexTable: self.messageHistoryIndexTable, messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, messageMediaTable: self.mediaTable, historyMetadataTable: self.messageHistoryMetadataTable, globallyUniqueMessageIdsTable: self.globallyUniqueMessageIdsTable, unsentTable: self.messageHistoryUnsentTable, tagsTable: self.messageHistoryTagsTable, globalTagsTable: self.globalMessageHistoryTagsTable, localTagsTable: self.localMessageHistoryTagsTable, readStateTable: self.readStateTable, synchronizeReadStateTable: self.synchronizeReadStateTable, textIndexTable: self.textIndexTable, summaryTable: self.messageHistoryTagsSummaryTable, pendingActionsTable: self.pendingMessageActionsTable)
self.messageHistoryTable = MessageHistoryTable(valueBox: self.valueBox, table: MessageHistoryTable.tableSpec(7), seedConfiguration: seedConfiguration, messageHistoryIndexTable: self.messageHistoryIndexTable, messageHistoryHoleIndexTable: self.messageHistoryHoleIndexTable, messageMediaTable: self.mediaTable, historyMetadataTable: self.messageHistoryMetadataTable, globallyUniqueMessageIdsTable: self.globallyUniqueMessageIdsTable, unsentTable: self.messageHistoryUnsentTable, failedTable: self.messageHistoryFailedTable, tagsTable: self.messageHistoryTagsTable, globalTagsTable: self.globalMessageHistoryTagsTable, localTagsTable: self.localMessageHistoryTagsTable, readStateTable: self.readStateTable, synchronizeReadStateTable: self.synchronizeReadStateTable, textIndexTable: self.textIndexTable, summaryTable: self.messageHistoryTagsSummaryTable, pendingActionsTable: self.pendingMessageActionsTable)
self.peerChatStateTable = PeerChatStateTable(valueBox: self.valueBox, table: PeerChatStateTable.tableSpec(13))
self.peerNameTokenIndexTable = ReverseIndexReferenceTable<PeerIdReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<PeerIdReverseIndexReference>.tableSpec(26))
self.peerNameIndexTable = PeerNameIndexTable(valueBox: self.valueBox, table: PeerNameIndexTable.tableSpec(27), peerTable: self.peerTable, peerNameTokenIndexTable: self.peerNameTokenIndexTable)
@ -1267,6 +1269,7 @@ public final class Postbox {
tables.append(self.globallyUniqueMessageIdsTable)
tables.append(self.messageHistoryMetadataTable)
tables.append(self.messageHistoryUnsentTable)
tables.append(self.messageHistoryFailedTable)
tables.append(self.messageHistoryTagsTable)
tables.append(self.globalMessageHistoryTagsTable)
tables.append(self.localMessageHistoryTagsTable)
@ -1700,7 +1703,7 @@ public final class Postbox {
let transactionParticipationInTotalUnreadCountUpdates = self.peerNotificationSettingsTable.transactionParticipationInTotalUnreadCountUpdates(postbox: self)
self.chatListIndexTable.commitWithTransaction(postbox: self, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, updatedPeers: updatedPeers, transactionParticipationInTotalUnreadCountUpdates: transactionParticipationInTotalUnreadCountUpdates, updatedRootUnreadState: &self.currentUpdatedTotalUnreadState, updatedGroupTotalUnreadSummaries: &self.currentUpdatedGroupTotalUnreadSummaries, currentUpdatedGroupSummarySynchronizeOperations: &self.currentUpdatedGroupSummarySynchronizeOperations)
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadState: self.currentUpdatedTotalUnreadState, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId)
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadState: self.currentUpdatedTotalUnreadState, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds)
var updatedTransactionState: Int64?
var updatedMasterClientId: Int64?
if !transaction.isEmpty {

View file

@ -40,6 +40,7 @@ final class PostboxTransaction {
let replacedAdditionalChatListItems: [PeerId]?
let updatedNoticeEntryKeys: Set<NoticeEntryKey>
let updatedCacheEntryKeys: Set<ItemCacheEntryId>
let updatedFailedMessagePeerIds: Set<PeerId>
var isEmpty: Bool {
if currentUpdatedState != nil {
@ -159,10 +160,13 @@ final class PostboxTransaction {
if !updatedCacheEntryKeys.isEmpty {
return false
}
if !updatedFailedMessagePeerIds.isEmpty {
return false
}
return true
}
init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: PeerNotificationSettings], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?], currentUpdatedTotalUnreadState: ChatListTotalUnreadState?, currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, replacedAdditionalChatListItems: [PeerId]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?) {
init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: PeerNotificationSettings], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?], currentUpdatedTotalUnreadState: ChatListTotalUnreadState?, currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, replacedAdditionalChatListItems: [PeerId]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>) {
self.currentUpdatedState = currentUpdatedState
self.currentPeerHoleOperations = currentPeerHoleOperations
self.currentOperationsByPeerId = currentOperationsByPeerId
@ -201,5 +205,6 @@ final class PostboxTransaction {
self.replacedAdditionalChatListItems = replacedAdditionalChatListItems
self.updatedNoticeEntryKeys = updatedNoticeEntryKeys
self.updatedCacheEntryKeys = updatedCacheEntryKeys
self.updatedFailedMessagePeerIds = updatedFailedMessagePeerIds
}
}

View file

@ -349,7 +349,8 @@ final class ViewTracker {
}
}
if !transaction.chatListOperations.isEmpty || !transaction.currentUpdatedPeerNotificationSettings.isEmpty || !transaction.currentUpdatedPeers.isEmpty || !transaction.currentInvalidateMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentOperationsByPeerId.isEmpty || transaction.replacedAdditionalChatListItems != nil || !transaction.currentUpdatedPeerPresences.isEmpty {
if !transaction.chatListOperations.isEmpty || !transaction.currentUpdatedPeerNotificationSettings.isEmpty || !transaction.currentUpdatedPeers.isEmpty || !transaction.currentInvalidateMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentOperationsByPeerId.isEmpty || transaction.replacedAdditionalChatListItems != nil || !transaction.currentUpdatedPeerPresences.isEmpty ||
!transaction.updatedFailedMessagePeerIds.isEmpty {
for (mutableView, pipe) in self.chatListViews.copyItems() {
let context = MutableChatListViewReplayContext()
if mutableView.replay(postbox: postbox, operations: transaction.chatListOperations, updatedPeerNotificationSettings: transaction.currentUpdatedPeerNotificationSettings, updatedPeers: transaction.currentUpdatedPeers, updatedPeerPresences: transaction.currentUpdatedPeerPresences, transaction: transaction, context: context) {

View file

@ -215,22 +215,22 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
let timestamp = self.referenceTimestamp
let timestamp1 = timestamp + 120
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let presenceTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + 60 * 60)
let timestamp2 = timestamp + 3660
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp3 = timestamp + 3200
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp4 = timestamp + 3000
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp5 = timestamp + 1000
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let width: CGFloat
if case .regular = layout.metrics.widthClass {

View file

@ -526,17 +526,17 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
let timestamp = self.referenceTimestamp
let timestamp1 = timestamp + 120
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let presenceTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + 60 * 60)
let timestamp2 = timestamp + 3660
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp3 = timestamp + 3200
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp4 = timestamp + 3000
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, availableHeight: layout.size.height)
if let chatNodes = self.chatNodes {

View file

@ -351,24 +351,24 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
let timestamp = self.referenceTimestamp
let timestamp1 = timestamp + 120
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: 0, messageIndex: MessageIndex(id: MessageId(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer1.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp1, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: selfPeer, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer1), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 0, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let presenceTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + 60 * 60)
let timestamp2 = timestamp + 3660
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer2.id, namespace: 0, id: 0), timestamp: timestamp2)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer2.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp2, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer2, text: "", attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer2), combinedReadState: nil, notificationSettings: nil, presence: TelegramUserPresence(status: .present(until: presenceTimestamp), lastActivity: presenceTimestamp), summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: [(peer2, .typingText)], isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp3 = timestamp + 3200
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer3.id, namespace: 0, id: 0), timestamp: timestamp3)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer3.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp3, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer3Author, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer3), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp4 = timestamp + 3000
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer4.id, namespace: 0, id: 0), timestamp: timestamp4)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp4, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer4, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer4), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let timestamp5 = timestamp + 1000
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer5.id, namespace: 0, id: 0), timestamp: timestamp5)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer4.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp5, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer5, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer5), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer6.id, namespace: 0, id: 0), timestamp: timestamp - 360)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer6.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 360, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer6), combinedReadState: CombinedPeerReadState(states: [(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: 0, maxOutgoingReadId: 0, maxKnownId: 0, count: 1, markedUnread: false))]), notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer7.id, namespace: 0, id: 0), timestamp: timestamp - 420)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer7.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 420, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer7), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
items.append(ChatListItem(presentationData: chatListPresentationData, context: self.context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: MessageIndex(id: MessageId(peerId: peer7.id, namespace: 0, id: 0), timestamp: timestamp - 420)), content: .peer(message: Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer7.id, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, timestamp: timestamp - 420, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer6, text: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []), peer: RenderedPeer(peer: peer7), combinedReadState: nil, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(tagSummaryCount: nil, actionsSummaryCount: nil), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction))
let width: CGFloat
if case .regular = layout.metrics.widthClass {

View file

@ -83,6 +83,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode {
private var sliderView: TGPhotoEditorSliderView?
private let leftIconNode: ASImageNode
private let rightIconNode: ASImageNode
private let disabledOverlayNode: ASDisplayNode
private var item: ThemeSettingsFontSizeItem?
private var layoutParams: ListViewItemLayoutParams?
@ -111,10 +112,14 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode {
self.rightIconNode.displaysAsynchronously = false
self.rightIconNode.displayWithoutProcessing = true
self.disabledOverlayNode = ASDisplayNode()
super.init(layerBacked: false, dynamicBounce: false)
self.addSubnode(self.leftIconNode)
self.addSubnode(self.rightIconNode)
self.addSubnode(self.disabledOverlayNode)
}
override func didLoad() {
@ -159,7 +164,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode {
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 38.0, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 38.0 * 2.0, height: 44.0))
}
self.view.addSubview(sliderView)
self.view.insertSubview(sliderView, belowSubview: self.disabledOverlayNode.view)
sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged)
self.sliderView = sliderView
}
@ -204,6 +209,10 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode {
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
strongSelf.disabledOverlayNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4)
strongSelf.disabledOverlayNode.isHidden = item.enabled
strongSelf.disabledOverlayNode.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 8.0), size: CGSize(width: params.width - params.leftInset - params.rightInset, height: 44.0))
if strongSelf.backgroundNode.supernode == nil {
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
}

View file

@ -804,7 +804,7 @@ public final class ShareController: ViewController {
var peers: [RenderedPeer] = []
for entry in view.0.entries.reversed() {
switch entry {
case let .MessageEntry(_, _, _, _, _, renderedPeer, _, _):
case let .MessageEntry(_, _, _, _, _, renderedPeer, _, _, _):
if let peer = renderedPeer.peers[renderedPeer.peerId], peer.id != accountPeer.id, canSendMessagesToPeer(peer) {
peers.append(renderedPeer)
}

View file

@ -128,6 +128,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1690108678] = { return Api.InputEncryptedFile.parse_inputEncryptedFileUploaded($0) }
dict[1511503333] = { return Api.InputEncryptedFile.parse_inputEncryptedFile($0) }
dict[767652808] = { return Api.InputEncryptedFile.parse_inputEncryptedFileBigUploaded($0) }
dict[-1456996667] = { return Api.messages.InactiveChats.parse_inactiveChats($0) }
dict[1443858741] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedMessage($0) }
dict[-1802240206] = { return Api.messages.SentEncryptedMessage.parse_sentEncryptedFile($0) }
dict[1571494644] = { return Api.ExportedMessageLink.parse_exportedMessageLink($0) }
@ -922,6 +923,8 @@ public struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.InputEncryptedFile:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.InactiveChats:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.SentEncryptedMessage:
_1.serialize(buffer, boxed)
case let _1 as Api.ExportedMessageLink:
@ -1485,6 +1488,66 @@ public struct messages {
}
}
}
public enum InactiveChats: TypeConstructorDescription {
case inactiveChats(dates: [Int32], chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inactiveChats(let dates, let chats, let users):
if boxed {
buffer.appendInt32(-1456996667)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(dates.count))
for item in dates {
serializeInt32(item, buffer: buffer, boxed: false)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inactiveChats(let dates, let chats, let users):
return ("inactiveChats", [("dates", dates), ("chats", chats), ("users", users)])
}
}
public static func parse_inactiveChats(_ reader: BufferReader) -> InactiveChats? {
var _1: [Int32]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
}
var _2: [Api.Chat]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _3: [Api.User]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.messages.InactiveChats.inactiveChats(dates: _1!, chats: _2!, users: _3!)
}
else {
return nil
}
}
}
public enum SentEncryptedMessage: TypeConstructorDescription {
case sentEncryptedMessage(date: Int32)

View file

@ -3761,6 +3761,20 @@ public extension Api {
return result
})
}
public static func getInactiveChannels() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.InactiveChats>) {
let buffer = Buffer()
buffer.appendInt32(300429806)
return (FunctionDescription(name: "channels.getInactiveChannels", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.InactiveChats? in
let reader = BufferReader(buffer)
var result: Api.messages.InactiveChats?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.InactiveChats
}
return result
})
}
}
public struct payments {
public static func getPaymentForm(msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.PaymentForm>) {

View file

@ -336,7 +336,7 @@ final class ChatHistoryPreloadManager {
var indices: [(ChatHistoryPreloadIndex, Bool, Bool)] = []
for entry in view.0.entries {
if case let .MessageEntry(index, _, readState, notificationSettings, _, _, _, _) = entry {
if case let .MessageEntry(index, _, readState, notificationSettings, _, _, _, _, _) = entry {
var hasUnread = false
if let readState = readState {
hasUnread = readState.count != 0

View file

@ -133,6 +133,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
case cellularDataPermissionWarning = 13
case chatMessageSearchResultsTip = 14
case chatMessageOptionsTip = 15
case chatTextSelectionTip = 16
var key: ValueBoxKey {
let v = ValueBoxKey(length: 4)
@ -238,6 +239,10 @@ private struct ApplicationSpecificNoticeKeys {
static func chatMessageOptionsTip() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatMessageOptionsTip.key)
}
static func chatTextSelectionTip() -> NoticeEntryKey {
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatTextSelectionTip.key)
}
}
public struct ApplicationSpecificNotice {
@ -573,6 +578,28 @@ public struct ApplicationSpecificNotice {
}
}
public static func getChatTextSelectionTips(accountManager: AccountManager) -> Signal<Int32, NoError> {
return accountManager.transaction { transaction -> Int32 in
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatTextSelectionTip()) as? ApplicationSpecificCounterNotice {
return value.value
} else {
return 0
}
}
}
public static func incrementChatTextSelectionTips(accountManager: AccountManager, count: Int32 = 1) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
var currentValue: Int32 = 0
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatTextSelectionTip()) as? ApplicationSpecificCounterNotice {
currentValue = value.value
}
currentValue += count
transaction.setNotice(ApplicationSpecificNoticeKeys.chatTextSelectionTip(), ApplicationSpecificCounterNotice(value: currentValue))
}
}
public static func reset(accountManager: AccountManager) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_lamp.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -162,9 +162,11 @@ final class ChatButtonKeyboardInputNode: ChatInputNode {
@objc func buttonPressed(_ button: ASButtonNode) {
if let button = button as? ChatButtonKeyboardInputButtonNode, let markupButton = button.button {
var dismissIfOnce = false
switch markupButton.action {
case .text:
self.controllerInteraction.sendMessage(markupButton.title)
dismissIfOnce = true
case let .url(url):
self.controllerInteraction.openUrl(url, true, nil, nil)
case .requestMap:
@ -209,6 +211,18 @@ final class ChatButtonKeyboardInputNode: ChatInputNode {
self.controllerInteraction.requestMessageActionUrlAuth(url, message.id, buttonId)
}
}
if dismissIfOnce {
if let message = self.message {
for attribute in message.attributes {
if let attribute = attribute as? ReplyMarkupMessageAttribute {
if attribute.flags.contains(.once) {
self.controllerInteraction.dismissReplyMarkupMessage(message)
}
break
}
}
}
}
}
}
}

View file

@ -561,7 +561,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
break
}
}
let _ = combineLatest(queue: .mainQueue(), contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: strongSelf.presentationInterfaceState, context: strongSelf.context, messages: updatedMessages, controllerInteraction: strongSelf.controllerInteraction, selectAll: selectAll, interfaceInteraction: strongSelf.interfaceInteraction), loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .animatedEmoji, forceActualized: false)).start(next: { actions, animatedEmojiStickers in
let _ = combineLatest(queue: .mainQueue(), contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: strongSelf.presentationInterfaceState, context: strongSelf.context, messages: updatedMessages, controllerInteraction: strongSelf.controllerInteraction, selectAll: selectAll, interfaceInteraction: strongSelf.interfaceInteraction), loadedStickerPack(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, reference: .animatedEmoji, forceActualized: false), ApplicationSpecificNotice.getChatTextSelectionTips(accountManager: strongSelf.context.sharedContext.accountManager)
).start(next: { actions, animatedEmojiStickers, chatTextSelectionTips in
guard let strongSelf = self, !actions.isEmpty else {
return
}
@ -590,7 +591,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if Namespaces.Message.allScheduled.contains(message.id.namespace) {
reactionItems = []
}
let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message)), items: .single(actions), reactionItems: reactionItems, recognizer: recognizer)
let displayTextSelectionTip = !message.text.isEmpty && chatTextSelectionTips < 3
if displayTextSelectionTip {
let _ = ApplicationSpecificNotice.incrementChatTextSelectionTips(accountManager: strongSelf.context.sharedContext.accountManager).start()
}
let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message)), items: .single(actions), reactionItems: reactionItems, recognizer: recognizer, displayTextSelectionTip: displayTextSelectionTip)
strongSelf.currentContextController = controller
controller.reactionSelected = { [weak controller] value in
guard let strongSelf = self, let message = updatedMessages.first else {
@ -1721,6 +1728,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let strongSelf = self, let validLayout = strongSelf.validLayout, min(validLayout.size.width, validLayout.size.height) > 320.0 {
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .swipeToReply(title: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintTitle, text: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintText), elevatedLayout: true, action: { _ in }), in: .window(.root))
}
}, dismissReplyMarkupMessage: { [weak self] message in
guard let strongSelf = self, strongSelf.presentationInterfaceState.keyboardButtonsMessage?.id == message.id else {
return
}
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
return $0.updatedInputMode({ _ in .text }).updatedInterfaceState({
$0.withUpdatedMessageActionsState({ value in
var value = value
value.closedButtonKeyboardMessageId = message.id
return value
})
})
})
}, requestMessageUpdate: { [weak self] id in
if let strongSelf = self {
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)

View file

@ -101,6 +101,7 @@ public final class ChatControllerInteraction {
let updateMessageReaction: (MessageId, String?) -> Void
let openMessageReactions: (MessageId) -> Void
let displaySwipeToReplyHint: () -> Void
let dismissReplyMarkupMessage: (Message) -> Void
let requestMessageUpdate: (MessageId) -> Void
let cancelInteractiveKeyboardGestures: () -> Void
@ -115,7 +116,7 @@ public final class ChatControllerInteraction {
var searchTextHighightState: (String, [MessageIndex])?
var seenOneTimeAnimatedMedia = Set<MessageId>()
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?, Message?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String?) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String?) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, dismissReplyMarkupMessage: @escaping (Message) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
self.openMessage = openMessage
self.openPeer = openPeer
self.openPeerMention = openPeerMention
@ -168,6 +169,7 @@ public final class ChatControllerInteraction {
self.updateMessageReaction = updateMessageReaction
self.openMessageReactions = openMessageReactions
self.displaySwipeToReplyHint = displaySwipeToReplyHint
self.dismissReplyMarkupMessage = dismissReplyMarkupMessage
self.requestMessageUpdate = requestMessageUpdate
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
@ -205,6 +207,7 @@ public final class ChatControllerInteraction {
}, updateMessageReaction: { _, _ in
}, openMessageReactions: { _ in
}, displaySwipeToReplyHint: {
}, dismissReplyMarkupMessage: { _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View file

@ -7,6 +7,7 @@ import AsyncDisplayKit
import TelegramCore
import SyncCore
import TelegramPresentationData
import TelegramUIPreferences
import AccountContext
private class ChatGridLiveSelectorRecognizer: UIPanGestureRecognizer {
@ -73,11 +74,11 @@ struct ChatHistoryGridViewTransition {
let stationaryItems: GridNodeStationaryItems
}
private func mappedInsertEntries(context: AccountContext, peerId: PeerId, controllerInteraction: ChatControllerInteraction, entries: [ChatHistoryViewTransitionInsertEntry], theme: PresentationTheme, strings: PresentationStrings) -> [GridNodeInsertItem] {
private func mappedInsertEntries(context: AccountContext, peerId: PeerId, controllerInteraction: ChatControllerInteraction, entries: [ChatHistoryViewTransitionInsertEntry], theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) -> [GridNodeInsertItem] {
return entries.map { entry -> GridNodeInsertItem in
switch entry.entry {
case let .MessageEntry(message, _, _, _, _, _):
return GridNodeInsertItem(index: entry.index, item: GridMessageItem(theme: theme, strings: strings, context: context, message: message, controllerInteraction: controllerInteraction), previousIndex: entry.previousIndex)
return GridNodeInsertItem(index: entry.index, item: GridMessageItem(theme: theme, strings: strings, fontSize: fontSize, context: context, message: message, controllerInteraction: controllerInteraction), previousIndex: entry.previousIndex)
case .MessageGroupEntry:
return GridNodeInsertItem(index: entry.index, item: GridHoleItem(), previousIndex: entry.previousIndex)
case .UnreadEntry:
@ -90,11 +91,11 @@ private func mappedInsertEntries(context: AccountContext, peerId: PeerId, contro
}
}
private func mappedUpdateEntries(context: AccountContext, peerId: PeerId, controllerInteraction: ChatControllerInteraction, entries: [ChatHistoryViewTransitionUpdateEntry], theme: PresentationTheme, strings: PresentationStrings) -> [GridNodeUpdateItem] {
private func mappedUpdateEntries(context: AccountContext, peerId: PeerId, controllerInteraction: ChatControllerInteraction, entries: [ChatHistoryViewTransitionUpdateEntry], theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) -> [GridNodeUpdateItem] {
return entries.map { entry -> GridNodeUpdateItem in
switch entry.entry {
case let .MessageEntry(message, _, _, _, _, _):
return GridNodeUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: GridMessageItem(theme: theme, strings: strings, context: context, message: message, controllerInteraction: controllerInteraction))
return GridNodeUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: GridMessageItem(theme: theme, strings: strings, fontSize: fontSize, context: context, message: message, controllerInteraction: controllerInteraction))
case .MessageGroupEntry:
return GridNodeUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: GridHoleItem())
case .UnreadEntry:
@ -189,7 +190,7 @@ private func mappedChatHistoryViewListTransition(context: AccountContext, peerId
}
}
return ChatHistoryGridViewTransition(historyView: transition.historyView, topOffsetWithinMonth: topOffsetWithinMonth, deleteItems: transition.deleteItems.map { $0.index }, insertItems: mappedInsertEntries(context: context, peerId: peerId, controllerInteraction: controllerInteraction, entries: transition.insertEntries, theme: presentationData.theme.theme, strings: presentationData.strings), updateItems: mappedUpdateEntries(context: context, peerId: peerId, controllerInteraction: controllerInteraction, entries: transition.updateEntries, theme: presentationData.theme.theme, strings: presentationData.strings), scrollToItem: mappedScrollToItem, stationaryItems: stationaryItems)
return ChatHistoryGridViewTransition(historyView: transition.historyView, topOffsetWithinMonth: topOffsetWithinMonth, deleteItems: transition.deleteItems.map { $0.index }, insertItems: mappedInsertEntries(context: context, peerId: peerId, controllerInteraction: controllerInteraction, entries: transition.insertEntries, theme: presentationData.theme.theme, strings: presentationData.strings, fontSize: presentationData.fontSize), updateItems: mappedUpdateEntries(context: context, peerId: peerId, controllerInteraction: controllerInteraction, entries: transition.updateEntries, theme: presentationData.theme.theme, strings: presentationData.strings, fontSize: presentationData.fontSize), scrollToItem: mappedScrollToItem, stationaryItems: stationaryItems)
}
private func gridNodeLayoutForContainerLayout(size: CGSize) -> GridNodeLayoutType {

View file

@ -5,6 +5,7 @@ import Display
import TelegramCore
import SyncCore
import TelegramPresentationData
import TelegramUIPreferences
import AccountContext
enum ChatInputContextPanelPlacement {
@ -17,10 +18,12 @@ class ChatInputContextPanelNode: ASDisplayNode {
var interfaceInteraction: ChatPanelInterfaceInteraction?
var placement: ChatInputContextPanelPlacement = .overPanels
var theme: PresentationTheme
var fontSize: PresentationFontSize
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.context = context
self.theme = theme
self.fontSize = fontSize
super.init()
}

View file

@ -59,7 +59,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
if let currentPanel = currentPanel as? DisabledContextResultsChatInputContextPanelNode {
return currentPanel
} else {
let panel = DisabledContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
let panel = DisabledContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize)
panel.interfaceInteraction = interfaceInteraction
return panel
}
@ -75,7 +75,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
currentPanel.updateResults(results.map({ $0.file }))
return currentPanel
} else {
let panel = HorizontalStickersChatContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
let panel = HorizontalStickersChatContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize)
panel.controllerInteraction = controllerInteraction
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(results.map({ $0.file }))
@ -88,7 +88,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
currentPanel.updateResults(results)
return currentPanel
} else {
let panel = HashtagChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
let panel = HashtagChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize)
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(results)
return panel
@ -100,7 +100,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
currentPanel.updateResults(results)
return currentPanel
} else {
let panel = EmojisChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
let panel = EmojisChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize)
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(results)
return panel
@ -112,7 +112,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
currentPanel.updateResults(peers)
return currentPanel
} else {
let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, mode: .input)
let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, mode: .input)
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(peers)
return panel
@ -126,7 +126,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
currentPanel.updateResults(commands)
return currentPanel
} else {
let panel = CommandChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
let panel = CommandChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize)
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(commands)
return panel
@ -142,7 +142,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
currentPanel.updateResults(results)
return currentPanel
} else {
let panel = VerticalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
let panel = VerticalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize)
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(results)
return panel
@ -152,7 +152,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
currentPanel.updateResults(results)
return currentPanel
} else {
let panel = HorizontalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
let panel = HorizontalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize)
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(results)
return panel
@ -178,7 +178,7 @@ func chatOverlayContextPanelForChatPresentationIntefaceState(_ chatPresentationI
currentPanel.updateResults(peers)
return currentPanel
} else {
let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, mode: .search)
let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, mode: .search)
panel.interfaceInteraction = interfaceInteraction
panel.updateResults(peers)
return panel

View file

@ -417,6 +417,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, updateMessageReaction: { _, _ in
}, openMessageReactions: { _ in
}, displaySwipeToReplyHint: {
}, dismissReplyMarkupMessage: { _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,

View file

@ -11,6 +11,7 @@ import TelegramStringFormatting
import MergeLists
import ChatListUI
import AccountContext
import ContextUI
private enum ChatListSearchEntryStableId: Hashable {
case messageId(MessageId)
@ -76,7 +77,7 @@ private enum ChatListSearchEntry: Comparable, Identifiable {
public func item(context: AccountContext, interaction: ChatListNodeInteraction) -> ListViewItem {
switch self {
case let .message(message, peer, readState, presentationData):
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: true), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true, displayAsMessage: true, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
}
}
}
@ -129,7 +130,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
private let previousEntries = Atomic<[ChatListSearchEntry]?>(value: nil)
init(context: AccountContext, location: SearchMessagesLocation, searchQuery: String, searchResult: SearchMessagesResult, searchState: SearchMessagesState) {
init(context: AccountContext, location: SearchMessagesLocation, searchQuery: String, searchResult: SearchMessagesResult, searchState: SearchMessagesState, presentInGlobalOverlay: @escaping (ViewController) -> Void) {
self.context = context
self.location = location
self.searchQuery = searchQuery
@ -183,7 +184,24 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
}, updatePeerGrouping: { _, _ in
}, togglePeerMarkedUnread: { _, _ in
}, toggleArchivedFolderHiddenByDefault: {
}, activateChatPreview: { _, _, _ in
}, activateChatPreview: { [weak self] item, node, gesture in
guard let strongSelf = self else {
gesture?.cancel()
return
}
switch item.content {
case let .peer(peer):
if let message = peer.message {
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peer.peerId), subject: .message(message.id), botStart: nil, mode: .standard(previewing: true))
chatController.canReadHistory.set(false)
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single([]), reactionItems: [], gesture: gesture)
presentInGlobalOverlay(contextController)
} else {
gesture?.cancel()
}
default:
gesture?.cancel()
}
})
interaction.searchTextHighightState = searchQuery
self.interaction = interaction
@ -317,3 +335,32 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
}
}
}
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
let controller: ViewController
weak var sourceNode: ASDisplayNode?
let navigationController: NavigationController? = nil
let passthroughTouches: Bool = true
init(controller: ViewController, sourceNode: ASDisplayNode?) {
self.controller = controller
self.sourceNode = sourceNode
}
func transitionInfo() -> ContextControllerTakeControllerInfo? {
let sourceNode = self.sourceNode
return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in
if let sourceNode = sourceNode {
return (sourceNode, sourceNode.bounds)
} else {
return nil
}
})
}
func animatedIn() {
}
}

View file

@ -64,7 +64,9 @@ final class ChatSearchResultsController: ViewController {
}
override public func loadDisplayNode() {
self.displayNode = ChatSearchResultsControllerNode(context: self.context, location: self.location, searchQuery: self.searchQuery, searchResult: self.searchResult, searchState: self.searchState)
self.displayNode = ChatSearchResultsControllerNode(context: self.context, location: self.location, searchQuery: self.searchQuery, searchResult: self.searchResult, searchState: self.searchState, presentInGlobalOverlay: { [weak self] c in
self?.presentInGlobalOverlay(c)
})
self.controllerNode.resultSelected = { [weak self] messageIndex in
self?.navigateToMessageIndex(messageIndex)
self?.dismiss()

View file

@ -6,6 +6,7 @@ import TelegramCore
import SyncCore
import Display
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
@ -34,8 +35,8 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
return lhs.index < rhs.index
}
func item(context: AccountContext, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> ListViewItem {
return CommandChatInputPanelItem(context: context, theme: self.theme, command: self.command, commandSelected: commandSelected)
func item(context: AccountContext, fontSize: PresentationFontSize, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> ListViewItem {
return CommandChatInputPanelItem(context: context, theme: self.theme, fontSize: fontSize, command: self.command, commandSelected: commandSelected)
}
}
@ -45,12 +46,12 @@ private struct CommandChatInputContextPanelTransition {
let updates: [ListViewUpdateItem]
}
private func preparedTransition(from fromEntries: [CommandChatInputContextPanelEntry], to toEntries: [CommandChatInputContextPanelEntry], context: AccountContext, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> CommandChatInputContextPanelTransition {
private func preparedTransition(from fromEntries: [CommandChatInputContextPanelEntry], to toEntries: [CommandChatInputContextPanelEntry], context: AccountContext, fontSize: PresentationFontSize, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> CommandChatInputContextPanelTransition {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, commandSelected: commandSelected), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, commandSelected: commandSelected), directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, fontSize: fontSize, commandSelected: commandSelected), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, fontSize: fontSize, commandSelected: commandSelected), directionHint: nil) }
return CommandChatInputContextPanelTransition(deletions: deletions, insertions: insertions, updates: updates)
}
@ -62,7 +63,7 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode {
private var enqueuedTransitions: [(CommandChatInputContextPanelTransition, Bool)] = []
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.listView = ListView()
self.listView.isOpaque = false
self.listView.stackFromBottom = true
@ -70,7 +71,7 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode {
self.listView.limitHitTestToNodes = true
self.listView.view.disablesInteractiveTransitionGestureRecognizer = true
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.isOpaque = false
self.clipsToBounds = true
@ -96,7 +97,7 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode {
private func prepareTransition(from: [CommandChatInputContextPanelEntry]? , to: [CommandChatInputContextPanelEntry]) {
let firstTime = self.currentEntries == nil
let transition = preparedTransition(from: from ?? [], to: to, context: self.context, commandSelected: { [weak self] command, sendImmediately in
let transition = preparedTransition(from: from ?? [], to: to, context: self.context, fontSize: self.fontSize, commandSelected: { [weak self] command, sendImmediately in
if let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction {
if sendImmediately {
interfaceInteraction.sendBotCommand(command.peer, "/" + command.command.text)

View file

@ -7,20 +7,23 @@ import SyncCore
import SwiftSignalKit
import Postbox
import TelegramPresentationData
import TelegramUIPreferences
import AvatarNode
import AccountContext
final class CommandChatInputPanelItem: ListViewItem {
fileprivate let context: AccountContext
fileprivate let theme: PresentationTheme
fileprivate let fontSize: PresentationFontSize
fileprivate let command: PeerCommand
fileprivate let commandSelected: (PeerCommand, Bool) -> Void
let selectable: Bool = true
public init(context: AccountContext, theme: PresentationTheme, command: PeerCommand, commandSelected: @escaping (PeerCommand, Bool) -> Void) {
public init(context: AccountContext, theme: PresentationTheme, fontSize: PresentationFontSize, command: PeerCommand, commandSelected: @escaping (PeerCommand, Bool) -> Void) {
self.context = context
self.theme = theme
self.fontSize = fontSize
self.command = command
self.commandSelected = commandSelected
}
@ -78,8 +81,6 @@ final class CommandChatInputPanelItem: ListViewItem {
}
private let avatarFont = avatarPlaceholderFont(size: 16.0)
private let textFont = Font.medium(14.0)
private let descriptionFont = Font.regular(14.0)
final class CommandChatInputPanelItemNode: ListViewItemNode {
static let itemHeight: CGFloat = 42.0
@ -134,6 +135,9 @@ final class CommandChatInputPanelItemNode: ListViewItemNode {
let makeTextLayout = TextNode.asyncLayout(self.textNode)
return { [weak self] item, params, mergedTop, mergedBottom in
let textFont = Font.medium(floor(item.fontSize.baseDisplaySize * 14.0 / 17.0))
let descriptionFont = Font.regular(floor(item.fontSize.baseDisplaySize * 14.0 / 17.0))
let leftInset: CGFloat = 55.0 + params.leftInset
let rightInset: CGFloat = 10.0 + params.rightInset

View file

@ -6,6 +6,7 @@ import AsyncDisplayKit
import Display
import TelegramPresentationData
import TelegramStringFormatting
import TelegramUIPreferences
import AccountContext
final class DisabledContextResultsChatInputContextPanelNode: ChatInputContextPanelNode {
@ -15,14 +16,14 @@ final class DisabledContextResultsChatInputContextPanelNode: ChatInputContextPan
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.containerNode = ASDisplayNode()
self.separatorNode = ASDisplayNode()
self.textNode = ImmediateTextNode()
self.textNode.maximumNumberOfLines = 0
self.textNode.textAlignment = .center
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.isOpaque = false
self.clipsToBounds = true

View file

@ -6,6 +6,7 @@ import TelegramCore
import SyncCore
import Display
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
import Emoji
@ -105,7 +106,7 @@ final class EmojisChatInputContextPanelNode: ChatInputContextPanelNode {
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
private var presentationInterfaceState: ChatPresentationInterfaceState?
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.backgroundNode = ASImageNode()
self.backgroundNode.displayWithoutProcessing = true
self.backgroundNode.displaysAsynchronously = false
@ -130,7 +131,7 @@ final class EmojisChatInputContextPanelNode: ChatInputContextPanelNode {
self.listView.view.disablesInteractiveTransitionGestureRecognizer = true
self.listView.transform = CATransform3DMakeRotation(-CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.placement = .overTextInput
self.isOpaque = false

View file

@ -7,6 +7,7 @@ import SyncCore
import Postbox
import SwiftSignalKit
import TelegramPresentationData
import TelegramUIPreferences
import TelegramStringFormatting
import AccountContext
import RadialStatusNode
@ -39,6 +40,7 @@ final class GridMessageItemSection: GridSection {
fileprivate let theme: PresentationTheme
private let strings: PresentationStrings
private let fontSize: PresentationFontSize
private let roundedTimestamp: Int32
private let month: Int32
@ -48,9 +50,10 @@ final class GridMessageItemSection: GridSection {
return self.roundedTimestamp.hashValue
}
init(timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings) {
init(timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.theme = theme
self.strings = strings
self.fontSize = fontSize
var now = time_t(timestamp)
var timeinfoNow: tm = tm()
@ -70,20 +73,20 @@ final class GridMessageItemSection: GridSection {
}
func node() -> ASDisplayNode {
return GridMessageItemSectionNode(theme: self.theme, strings: self.strings, roundedTimestamp: self.roundedTimestamp, month: self.month, year: self.year)
return GridMessageItemSectionNode(theme: self.theme, strings: self.strings, fontSize: self.fontSize, roundedTimestamp: self.roundedTimestamp, month: self.month, year: self.year)
}
}
private let sectionTitleFont = Font.regular(14.0)
final class GridMessageItemSectionNode: ASDisplayNode {
var theme: PresentationTheme
var strings: PresentationStrings
var fontSize: PresentationFontSize
let titleNode: ASTextNode
init(theme: PresentationTheme, strings: PresentationStrings, roundedTimestamp: Int32, month: Int32, year: Int32) {
init(theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, roundedTimestamp: Int32, month: Int32, year: Int32) {
self.theme = theme
self.strings = strings
self.fontSize = fontSize
self.titleNode = ASTextNode()
self.titleNode.isUserInteractionEnabled = false
@ -92,6 +95,8 @@ final class GridMessageItemSectionNode: ASDisplayNode {
self.backgroundColor = theme.list.plainBackgroundColor.withAlphaComponent(0.9)
let sectionTitleFont = Font.regular(floor(fontSize.baseDisplaySize * 14.0 / 17.0))
let dateText = stringForMonth(strings: strings, month: month, ofYear: year)
self.addSubnode(self.titleNode)
self.titleNode.attributedText = NSAttributedString(string: dateText, font: sectionTitleFont, textColor: theme.list.itemPrimaryTextColor)
@ -105,7 +110,7 @@ final class GridMessageItemSectionNode: ASDisplayNode {
let bounds = self.bounds
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - 24.0, height: CGFloat.greatestFiniteMagnitude))
self.titleNode.frame = CGRect(origin: CGPoint(x: 12.0, y: 8.0), size: titleSize)
self.titleNode.frame = CGRect(origin: CGPoint(x: 12.0, y: floor((bounds.size.height - titleSize.height) / 2.0)), size: titleSize)
}
}
@ -117,13 +122,13 @@ final class GridMessageItem: GridItem {
private let controllerInteraction: ChatControllerInteraction
let section: GridSection?
init(theme: PresentationTheme, strings: PresentationStrings, context: AccountContext, message: Message, controllerInteraction: ChatControllerInteraction) {
init(theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, context: AccountContext, message: Message, controllerInteraction: ChatControllerInteraction) {
self.theme = theme
self.strings = strings
self.context = context
self.message = message
self.controllerInteraction = controllerInteraction
self.section = GridMessageItemSection(timestamp: message.timestamp, theme: theme, strings: strings)
self.section = GridMessageItemSection(timestamp: message.timestamp, theme: theme, strings: strings, fontSize: fontSize)
}
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {

View file

@ -6,6 +6,7 @@ import TelegramCore
import SyncCore
import Display
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
import AccountContext
@ -35,8 +36,8 @@ private struct HashtagChatInputContextPanelEntry: Comparable, Identifiable {
return lhs.index < rhs.index
}
func item(account: Account, hashtagSelected: @escaping (String) -> Void) -> ListViewItem {
return HashtagChatInputPanelItem(theme: self.theme, text: self.text, hashtagSelected: hashtagSelected)
func item(account: Account, fontSize: PresentationFontSize, hashtagSelected: @escaping (String) -> Void) -> ListViewItem {
return HashtagChatInputPanelItem(theme: self.theme, fontSize: fontSize, text: self.text, hashtagSelected: hashtagSelected)
}
}
@ -46,12 +47,12 @@ private struct HashtagChatInputContextPanelTransition {
let updates: [ListViewUpdateItem]
}
private func preparedTransition(from fromEntries: [HashtagChatInputContextPanelEntry], to toEntries: [HashtagChatInputContextPanelEntry], account: Account, hashtagSelected: @escaping (String) -> Void) -> HashtagChatInputContextPanelTransition {
private func preparedTransition(from fromEntries: [HashtagChatInputContextPanelEntry], to toEntries: [HashtagChatInputContextPanelEntry], account: Account, fontSize: PresentationFontSize, hashtagSelected: @escaping (String) -> Void) -> HashtagChatInputContextPanelTransition {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, hashtagSelected: hashtagSelected), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, hashtagSelected: hashtagSelected), directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, fontSize: fontSize, hashtagSelected: hashtagSelected), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, fontSize: fontSize, hashtagSelected: hashtagSelected), directionHint: nil) }
return HashtagChatInputContextPanelTransition(deletions: deletions, insertions: insertions, updates: updates)
}
@ -63,7 +64,7 @@ final class HashtagChatInputContextPanelNode: ChatInputContextPanelNode {
private var enqueuedTransitions: [(HashtagChatInputContextPanelTransition, Bool)] = []
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.listView = ListView()
self.listView.isOpaque = false
self.listView.stackFromBottom = true
@ -71,7 +72,7 @@ final class HashtagChatInputContextPanelNode: ChatInputContextPanelNode {
self.listView.limitHitTestToNodes = true
self.listView.view.disablesInteractiveTransitionGestureRecognizer = true
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.isOpaque = false
self.clipsToBounds = true
@ -97,7 +98,7 @@ final class HashtagChatInputContextPanelNode: ChatInputContextPanelNode {
private func prepareTransition(from: [HashtagChatInputContextPanelEntry]? , to: [HashtagChatInputContextPanelEntry]) {
let firstTime = from == nil
let transition = preparedTransition(from: from ?? [], to: to, account: self.context.account, hashtagSelected: { [weak self] text in
let transition = preparedTransition(from: from ?? [], to: to, account: self.context.account, fontSize: self.fontSize, hashtagSelected: { [weak self] text in
if let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction {
interfaceInteraction.updateTextInputStateAndMode { textInputState, inputMode in
var hashtagQueryRange: NSRange?

View file

@ -7,16 +7,19 @@ import SyncCore
import SwiftSignalKit
import Postbox
import TelegramPresentationData
import TelegramUIPreferences
final class HashtagChatInputPanelItem: ListViewItem {
fileprivate let theme: PresentationTheme
fileprivate let fontSize: PresentationFontSize
fileprivate let text: String
private let hashtagSelected: (String) -> Void
let selectable: Bool = true
public init(theme: PresentationTheme, text: String, hashtagSelected: @escaping (String) -> Void) {
public init(theme: PresentationTheme, fontSize: PresentationFontSize, text: String, hashtagSelected: @escaping (String) -> Void) {
self.theme = theme
self.fontSize = fontSize
self.text = text
self.hashtagSelected = hashtagSelected
}
@ -73,8 +76,6 @@ final class HashtagChatInputPanelItem: ListViewItem {
}
}
private let textFont = Font.medium(14.0)
final class HashtagChatInputPanelItemNode: ListViewItemNode {
static let itemHeight: CGFloat = 42.0
private let textNode: TextNode
@ -115,6 +116,8 @@ final class HashtagChatInputPanelItemNode: ListViewItemNode {
func asyncLayout() -> (_ item: HashtagChatInputPanelItem, _ params: ListViewItemLayoutParams, _ mergedTop: Bool, _ mergedBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation) -> Void) {
let makeTextLayout = TextNode.asyncLayout(self.textNode)
return { [weak self] item, params, mergedTop, mergedBottom in
let textFont = Font.medium(floor(item.fontSize.baseDisplaySize * 14.0 / 17.0))
let baseWidth = params.width - params.leftInset - params.rightInset
let leftInset: CGFloat = 15.0 + params.leftInset

View file

@ -7,6 +7,7 @@ import SyncCore
import Display
import SwiftSignalKit
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
import StickerPackPreviewUI
@ -86,7 +87,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont
private var enqueuedTransitions: [(HorizontalListContextResultsChatInputContextPanelTransition, Bool)] = []
private var hasValidLayout = false
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.strings = strings
self.separatorNode = ASDisplayNode()
@ -100,7 +101,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont
self.listView.transform = CATransform3DMakeRotation(-CGFloat(CGFloat.pi / 2.0), 0.0, 0.0, 1.0)
self.listView.isHidden = true
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.isOpaque = false
self.clipsToBounds = true

View file

@ -7,6 +7,7 @@ import SyncCore
import Display
import SwiftSignalKit
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
import StickerPackPreviewUI
@ -109,7 +110,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode {
private var stickerPreviewController: StickerPreviewController?
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.strings = strings
self.backgroundNode = ASImageNode()
@ -136,7 +137,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode {
self.stickersInteraction = HorizontalStickersChatContextPanelInteraction()
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.placement = .overTextInput
self.isOpaque = false

View file

@ -3,6 +3,7 @@ import UIKit
import Display
import AsyncDisplayKit
import TelegramPresentationData
import TelegramUIPreferences
import TelegramStringFormatting
private let timezoneOffset: Int32 = {
@ -22,11 +23,13 @@ final class ListMessageDateHeader: ListViewItemHeader {
let id: Int64
let theme: PresentationTheme
let strings: PresentationStrings
let fontSize: PresentationFontSize
init(timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings) {
init(timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.timestamp = timestamp
self.theme = theme
self.strings = strings
self.fontSize = fontSize
var time: time_t = time_t(timestamp + timezoneOffset)
var timeinfo: tm = tm()
@ -44,25 +47,24 @@ final class ListMessageDateHeader: ListViewItemHeader {
let height: CGFloat = 36.0
func node() -> ListViewItemHeaderNode {
return ListMessageDateHeaderNode(theme: self.theme, strings: self.strings, roundedTimestamp: self.roundedTimestamp, month: self.month, year: self.year)
return ListMessageDateHeaderNode(theme: self.theme, strings: self.strings, fontSize: self.fontSize, roundedTimestamp: self.roundedTimestamp, month: self.month, year: self.year)
}
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) {
}
}
private let sectionTitleFont = Font.regular(14.0)
final class ListMessageDateHeaderNode: ListViewItemHeaderNode {
var theme: PresentationTheme
var strings: PresentationStrings
var fontSize: PresentationFontSize
let titleNode: ASTextNode
let backgroundNode: ASDisplayNode
init(theme: PresentationTheme, strings: PresentationStrings, roundedTimestamp: Int32, month: Int32, year: Int32) {
init(theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, roundedTimestamp: Int32, month: Int32, year: Int32) {
self.theme = theme
self.strings = strings
self.fontSize = fontSize
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isLayerBacked = true
@ -75,6 +77,8 @@ final class ListMessageDateHeaderNode: ListViewItemHeaderNode {
let dateText = stringForMonth(strings: strings, month: month, ofYear: year)
let sectionTitleFont = Font.regular(floor(fontSize.baseDisplaySize * 14.0 / 17.0))
self.addSubnode(self.backgroundNode)
self.addSubnode(self.titleNode)
self.titleNode.attributedText = NSAttributedString(string: dateText, font: sectionTitleFont, textColor: theme.list.itemPrimaryTextColor)
@ -97,7 +101,7 @@ final class ListMessageDateHeaderNode: ListViewItemHeaderNode {
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
let titleSize = self.titleNode.measure(CGSize(width: size.width - leftInset - rightInset - 24.0, height: CGFloat.greatestFiniteMagnitude))
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + 12.0, y: 8.0), size: titleSize)
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + 12.0, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size)
}
}

View file

@ -35,7 +35,7 @@ final class ListMessageItem: ListViewItem {
self.controllerInteraction = controllerInteraction
self.message = message
if displayHeader {
self.header = ListMessageDateHeader(timestamp: message.timestamp, theme: theme, strings: strings)
self.header = ListMessageDateHeader(timestamp: message.timestamp, theme: theme, strings: strings, fontSize: fontSize)
} else {
self.header = nil
}

View file

@ -6,6 +6,7 @@ import TelegramCore
import SyncCore
import Display
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import TextFormat
import AccountContext
@ -27,8 +28,8 @@ private struct MentionChatInputContextPanelEntry: Comparable, Identifiable {
return lhs.index < rhs.index
}
func item(context: AccountContext, theme: PresentationTheme, inverted: Bool, peerSelected: @escaping (Peer) -> Void) -> ListViewItem {
return MentionChatInputPanelItem(context: context, theme: theme, inverted: inverted, peer: self.peer, peerSelected: peerSelected)
func item(context: AccountContext, theme: PresentationTheme, fontSize: PresentationFontSize, inverted: Bool, peerSelected: @escaping (Peer) -> Void) -> ListViewItem {
return MentionChatInputPanelItem(context: context, theme: theme, fontSize: fontSize, inverted: inverted, peer: self.peer, peerSelected: peerSelected)
}
}
@ -38,12 +39,12 @@ private struct CommandChatInputContextPanelTransition {
let updates: [ListViewUpdateItem]
}
private func preparedTransition(from fromEntries: [MentionChatInputContextPanelEntry], to toEntries: [MentionChatInputContextPanelEntry], context: AccountContext, theme: PresentationTheme, inverted: Bool, forceUpdate: Bool, peerSelected: @escaping (Peer) -> Void) -> CommandChatInputContextPanelTransition {
private func preparedTransition(from fromEntries: [MentionChatInputContextPanelEntry], to toEntries: [MentionChatInputContextPanelEntry], context: AccountContext, theme: PresentationTheme, fontSize: PresentationFontSize, inverted: Bool, forceUpdate: Bool, peerSelected: @escaping (Peer) -> Void) -> CommandChatInputContextPanelTransition {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, allUpdated: forceUpdate)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, theme: theme, inverted: inverted, peerSelected: peerSelected), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, theme: theme, inverted: inverted, peerSelected: peerSelected), directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, theme: theme, fontSize: fontSize, inverted: inverted, peerSelected: peerSelected), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, theme: theme, fontSize: fontSize, inverted: inverted, peerSelected: peerSelected), directionHint: nil) }
return CommandChatInputContextPanelTransition(deletions: deletions, insertions: insertions, updates: updates)
}
@ -62,7 +63,7 @@ final class MentionChatInputContextPanelNode: ChatInputContextPanelNode {
private var enqueuedTransitions: [(CommandChatInputContextPanelTransition, Bool)] = []
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, mode: MentionChatInputContextPanelMode) {
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, mode: MentionChatInputContextPanelMode) {
self.mode = mode
self.listView = ListView()
@ -72,7 +73,7 @@ final class MentionChatInputContextPanelNode: ChatInputContextPanelNode {
self.listView.limitHitTestToNodes = true
self.listView.view.disablesInteractiveTransitionGestureRecognizer = true
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.isOpaque = false
self.clipsToBounds = true
@ -102,7 +103,7 @@ final class MentionChatInputContextPanelNode: ChatInputContextPanelNode {
private func updateToEntries(entries: [MentionChatInputContextPanelEntry], forceUpdate: Bool) {
let firstTime = self.currentEntries == nil
let transition = preparedTransition(from: self.currentEntries ?? [], to: entries, context: self.context, theme: self.theme, inverted: self.mode == .search, forceUpdate: forceUpdate, peerSelected: { [weak self] peer in
let transition = preparedTransition(from: self.currentEntries ?? [], to: entries, context: self.context, theme: self.theme, fontSize: self.fontSize, inverted: self.mode == .search, forceUpdate: forceUpdate, peerSelected: { [weak self] peer in
if let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction {
switch strongSelf.mode {
case .input:

View file

@ -7,21 +7,24 @@ import SyncCore
import SwiftSignalKit
import Postbox
import TelegramPresentationData
import TelegramUIPreferences
import AvatarNode
import AccountContext
final class MentionChatInputPanelItem: ListViewItem {
fileprivate let context: AccountContext
fileprivate let theme: PresentationTheme
fileprivate let fontSize: PresentationFontSize
fileprivate let inverted: Bool
fileprivate let peer: Peer
private let peerSelected: (Peer) -> Void
let selectable: Bool = true
public init(context: AccountContext, theme: PresentationTheme, inverted: Bool, peer: Peer, peerSelected: @escaping (Peer) -> Void) {
public init(context: AccountContext, theme: PresentationTheme, fontSize: PresentationFontSize, inverted: Bool, peer: Peer, peerSelected: @escaping (Peer) -> Void) {
self.context = context
self.theme = theme
self.fontSize = fontSize
self.inverted = inverted
self.peer = peer
self.peerSelected = peerSelected
@ -80,8 +83,6 @@ final class MentionChatInputPanelItem: ListViewItem {
}
private let avatarFont = avatarPlaceholderFont(size: 16.0)
private let primaryFont = Font.medium(14.0)
private let secondaryFont = Font.regular(14.0)
final class MentionChatInputPanelItemNode: ListViewItemNode {
static let itemHeight: CGFloat = 42.0
@ -133,6 +134,9 @@ final class MentionChatInputPanelItemNode: ListViewItemNode {
let previousItem = self.item
return { [weak self] item, params, mergedTop, mergedBottom in
let primaryFont = Font.medium(floor(item.fontSize.baseDisplaySize * 14.0 / 17.0))
let secondaryFont = Font.regular(floor(item.fontSize.baseDisplaySize * 14.0 / 17.0))
let leftInset: CGFloat = 55.0 + params.leftInset
let rightInset: CGFloat = 10.0 + params.rightInset

View file

@ -118,6 +118,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
}, updateMessageReaction: { _, _ in
}, openMessageReactions: { _ in
}, displaySwipeToReplyHint: {
}, dismissReplyMarkupMessage: { _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))

View file

@ -423,6 +423,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
}, updateMessageReaction: { _, _ in
}, openMessageReactions: { _ in
}, displaySwipeToReplyHint: {
}, dismissReplyMarkupMessage: { _ in
}, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View file

@ -7,6 +7,7 @@ import SyncCore
import Display
import SwiftSignalKit
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
import StickerPackPreviewUI
@ -80,7 +81,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode {
private var stickerPreviewController: StickerPreviewController?
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.strings = strings
self.listView = ListView()
@ -92,7 +93,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode {
self.stickersInteraction = StickersChatInputContextPanelInteraction()
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.isOpaque = false
self.clipsToBounds = true

View file

@ -6,6 +6,7 @@ import TelegramCore
import SyncCore
import Display
import TelegramPresentationData
import TelegramUIPreferences
import MergeLists
import AccountContext
@ -127,7 +128,7 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex
private var enqueuedTransitions: [(VerticalListContextResultsChatInputContextPanelTransition, Bool)] = []
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) {
self.listView = ListView()
self.listView.isOpaque = false
self.listView.stackFromBottom = true
@ -136,7 +137,7 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex
self.listView.isHidden = true
self.listView.view.disablesInteractiveTransitionGestureRecognizer = true
super.init(context: context, theme: theme, strings: strings)
super.init(context: context, theme: theme, strings: strings, fontSize: fontSize)
self.isOpaque = false
self.clipsToBounds = true

View file

@ -34,12 +34,12 @@ private func cancelScrollViewGestures(view: UIView?) {
}
}
private func generateKnobImage(color: UIColor, inverted: Bool = false) -> UIImage? {
private func generateKnobImage(color: UIColor, diameter: CGFloat, inverted: Bool = false) -> UIImage? {
let f: (CGSize, CGContext) -> Void = { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(color.cgColor)
context.fill(CGRect(origin: CGPoint(x: (size.width - 2.0) / 2.0, y: size.width / 2.0), size: CGSize(width: 2.0, height: size.height - size.width / 2.0 - 1.0)))
context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.width)))
context.fillEllipse(in: CGRect(origin: CGPoint(x: floor((size.width - diameter) / 2.0), y: floor((size.width - diameter) / 2.0)), size: CGSize(width: diameter, height: diameter)))
context.fillEllipse(in: CGRect(origin: CGPoint(x: (size.width - 2.0) / 2.0, y: size.width + 2.0), size: CGSize(width: 2.0, height: 2.0)))
}
let size = CGSize(width: 12.0, height: 12.0 + 2.0 + 2.0)
@ -53,10 +53,12 @@ private func generateKnobImage(color: UIColor, inverted: Bool = false) -> UIImag
public final class TextSelectionTheme {
public let selection: UIColor
public let knob: UIColor
public let knobDiameter: CGFloat
public init(selection: UIColor, knob: UIColor) {
public init(selection: UIColor, knob: UIColor, knobDiameter: CGFloat = 12.0) {
self.selection = selection
self.knob = knob
self.knobDiameter = knobDiameter
}
}
@ -204,6 +206,9 @@ public final class TextSelectionNode: ASDisplayNode {
public let highlightAreaNode: ASDisplayNode
private var recognizer: TextSelectionGetureRecognizer?
private var displayLinkAnimator: DisplayLinkAnimator?
public init(theme: TextSelectionTheme, strings: PresentationStrings, textNode: TextNode, updateIsActive: @escaping (Bool) -> Void, present: @escaping (ViewController, Any?) -> Void, rootNode: ASDisplayNode, performAction: @escaping (String, TextSelectionAction) -> Void) {
self.theme = theme
self.strings = strings
@ -214,13 +219,13 @@ public final class TextSelectionNode: ASDisplayNode {
self.performAction = performAction
self.leftKnob = ASImageNode()
self.leftKnob.isUserInteractionEnabled = false
self.leftKnob.image = generateKnobImage(color: theme.knob)
self.leftKnob.image = generateKnobImage(color: theme.knob, diameter: theme.knobDiameter)
self.leftKnob.displaysAsynchronously = false
self.leftKnob.displayWithoutProcessing = true
self.leftKnob.alpha = 0.0
self.rightKnob = ASImageNode()
self.rightKnob.isUserInteractionEnabled = false
self.rightKnob.image = generateKnobImage(color: theme.knob, inverted: true)
self.rightKnob.image = generateKnobImage(color: theme.knob, diameter: theme.knobDiameter, inverted: true)
self.rightKnob.displaysAsynchronously = false
self.rightKnob.displayWithoutProcessing = true
self.rightKnob.alpha = 0.0
@ -255,7 +260,6 @@ public final class TextSelectionNode: ASDisplayNode {
let mappedPoint = strongSelf.view.convert(point, to: strongSelf.textNode.view)
if let stringIndex = strongSelf.textNode.attributesAtPoint(mappedPoint, orNearest: true)?.0 {
//let string = attributedString.string as NSString
var updatedMin = currentRange.0
var updatedMax = currentRange.1
switch knob {
@ -324,6 +328,7 @@ public final class TextSelectionNode: ASDisplayNode {
self?.dismissSelection()
self?.updateIsActive(false)
}
self.recognizer = recognizer
self.view.addGestureRecognizer(recognizer)
}
@ -337,6 +342,60 @@ public final class TextSelectionNode: ASDisplayNode {
}
}
public func pretendInitiateSelection() {
guard let cachedLayout = self.textNode.cachedLayout, let attributedString = cachedLayout.attributedString else {
return
}
var resultRange: NSRange?
let stringIndex = 0
let string = attributedString.string as NSString
let inputRange = CFRangeMake(0, string.length)
let flag = UInt(kCFStringTokenizerUnitWord)
let locale = CFLocaleCopyCurrent()
let tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, string as CFString, inputRange, flag, locale)
var tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)
while !tokenType.isEmpty {
let currentTokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer)
if currentTokenRange.location <= stringIndex && currentTokenRange.location + currentTokenRange.length > stringIndex {
resultRange = NSRange(location: currentTokenRange.location, length: currentTokenRange.length)
break
}
tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)
}
if resultRange == nil {
resultRange = NSRange(location: stringIndex, length: 1)
}
self.currentRange = resultRange.flatMap {
($0.lowerBound, $0.upperBound)
}
self.updateSelection(range: resultRange, animateIn: true)
self.updateIsActive(true)
}
public func pretendExtendSelection(to index: Int) {
guard let cachedLayout = self.textNode.cachedLayout, let attributedString = cachedLayout.attributedString, let endRangeRect = cachedLayout.rangeRects(in: NSRange(location: index, length: 1))?.first else {
return
}
let startPoint = self.rightKnob.frame.center
let endPoint = endRangeRect.center
let displayLinkAnimator = DisplayLinkAnimator(duration: 0.3, from: 0.0, to: 1.0, update: { [weak self] progress in
guard let strongSelf = self else {
return
}
let point = CGPoint(x: (1.0 - progress) * startPoint.x + progress * endPoint.x, y: (1.0 - progress) * startPoint.y + progress * endPoint.y)
strongSelf.recognizer?.moveKnob?(.right, point)
}, completion: { [weak self] in
guard let strongSelf = self else {
return
}
})
self.displayLinkAnimator = displayLinkAnimator
}
private func updateSelection(range: NSRange?, animateIn: Bool) {
var rects: [CGRect]?
@ -362,8 +421,8 @@ public final class TextSelectionNode: ASDisplayNode {
highlightOverlay.frame = self.bounds
highlightOverlay.updateRects(rects)
if let image = self.leftKnob.image {
self.leftKnob.frame = CGRect(origin: CGPoint(x: floor(rects[0].minX - 1.0 - image.size.width / 2.0), y: rects[0].minY - 1.0 - image.size.width), size: CGSize(width: image.size.width, height: image.size.width + rects[0].height + 2.0))
self.rightKnob.frame = CGRect(origin: CGPoint(x: floor(rects[rects.count - 1].maxX + 1.0 - image.size.width / 2.0), y: rects[rects.count - 1].maxY + 1.0 - (rects[0].height + 2.0)), size: CGSize(width: image.size.width, height: image.size.width + rects[0].height + 2.0))
self.leftKnob.frame = CGRect(origin: CGPoint(x: floor(rects[0].minX - 1.0 - image.size.width / 2.0), y: rects[0].minY - 1.0 - self.theme.knobDiameter), size: CGSize(width: image.size.width, height: self.theme.knobDiameter + rects[0].height + 2.0))
self.rightKnob.frame = CGRect(origin: CGPoint(x: floor(rects[rects.count - 1].maxX + 1.0 - image.size.width / 2.0), y: rects[rects.count - 1].maxY + 1.0 - (rects[0].height + 2.0)), size: CGSize(width: image.size.width, height: self.theme.knobDiameter + rects[0].height + 2.0))
}
if self.leftKnob.alpha.isZero {
highlightOverlay.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)

View file

@ -319,7 +319,7 @@ func makeBridgeMedia(message: Message, strings: PresentationStrings, chatPeer: P
}
func makeBridgeChat(_ entry: ChatListEntry, strings: PresentationStrings) -> (TGBridgeChat, [Int64 : TGBridgeUser])? {
if case let .MessageEntry(index, message, readState, _, _, renderedPeer, _, _) = entry {
if case let .MessageEntry(index, message, readState, _, _, renderedPeer, _, _, hasFailed) = entry {
guard index.messageIndex.id.peerId.namespace != Namespaces.Peer.SecretChat else {
return nil
}
@ -332,7 +332,7 @@ func makeBridgeChat(_ entry: ChatListEntry, strings: PresentationStrings) -> (TG
bridgeChat.text = message.text
bridgeChat.outgoing = !message.flags.contains(.Incoming)
bridgeChat.deliveryState = makeBridgeDeliveryState(message)
bridgeChat.deliveryError = message.flags.contains(.Failed)
bridgeChat.deliveryError = hasFailed
bridgeChat.media = makeBridgeMedia(message: message, strings: strings, filterUnsupportedActions: false)
}
bridgeChat.unread = readState?.isUnread ?? false

View file

@ -12,6 +12,23 @@ fi
mkdir -p "$target_directory"
jdk_archive_name="jdk.tar.gz"
jdk_archive_path="$target_directory/$jdk_archive_name"
jdk_unpacked_path="$target_directory/jdk8u232-b09"
jdk_url="https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u232-b09/OpenJDK8U-jdk_x64_mac_hotspot_8u232b09.tar.gz"
if [ ! -f "$jdk_archive_path" ]; then
echo "Fetching JDK 8"
curl "$jdk_url" -L -o "$target_directory/jdk.tar.gz"
fi
if [ ! -d "$jdk_unpacked_path" ]; then
echo "Unpacking JDK 8"
pushd "$target_directory"
tar -xf "$jdk_archive_name"
popd
fi
patch_file="$(ls *.patch | head -1)"
patch_path="$(pwd)/$patch_file"
@ -39,10 +56,7 @@ git reset --hard "$commit_sha"
git apply --check "$patch_path"
git apply "$patch_path"
ant
./bin/buck build --show-output buck
#result_path="$(pwd)/buck-out/gen/programs/buck.pex"
PATH="$PATH:$jdk_unpacked_path/Contents/Home/bin" ant
PATH="$PATH:$jdk_unpacked_path/Contents/Home/bin" ./bin/buck build --show-output buck
cd "$dir"