mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Comment [WIP]
This commit is contained in:
parent
4076d3dc4d
commit
e2f8229ae2
@ -1556,6 +1556,7 @@
|
|||||||
|
|
||||||
"Channel.ErrorAccessDenied" = "Sorry, this channel is private.";
|
"Channel.ErrorAccessDenied" = "Sorry, this channel is private.";
|
||||||
"Group.ErrorAccessDenied" = "Sorry, this group is private.";
|
"Group.ErrorAccessDenied" = "Sorry, this group is private.";
|
||||||
|
"CommentsGroup.ErrorAccessDenied" = "Sorry, you can't access this chat because you were banned by an admin";
|
||||||
"Conversation.InputTextBroadcastPlaceholder" = "Broadcast";
|
"Conversation.InputTextBroadcastPlaceholder" = "Broadcast";
|
||||||
|
|
||||||
"Channel.NotificationLoading" = "Loading...";
|
"Channel.NotificationLoading" = "Loading...";
|
||||||
@ -5810,3 +5811,6 @@ Any member of this group will be able to see messages in the channel.";
|
|||||||
"Channel.CommentsGroup.Header" = "Select a group chat that will be used to host comments from your channel.";
|
"Channel.CommentsGroup.Header" = "Select a group chat that will be used to host comments from your channel.";
|
||||||
"Channel.CommentsGroup.HeaderSet" = "%@ is selected as the group that will be used to host comments for your channel.";
|
"Channel.CommentsGroup.HeaderSet" = "%@ is selected as the group that will be used to host comments for your channel.";
|
||||||
"Channel.CommentsGroup.HeaderGroupSet" = "%@ is linking the group as it's discussion board.";
|
"Channel.CommentsGroup.HeaderGroupSet" = "%@ is linking the group as it's discussion board.";
|
||||||
|
|
||||||
|
"RepliesChat.DescriptionTitle" = "What is it?";
|
||||||
|
"RepliesChat.DescriptionText" = "This is a chat with replies.";
|
||||||
|
@ -149,7 +149,9 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let status: ContactsPeerItemStatus
|
let status: ContactsPeerItemStatus
|
||||||
if let user = primaryPeer as? TelegramUser {
|
if primaryPeer.id.isReplies {
|
||||||
|
status = .none
|
||||||
|
} else if let user = primaryPeer as? TelegramUser {
|
||||||
let servicePeer = isServicePeer(primaryPeer)
|
let servicePeer = isServicePeer(primaryPeer)
|
||||||
if user.flags.contains(.isSupport) && !servicePeer {
|
if user.flags.contains(.isSupport) && !servicePeer {
|
||||||
status = .custom(string: strings.Bot_GenericSupportStatus, multiline: false)
|
status = .custom(string: strings.Bot_GenericSupportStatus, multiline: false)
|
||||||
|
@ -1843,7 +1843,9 @@ private func statusStringForPeerType(accountPeerId: PeerId, strings: Presentatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let user = peer as? TelegramUser {
|
if peer.id.isReplies {
|
||||||
|
return nil
|
||||||
|
} else if let user = peer as? TelegramUser {
|
||||||
if user.botInfo != nil || user.flags.contains(.isSupport) {
|
if user.botInfo != nil || user.flags.contains(.isSupport) {
|
||||||
return (strings.ChatList_PeerTypeBot, false)
|
return (strings.ChatList_PeerTypeBot, false)
|
||||||
} else if isContact {
|
} else if isContact {
|
||||||
|
@ -425,6 +425,9 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
|||||||
} else if peer.flags.contains(.isSupport), !servicePeer {
|
} else if peer.flags.contains(.isSupport), !servicePeer {
|
||||||
statusText = item.presentationData.strings.Bot_GenericSupportStatus
|
statusText = item.presentationData.strings.Bot_GenericSupportStatus
|
||||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||||
|
} else if peer.id.isReplies {
|
||||||
|
statusText = ""
|
||||||
|
statusColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||||
} else if let _ = peer.botInfo {
|
} else if let _ = peer.botInfo {
|
||||||
statusText = item.presentationData.strings.Bot_GenericBotStatus
|
statusText = item.presentationData.strings.Bot_GenericBotStatus
|
||||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||||
|
@ -139,6 +139,7 @@ private final class OverlayStatusControllerImpl: ViewController, StandalonePrese
|
|||||||
private let type: OverlayStatusControllerType
|
private let type: OverlayStatusControllerType
|
||||||
|
|
||||||
private var animatedDidAppear = false
|
private var animatedDidAppear = false
|
||||||
|
private var isDismissed = false
|
||||||
|
|
||||||
private var controllerNode: OverlayStatusControllerNode {
|
private var controllerNode: OverlayStatusControllerNode {
|
||||||
return self.displayNode as! OverlayStatusControllerNode
|
return self.displayNode as! OverlayStatusControllerNode
|
||||||
@ -181,8 +182,12 @@ private final class OverlayStatusControllerImpl: ViewController, StandalonePrese
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func dismiss(completion: (() -> Void)? = nil) {
|
override public func dismiss(completion: (() -> Void)? = nil) {
|
||||||
self.controllerNode.dismiss()
|
if self.isDismissed {
|
||||||
completion?()
|
completion?()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.isDismissed = true
|
||||||
|
self.controllerNode.dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct PeerChatThreadId: Hashable {
|
||||||
|
public var peerId: PeerId
|
||||||
|
public var threadId: Int64
|
||||||
|
|
||||||
|
public init(peerId: PeerId, threadId: Int64) {
|
||||||
|
self.peerId = peerId
|
||||||
|
self.threadId = threadId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class PeerChatThreadInterfaceStateTable: Table {
|
||||||
|
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
||||||
|
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var states: [PeerChatThreadId: PeerChatInterfaceState?] = [:]
|
||||||
|
private var peerIdsWithUpdatedStates = Set<PeerChatThreadId>()
|
||||||
|
|
||||||
|
private let sharedKey = ValueBoxKey(length: 8 + 8)
|
||||||
|
|
||||||
|
private func key(_ peerId: PeerChatThreadId, sharedKey: ValueBoxKey = ValueBoxKey(length: 8)) -> ValueBoxKey {
|
||||||
|
sharedKey.setInt64(0, value: peerId.peerId.toInt64())
|
||||||
|
sharedKey.setInt64(8, value: peerId.threadId)
|
||||||
|
return sharedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func get(_ peerId: PeerChatThreadId) -> PeerChatInterfaceState? {
|
||||||
|
if let cachedValue = self.states[peerId] {
|
||||||
|
return cachedValue
|
||||||
|
} else if let value = self.valueBox.get(self.table, key: self.key(peerId, sharedKey: self.sharedKey)), let state = PostboxDecoder(buffer: value).decodeRootObject() as? PeerChatInterfaceState {
|
||||||
|
self.states[peerId] = state
|
||||||
|
return state
|
||||||
|
} else {
|
||||||
|
self.states[peerId] = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(_ peerId: PeerChatThreadId, state: PeerChatInterfaceState?) -> Bool {
|
||||||
|
let currentState = self.get(peerId)
|
||||||
|
var updated = false
|
||||||
|
if let currentState = currentState, let state = state {
|
||||||
|
if !currentState.isEqual(to: state) {
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
} else if (currentState != nil) != (state != nil) {
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
if updated {
|
||||||
|
self.states[peerId] = state
|
||||||
|
self.peerIdsWithUpdatedStates.insert(peerId)
|
||||||
|
}
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
|
override func clearMemoryCache() {
|
||||||
|
self.states.removeAll()
|
||||||
|
self.peerIdsWithUpdatedStates.removeAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func beforeCommit() {
|
||||||
|
if !self.peerIdsWithUpdatedStates.isEmpty {
|
||||||
|
let sharedEncoder = PostboxEncoder()
|
||||||
|
for peerId in self.peerIdsWithUpdatedStates {
|
||||||
|
if let state = self.states[peerId] {
|
||||||
|
if let state = state {
|
||||||
|
sharedEncoder.reset()
|
||||||
|
sharedEncoder.encodeRootObject(state)
|
||||||
|
self.valueBox.set(self.table, key: self.key(peerId, sharedKey: self.sharedKey), value: sharedEncoder.readBufferNoCopy())
|
||||||
|
} else {
|
||||||
|
self.valueBox.remove(self.table, key: self.key(peerId, sharedKey: self.sharedKey), secure: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.peerIdsWithUpdatedStates.removeAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -274,6 +274,11 @@ public final class Transaction {
|
|||||||
self.postbox?.updatePeerChatInterfaceState(id, update: update)
|
self.postbox?.updatePeerChatInterfaceState(id, update: update)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func updatePeerChatThreadInterfaceState(_ id: PeerId, threadId: Int64, update: (PeerChatInterfaceState?) -> (PeerChatInterfaceState?)) {
|
||||||
|
assert(!self.disposed)
|
||||||
|
self.postbox?.updatePeerChatThreadInterfaceState(id, threadId: threadId, update: update)
|
||||||
|
}
|
||||||
|
|
||||||
public func getPeer(_ id: PeerId) -> Peer? {
|
public func getPeer(_ id: PeerId) -> Peer? {
|
||||||
assert(!self.disposed)
|
assert(!self.disposed)
|
||||||
return self.postbox?.peerTable.get(id)
|
return self.postbox?.peerTable.get(id)
|
||||||
@ -1294,6 +1299,7 @@ public final class Postbox {
|
|||||||
let itemCollectionItemTable: ItemCollectionItemTable
|
let itemCollectionItemTable: ItemCollectionItemTable
|
||||||
let itemCollectionReverseIndexTable: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>
|
let itemCollectionReverseIndexTable: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>
|
||||||
let peerChatInterfaceStateTable: PeerChatInterfaceStateTable
|
let peerChatInterfaceStateTable: PeerChatInterfaceStateTable
|
||||||
|
let peerChatThreadInterfaceStateTable: PeerChatThreadInterfaceStateTable
|
||||||
let itemCacheMetaTable: ItemCacheMetaTable
|
let itemCacheMetaTable: ItemCacheMetaTable
|
||||||
let itemCacheTable: ItemCacheTable
|
let itemCacheTable: ItemCacheTable
|
||||||
let peerNameTokenIndexTable: ReverseIndexReferenceTable<PeerIdReverseIndexReference>
|
let peerNameTokenIndexTable: ReverseIndexReferenceTable<PeerIdReverseIndexReference>
|
||||||
@ -1394,6 +1400,7 @@ public final class Postbox {
|
|||||||
self.itemCollectionReverseIndexTable = ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>.tableSpec(36))
|
self.itemCollectionReverseIndexTable = ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>(valueBox: self.valueBox, table: ReverseIndexReferenceTable<ItemCollectionItemReverseIndexReference>.tableSpec(36))
|
||||||
self.itemCollectionItemTable = ItemCollectionItemTable(valueBox: self.valueBox, table: ItemCollectionItemTable.tableSpec(22), reverseIndexTable: self.itemCollectionReverseIndexTable)
|
self.itemCollectionItemTable = ItemCollectionItemTable(valueBox: self.valueBox, table: ItemCollectionItemTable.tableSpec(22), reverseIndexTable: self.itemCollectionReverseIndexTable)
|
||||||
self.peerChatInterfaceStateTable = PeerChatInterfaceStateTable(valueBox: self.valueBox, table: PeerChatInterfaceStateTable.tableSpec(23))
|
self.peerChatInterfaceStateTable = PeerChatInterfaceStateTable(valueBox: self.valueBox, table: PeerChatInterfaceStateTable.tableSpec(23))
|
||||||
|
self.peerChatThreadInterfaceStateTable = PeerChatThreadInterfaceStateTable(valueBox: self.valueBox, table: PeerChatThreadInterfaceStateTable.tableSpec(64))
|
||||||
self.itemCacheMetaTable = ItemCacheMetaTable(valueBox: self.valueBox, table: ItemCacheMetaTable.tableSpec(24))
|
self.itemCacheMetaTable = ItemCacheMetaTable(valueBox: self.valueBox, table: ItemCacheMetaTable.tableSpec(24))
|
||||||
self.itemCacheTable = ItemCacheTable(valueBox: self.valueBox, table: ItemCacheTable.tableSpec(25))
|
self.itemCacheTable = ItemCacheTable(valueBox: self.valueBox, table: ItemCacheTable.tableSpec(25))
|
||||||
self.chatListIndexTable = ChatListIndexTable(valueBox: self.valueBox, table: ChatListIndexTable.tableSpec(8), peerNameIndexTable: self.peerNameIndexTable, metadataTable: self.messageHistoryMetadataTable, readStateTable: self.readStateTable, notificationSettingsTable: self.peerNotificationSettingsTable)
|
self.chatListIndexTable = ChatListIndexTable(valueBox: self.valueBox, table: ChatListIndexTable.tableSpec(8), peerNameIndexTable: self.peerNameIndexTable, metadataTable: self.messageHistoryMetadataTable, readStateTable: self.readStateTable, notificationSettingsTable: self.peerNotificationSettingsTable)
|
||||||
@ -1445,6 +1452,7 @@ public final class Postbox {
|
|||||||
tables.append(self.itemCollectionItemTable)
|
tables.append(self.itemCollectionItemTable)
|
||||||
tables.append(self.itemCollectionReverseIndexTable)
|
tables.append(self.itemCollectionReverseIndexTable)
|
||||||
tables.append(self.peerChatInterfaceStateTable)
|
tables.append(self.peerChatInterfaceStateTable)
|
||||||
|
tables.append(self.peerChatThreadInterfaceStateTable)
|
||||||
tables.append(self.itemCacheMetaTable)
|
tables.append(self.itemCacheMetaTable)
|
||||||
tables.append(self.itemCacheTable)
|
tables.append(self.itemCacheTable)
|
||||||
tables.append(self.peerNameIndexTable)
|
tables.append(self.peerNameIndexTable)
|
||||||
@ -2119,6 +2127,11 @@ public final class Postbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate func updatePeerChatThreadInterfaceState(_ id: PeerId, threadId: Int64, update: (PeerChatInterfaceState?) -> (PeerChatInterfaceState?)) {
|
||||||
|
let updatedState = update(self.peerChatThreadInterfaceStateTable.get(PeerChatThreadId(peerId: id, threadId: threadId)))
|
||||||
|
let _ = self.peerChatThreadInterfaceStateTable.set(PeerChatThreadId(peerId: id, threadId: threadId), state: updatedState)
|
||||||
|
}
|
||||||
|
|
||||||
fileprivate func replaceRemoteContactCount(_ count: Int32) {
|
fileprivate func replaceRemoteContactCount(_ count: Int32) {
|
||||||
self.metadataTable.setRemoteContactCount(count)
|
self.metadataTable.setRemoteContactCount(count)
|
||||||
self.currentReplaceRemoteContactCount = count
|
self.currentReplaceRemoteContactCount = count
|
||||||
@ -2666,11 +2679,11 @@ public final class Postbox {
|
|||||||
let initialData: InitialMessageHistoryData
|
let initialData: InitialMessageHistoryData
|
||||||
switch peerIds {
|
switch peerIds {
|
||||||
case let .single(peerId):
|
case let .single(peerId):
|
||||||
initialData = self.initialMessageHistoryData(peerId: peerId)
|
initialData = self.initialMessageHistoryData(peerId: peerId, threadId: nil)
|
||||||
case let .associated(peerId, _):
|
case let .associated(peerId, _):
|
||||||
initialData = self.initialMessageHistoryData(peerId: peerId)
|
initialData = self.initialMessageHistoryData(peerId: peerId, threadId: nil)
|
||||||
case let .external(input):
|
case let .external(input):
|
||||||
initialData = self.initialMessageHistoryData(peerId: input.peerId)
|
initialData = self.initialMessageHistoryData(peerId: input.peerId, threadId: input.threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
subscriber.putNext((MessageHistoryView(mutableView), initialUpdateType, initialData))
|
subscriber.putNext((MessageHistoryView(mutableView), initialUpdateType, initialData))
|
||||||
@ -2687,7 +2700,19 @@ public final class Postbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func initialMessageHistoryData(peerId: PeerId) -> InitialMessageHistoryData {
|
private func initialMessageHistoryData(peerId: PeerId, threadId: Int64?) -> InitialMessageHistoryData {
|
||||||
|
if let threadId = threadId {
|
||||||
|
let chatInterfaceState = self.peerChatThreadInterfaceStateTable.get(PeerChatThreadId(peerId: peerId, threadId: threadId))
|
||||||
|
var associatedMessages: [MessageId: Message] = [:]
|
||||||
|
if let chatInterfaceState = chatInterfaceState {
|
||||||
|
for id in chatInterfaceState.associatedMessageIds {
|
||||||
|
if let message = self.getMessage(id) {
|
||||||
|
associatedMessages[message.id] = message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return InitialMessageHistoryData(peer: self.peerTable.get(peerId), chatInterfaceState: chatInterfaceState, associatedMessages: associatedMessages)
|
||||||
|
} else {
|
||||||
let chatInterfaceState = self.peerChatInterfaceStateTable.get(peerId)
|
let chatInterfaceState = self.peerChatInterfaceStateTable.get(peerId)
|
||||||
var associatedMessages: [MessageId: Message] = [:]
|
var associatedMessages: [MessageId: Message] = [:]
|
||||||
if let chatInterfaceState = chatInterfaceState {
|
if let chatInterfaceState = chatInterfaceState {
|
||||||
@ -2699,6 +2724,7 @@ public final class Postbox {
|
|||||||
}
|
}
|
||||||
return InitialMessageHistoryData(peer: self.peerTable.get(peerId), chatInterfaceState: chatInterfaceState, associatedMessages: associatedMessages)
|
return InitialMessageHistoryData(peer: self.peerTable.get(peerId), chatInterfaceState: chatInterfaceState, associatedMessages: associatedMessages)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func messageIndexAtId(_ id: MessageId) -> Signal<MessageIndex?, NoError> {
|
public func messageIndexAtId(_ id: MessageId) -> Signal<MessageIndex?, NoError> {
|
||||||
return self.transaction { transaction -> Signal<MessageIndex?, NoError> in
|
return self.transaction { transaction -> Signal<MessageIndex?, NoError> in
|
||||||
|
@ -159,7 +159,7 @@ struct FetchMessageHistoryHoleResult: Equatable {
|
|||||||
var actualThreadId: Int64?
|
var actualThreadId: Int64?
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryHoleSource, postbox: Postbox, peerInput: FetchMessageHistoryHoleThreadInput, namespace: MessageId.Namespace, direction: MessageHistoryViewRelativeHoleDirection, space: MessageHistoryHoleSpace, count rawCount: Int) -> Signal<FetchMessageHistoryHoleResult, NoError> {
|
func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryHoleSource, postbox: Postbox, peerInput: FetchMessageHistoryHoleThreadInput, namespace: MessageId.Namespace, direction: MessageHistoryViewRelativeHoleDirection, space: MessageHistoryHoleSpace, count rawCount: Int) -> Signal<FetchMessageHistoryHoleResult?, NoError> {
|
||||||
let count = min(100, rawCount)
|
let count = min(100, rawCount)
|
||||||
|
|
||||||
return postbox.stateView()
|
return postbox.stateView()
|
||||||
@ -171,7 +171,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> mapToSignal { _ -> Signal<FetchMessageHistoryHoleResult, NoError> in
|
|> mapToSignal { _ -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||||
return postbox.transaction { transaction -> (Api.InputPeer?, Int32) in
|
return postbox.transaction { transaction -> (Api.InputPeer?, Int32) in
|
||||||
switch peerInput {
|
switch peerInput {
|
||||||
case let .direct(peerId, _):
|
case let .direct(peerId, _):
|
||||||
@ -180,7 +180,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||||||
return (transaction.getPeer(channelMessageId.peerId).flatMap(forceApiInputPeer), 0)
|
return (transaction.getPeer(channelMessageId.peerId).flatMap(forceApiInputPeer), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> mapToSignal { (inputPeer, hash) -> Signal<FetchMessageHistoryHoleResult, NoError> in
|
|> mapToSignal { (inputPeer, hash) -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||||
guard let inputPeer = inputPeer else {
|
guard let inputPeer = inputPeer else {
|
||||||
return .single(FetchMessageHistoryHoleResult(removedIndices: IndexSet(), strictRemovedIndices: IndexSet(), actualPeerId: nil, actualThreadId: nil))
|
return .single(FetchMessageHistoryHoleResult(removedIndices: IndexSet(), strictRemovedIndices: IndexSet(), actualPeerId: nil, actualThreadId: nil))
|
||||||
}
|
}
|
||||||
@ -404,8 +404,27 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||||||
}
|
}
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|> retryRequest
|
|> retry(retryOnError: { error in
|
||||||
|> mapToSignal { result -> Signal<FetchMessageHistoryHoleResult, NoError> in
|
if error.errorDescription == "CHANNEL_PRIVATE" {
|
||||||
|
switch peerInput {
|
||||||
|
case let .direct(_, threadId):
|
||||||
|
if threadId != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case .threadFromChannel:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}, delayIncrement: 0.1, maxDelay: 2.0, maxRetries: 0, onQueue: .concurrentDefaultQueue())
|
||||||
|
|> map(Optional.init)
|
||||||
|
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||||
|
guard let result = result else {
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
let messages: [Api.Message]
|
let messages: [Api.Message]
|
||||||
let chats: [Api.Chat]
|
let chats: [Api.Chat]
|
||||||
let users: [Api.User]
|
let users: [Api.User]
|
||||||
|
@ -225,7 +225,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
self.currentHole?.1.dispose()
|
self.currentHole?.1.dispose()
|
||||||
if let entry = entry {
|
if let entry = entry {
|
||||||
self.currentHole = (entry, self.fetchHole(entry: entry).start(next: { [weak self] removedHoleIndices in
|
self.currentHole = (entry, self.fetchHole(entry: entry).start(next: { [weak self] removedHoleIndices in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self, let removedHoleIndices = removedHoleIndices else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if var currentHoles = strongSelf.stateValue?.holeIndices[Namespaces.Message.Cloud] {
|
if var currentHoles = strongSelf.stateValue?.holeIndices[Namespaces.Message.Cloud] {
|
||||||
@ -239,7 +239,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchHole(entry: MessageHistoryHolesViewEntry) -> Signal<FetchMessageHistoryHoleResult, NoError> {
|
private func fetchHole(entry: MessageHistoryHolesViewEntry) -> Signal<FetchMessageHistoryHoleResult?, NoError> {
|
||||||
switch entry.hole {
|
switch entry.hole {
|
||||||
case let .peer(hole):
|
case let .peer(hole):
|
||||||
let fetchCount = min(entry.count, 100)
|
let fetchCount = min(entry.count, 100)
|
||||||
@ -386,8 +386,9 @@ public struct ChatReplyThreadMessage: Equatable {
|
|||||||
public var maxReadOutgoingMessageId: MessageId?
|
public var maxReadOutgoingMessageId: MessageId?
|
||||||
public var initialFilledHoles: IndexSet
|
public var initialFilledHoles: IndexSet
|
||||||
public var initialAnchor: Anchor
|
public var initialAnchor: Anchor
|
||||||
|
public var isNotAvailable: Bool
|
||||||
|
|
||||||
fileprivate init(messageId: MessageId, isChannelPost: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, initialFilledHoles: IndexSet, initialAnchor: Anchor) {
|
fileprivate init(messageId: MessageId, isChannelPost: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, initialFilledHoles: IndexSet, initialAnchor: Anchor, isNotAvailable: Bool) {
|
||||||
self.messageId = messageId
|
self.messageId = messageId
|
||||||
self.isChannelPost = isChannelPost
|
self.isChannelPost = isChannelPost
|
||||||
self.maxMessage = maxMessage
|
self.maxMessage = maxMessage
|
||||||
@ -395,6 +396,7 @@ public struct ChatReplyThreadMessage: Equatable {
|
|||||||
self.maxReadOutgoingMessageId = maxReadOutgoingMessageId
|
self.maxReadOutgoingMessageId = maxReadOutgoingMessageId
|
||||||
self.initialFilledHoles = initialFilledHoles
|
self.initialFilledHoles = initialFilledHoles
|
||||||
self.initialAnchor = initialAnchor
|
self.initialAnchor = initialAnchor
|
||||||
|
self.isNotAvailable = isNotAvailable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,11 +592,11 @@ public func fetchChannelReplyThreadMessage(account: Account, messageId: MessageI
|
|||||||
}
|
}
|
||||||
|
|
||||||
let preloadedHistory = preloadedHistoryPosition
|
let preloadedHistory = preloadedHistoryPosition
|
||||||
|> mapToSignal { peerInput, commentsPeerId, threadMessageId, anchor, maxMessageId -> Signal<(FetchMessageHistoryHoleResult, ChatReplyThreadMessage.Anchor), FetchChannelReplyThreadMessageError> in
|
|> mapToSignal { peerInput, commentsPeerId, threadMessageId, anchor, maxMessageId -> Signal<(FetchMessageHistoryHoleResult?, ChatReplyThreadMessage.Anchor), FetchChannelReplyThreadMessageError> in
|
||||||
guard let maxMessageId = maxMessageId else {
|
guard let maxMessageId = maxMessageId else {
|
||||||
return .single((FetchMessageHistoryHoleResult(removedIndices: IndexSet(integersIn: 1 ..< Int(Int32.max - 1)), strictRemovedIndices: IndexSet()), .automatic))
|
return .single((FetchMessageHistoryHoleResult(removedIndices: IndexSet(integersIn: 1 ..< Int(Int32.max - 1)), strictRemovedIndices: IndexSet()), .automatic))
|
||||||
}
|
}
|
||||||
return account.postbox.transaction { transaction -> Signal<(FetchMessageHistoryHoleResult, ChatReplyThreadMessage.Anchor), FetchChannelReplyThreadMessageError> in
|
return account.postbox.transaction { transaction -> Signal<(FetchMessageHistoryHoleResult?, ChatReplyThreadMessage.Anchor), FetchChannelReplyThreadMessageError> in
|
||||||
if let threadMessageId = threadMessageId {
|
if let threadMessageId = threadMessageId {
|
||||||
var holes = transaction.getThreadIndexHoles(peerId: threadMessageId.peerId, threadId: makeMessageThreadId(threadMessageId), namespace: Namespaces.Message.Cloud)
|
var holes = transaction.getThreadIndexHoles(peerId: threadMessageId.peerId, threadId: makeMessageThreadId(threadMessageId), namespace: Namespaces.Message.Cloud)
|
||||||
holes.remove(integersIn: Int(maxMessageId.id + 1) ..< Int(Int32.max))
|
holes.remove(integersIn: Int(maxMessageId.id + 1) ..< Int(Int32.max))
|
||||||
@ -660,8 +662,11 @@ public func fetchChannelReplyThreadMessage(account: Account, messageId: MessageI
|
|||||||
}
|
}
|
||||||
return fetchMessageHistoryHole(accountPeerId: account.peerId, source: .network(account.network), postbox: account.postbox, peerInput: peerInput, namespace: Namespaces.Message.Cloud, direction: direction, space: .everywhere, count: 40)
|
return fetchMessageHistoryHole(accountPeerId: account.peerId, source: .network(account.network), postbox: account.postbox, peerInput: peerInput, namespace: Namespaces.Message.Cloud, direction: direction, space: .everywhere, count: 40)
|
||||||
|> castError(FetchChannelReplyThreadMessageError.self)
|
|> castError(FetchChannelReplyThreadMessageError.self)
|
||||||
|> mapToSignal { result -> Signal<(FetchMessageHistoryHoleResult, ChatReplyThreadMessage.Anchor), FetchChannelReplyThreadMessageError> in
|
|> mapToSignal { result -> Signal<(FetchMessageHistoryHoleResult?, ChatReplyThreadMessage.Anchor), FetchChannelReplyThreadMessageError> in
|
||||||
return account.postbox.transaction { transaction -> (FetchMessageHistoryHoleResult, ChatReplyThreadMessage.Anchor) in
|
return account.postbox.transaction { transaction -> (FetchMessageHistoryHoleResult?, ChatReplyThreadMessage.Anchor) in
|
||||||
|
guard let result = result else {
|
||||||
|
return (nil, .automatic)
|
||||||
|
}
|
||||||
let initialAnchor: ChatReplyThreadMessage.Anchor
|
let initialAnchor: ChatReplyThreadMessage.Anchor
|
||||||
switch anchor {
|
switch anchor {
|
||||||
case .lowerBound:
|
case .lowerBound:
|
||||||
@ -700,9 +705,11 @@ public func fetchChannelReplyThreadMessage(account: Account, messageId: MessageI
|
|||||||
}
|
}
|
||||||
let (initialFilledHoles, initialAnchor) = initialFilledHolesAndInitialAnchor
|
let (initialFilledHoles, initialAnchor) = initialFilledHolesAndInitialAnchor
|
||||||
return account.postbox.transaction { transaction -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> in
|
return account.postbox.transaction { transaction -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> in
|
||||||
|
if let initialFilledHoles = initialFilledHoles {
|
||||||
for range in initialFilledHoles.strictRemovedIndices.rangeView {
|
for range in initialFilledHoles.strictRemovedIndices.rangeView {
|
||||||
transaction.removeThreadIndexHole(peerId: discussionMessage.messageId.peerId, threadId: makeMessageThreadId(discussionMessage.messageId), namespace: Namespaces.Message.Cloud, space: .everywhere, range: Int32(range.lowerBound) ... Int32(range.upperBound))
|
transaction.removeThreadIndexHole(peerId: discussionMessage.messageId.peerId, threadId: makeMessageThreadId(discussionMessage.messageId), namespace: Namespaces.Message.Cloud, space: .everywhere, range: Int32(range.lowerBound) ... Int32(range.upperBound))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return .single(ChatReplyThreadMessage(
|
return .single(ChatReplyThreadMessage(
|
||||||
messageId: discussionMessage.messageId,
|
messageId: discussionMessage.messageId,
|
||||||
@ -710,8 +717,9 @@ public func fetchChannelReplyThreadMessage(account: Account, messageId: MessageI
|
|||||||
maxMessage: discussionMessage.maxMessage,
|
maxMessage: discussionMessage.maxMessage,
|
||||||
maxReadIncomingMessageId: discussionMessage.maxReadIncomingMessageId,
|
maxReadIncomingMessageId: discussionMessage.maxReadIncomingMessageId,
|
||||||
maxReadOutgoingMessageId: discussionMessage.maxReadOutgoingMessageId,
|
maxReadOutgoingMessageId: discussionMessage.maxReadOutgoingMessageId,
|
||||||
initialFilledHoles: initialFilledHoles.removedIndices,
|
initialFilledHoles: initialFilledHoles?.removedIndices ?? IndexSet(),
|
||||||
initialAnchor: initialAnchor
|
initialAnchor: initialAnchor,
|
||||||
|
isNotAvailable: initialFilledHoles == nil
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|> castError(FetchChannelReplyThreadMessageError.self)
|
|> castError(FetchChannelReplyThreadMessageError.self)
|
||||||
|
@ -4,8 +4,13 @@ import SwiftSignalKit
|
|||||||
|
|
||||||
import SyncCore
|
import SyncCore
|
||||||
|
|
||||||
public func updatePeerChatInterfaceState(account: Account, peerId: PeerId, state: SynchronizeableChatInterfaceState) -> Signal<Void, NoError> {
|
public func updatePeerChatInterfaceState(account: Account, peerId: PeerId, threadId: Int64?, state: SynchronizeableChatInterfaceState) -> Signal<Void, NoError> {
|
||||||
return account.postbox.transaction { transaction -> Void in
|
return account.postbox.transaction { transaction -> Void in
|
||||||
|
if let threadId = threadId {
|
||||||
|
transaction.updatePeerChatThreadInterfaceState(peerId, threadId: threadId, update: { _ in
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
} else {
|
||||||
let currentInputState = (transaction.getPeerChatInterfaceState(peerId) as? SynchronizeableChatInterfaceState)?.synchronizeableInputState
|
let currentInputState = (transaction.getPeerChatInterfaceState(peerId) as? SynchronizeableChatInterfaceState)?.synchronizeableInputState
|
||||||
let updatedInputState = state.synchronizeableInputState
|
let updatedInputState = state.synchronizeableInputState
|
||||||
|
|
||||||
@ -18,4 +23,5 @@ public func updatePeerChatInterfaceState(account: Account, peerId: PeerId, state
|
|||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -17,11 +17,13 @@ private let messageBoldItalicFont = Font.semiboldItalic(17.0)
|
|||||||
private let messageFixedFont = UIFont(name: "Menlo-Regular", size: 16.0) ?? UIFont.systemFont(ofSize: 17.0)
|
private let messageFixedFont = UIFont(name: "Menlo-Regular", size: 16.0) ?? UIFont.systemFont(ofSize: 17.0)
|
||||||
|
|
||||||
final class ChatBotInfoItem: ListViewItem {
|
final class ChatBotInfoItem: ListViewItem {
|
||||||
|
fileprivate let title: String
|
||||||
fileprivate let text: String
|
fileprivate let text: String
|
||||||
fileprivate let controllerInteraction: ChatControllerInteraction
|
fileprivate let controllerInteraction: ChatControllerInteraction
|
||||||
fileprivate let presentationData: ChatPresentationData
|
fileprivate let presentationData: ChatPresentationData
|
||||||
|
|
||||||
init(text: String, controllerInteraction: ChatControllerInteraction, presentationData: ChatPresentationData) {
|
init(title: String, text: String, controllerInteraction: ChatControllerInteraction, presentationData: ChatPresentationData) {
|
||||||
|
self.title = title
|
||||||
self.text = text
|
self.text = text
|
||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
@ -163,7 +165,7 @@ final class ChatBotInfoItemNode: ListViewItemNode {
|
|||||||
let verticalItemInset: CGFloat = 10.0
|
let verticalItemInset: CGFloat = 10.0
|
||||||
let verticalContentInset: CGFloat = 8.0
|
let verticalContentInset: CGFloat = 8.0
|
||||||
|
|
||||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Bot_DescriptionTitle, font: messageBoldFont, textColor: item.presentationData.theme.theme.chat.message.infoPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - horizontalEdgeInset * 2.0 - horizontalContentInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: messageBoldFont, textColor: item.presentationData.theme.theme.chat.message.infoPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - horizontalEdgeInset * 2.0 - horizontalContentInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - horizontalEdgeInset * 2.0 - horizontalContentInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - horizontalEdgeInset * 2.0 - horizontalContentInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
@ -174,7 +176,7 @@ final class ChatBotInfoItemNode: ListViewItemNode {
|
|||||||
let titleFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + verticalContentInset), size: titleLayout.size)
|
let titleFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + verticalContentInset), size: titleLayout.size)
|
||||||
let textFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + verticalContentInset + titleLayout.size.height + textSpacing), size: textLayout.size)
|
let textFrame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + horizontalContentInset, y: backgroundFrame.origin.y + verticalContentInset + titleLayout.size.height + textSpacing), size: textLayout.size)
|
||||||
|
|
||||||
let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: textLayout.size.height + verticalItemInset * 2.0 + verticalContentInset * 2.0 + 4.0), insets: UIEdgeInsets())
|
let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: textLayout.size.height + verticalItemInset * 2.0 + verticalContentInset * 2.0 + 18.0), insets: UIEdgeInsets())
|
||||||
return (itemLayout, { _ in
|
return (itemLayout, { _ in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.theme = item.presentationData.theme
|
strongSelf.theme = item.presentationData.theme
|
||||||
|
@ -3231,14 +3231,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
guard let strongSelf = self, let combinedInitialData = combinedInitialData else {
|
guard let strongSelf = self, let combinedInitialData = combinedInitialData else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if var interfaceState = combinedInitialData.initialData?.chatInterfaceState as? ChatInterfaceState {
|
if let interfaceState = combinedInitialData.initialData?.chatInterfaceState as? ChatInterfaceState {
|
||||||
switch strongSelf.chatLocation {
|
|
||||||
case .peer:
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
interfaceState = ChatInterfaceState()
|
|
||||||
}
|
|
||||||
|
|
||||||
var pinnedMessageId: MessageId?
|
var pinnedMessageId: MessageId?
|
||||||
var peerIsBlocked: Bool = false
|
var peerIsBlocked: Bool = false
|
||||||
var callsAvailable: Bool = true
|
var callsAvailable: Bool = true
|
||||||
@ -5715,16 +5708,24 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func saveInterfaceState(includeScrollState: Bool = true) {
|
private func saveInterfaceState(includeScrollState: Bool = true) {
|
||||||
if case let .peer(peerId) = self.chatLocation {
|
var peerId: PeerId
|
||||||
|
var threadId: Int64?
|
||||||
|
switch self.chatLocation {
|
||||||
|
case let .peer(peerIdValue):
|
||||||
|
peerId = peerIdValue
|
||||||
|
case let .replyThread(replyThreadMessage):
|
||||||
|
peerId = replyThreadMessage.messageId.peerId
|
||||||
|
threadId = makeMessageThreadId(replyThreadMessage.messageId)
|
||||||
|
}
|
||||||
|
|
||||||
let timestamp = Int32(Date().timeIntervalSince1970)
|
let timestamp = Int32(Date().timeIntervalSince1970)
|
||||||
var interfaceState = self.presentationInterfaceState.interfaceState.withUpdatedTimestamp(timestamp)
|
var interfaceState = self.presentationInterfaceState.interfaceState.withUpdatedTimestamp(timestamp)
|
||||||
if includeScrollState {
|
if includeScrollState && threadId == nil {
|
||||||
let scrollState = self.chatDisplayNode.historyNode.immediateScrollState()
|
let scrollState = self.chatDisplayNode.historyNode.immediateScrollState()
|
||||||
interfaceState = interfaceState.withUpdatedHistoryScrollState(scrollState)
|
interfaceState = interfaceState.withUpdatedHistoryScrollState(scrollState)
|
||||||
}
|
}
|
||||||
interfaceState = interfaceState.withUpdatedInputLanguage(self.chatDisplayNode.currentTextInputLanguage)
|
interfaceState = interfaceState.withUpdatedInputLanguage(self.chatDisplayNode.currentTextInputLanguage)
|
||||||
let _ = updatePeerChatInterfaceState(account: self.context.account, peerId: peerId, state: interfaceState).start()
|
let _ = updatePeerChatInterfaceState(account: self.context.account, peerId: peerId, threadId: threadId, state: interfaceState).start()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func viewDidDisappear(_ animated: Bool) {
|
override public func viewDidDisappear(_ animated: Bool) {
|
||||||
@ -8359,7 +8360,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
controllerInteraction.currentMessageWithLoadingReplyThread = displayProgressInMessage
|
controllerInteraction.currentMessageWithLoadingReplyThread = displayProgressInMessage
|
||||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage)
|
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage)
|
||||||
if let previousId = previousId {
|
if let previousId = previousId {
|
||||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage)
|
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(previousId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8368,7 +8369,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else {
|
guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let displayProgressInMessage = displayProgressInMessage, controllerInteraction.currentMessageWithLoadingReplyThread == messageId {
|
if let displayProgressInMessage = displayProgressInMessage, controllerInteraction.currentMessageWithLoadingReplyThread == displayProgressInMessage {
|
||||||
controllerInteraction.currentMessageWithLoadingReplyThread = nil
|
controllerInteraction.currentMessageWithLoadingReplyThread = nil
|
||||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage)
|
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage)
|
||||||
}
|
}
|
||||||
|
@ -1964,7 +1964,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
if let peer = chatPresentationInterfaceState.renderedPeer?.peer, let restrictionTextValue = peer.restrictionText(platform: "ios", contentSettings: self.context.currentContentSettings.with { $0 }), !restrictionTextValue.isEmpty {
|
if let peer = chatPresentationInterfaceState.renderedPeer?.peer, let restrictionTextValue = peer.restrictionText(platform: "ios", contentSettings: self.context.currentContentSettings.with { $0 }), !restrictionTextValue.isEmpty {
|
||||||
restrictionText = restrictionTextValue
|
restrictionText = restrictionTextValue
|
||||||
} else if chatPresentationInterfaceState.isNotAccessible {
|
} else if chatPresentationInterfaceState.isNotAccessible {
|
||||||
if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = peer.info {
|
if case .replyThread = self.chatLocation {
|
||||||
|
restrictionText = chatPresentationInterfaceState.strings.CommentsGroup_ErrorAccessDenied
|
||||||
|
} else if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
restrictionText = chatPresentationInterfaceState.strings.Channel_ErrorAccessDenied
|
restrictionText = chatPresentationInterfaceState.strings.Channel_ErrorAccessDenied
|
||||||
} else {
|
} else {
|
||||||
restrictionText = chatPresentationInterfaceState.strings.Group_ErrorAccessDenied
|
restrictionText = chatPresentationInterfaceState.strings.Group_ErrorAccessDenied
|
||||||
|
@ -182,7 +182,7 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if includeChatInfoEntry {
|
if includeChatInfoEntry {
|
||||||
if view.earlierId == nil {
|
if view.earlierId == nil, !view.isLoading {
|
||||||
var cachedPeerData: CachedPeerData?
|
var cachedPeerData: CachedPeerData?
|
||||||
for entry in view.additionalData {
|
for entry in view.additionalData {
|
||||||
if case let .cachedPeerData(_, data) = entry {
|
if case let .cachedPeerData(_, data) = entry {
|
||||||
@ -190,8 +190,10 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView,
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let cachedPeerData = cachedPeerData as? CachedUserData, let botInfo = cachedPeerData.botInfo, !botInfo.description.isEmpty {
|
if case let .peer(peerId) = location, peerId.isReplies {
|
||||||
entries.insert(.ChatInfoEntry(botInfo.description, presentationData), at: 0)
|
entries.insert(.ChatInfoEntry(presentationData.strings.RepliesChat_DescriptionTitle, presentationData.strings.RepliesChat_DescriptionText, presentationData), at: 0)
|
||||||
|
} else if let cachedPeerData = cachedPeerData as? CachedUserData, let botInfo = cachedPeerData.botInfo, !botInfo.description.isEmpty {
|
||||||
|
entries.insert(.ChatInfoEntry(presentationData.strings.Bot_DescriptionTitle, botInfo.description, presentationData), at: 0)
|
||||||
} else {
|
} else {
|
||||||
var isEmpty = true
|
var isEmpty = true
|
||||||
if entries.count <= 3 {
|
if entries.count <= 3 {
|
||||||
|
@ -38,7 +38,7 @@ enum ChatHistoryEntry: Identifiable, Comparable {
|
|||||||
case MessageGroupEntry(MessageGroupInfo, [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes)], ChatPresentationData)
|
case MessageGroupEntry(MessageGroupInfo, [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes)], ChatPresentationData)
|
||||||
case UnreadEntry(MessageIndex, ChatPresentationData)
|
case UnreadEntry(MessageIndex, ChatPresentationData)
|
||||||
case ReplyCountEntry(MessageIndex, Bool, Int, ChatPresentationData)
|
case ReplyCountEntry(MessageIndex, Bool, Int, ChatPresentationData)
|
||||||
case ChatInfoEntry(String, ChatPresentationData)
|
case ChatInfoEntry(String, String, ChatPresentationData)
|
||||||
case SearchEntry(PresentationTheme, PresentationStrings)
|
case SearchEntry(PresentationTheme, PresentationStrings)
|
||||||
|
|
||||||
var stableId: UInt64 {
|
var stableId: UInt64 {
|
||||||
@ -193,8 +193,8 @@ enum ChatHistoryEntry: Identifiable, Comparable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .ChatInfoEntry(lhsText, lhsPresentationData):
|
case let .ChatInfoEntry(lhsTitle, lhsText, lhsPresentationData):
|
||||||
if case let .ChatInfoEntry(rhsText, rhsPresentationData) = rhs, lhsText == rhsText, lhsPresentationData === rhsPresentationData {
|
if case let .ChatInfoEntry(rhsTitle, rhsText, rhsPresentationData) = rhs, lhsTitle == rhsTitle, lhsText == rhsText, lhsPresentationData === rhsPresentationData {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
@ -277,8 +277,8 @@ private func mappedInsertEntries(context: AccountContext, chatLocation: ChatLoca
|
|||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
||||||
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
||||||
case let .ChatInfoEntry(text, presentationData):
|
case let .ChatInfoEntry(title, text, presentationData):
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(text: text, controllerInteraction: controllerInteraction, presentationData: presentationData), directionHint: entry.directionHint)
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(title: title, text: text, controllerInteraction: controllerInteraction, presentationData: presentationData), directionHint: entry.directionHint)
|
||||||
case let .SearchEntry(theme, strings):
|
case let .SearchEntry(theme, strings):
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: {
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: {
|
||||||
controllerInteraction.openSearch()
|
controllerInteraction.openSearch()
|
||||||
@ -322,8 +322,8 @@ private func mappedUpdateEntries(context: AccountContext, chatLocation: ChatLoca
|
|||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
||||||
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
||||||
case let .ChatInfoEntry(text, presentationData):
|
case let .ChatInfoEntry(title, text, presentationData):
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(text: text, controllerInteraction: controllerInteraction, presentationData: presentationData), directionHint: entry.directionHint)
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatBotInfoItem(title: title, text: text, controllerInteraction: controllerInteraction, presentationData: presentationData), directionHint: entry.directionHint)
|
||||||
case let .SearchEntry(theme, strings):
|
case let .SearchEntry(theme, strings):
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: {
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSearchItem(theme: theme, placeholder: strings.Common_Search, activate: {
|
||||||
controllerInteraction.openSearch()
|
controllerInteraction.openSearch()
|
||||||
|
@ -348,6 +348,16 @@ func fetchAndPreloadReplyThreadInfo(context: AccountContext, subject: ReplyThrea
|
|||||||
scrollToLowerBoundMessage = index
|
scrollToLowerBoundMessage = index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if replyThreadMessage.isNotAvailable {
|
||||||
|
return .single(ReplyThreadInfo(
|
||||||
|
message: replyThreadMessage,
|
||||||
|
isChannelPost: replyThreadMessage.isChannelPost,
|
||||||
|
isEmpty: false,
|
||||||
|
scrollToLowerBoundMessage: nil,
|
||||||
|
contextHolder: chatLocationContextHolder
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
let preloadSignal = preloadedChatHistoryViewForLocation(
|
let preloadSignal = preloadedChatHistoryViewForLocation(
|
||||||
input,
|
input,
|
||||||
context: context,
|
context: context,
|
||||||
|
Binary file not shown.
@ -449,12 +449,12 @@ public final class WalletStrings: Equatable {
|
|||||||
public var Wallet_Send_ConfirmationConfirm: String { return self._s[218]! }
|
public var Wallet_Send_ConfirmationConfirm: String { return self._s[218]! }
|
||||||
public var Wallet_Created_ExportErrorTitle: String { return self._s[219]! }
|
public var Wallet_Created_ExportErrorTitle: String { return self._s[219]! }
|
||||||
public var Wallet_Info_TransactionPendingHeader: String { return self._s[220]! }
|
public var Wallet_Info_TransactionPendingHeader: String { return self._s[220]! }
|
||||||
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
||||||
let form = getPluralizationForm(self.lc, value)
|
let form = getPluralizationForm(self.lc, value)
|
||||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||||
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
|
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
|
||||||
}
|
}
|
||||||
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
||||||
let form = getPluralizationForm(self.lc, value)
|
let form = getPluralizationForm(self.lc, value)
|
||||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||||
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)
|
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user