mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
- Story search UI
- Delete message confirmation
This commit is contained in:
parent
6ccc9ed693
commit
d7bb7d55b4
46 changed files with 1534 additions and 951 deletions
|
|
@ -53,7 +53,7 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> {
|
|||
}
|
||||
|
||||
if !isMuted && hasUnread {
|
||||
signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: index.messageIndex.id.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: .combinedLocation)
|
||||
signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: index.messageIndex.id.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: .combinedLocation)
|
||||
|> take(1)
|
||||
|> map { view -> [INMessage] in
|
||||
var messages: [INMessage] = []
|
||||
|
|
|
|||
|
|
@ -678,7 +678,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
} else {
|
||||
inputTag = .tag(tags)
|
||||
}
|
||||
return context.account.postbox.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(message.index), ignoreMessagesInTimestampRange: nil, count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: inputTag, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [.combinedLocation])
|
||||
return context.account.postbox.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(message.index), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: inputTag, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [.combinedLocation])
|
||||
|> mapToSignal { (view, _, _) -> Signal<GalleryMessageHistoryView?, NoError> in
|
||||
let mapped = GalleryMessageHistoryView.view(view, peerIsCopyProtected)
|
||||
return .single(mapped)
|
||||
|
|
@ -1409,7 +1409,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
} else {
|
||||
namespaces = .not(Namespaces.Message.allNonRegular)
|
||||
}
|
||||
let signal = strongSelf.context.account.postbox.aroundMessageHistoryViewForLocation(strongSelf.context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(reloadAroundIndex), ignoreMessagesInTimestampRange: nil, count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: tag, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [.combinedLocation])
|
||||
let signal = strongSelf.context.account.postbox.aroundMessageHistoryViewForLocation(strongSelf.context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), anchor: .index(reloadAroundIndex), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 50, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: tag, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [.combinedLocation])
|
||||
|> mapToSignal { (view, _, _) -> Signal<GalleryMessageHistoryView?, NoError> in
|
||||
let mapped = GalleryMessageHistoryView.view(view, peerIsCopyProtected)
|
||||
return .single(mapped)
|
||||
|
|
|
|||
|
|
@ -1640,6 +1640,7 @@ struct ChatListViewState {
|
|||
includeFrom: true,
|
||||
to: .absoluteLowerBound().withPeerId(associatedMessageId.peerId).withNamespace(associatedMessageId.namespace),
|
||||
ignoreMessagesInTimestampRange: nil,
|
||||
ignoreMessageIds: Set(),
|
||||
limit: 2
|
||||
)
|
||||
for innerMessage in innerMessages {
|
||||
|
|
|
|||
|
|
@ -3227,7 +3227,7 @@ final class MessageHistoryTable: Table {
|
|||
return (messagesByMediaId, mediaRefs, count == 0 ? nil : lastIndex)
|
||||
}
|
||||
|
||||
func fetch(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags?, customTag: MemoryBuffer?, threadId: Int64?, from fromIndex: MessageIndex, includeFrom: Bool, to toIndex: MessageIndex, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, limit: Int) -> [IntermediateMessage] {
|
||||
func fetch(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags?, customTag: MemoryBuffer?, threadId: Int64?, from fromIndex: MessageIndex, includeFrom: Bool, to toIndex: MessageIndex, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, limit: Int) -> [IntermediateMessage] {
|
||||
precondition(fromIndex.id.peerId == toIndex.id.peerId)
|
||||
precondition(fromIndex.id.namespace == toIndex.id.namespace)
|
||||
|
||||
|
|
@ -3246,6 +3246,9 @@ final class MessageHistoryTable: Table {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !ignoreMessageIds.isEmpty && ignoreMessageIds.contains(index.id) {
|
||||
continue
|
||||
}
|
||||
if fromIndex < toIndex {
|
||||
if index < fromIndex || index > toIndex {
|
||||
continue
|
||||
|
|
@ -3274,6 +3277,9 @@ final class MessageHistoryTable: Table {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !ignoreMessageIds.isEmpty && ignoreMessageIds.contains(index.id) {
|
||||
continue
|
||||
}
|
||||
if fromIndex < toIndex {
|
||||
if index < fromIndex || index > toIndex {
|
||||
continue
|
||||
|
|
@ -3304,6 +3310,9 @@ final class MessageHistoryTable: Table {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !ignoreMessageIds.isEmpty && ignoreMessageIds.contains(index.id) {
|
||||
continue
|
||||
}
|
||||
if fromIndex < toIndex {
|
||||
if index < fromIndex || index > toIndex {
|
||||
continue
|
||||
|
|
@ -3343,6 +3352,9 @@ final class MessageHistoryTable: Table {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !ignoreMessageIds.isEmpty && ignoreMessageIds.contains(index.id) {
|
||||
continue
|
||||
}
|
||||
if let tag = tag {
|
||||
if self.tagsTable.entryExists(tag: tag, index: index) {
|
||||
indices.append(index)
|
||||
|
|
@ -3385,6 +3397,9 @@ final class MessageHistoryTable: Table {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !ignoreMessageIds.isEmpty && ignoreMessageIds.contains(index.id) {
|
||||
continue
|
||||
}
|
||||
if fromIndex < toIndex {
|
||||
if index < fromIndex || index > toIndex {
|
||||
continue
|
||||
|
|
@ -3400,7 +3415,7 @@ final class MessageHistoryTable: Table {
|
|||
assertionFailure()
|
||||
}
|
||||
}
|
||||
} else if ignoreMessagesInTimestampRange != nil {
|
||||
} else if ignoreMessagesInTimestampRange != nil || !ignoreMessageIds.isEmpty {
|
||||
var indices: [MessageIndex] = []
|
||||
var startIndex = fromIndex
|
||||
var localIncludeFrom = includeFrom
|
||||
|
|
@ -3435,6 +3450,9 @@ final class MessageHistoryTable: Table {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !ignoreMessageIds.isEmpty && ignoreMessageIds.contains(index.id) {
|
||||
continue
|
||||
}
|
||||
indices.append(index)
|
||||
if indices.count >= limit {
|
||||
break
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ public enum HistoryViewInputAnchor: Equatable {
|
|||
final class MutableMessageHistoryView: MutablePostboxView {
|
||||
private(set) var peerIds: MessageHistoryViewInput
|
||||
private let ignoreMessagesInTimestampRange: ClosedRange<Int32>?
|
||||
private let ignoreMessageIds: Set<MessageId>
|
||||
let tag: HistoryViewInputTag?
|
||||
private let appendMessagesFromTheSameGroup: Bool
|
||||
let namespaces: MessageIdNamespaces
|
||||
|
|
@ -337,6 +338,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
trackHoles: Bool,
|
||||
peerIds: MessageHistoryViewInput,
|
||||
ignoreMessagesInTimestampRange: ClosedRange<Int32>?,
|
||||
ignoreMessageIds: Set<MessageId>,
|
||||
anchor inputAnchor: HistoryViewInputAnchor,
|
||||
combinedReadStates: MessageHistoryViewReadState?,
|
||||
transientReadStates: MessageHistoryViewReadState?,
|
||||
|
|
@ -354,6 +356,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
self.trackHoles = trackHoles
|
||||
self.peerIds = peerIds
|
||||
self.ignoreMessagesInTimestampRange = ignoreMessagesInTimestampRange
|
||||
self.ignoreMessageIds = ignoreMessageIds
|
||||
self.combinedReadStates = combinedReadStates
|
||||
self.transientReadStates = transientReadStates
|
||||
self.tag = tag
|
||||
|
|
@ -382,12 +385,12 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
}
|
||||
}
|
||||
|
||||
self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, halfLimit: count + 1, locations: peerIds)
|
||||
self.state = HistoryViewState(postbox: postbox, inputAnchor: inputAnchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, halfLimit: count + 1, locations: peerIds)
|
||||
if case let .loading(loadingState) = self.state {
|
||||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
case let .ready(anchor, holes):
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, halfLimit: count + 1, locations: peerIds, postbox: postbox, holes: holes))
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, halfLimit: count + 1, locations: peerIds, postbox: postbox, holes: holes))
|
||||
self.sampledState = self.state.sample(postbox: postbox, clipHoles: self.clipHoles)
|
||||
case .loadHole:
|
||||
break
|
||||
|
|
@ -401,12 +404,12 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
}
|
||||
|
||||
private func reset(postbox: PostboxImpl) {
|
||||
self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, halfLimit: self.fillCount + 1, locations: self.peerIds)
|
||||
self.state = HistoryViewState(postbox: postbox, inputAnchor: self.anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, halfLimit: self.fillCount + 1, locations: self.peerIds)
|
||||
if case let .loading(loadingState) = self.state {
|
||||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
case let .ready(anchor, holes):
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
|
||||
case .loadHole:
|
||||
break
|
||||
}
|
||||
|
|
@ -415,7 +418,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
case let .ready(anchor, holes):
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
|
||||
case .loadHole:
|
||||
break
|
||||
}
|
||||
|
|
@ -771,7 +774,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
case let .ready(anchor, holes):
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
|
||||
self.state = .loaded(HistoryViewLoadedState(anchor: anchor, tag: self.tag, appendMessagesFromTheSameGroup: self.appendMessagesFromTheSameGroup, namespaces: self.namespaces, statistics: self.orderStatistics, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, halfLimit: self.fillCount + 1, locations: self.peerIds, postbox: postbox, holes: holes))
|
||||
case .loadHole:
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public enum MessageHistoryInput: Equatable, Hashable {
|
|||
}
|
||||
|
||||
private extension MessageHistoryInput {
|
||||
func fetch(postbox: PostboxImpl, peerId: PeerId, namespace: MessageId.Namespace, from fromIndex: MessageIndex, includeFrom: Bool, to toIndex: MessageIndex, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, limit: Int) -> [IntermediateMessage] {
|
||||
func fetch(postbox: PostboxImpl, peerId: PeerId, namespace: MessageId.Namespace, from fromIndex: MessageIndex, includeFrom: Bool, to toIndex: MessageIndex, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, limit: Int) -> [IntermediateMessage] {
|
||||
switch self {
|
||||
case let .automatic(threadId, tagInfo):
|
||||
var tag: MessageTags?
|
||||
|
|
@ -65,7 +65,7 @@ private extension MessageHistoryInput {
|
|||
}
|
||||
}
|
||||
|
||||
var items = postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: tag, customTag: customTag, threadId: threadId, from: fromIndex, includeFrom: includeFrom || shouldAddFromSameGroup, to: toIndex, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, limit: limit)
|
||||
var items = postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: tag, customTag: customTag, threadId: threadId, from: fromIndex, includeFrom: includeFrom || shouldAddFromSameGroup, to: toIndex, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, limit: limit)
|
||||
|
||||
if shouldAddFromSameGroup {
|
||||
enum Direction {
|
||||
|
|
@ -152,7 +152,7 @@ private extension MessageHistoryInput {
|
|||
case let .external(input, tag):
|
||||
switch input.content {
|
||||
case let .thread(peerId, id, _):
|
||||
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: tag, customTag: nil, threadId: id, from: fromIndex, includeFrom: includeFrom, to: toIndex, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, limit: limit)
|
||||
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: tag, customTag: nil, threadId: id, from: fromIndex, includeFrom: includeFrom, to: toIndex, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, limit: limit)
|
||||
case let .messages(allIndices, _, _):
|
||||
if allIndices.isEmpty {
|
||||
return []
|
||||
|
|
@ -213,6 +213,9 @@ private extension MessageHistoryInput {
|
|||
continue
|
||||
}
|
||||
}
|
||||
if !ignoreMessageIds.isEmpty && ignoreMessageIds.contains(index.id) {
|
||||
continue
|
||||
}
|
||||
indices.append(index)
|
||||
}
|
||||
if indices.count >= limit {
|
||||
|
|
@ -1301,18 +1304,20 @@ final class HistoryViewLoadedState {
|
|||
let input: MessageHistoryInput
|
||||
let statistics: MessageHistoryViewOrderStatistics
|
||||
let ignoreMessagesInTimestampRange: ClosedRange<Int32>?
|
||||
let ignoreMessageIds: Set<MessageId>
|
||||
let halfLimit: Int
|
||||
let seedConfiguration: SeedConfiguration
|
||||
var orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries]
|
||||
var holes: HistoryViewHoles
|
||||
var spacesWithRemovals = Set<PeerIdAndNamespace>()
|
||||
|
||||
init(anchor: HistoryViewAnchor, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, halfLimit: Int, locations: MessageHistoryViewInput, postbox: PostboxImpl, holes: HistoryViewHoles) {
|
||||
init(anchor: HistoryViewAnchor, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, halfLimit: Int, locations: MessageHistoryViewInput, postbox: PostboxImpl, holes: HistoryViewHoles) {
|
||||
precondition(halfLimit >= 3)
|
||||
self.anchor = anchor
|
||||
self.namespaces = namespaces
|
||||
self.statistics = statistics
|
||||
self.ignoreMessagesInTimestampRange = ignoreMessagesInTimestampRange
|
||||
self.ignoreMessageIds = ignoreMessageIds
|
||||
self.halfLimit = halfLimit
|
||||
self.seedConfiguration = postbox.seedConfiguration
|
||||
self.orderedEntriesBySpace = [:]
|
||||
|
|
@ -1419,7 +1424,7 @@ final class HistoryViewLoadedState {
|
|||
} else {
|
||||
nextLowerIndex = (anchorIndex, true)
|
||||
}
|
||||
lowerOrAtAnchorMessages.append(contentsOf: self.input.fetch(postbox: postbox, peerId: space.peerId, namespace: space.namespace, from: nextLowerIndex.index, includeFrom: nextLowerIndex.includeFrom, to: lowerBound, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, limit: self.halfLimit - lowerOrAtAnchorMessages.count).map(mapEntry))
|
||||
lowerOrAtAnchorMessages.append(contentsOf: self.input.fetch(postbox: postbox, peerId: space.peerId, namespace: space.namespace, from: nextLowerIndex.index, includeFrom: nextLowerIndex.includeFrom, to: lowerBound, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, limit: self.halfLimit - lowerOrAtAnchorMessages.count).map(mapEntry))
|
||||
}
|
||||
if higherThanAnchorMessages.count < self.halfLimit {
|
||||
let nextHigherIndex: MessageIndex
|
||||
|
|
@ -1428,7 +1433,7 @@ final class HistoryViewLoadedState {
|
|||
} else {
|
||||
nextHigherIndex = anchorIndex
|
||||
}
|
||||
higherThanAnchorMessages.append(contentsOf: self.input.fetch(postbox: postbox, peerId: space.peerId, namespace: space.namespace, from: nextHigherIndex, includeFrom: false, to: upperBound, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, limit: self.halfLimit - higherThanAnchorMessages.count).map(mapEntry))
|
||||
higherThanAnchorMessages.append(contentsOf: self.input.fetch(postbox: postbox, peerId: space.peerId, namespace: space.namespace, from: nextHigherIndex, includeFrom: false, to: upperBound, ignoreMessagesInTimestampRange: self.ignoreMessagesInTimestampRange, ignoreMessageIds: self.ignoreMessageIds, limit: self.halfLimit - higherThanAnchorMessages.count).map(mapEntry))
|
||||
}
|
||||
|
||||
lowerOrAtAnchorMessages.reverse()
|
||||
|
|
@ -1703,6 +1708,9 @@ final class HistoryViewLoadedState {
|
|||
return false
|
||||
}
|
||||
}
|
||||
if !self.ignoreMessageIds.isEmpty && self.ignoreMessageIds.contains(entry.index.id) {
|
||||
return false
|
||||
}
|
||||
|
||||
let space = PeerIdAndNamespace(peerId: entry.index.id.peerId, namespace: entry.index.id.namespace)
|
||||
|
||||
|
|
@ -2120,90 +2128,90 @@ enum HistoryViewState {
|
|||
case loaded(HistoryViewLoadedState)
|
||||
case loading(HistoryViewLoadingState)
|
||||
|
||||
init(postbox: PostboxImpl, inputAnchor: HistoryViewInputAnchor, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, halfLimit: Int, locations: MessageHistoryViewInput) {
|
||||
init(postbox: PostboxImpl, inputAnchor: HistoryViewInputAnchor, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, halfLimit: Int, locations: MessageHistoryViewInput) {
|
||||
switch inputAnchor {
|
||||
case let .index(index):
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .index(index), tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
case .lowerBound:
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .lowerBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
case .upperBound:
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
case .unread:
|
||||
let anchorPeerId: PeerId
|
||||
switch locations {
|
||||
case let .single(peerId, threadId):
|
||||
anchorPeerId = peerId
|
||||
if threadId != nil {
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
return
|
||||
}
|
||||
case let .associated(peerId, _):
|
||||
anchorPeerId = peerId
|
||||
case .external:
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
return
|
||||
case let .index(index):
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .index(index), tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
case .lowerBound:
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .lowerBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
case .upperBound:
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
case .unread:
|
||||
let anchorPeerId: PeerId
|
||||
switch locations {
|
||||
case let .single(peerId, threadId):
|
||||
anchorPeerId = peerId
|
||||
if threadId != nil {
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
return
|
||||
}
|
||||
if postbox.chatListIndexTable.get(peerId: anchorPeerId).includedIndex(peerId: anchorPeerId) != nil, let combinedState = postbox.readStateTable.getCombinedState(anchorPeerId) {
|
||||
var messageId: MessageId?
|
||||
var anchor: HistoryViewAnchor?
|
||||
loop: for (namespace, state) in combinedState.states {
|
||||
switch state {
|
||||
case let .idBased(maxIncomingReadId, _, _, count, _):
|
||||
if count == 0 {
|
||||
anchor = .upperBound
|
||||
break loop
|
||||
} else {
|
||||
messageId = MessageId(peerId: anchorPeerId, namespace: namespace, id: maxIncomingReadId)
|
||||
break loop
|
||||
}
|
||||
case let .indexBased(maxIncomingReadIndex, _, count, _):
|
||||
if count == 0 {
|
||||
anchor = .upperBound
|
||||
break loop
|
||||
} else {
|
||||
anchor = .index(maxIncomingReadIndex)
|
||||
break loop
|
||||
}
|
||||
}
|
||||
}
|
||||
if let messageId = messageId {
|
||||
let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, threadId: nil, namespaces: namespaces, messageId: messageId, halfLimit: halfLimit)
|
||||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
case let .ready(anchor, holes):
|
||||
self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
|
||||
case .loadHole:
|
||||
self = .loading(loadingState)
|
||||
}
|
||||
case let .associated(peerId, _):
|
||||
anchorPeerId = peerId
|
||||
case .external:
|
||||
self = .loaded(HistoryViewLoadedState(anchor: .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
return
|
||||
}
|
||||
if postbox.chatListIndexTable.get(peerId: anchorPeerId).includedIndex(peerId: anchorPeerId) != nil, let combinedState = postbox.readStateTable.getCombinedState(anchorPeerId) {
|
||||
var messageId: MessageId?
|
||||
var anchor: HistoryViewAnchor?
|
||||
loop: for (namespace, state) in combinedState.states {
|
||||
switch state {
|
||||
case let .idBased(maxIncomingReadId, _, _, count, _):
|
||||
if count == 0 {
|
||||
anchor = .upperBound
|
||||
break loop
|
||||
} else {
|
||||
self = .loaded(HistoryViewLoadedState(anchor: anchor ?? .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
messageId = MessageId(peerId: anchorPeerId, namespace: namespace, id: maxIncomingReadId)
|
||||
break loop
|
||||
}
|
||||
} else {
|
||||
preconditionFailure()
|
||||
}
|
||||
case let .message(messageId):
|
||||
var threadId: Int64?
|
||||
switch locations {
|
||||
case let .single(_, threadIdValue):
|
||||
threadId = threadIdValue
|
||||
case let .external(input):
|
||||
switch input.content {
|
||||
case let .thread(_, id, _):
|
||||
threadId = id
|
||||
case .messages:
|
||||
break
|
||||
case let .indexBased(maxIncomingReadIndex, _, count, _):
|
||||
if count == 0 {
|
||||
anchor = .upperBound
|
||||
break loop
|
||||
} else {
|
||||
anchor = .index(maxIncomingReadIndex)
|
||||
break loop
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, threadId: threadId, namespaces: namespaces, messageId: messageId, halfLimit: halfLimit)
|
||||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
}
|
||||
if let messageId = messageId {
|
||||
let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, threadId: nil, namespaces: namespaces, messageId: messageId, halfLimit: halfLimit)
|
||||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
case let .ready(anchor, holes):
|
||||
self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
|
||||
self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
|
||||
case .loadHole:
|
||||
self = .loading(loadingState)
|
||||
}
|
||||
} else {
|
||||
self = .loaded(HistoryViewLoadedState(anchor: anchor ?? .upperBound, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces))))
|
||||
}
|
||||
} else {
|
||||
preconditionFailure()
|
||||
}
|
||||
case let .message(messageId):
|
||||
var threadId: Int64?
|
||||
switch locations {
|
||||
case let .single(_, threadIdValue):
|
||||
threadId = threadIdValue
|
||||
case let .external(input):
|
||||
switch input.content {
|
||||
case let .thread(_, id, _):
|
||||
threadId = id
|
||||
case .messages:
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
let loadingState = HistoryViewLoadingState(postbox: postbox, locations: locations, tag: tag, threadId: threadId, namespaces: namespaces, messageId: messageId, halfLimit: halfLimit)
|
||||
let sampledState = loadingState.checkAndSample(postbox: postbox)
|
||||
switch sampledState {
|
||||
case let .ready(anchor, holes):
|
||||
self = .loaded(HistoryViewLoadedState(anchor: anchor, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, statistics: statistics, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: holes))
|
||||
case .loadHole:
|
||||
self = .loading(loadingState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
|
|||
}
|
||||
}
|
||||
self.anchor = anchor
|
||||
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, trackHoles: true, peerIds: peerIds, ignoreMessagesInTimestampRange: nil, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [])
|
||||
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, trackHoles: true, peerIds: peerIds, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [])
|
||||
let _ = self.updateFromView()
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
|
|||
case let .peer(id, threadId):
|
||||
peerIds = postbox.peerIdsForLocation(.peer(peerId: id, threadId: threadId), ignoreRelatedChats: false)
|
||||
}
|
||||
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, trackHoles: false, peerIds: peerIds, ignoreMessagesInTimestampRange: nil, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [])
|
||||
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, trackHoles: false, peerIds: peerIds, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [])
|
||||
return self.updateFromView()
|
||||
} else if self.wrappedView.replay(postbox: postbox, transaction: transaction) {
|
||||
var reloadView = false
|
||||
|
|
@ -167,7 +167,7 @@ final class MutableMessageOfInterestHolesView: MutablePostboxView {
|
|||
case let .peer(id, threadId):
|
||||
peerIds = postbox.peerIdsForLocation(.peer(peerId: id, threadId: threadId), ignoreRelatedChats: false)
|
||||
}
|
||||
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, trackHoles: false, peerIds: peerIds, ignoreMessagesInTimestampRange: nil, anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [])
|
||||
self.wrappedView = MutableMessageHistoryView(postbox: postbox, orderStatistics: [], clipHoles: true, trackHoles: false, peerIds: peerIds, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), anchor: self.anchor, combinedReadStates: nil, transientReadStates: nil, tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .all, count: self.count, topTaggedMessages: [:], additionalDatas: [])
|
||||
}
|
||||
|
||||
return self.updateFromView()
|
||||
|
|
|
|||
|
|
@ -1077,7 +1077,7 @@ public final class Transaction {
|
|||
guard let postbox = self.postbox else {
|
||||
return []
|
||||
}
|
||||
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: nil, threadId: threadId, from: from, includeFrom: includeFrom, to: to, ignoreMessagesInTimestampRange: nil, limit: limit).map(postbox.renderIntermediateMessage(_:))
|
||||
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: nil, threadId: threadId, from: from, includeFrom: includeFrom, to: to, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), limit: limit).map(postbox.renderIntermediateMessage(_:))
|
||||
}
|
||||
|
||||
public func getMessagesWithCustomTag(peerId: PeerId, namespace: MessageId.Namespace, threadId: Int64?, customTag: MemoryBuffer, from: MessageIndex, includeFrom: Bool, to: MessageIndex, limit: Int) -> [Message] {
|
||||
|
|
@ -1085,7 +1085,7 @@ public final class Transaction {
|
|||
guard let postbox = self.postbox else {
|
||||
return []
|
||||
}
|
||||
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: customTag, threadId: threadId, from: from, includeFrom: includeFrom, to: to, ignoreMessagesInTimestampRange: nil, limit: limit).map(postbox.renderIntermediateMessage(_:))
|
||||
return postbox.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: customTag, threadId: threadId, from: from, includeFrom: includeFrom, to: to, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), limit: limit).map(postbox.renderIntermediateMessage(_:))
|
||||
}
|
||||
|
||||
public func scanMessages(peerId: PeerId, namespace: MessageId.Namespace, tag: MessageTags, _ f: (Message) -> Bool) {
|
||||
|
|
@ -1107,7 +1107,7 @@ public final class Transaction {
|
|||
self.postbox?.scanMessageAttributes(peerId: peerId, namespace: namespace, limit: limit, f)
|
||||
}
|
||||
|
||||
public func getMessagesHistoryViewState(input: MessageHistoryViewInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, count: Int, clipHoles: Bool, anchor: HistoryViewInputAnchor, namespaces: MessageIdNamespaces) -> MessageHistoryView {
|
||||
public func getMessagesHistoryViewState(input: MessageHistoryViewInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, count: Int, clipHoles: Bool, anchor: HistoryViewInputAnchor, namespaces: MessageIdNamespaces) -> MessageHistoryView {
|
||||
precondition(!self.disposed)
|
||||
guard let postbox = self.postbox else {
|
||||
preconditionFailure()
|
||||
|
|
@ -1121,7 +1121,7 @@ public final class Transaction {
|
|||
view = next.0
|
||||
}, error: { _ in }, completed: {})
|
||||
|
||||
let disposable = postbox.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: input, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: MessageHistoryViewOrderStatistics(), additionalData: [], useRootInterfaceStateForThread: false)
|
||||
let disposable = postbox.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: input, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: MessageHistoryViewOrderStatistics(), additionalData: [], useRootInterfaceStateForThread: false)
|
||||
disposable.dispose()
|
||||
|
||||
return view!
|
||||
|
|
@ -2269,7 +2269,7 @@ final class PostboxImpl {
|
|||
if let states = initialCombinedStates?.states {
|
||||
for (namespace, state) in states {
|
||||
if namespace != messageIndex.id.namespace && state.count != 0 {
|
||||
if let item = self.messageHistoryTable.fetch(peerId: messageIndex.id.peerId, namespace: namespace, tag: nil, customTag: nil, threadId: nil, from: MessageIndex(id: MessageId(peerId: messageIndex.id.peerId, namespace: namespace, id: 1), timestamp: messageIndex.timestamp), includeFrom: true, to: MessageIndex.lowerBound(peerId: messageIndex.id.peerId, namespace: namespace), ignoreMessagesInTimestampRange: nil, limit: 1).first {
|
||||
if let item = self.messageHistoryTable.fetch(peerId: messageIndex.id.peerId, namespace: namespace, tag: nil, customTag: nil, threadId: nil, from: MessageIndex(id: MessageId(peerId: messageIndex.id.peerId, namespace: namespace, id: 1), timestamp: messageIndex.timestamp), includeFrom: true, to: MessageIndex.lowerBound(peerId: messageIndex.id.peerId, namespace: namespace), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), limit: 1).first {
|
||||
resultIds.append(contentsOf: self.messageHistoryTable.applyInteractiveMaxReadIndex(postbox: self, messageIndex: item.index, operationsByPeerId: &self.currentOperationsByPeerId, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations))
|
||||
}
|
||||
}
|
||||
|
|
@ -3123,7 +3123,7 @@ final class PostboxImpl {
|
|||
return peerIds
|
||||
}
|
||||
|
||||
public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, count: Int, clipHoles: Bool = true, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, customUnreadMessageId: MessageId?, additionalData: [AdditionalMessageHistoryViewData], useRootInterfaceStateForThread: Bool) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, count: Int, clipHoles: Bool = true, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, customUnreadMessageId: MessageId?, additionalData: [AdditionalMessageHistoryViewData], useRootInterfaceStateForThread: Bool) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
return self.resolvedChatLocationInput(chatLocation: chatLocation)
|
||||
|> mapToSignal { chatLocationData in
|
||||
let (chatLocation, isHoleFill) = chatLocationData
|
||||
|
|
@ -3181,7 +3181,7 @@ final class PostboxImpl {
|
|||
anchor = .upperBound
|
||||
}
|
||||
}
|
||||
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
})
|
||||
|
||||
return signal
|
||||
|
|
@ -3195,13 +3195,13 @@ final class PostboxImpl {
|
|||
}
|
||||
}
|
||||
|
||||
public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, messageId: MessageId, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, messageId: MessageId, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
return self.resolvedChatLocationInput(chatLocation: chatLocation)
|
||||
|> mapToSignal { chatLocationData in
|
||||
let (chatLocation, isHoleFill) = chatLocationData
|
||||
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal { subscriber, transaction in
|
||||
let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: ignoreRelatedChats)
|
||||
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, clipHoles: clipHoles, anchor: .message(messageId), fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, clipHoles: clipHoles, anchor: .message(messageId), fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
}
|
||||
|
||||
return signal
|
||||
|
|
@ -3215,14 +3215,14 @@ final class PostboxImpl {
|
|||
}
|
||||
}
|
||||
|
||||
public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, anchor: HistoryViewInputAnchor, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, ignoreMessageIds: Set<MessageId>, anchor: HistoryViewInputAnchor, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set<MessageId.Namespace>, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
return self.resolvedChatLocationInput(chatLocation: chatLocation)
|
||||
|> mapToSignal { chatLocationData -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in
|
||||
let (chatLocation, isHoleFill) = chatLocationData
|
||||
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal { subscriber, transaction in
|
||||
let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: ignoreRelatedChats)
|
||||
|
||||
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, clipHoles: clipHoles, anchor: anchor, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
}
|
||||
|
||||
return signal
|
||||
|
|
@ -3241,6 +3241,7 @@ final class PostboxImpl {
|
|||
subscriber: Subscriber<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>,
|
||||
peerIds: MessageHistoryViewInput,
|
||||
ignoreMessagesInTimestampRange: ClosedRange<Int32>?,
|
||||
ignoreMessageIds: Set<MessageId>,
|
||||
count: Int,
|
||||
clipHoles: Bool,
|
||||
anchor: HistoryViewInputAnchor,
|
||||
|
|
@ -3350,7 +3351,7 @@ final class PostboxImpl {
|
|||
readStates = transientReadStates
|
||||
}
|
||||
|
||||
let mutableView = MutableMessageHistoryView(postbox: self, orderStatistics: orderStatistics, clipHoles: clipHoles, trackHoles: true, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, anchor: anchor, combinedReadStates: readStates, transientReadStates: transientReadStates, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, count: count, topTaggedMessages: topTaggedMessages, additionalDatas: additionalDataEntries)
|
||||
let mutableView = MutableMessageHistoryView(postbox: self, orderStatistics: orderStatistics, clipHoles: clipHoles, trackHoles: true, peerIds: peerIds, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, anchor: anchor, combinedReadStates: readStates, transientReadStates: transientReadStates, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: namespaces, count: count, topTaggedMessages: topTaggedMessages, additionalDatas: additionalDataEntries)
|
||||
|
||||
let initialUpdateType: ViewUpdateType = .Initial
|
||||
|
||||
|
|
@ -4091,7 +4092,7 @@ final class PostboxImpl {
|
|||
var index = MessageIndex.upperBound(peerId: peerId, namespace: namespace)
|
||||
var remainingLimit = limit
|
||||
while remainingLimit > 0 {
|
||||
let messages = self.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: nil, threadId: nil, from: index, includeFrom: false, to: lowerBound, ignoreMessagesInTimestampRange: nil, limit: 10)
|
||||
let messages = self.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: nil, threadId: nil, from: index, includeFrom: false, to: lowerBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), limit: 10)
|
||||
remainingLimit -= 10
|
||||
for message in messages {
|
||||
if !f(self.renderIntermediateMessage(message)) {
|
||||
|
|
@ -4110,7 +4111,7 @@ final class PostboxImpl {
|
|||
var remainingLimit = limit
|
||||
var index = MessageIndex.upperBound(peerId: peerId, namespace: namespace)
|
||||
while remainingLimit > 0 {
|
||||
let messages = self.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: nil, threadId: nil, from: index, includeFrom: false, to: MessageIndex.lowerBound(peerId: peerId, namespace: namespace), ignoreMessagesInTimestampRange: nil, limit: 32)
|
||||
let messages = self.messageHistoryTable.fetch(peerId: peerId, namespace: namespace, tag: nil, customTag: nil, threadId: nil, from: index, includeFrom: false, to: MessageIndex.lowerBound(peerId: peerId, namespace: namespace), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), limit: 32)
|
||||
for message in messages {
|
||||
let attributes = MessageHistoryTable.renderMessageAttributes(message)
|
||||
if !f(message.id, attributes) {
|
||||
|
|
@ -4422,6 +4423,7 @@ public class Postbox {
|
|||
public func aroundMessageOfInterestHistoryViewForChatLocation(
|
||||
_ chatLocation: ChatLocationInput,
|
||||
ignoreMessagesInTimestampRange: ClosedRange<Int32>?,
|
||||
ignoreMessageIds: Set<MessageId>,
|
||||
count: Int,
|
||||
clipHoles: Bool = true,
|
||||
topTaggedMessageIdNamespaces: Set<MessageId.Namespace>,
|
||||
|
|
@ -4440,6 +4442,7 @@ public class Postbox {
|
|||
disposable.set(impl.aroundMessageOfInterestHistoryViewForChatLocation(
|
||||
chatLocation,
|
||||
ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange,
|
||||
ignoreMessageIds: ignoreMessageIds,
|
||||
count: count,
|
||||
clipHoles: clipHoles,
|
||||
topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces,
|
||||
|
|
@ -4460,6 +4463,7 @@ public class Postbox {
|
|||
public func aroundIdMessageHistoryViewForLocation(
|
||||
_ chatLocation: ChatLocationInput,
|
||||
ignoreMessagesInTimestampRange: ClosedRange<Int32>?,
|
||||
ignoreMessageIds: Set<MessageId>,
|
||||
count: Int,
|
||||
clipHoles: Bool = true,
|
||||
ignoreRelatedChats: Bool = false,
|
||||
|
|
@ -4479,6 +4483,7 @@ public class Postbox {
|
|||
disposable.set(impl.aroundIdMessageHistoryViewForLocation(
|
||||
chatLocation,
|
||||
ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange,
|
||||
ignoreMessageIds: ignoreMessageIds,
|
||||
count: count,
|
||||
clipHoles: clipHoles,
|
||||
ignoreRelatedChats: ignoreRelatedChats,
|
||||
|
|
@ -4501,6 +4506,7 @@ public class Postbox {
|
|||
_ chatLocation: ChatLocationInput,
|
||||
anchor: HistoryViewInputAnchor,
|
||||
ignoreMessagesInTimestampRange: ClosedRange<Int32>?,
|
||||
ignoreMessageIds: Set<MessageId>,
|
||||
count: Int,
|
||||
clipHoles: Bool = true,
|
||||
ignoreRelatedChats: Bool = false,
|
||||
|
|
@ -4520,6 +4526,7 @@ public class Postbox {
|
|||
disposable.set(impl.aroundMessageHistoryViewForLocation(
|
||||
chatLocation,
|
||||
ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange,
|
||||
ignoreMessageIds: ignoreMessageIds,
|
||||
anchor: anchor,
|
||||
count: count,
|
||||
clipHoles: clipHoles,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ public enum PostboxViewKey: Hashable {
|
|||
public var trackHoles: Bool
|
||||
public var orderStatistics: MessageHistoryViewOrderStatistics
|
||||
public var ignoreMessagesInTimestampRange: ClosedRange<Int32>?
|
||||
public var ignoreMessageIds: Set<MessageId>
|
||||
public var anchor: HistoryViewInputAnchor
|
||||
public var combinedReadStates: MessageHistoryViewReadState?
|
||||
public var transientReadStates: MessageHistoryViewReadState?
|
||||
|
|
@ -23,6 +24,7 @@ public enum PostboxViewKey: Hashable {
|
|||
trackHoles: Bool,
|
||||
orderStatistics: MessageHistoryViewOrderStatistics = [],
|
||||
ignoreMessagesInTimestampRange: ClosedRange<Int32>? = nil,
|
||||
ignoreMessageIds: Set<MessageId> = Set(),
|
||||
anchor: HistoryViewInputAnchor,
|
||||
combinedReadStates: MessageHistoryViewReadState? = nil,
|
||||
transientReadStates: MessageHistoryViewReadState? = nil,
|
||||
|
|
@ -37,6 +39,7 @@ public enum PostboxViewKey: Hashable {
|
|||
self.trackHoles = trackHoles
|
||||
self.orderStatistics = orderStatistics
|
||||
self.ignoreMessagesInTimestampRange = ignoreMessagesInTimestampRange
|
||||
self.ignoreMessageIds = ignoreMessageIds
|
||||
self.anchor = anchor
|
||||
self.combinedReadStates = combinedReadStates
|
||||
self.transientReadStates = transientReadStates
|
||||
|
|
@ -647,6 +650,7 @@ func postboxViewForKey(postbox: PostboxImpl, key: PostboxViewKey) -> MutablePost
|
|||
trackHoles: historyView.trackHoles,
|
||||
peerIds: .single(peerId: historyView.peerId, threadId: historyView.threadId),
|
||||
ignoreMessagesInTimestampRange: historyView.ignoreMessagesInTimestampRange,
|
||||
ignoreMessageIds: historyView.ignoreMessageIds,
|
||||
anchor: historyView.anchor,
|
||||
combinedReadStates: historyView.combinedReadStates,
|
||||
transientReadStates: historyView.transientReadStates,
|
||||
|
|
|
|||
|
|
@ -1135,7 +1135,7 @@ private func statsEntries(
|
|||
data: ChannelStats,
|
||||
peer: EnginePeer?,
|
||||
messages: [Message]?,
|
||||
stories: PeerStoryListContext.State?,
|
||||
stories: StoryListContext.State?,
|
||||
interactions: [ChannelStatsPostInteractions.PostId: ChannelStatsPostInteractions]?
|
||||
) -> [StatsEntry] {
|
||||
var entries: [StatsEntry] = []
|
||||
|
|
@ -1217,8 +1217,8 @@ private func statsEntries(
|
|||
}
|
||||
if let stories {
|
||||
for story in stories.items {
|
||||
if let _ = interactions[.story(peerId: peer.id, id: story.id)] {
|
||||
posts.append(.story(peer, story))
|
||||
if let _ = interactions[.story(peerId: peer.id, id: story.storyItem.id)] {
|
||||
posts.append(.story(peer, story.storyItem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1463,8 +1463,8 @@ private func channelStatsControllerEntries(
|
|||
peer: EnginePeer?,
|
||||
data: ChannelStats?,
|
||||
messages: [Message]?,
|
||||
stories: PeerStoryListContext.State?,
|
||||
interactions: [ChannelStatsPostInteractions.PostId: ChannelStatsPostInteractions]?,
|
||||
stories: StoryListContext.State?,
|
||||
interactions: [ChannelStatsPostInteractions.PostId: ChannelStatsPostInteractions]?,
|
||||
boostData: ChannelBoostStatus?,
|
||||
boostersState: ChannelBoostersContext.State?,
|
||||
giftsState: ChannelBoostersContext.State?,
|
||||
|
|
@ -1543,7 +1543,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
|||
let withdrawalDisposable = MetaDisposable()
|
||||
actionsDisposable.add(withdrawalDisposable)
|
||||
|
||||
let storiesPromise = Promise<PeerStoryListContext.State?>()
|
||||
let storiesPromise = Promise<StoryListContext.State?>()
|
||||
|
||||
let statsContext = ChannelStatsContext(postbox: context.account.postbox, network: context.account.network, peerId: peerId)
|
||||
let dataSignal: Signal<ChannelStats?, NoError> = statsContext.state
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||
dict[1903173033] = { return Api.ForumTopic.parse_forumTopic($0) }
|
||||
dict[37687451] = { return Api.ForumTopic.parse_forumTopicDeleted($0) }
|
||||
dict[-394605632] = { return Api.FoundStory.parse_foundStory($0) }
|
||||
dict[-1107729093] = { return Api.Game.parse_game($0) }
|
||||
dict[-1297942941] = { return Api.GeoPoint.parse_geoPoint($0) }
|
||||
dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) }
|
||||
|
|
@ -1344,6 +1345,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[276907596] = { return Api.storage.FileType.parse_fileWebp($0) }
|
||||
dict[1862033025] = { return Api.stories.AllStories.parse_allStories($0) }
|
||||
dict[291044926] = { return Api.stories.AllStories.parse_allStoriesNotModified($0) }
|
||||
dict[-488736969] = { return Api.stories.FoundStories.parse_foundStories($0) }
|
||||
dict[-890861720] = { return Api.stories.PeerStories.parse_peerStories($0) }
|
||||
dict[1673780490] = { return Api.stories.Stories.parse_stories($0) }
|
||||
dict[-1436583780] = { return Api.stories.StoryReactionsList.parse_storyReactionsList($0) }
|
||||
|
|
@ -1380,7 +1382,7 @@ public extension Api {
|
|||
return parser(reader)
|
||||
}
|
||||
else {
|
||||
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
|
||||
telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -1618,6 +1620,8 @@ public extension Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.ForumTopic:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.FoundStory:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.Game:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.GeoPoint:
|
||||
|
|
@ -2380,6 +2384,8 @@ public extension Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.stories.AllStories:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.stories.FoundStories:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.stories.PeerStories:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.stories.Stories:
|
||||
|
|
|
|||
|
|
@ -1212,6 +1212,80 @@ public extension Api.stories {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api.stories {
|
||||
enum FoundStories: TypeConstructorDescription {
|
||||
case foundStories(flags: Int32, count: Int32, stories: [Api.FoundStory], nextOffset: String?, chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .foundStories(let flags, let count, let stories, let nextOffset, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-488736969)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(stories.count))
|
||||
for item in stories {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, 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 .foundStories(let flags, let count, let stories, let nextOffset, let chats, let users):
|
||||
return ("foundStories", [("flags", flags as Any), ("count", count as Any), ("stories", stories as Any), ("nextOffset", nextOffset as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_foundStories(_ reader: BufferReader) -> FoundStories? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: [Api.FoundStory]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.FoundStory.self)
|
||||
}
|
||||
var _4: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
|
||||
var _5: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _6: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.stories.FoundStories.foundStories(flags: _1!, count: _2!, stories: _3!, nextOffset: _4, chats: _5!, users: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.stories {
|
||||
enum PeerStories: TypeConstructorDescription {
|
||||
case peerStories(stories: Api.PeerStories, chats: [Api.Chat], users: [Api.User])
|
||||
|
|
@ -1562,175 +1636,3 @@ public extension Api.stories {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api.updates {
|
||||
indirect enum ChannelDifference: TypeConstructorDescription {
|
||||
case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User])
|
||||
case channelDifferenceEmpty(flags: Int32, pts: Int32, timeout: Int32?)
|
||||
case channelDifferenceTooLong(flags: Int32, timeout: Int32?, dialog: Api.Dialog, messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(543450958)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(pts, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(newMessages.count))
|
||||
for item in newMessages {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(otherUpdates.count))
|
||||
for item in otherUpdates {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
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
|
||||
case .channelDifferenceEmpty(let flags, let pts, let timeout):
|
||||
if boxed {
|
||||
buffer.appendInt32(1041346555)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(pts, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1531132162)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)}
|
||||
dialog.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(messages.count))
|
||||
for item in messages {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
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 .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users):
|
||||
return ("channelDifference", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any), ("newMessages", newMessages as Any), ("otherUpdates", otherUpdates as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
case .channelDifferenceEmpty(let flags, let pts, let timeout):
|
||||
return ("channelDifferenceEmpty", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any)])
|
||||
case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users):
|
||||
return ("channelDifferenceTooLong", [("flags", flags as Any), ("timeout", timeout as Any), ("dialog", dialog as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_channelDifference(_ reader: BufferReader) -> ChannelDifference? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() }
|
||||
var _4: [Api.Message]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
}
|
||||
var _5: [Api.Update]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self)
|
||||
}
|
||||
var _6: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _7: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.updates.ChannelDifference.channelDifference(flags: _1!, pts: _2!, timeout: _3, newMessages: _4!, otherUpdates: _5!, chats: _6!, users: _7!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_channelDifferenceEmpty(_ reader: BufferReader) -> ChannelDifference? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.updates.ChannelDifference.channelDifferenceEmpty(flags: _1!, pts: _2!, timeout: _3)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_channelDifferenceTooLong(_ reader: BufferReader) -> ChannelDifference? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() }
|
||||
var _3: Api.Dialog?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.Dialog
|
||||
}
|
||||
var _4: [Api.Message]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
}
|
||||
var _5: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _6: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.updates.ChannelDifference.channelDifferenceTooLong(flags: _1!, timeout: _2, dialog: _3!, messages: _4!, chats: _5!, users: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,175 @@
|
|||
public extension Api.updates {
|
||||
indirect enum ChannelDifference: TypeConstructorDescription {
|
||||
case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User])
|
||||
case channelDifferenceEmpty(flags: Int32, pts: Int32, timeout: Int32?)
|
||||
case channelDifferenceTooLong(flags: Int32, timeout: Int32?, dialog: Api.Dialog, messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(543450958)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(pts, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(newMessages.count))
|
||||
for item in newMessages {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(otherUpdates.count))
|
||||
for item in otherUpdates {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
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
|
||||
case .channelDifferenceEmpty(let flags, let pts, let timeout):
|
||||
if boxed {
|
||||
buffer.appendInt32(1041346555)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(pts, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1531132162)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)}
|
||||
dialog.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(messages.count))
|
||||
for item in messages {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
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 .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users):
|
||||
return ("channelDifference", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any), ("newMessages", newMessages as Any), ("otherUpdates", otherUpdates as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
case .channelDifferenceEmpty(let flags, let pts, let timeout):
|
||||
return ("channelDifferenceEmpty", [("flags", flags as Any), ("pts", pts as Any), ("timeout", timeout as Any)])
|
||||
case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users):
|
||||
return ("channelDifferenceTooLong", [("flags", flags as Any), ("timeout", timeout as Any), ("dialog", dialog as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_channelDifference(_ reader: BufferReader) -> ChannelDifference? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() }
|
||||
var _4: [Api.Message]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
}
|
||||
var _5: [Api.Update]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self)
|
||||
}
|
||||
var _6: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _7: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
|
||||
return Api.updates.ChannelDifference.channelDifference(flags: _1!, pts: _2!, timeout: _3, newMessages: _4!, otherUpdates: _5!, chats: _6!, users: _7!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_channelDifferenceEmpty(_ reader: BufferReader) -> ChannelDifference? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.updates.ChannelDifference.channelDifferenceEmpty(flags: _1!, pts: _2!, timeout: _3)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_channelDifferenceTooLong(_ reader: BufferReader) -> ChannelDifference? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() }
|
||||
var _3: Api.Dialog?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.Dialog
|
||||
}
|
||||
var _4: [Api.Message]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
}
|
||||
var _5: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _6: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.updates.ChannelDifference.channelDifferenceTooLong(flags: _1!, timeout: _2, dialog: _3!, messages: _4!, chats: _5!, users: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.updates {
|
||||
enum Difference: TypeConstructorDescription {
|
||||
case difference(newMessages: [Api.Message], newEncryptedMessages: [Api.EncryptedMessage], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User], state: Api.updates.State)
|
||||
|
|
|
|||
|
|
@ -8795,13 +8795,12 @@ public extension Api.functions.payments {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func refundStarsCharge(userId: Api.InputUser, msgId: Int32, chargeId: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
static func refundStarsCharge(userId: Api.InputUser, chargeId: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-258950164)
|
||||
buffer.appendInt32(632196938)
|
||||
userId.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
serializeString(chargeId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "payments.refundStarsCharge", parameters: [("userId", String(describing: userId)), ("msgId", String(describing: msgId)), ("chargeId", String(describing: chargeId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
return (FunctionDescription(name: "payments.refundStarsCharge", parameters: [("userId", String(describing: userId)), ("chargeId", String(describing: chargeId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
|
|
@ -10393,6 +10392,23 @@ public extension Api.functions.stories {
|
|||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.stories {
|
||||
static func searchPosts(hashtag: String, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stories.FoundStories>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-688008311)
|
||||
serializeString(hashtag, buffer: buffer, boxed: false)
|
||||
serializeString(offset, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "stories.searchPosts", parameters: [("hashtag", String(describing: hashtag)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stories.FoundStories? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.stories.FoundStories?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.stories.FoundStories
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.stories {
|
||||
static func sendReaction(flags: Int32, peer: Api.InputPeer, storyId: Int32, reaction: Api.Reaction) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
|
|
|
|||
|
|
@ -472,6 +472,50 @@ public extension Api {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum FoundStory: TypeConstructorDescription {
|
||||
case foundStory(peer: Api.Peer, story: Api.StoryItem)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .foundStory(let peer, let story):
|
||||
if boxed {
|
||||
buffer.appendInt32(-394605632)
|
||||
}
|
||||
peer.serialize(buffer, true)
|
||||
story.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .foundStory(let peer, let story):
|
||||
return ("foundStory", [("peer", peer as Any), ("story", story as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_foundStory(_ reader: BufferReader) -> FoundStory? {
|
||||
var _1: Api.Peer?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _2: Api.StoryItem?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.StoryItem
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.FoundStory.foundStory(peer: _1!, story: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum Game: TypeConstructorDescription {
|
||||
case game(flags: Int32, id: Int64, accessHash: Int64, shortName: String, title: String, description: String, photo: Api.Photo, document: Api.Document?)
|
||||
|
|
@ -1268,69 +1312,3 @@ public extension Api {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
indirect enum InputBotApp: TypeConstructorDescription {
|
||||
case inputBotAppID(id: Int64, accessHash: Int64)
|
||||
case inputBotAppShortName(botId: Api.InputUser, shortName: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputBotAppID(let id, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1457472134)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputBotAppShortName(let botId, let shortName):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1869872121)
|
||||
}
|
||||
botId.serialize(buffer, true)
|
||||
serializeString(shortName, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputBotAppID(let id, let accessHash):
|
||||
return ("inputBotAppID", [("id", id as Any), ("accessHash", accessHash as Any)])
|
||||
case .inputBotAppShortName(let botId, let shortName):
|
||||
return ("inputBotAppShortName", [("botId", botId as Any), ("shortName", shortName as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputBotAppID(_ reader: BufferReader) -> InputBotApp? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputBotApp.inputBotAppID(id: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputBotAppShortName(_ reader: BufferReader) -> InputBotApp? {
|
||||
var _1: Api.InputUser?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputUser
|
||||
}
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputBotApp.inputBotAppShortName(botId: _1!, shortName: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,69 @@
|
|||
public extension Api {
|
||||
indirect enum InputBotApp: TypeConstructorDescription {
|
||||
case inputBotAppID(id: Int64, accessHash: Int64)
|
||||
case inputBotAppShortName(botId: Api.InputUser, shortName: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputBotAppID(let id, let accessHash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1457472134)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeInt64(accessHash, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputBotAppShortName(let botId, let shortName):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1869872121)
|
||||
}
|
||||
botId.serialize(buffer, true)
|
||||
serializeString(shortName, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputBotAppID(let id, let accessHash):
|
||||
return ("inputBotAppID", [("id", id as Any), ("accessHash", accessHash as Any)])
|
||||
case .inputBotAppShortName(let botId, let shortName):
|
||||
return ("inputBotAppShortName", [("botId", botId as Any), ("shortName", shortName as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputBotAppID(_ reader: BufferReader) -> InputBotApp? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputBotApp.inputBotAppID(id: _1!, accessHash: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputBotAppShortName(_ reader: BufferReader) -> InputBotApp? {
|
||||
var _1: Api.InputUser?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.InputUser
|
||||
}
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputBotApp.inputBotAppShortName(botId: _1!, shortName: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputBotInlineMessage: TypeConstructorDescription {
|
||||
case inputBotInlineMessageGame(flags: Int32, replyMarkup: Api.ReplyMarkup?)
|
||||
|
|
@ -1236,59 +1302,3 @@ public extension Api {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputCollectible: TypeConstructorDescription {
|
||||
case inputCollectiblePhone(phone: String)
|
||||
case inputCollectibleUsername(username: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputCollectiblePhone(let phone):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1562241884)
|
||||
}
|
||||
serializeString(phone, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputCollectibleUsername(let username):
|
||||
if boxed {
|
||||
buffer.appendInt32(-476815191)
|
||||
}
|
||||
serializeString(username, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputCollectiblePhone(let phone):
|
||||
return ("inputCollectiblePhone", [("phone", phone as Any)])
|
||||
case .inputCollectibleUsername(let username):
|
||||
return ("inputCollectibleUsername", [("username", username as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputCollectiblePhone(_ reader: BufferReader) -> InputCollectible? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputCollectible.inputCollectiblePhone(phone: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputCollectibleUsername(_ reader: BufferReader) -> InputCollectible? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputCollectible.inputCollectibleUsername(username: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,59 @@
|
|||
public extension Api {
|
||||
enum InputCollectible: TypeConstructorDescription {
|
||||
case inputCollectiblePhone(phone: String)
|
||||
case inputCollectibleUsername(username: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .inputCollectiblePhone(let phone):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1562241884)
|
||||
}
|
||||
serializeString(phone, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputCollectibleUsername(let username):
|
||||
if boxed {
|
||||
buffer.appendInt32(-476815191)
|
||||
}
|
||||
serializeString(username, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .inputCollectiblePhone(let phone):
|
||||
return ("inputCollectiblePhone", [("phone", phone as Any)])
|
||||
case .inputCollectibleUsername(let username):
|
||||
return ("inputCollectibleUsername", [("username", username as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_inputCollectiblePhone(_ reader: BufferReader) -> InputCollectible? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputCollectible.inputCollectiblePhone(phone: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputCollectibleUsername(_ reader: BufferReader) -> InputCollectible? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.InputCollectible.inputCollectibleUsername(username: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum InputContact: TypeConstructorDescription {
|
||||
case inputPhoneContact(clientId: Int64, phone: String, firstName: String, lastName: String)
|
||||
|
|
|
|||
|
|
@ -1962,7 +1962,7 @@ public final class AccountViewTracker {
|
|||
|
||||
public func scheduledMessagesViewForLocation(_ chatLocation: ChatLocationInput, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
if let account = self.account {
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just(Namespaces.Message.allScheduled), orderStatistics: [], additionalData: additionalData)
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just(Namespaces.Message.allScheduled), orderStatistics: [], additionalData: additionalData)
|
||||
return withState(signal, { [weak self] () -> Int32 in
|
||||
if let strongSelf = self {
|
||||
return OSAtomicIncrement32(&strongSelf.nextViewId)
|
||||
|
|
@ -1995,7 +1995,7 @@ public final class AccountViewTracker {
|
|||
return .never()
|
||||
}
|
||||
let chatLocation: ChatLocationInput = .peer(peerId: account.peerId, threadId: Int64(quickReplyId))
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just(Namespaces.Message.allQuickReply), orderStatistics: [], additionalData: additionalData)
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just(Namespaces.Message.allQuickReply), orderStatistics: [], additionalData: additionalData)
|
||||
return withState(signal, { [weak self] () -> Int32 in
|
||||
if let strongSelf = self {
|
||||
return OSAtomicIncrement32(&strongSelf.nextViewId)
|
||||
|
|
@ -2025,7 +2025,7 @@ public final class AccountViewTracker {
|
|||
return .never()
|
||||
}
|
||||
let chatLocation: ChatLocationInput = .peer(peerId: account.peerId, threadId: nil)
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just([Namespaces.Message.QuickReplyLocal]), orderStatistics: [], additionalData: [])
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just([Namespaces.Message.QuickReplyLocal]), orderStatistics: [], additionalData: [])
|
||||
|> map { view, update, initialData in
|
||||
var entries: [MessageHistoryEntry] = []
|
||||
for entry in view.entries {
|
||||
|
|
@ -2049,7 +2049,7 @@ public final class AccountViewTracker {
|
|||
return signal
|
||||
}
|
||||
|
||||
public func aroundMessageOfInterestHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>? = nil, count: Int, tag: HistoryViewInputTag? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
public func aroundMessageOfInterestHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>? = nil, ignoreMessageIds: Set<MessageId> = Set(), count: Int, tag: HistoryViewInputTag? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
if let account = self.account {
|
||||
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
|
||||
if let peerId = chatLocation.peerId, let threadId = chatLocation.threadId, tag == nil {
|
||||
|
|
@ -2074,6 +2074,7 @@ public final class AccountViewTracker {
|
|||
chatLocation,
|
||||
anchor: anchor,
|
||||
ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange,
|
||||
ignoreMessageIds: ignoreMessageIds,
|
||||
count: count,
|
||||
fixedCombinedReadStates: .peer([peerId: CombinedPeerReadState(states: [
|
||||
(Namespaces.Message.Cloud, PeerReadState.idBased(maxIncomingReadId: Int32.max - 1, maxOutgoingReadId: Int32.max - 1, maxKnownId: Int32.max - 1, count: 0, markedUnread: false))
|
||||
|
|
@ -2102,6 +2103,7 @@ public final class AccountViewTracker {
|
|||
chatLocation,
|
||||
anchor: anchor,
|
||||
ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange,
|
||||
ignoreMessageIds: ignoreMessageIds,
|
||||
count: count,
|
||||
fixedCombinedReadStates: nil,
|
||||
topTaggedMessageIdNamespaces: [],
|
||||
|
|
@ -2115,10 +2117,10 @@ public final class AccountViewTracker {
|
|||
}
|
||||
}
|
||||
|
||||
return account.postbox.aroundMessageOfInterestHistoryViewForChatLocation(chatLocation, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, customUnreadMessageId: nil, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
return account.postbox.aroundMessageOfInterestHistoryViewForChatLocation(chatLocation, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, customUnreadMessageId: nil, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
}
|
||||
} else {
|
||||
signal = account.postbox.aroundMessageOfInterestHistoryViewForChatLocation(chatLocation, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, customUnreadMessageId: nil, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
signal = account.postbox.aroundMessageOfInterestHistoryViewForChatLocation(chatLocation, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, customUnreadMessageId: nil, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
}
|
||||
return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, fixedCombinedReadStates: nil, addHoleIfNeeded: true)
|
||||
} else {
|
||||
|
|
@ -2126,16 +2128,16 @@ public final class AccountViewTracker {
|
|||
}
|
||||
}
|
||||
|
||||
public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>? = nil, count: Int, ignoreRelatedChats: Bool, messageId: MessageId, tag: HistoryViewInputTag? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>? = nil, ignoreMessageIds: Set<MessageId> = Set(), count: Int, ignoreRelatedChats: Bool, messageId: MessageId, tag: HistoryViewInputTag? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
if let account = self.account {
|
||||
let signal = account.postbox.aroundIdMessageHistoryViewForLocation(chatLocation, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: messageId, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
let signal = account.postbox.aroundIdMessageHistoryViewForLocation(chatLocation, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: messageId, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, fixedCombinedReadStates: nil, addHoleIfNeeded: false)
|
||||
} else {
|
||||
return .never()
|
||||
}
|
||||
}
|
||||
|
||||
public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>? = nil, index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, tag: HistoryViewInputTag? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>? = nil, ignoreMessageIds: Set<MessageId> = Set(), index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, clipHoles: Bool = true, ignoreRelatedChats: Bool = false, fixedCombinedReadStates: MessageHistoryViewReadState?, tag: HistoryViewInputTag? = nil, appendMessagesFromTheSameGroup: Bool = false, orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = [], useRootInterfaceStateForThread: Bool = false) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
if let account = self.account {
|
||||
let inputAnchor: HistoryViewInputAnchor
|
||||
switch index {
|
||||
|
|
@ -2146,7 +2148,7 @@ public final class AccountViewTracker {
|
|||
case let .message(index):
|
||||
inputAnchor = .index(index)
|
||||
}
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: inputAnchor, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, clipHoles: clipHoles, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: inputAnchor, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, clipHoles: clipHoles, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData), useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal, fixedCombinedReadStates: fixedCombinedReadStates, addHoleIfNeeded: false)
|
||||
} else {
|
||||
return .never()
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ func _internal_shortcutMessageList(account: Account, onlyRemote: Bool) -> Signal
|
|||
if onlyRemote {
|
||||
pendingShortcuts = .single([:])
|
||||
} else {
|
||||
pendingShortcuts = account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 100, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just(Set([Namespaces.Message.QuickReplyLocal])), orderStatistics: [])
|
||||
pendingShortcuts = account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 100, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .just(Set([Namespaces.Message.QuickReplyLocal])), orderStatistics: [])
|
||||
|> map { view , _, _ -> [String: EngineMessage] in
|
||||
var topMessages: [String: EngineMessage] = [:]
|
||||
for entry in view.entries {
|
||||
|
|
|
|||
|
|
@ -840,6 +840,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
|||
maxReadOutgoingMessageId: nil
|
||||
)),
|
||||
ignoreMessagesInTimestampRange: nil,
|
||||
ignoreMessageIds: Set(),
|
||||
count: 40,
|
||||
clipHoles: true,
|
||||
anchor: inputAnchor,
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ public final class SparseMessageList {
|
|||
|
||||
let location: ChatLocationInput = .peer(peerId: self.peerId, threadId: self.threadId)
|
||||
|
||||
self.topItemsDisposable.set((self.account.postbox.aroundMessageHistoryViewForLocation(location, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: count, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: .tag(self.messageTag), appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: [])
|
||||
self.topItemsDisposable.set((self.account.postbox.aroundMessageHistoryViewForLocation(location, anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: count, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: .tag(self.messageTag), appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: [])
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] view, updateType, _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -533,7 +533,69 @@ private final class CachedPeerStoryListHead: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
public final class PeerStoryListContext {
|
||||
public struct StoryListContextState: Equatable {
|
||||
public final class Item: Equatable {
|
||||
public let storyItem: EngineStoryItem
|
||||
public let peer: EnginePeer?
|
||||
|
||||
public init(storyItem: EngineStoryItem, peer: EnginePeer?) {
|
||||
self.storyItem = storyItem
|
||||
self.peer = peer
|
||||
}
|
||||
|
||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if lhs.storyItem != rhs.storyItem {
|
||||
return false
|
||||
}
|
||||
if lhs.peer != rhs.peer {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public var peerReference: PeerReference?
|
||||
public var items: [Item]
|
||||
public var pinnedIds: Set<Int32>
|
||||
public var totalCount: Int
|
||||
public var loadMoreToken: AnyHashable?
|
||||
public var isCached: Bool
|
||||
public var hasCache: Bool
|
||||
public var allEntityFiles: [MediaId: TelegramMediaFile]
|
||||
|
||||
public init(
|
||||
peerReference: PeerReference?,
|
||||
items: [Item],
|
||||
pinnedIds: Set<Int32>,
|
||||
totalCount: Int,
|
||||
loadMoreToken: AnyHashable?,
|
||||
isCached: Bool,
|
||||
hasCache: Bool,
|
||||
allEntityFiles: [MediaId: TelegramMediaFile]
|
||||
) {
|
||||
self.peerReference = peerReference
|
||||
self.items = items
|
||||
self.pinnedIds = pinnedIds
|
||||
self.totalCount = totalCount
|
||||
self.loadMoreToken = loadMoreToken
|
||||
self.isCached = isCached
|
||||
self.hasCache = hasCache
|
||||
self.allEntityFiles = allEntityFiles
|
||||
}
|
||||
}
|
||||
|
||||
public protocol StoryListContext: AnyObject {
|
||||
typealias State = StoryListContextState
|
||||
|
||||
var state: Signal<State, NoError> { get }
|
||||
|
||||
func loadMore(completion: (() -> Void)?)
|
||||
}
|
||||
|
||||
public final class PeerStoryListContext: StoryListContext {
|
||||
private final class Impl {
|
||||
private let queue: Queue
|
||||
private let account: Account
|
||||
|
|
@ -555,7 +617,7 @@ public final class PeerStoryListContext {
|
|||
|
||||
private var updatesDisposable: Disposable?
|
||||
|
||||
private var completionCallbacksByToken: [Int: [() -> Void]] = [:]
|
||||
private var completionCallbacksByToken: [AnyHashable: [() -> Void]] = [:]
|
||||
|
||||
init(queue: Queue, account: Account, peerId: EnginePeer.Id, isArchived: Bool) {
|
||||
self.queue = queue
|
||||
|
|
@ -563,9 +625,9 @@ public final class PeerStoryListContext {
|
|||
self.peerId = peerId
|
||||
self.isArchived = isArchived
|
||||
|
||||
self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: 0, isCached: true, hasCache: false, allEntityFiles: [:])
|
||||
self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: AnyHashable(0 as Int), isCached: true, hasCache: false, allEntityFiles: [:])
|
||||
|
||||
let _ = (account.postbox.transaction { transaction -> (PeerReference?, [EngineStoryItem], [Int32], Int, [MediaId: TelegramMediaFile], Bool) in
|
||||
let _ = (account.postbox.transaction { transaction -> (PeerReference?, [State.Item], [Int32], Int, [MediaId: TelegramMediaFile], Bool) in
|
||||
let key = ValueBoxKey(length: 8 + 1)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
key.setInt8(8, value: isArchived ? 1 : 0)
|
||||
|
|
@ -573,7 +635,7 @@ public final class PeerStoryListContext {
|
|||
guard let cached = cached else {
|
||||
return (nil, [], [], 0, [:], false)
|
||||
}
|
||||
var items: [EngineStoryItem] = []
|
||||
var items: [State.Item] = []
|
||||
var allEntityFiles: [MediaId: TelegramMediaFile] = [:]
|
||||
for storedItem in cached.items {
|
||||
if case let .item(item) = storedItem, let media = item.media {
|
||||
|
|
@ -613,7 +675,10 @@ public final class PeerStoryListContext {
|
|||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
|
||||
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) }
|
||||
)
|
||||
items.append(mappedItem)
|
||||
items.append(State.Item(
|
||||
storyItem: mappedItem,
|
||||
peer: nil
|
||||
))
|
||||
|
||||
for entity in mappedItem.entities {
|
||||
if case let .CustomEmoji(_, fileId) = entity.type {
|
||||
|
|
@ -649,10 +714,10 @@ public final class PeerStoryListContext {
|
|||
return
|
||||
}
|
||||
|
||||
var updatedState = State(peerReference: peerReference, items: items, pinnedIds: Set(pinnedIds), totalCount: totalCount, loadMoreToken: 0, isCached: true, hasCache: hasCache, allEntityFiles: allEntityFiles)
|
||||
var updatedState = State(peerReference: peerReference, items: items, pinnedIds: Set(pinnedIds), totalCount: totalCount, loadMoreToken: AnyHashable(0 as Int), isCached: true, hasCache: hasCache, allEntityFiles: allEntityFiles)
|
||||
updatedState.items.sort(by: { lhs, rhs in
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.id)
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.storyItem.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.storyItem.id)
|
||||
if lhsPinned != rhsPinned {
|
||||
if lhsPinned {
|
||||
return true
|
||||
|
|
@ -660,7 +725,7 @@ public final class PeerStoryListContext {
|
|||
return false
|
||||
}
|
||||
}
|
||||
return lhs.timestamp > rhs.timestamp
|
||||
return lhs.storyItem.timestamp > rhs.storyItem.timestamp
|
||||
})
|
||||
self.stateValue = updatedState
|
||||
|
||||
|
|
@ -673,7 +738,7 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
|
||||
func loadMore(completion: (() -> Void)?) {
|
||||
guard let loadMoreToken = self.stateValue.loadMoreToken else {
|
||||
guard let loadMoreTokenValue = self.stateValue.loadMoreToken, let loadMoreToken = loadMoreTokenValue.base as? Int else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -699,7 +764,7 @@ public final class PeerStoryListContext {
|
|||
self.requestDisposable = (self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<([EngineStoryItem], Int, PeerReference?, Bool), NoError> in
|
||||
|> mapToSignal { inputPeer -> Signal<([State.Item], Int, PeerReference?, Bool), NoError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .single(([], 0, nil, false))
|
||||
}
|
||||
|
|
@ -717,13 +782,13 @@ public final class PeerStoryListContext {
|
|||
|> `catch` { _ -> Signal<Api.stories.Stories?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<([EngineStoryItem], Int, PeerReference?, Bool), NoError> in
|
||||
|> mapToSignal { result -> Signal<([State.Item], Int, PeerReference?, Bool), NoError> in
|
||||
guard let result = result else {
|
||||
return .single(([], 0, nil, false))
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> ([EngineStoryItem], Int, PeerReference?, Bool) in
|
||||
var storyItems: [EngineStoryItem] = []
|
||||
return account.postbox.transaction { transaction -> ([State.Item], Int, PeerReference?, Bool) in
|
||||
var storyItems: [State.Item] = []
|
||||
var totalCount: Int = 0
|
||||
var hasMore: Bool = false
|
||||
|
||||
|
|
@ -775,7 +840,10 @@ public final class PeerStoryListContext {
|
|||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
|
||||
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) }
|
||||
)
|
||||
storyItems.append(mappedItem)
|
||||
storyItems.append(State.Item(
|
||||
storyItem: mappedItem,
|
||||
peer: nil
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -784,7 +852,7 @@ public final class PeerStoryListContext {
|
|||
let key = ValueBoxKey(length: 8 + 1)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
key.setInt8(8, value: isArchived ? 1 : 0)
|
||||
if let entry = CodableEntry(CachedPeerStoryListHead(items: storyItems.prefix(100).map { .item($0.asStoryItem()) }, pinnedIds: Array(pinnedIds), totalCount: count)) {
|
||||
if let entry = CodableEntry(CachedPeerStoryListHead(items: storyItems.prefix(100).map { .item($0.storyItem.asStoryItem()) }, pinnedIds: Array(pinnedIds), totalCount: count)) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerStoryListHeads, key: key), entry: entry)
|
||||
}
|
||||
}
|
||||
|
|
@ -795,7 +863,7 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
}
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] storyItems, totalCount, peerReference, hasMore in
|
||||
guard let `self` = self else {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -808,12 +876,12 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
updatedState.hasCache = true
|
||||
|
||||
var existingIds = Set(updatedState.items.map { $0.id })
|
||||
var existingIds = Set(updatedState.items.map { $0.storyItem.id })
|
||||
for item in storyItems {
|
||||
if existingIds.contains(item.id) {
|
||||
if existingIds.contains(item.storyItem.id) {
|
||||
continue
|
||||
}
|
||||
existingIds.insert(item.id)
|
||||
existingIds.insert(item.storyItem.id)
|
||||
|
||||
updatedState.items.append(item)
|
||||
}
|
||||
|
|
@ -823,7 +891,7 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
|
||||
if hasMore {
|
||||
updatedState.loadMoreToken = (storyItems.last?.id).flatMap(Int.init)
|
||||
updatedState.loadMoreToken = (storyItems.last?.storyItem.id).flatMap(Int.init).flatMap({ AnyHashable($0) })
|
||||
} else {
|
||||
updatedState.loadMoreToken = nil
|
||||
}
|
||||
|
|
@ -834,7 +902,7 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
self.stateValue = updatedState
|
||||
|
||||
if let callbacks = self.completionCallbacksByToken.removeValue(forKey: loadMoreToken) {
|
||||
if let callbacks = self.completionCallbacksByToken.removeValue(forKey: AnyHashable(loadMoreToken)) {
|
||||
for f in callbacks {
|
||||
f()
|
||||
}
|
||||
|
|
@ -882,17 +950,19 @@ public final class PeerStoryListContext {
|
|||
return peers
|
||||
}
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] peers in
|
||||
guard let `self` = self else {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var finalUpdatedState: State?
|
||||
finalUpdatedState = nil
|
||||
let _ = finalUpdatedState
|
||||
|
||||
for update in updates {
|
||||
switch update {
|
||||
case let .deleted(peerId, id):
|
||||
if self.peerId == peerId {
|
||||
if let index = (finalUpdatedState ?? self.stateValue).items.firstIndex(where: { $0.id == id }) {
|
||||
if let index = (finalUpdatedState ?? self.stateValue).items.firstIndex(where: { $0.storyItem.id == id }) {
|
||||
var updatedState = finalUpdatedState ?? self.stateValue
|
||||
updatedState.items.remove(at: index)
|
||||
updatedState.totalCount = max(0, updatedState.totalCount - 1)
|
||||
|
|
@ -901,13 +971,13 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
case let .added(peerId, item):
|
||||
if self.peerId == peerId {
|
||||
if let index = (finalUpdatedState ?? self.stateValue).items.firstIndex(where: { $0.id == item.id }) {
|
||||
if let index = (finalUpdatedState ?? self.stateValue).items.firstIndex(where: { $0.storyItem.id == item.id }) {
|
||||
if !self.isArchived {
|
||||
if case let .item(item) = item {
|
||||
if item.isPinned {
|
||||
if let media = item.media {
|
||||
var updatedState = finalUpdatedState ?? self.stateValue
|
||||
updatedState.items[index] = EngineStoryItem(
|
||||
updatedState.items[index] = State.Item(storyItem: EngineStoryItem(
|
||||
id: item.id,
|
||||
timestamp: item.timestamp,
|
||||
expirationTimestamp: item.expirationTimestamp,
|
||||
|
|
@ -942,7 +1012,7 @@ public final class PeerStoryListContext {
|
|||
myReaction: item.myReaction,
|
||||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
|
||||
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) }
|
||||
)
|
||||
), peer: nil)
|
||||
finalUpdatedState = updatedState
|
||||
}
|
||||
} else {
|
||||
|
|
@ -956,7 +1026,7 @@ public final class PeerStoryListContext {
|
|||
if case let .item(item) = item {
|
||||
if let media = item.media {
|
||||
var updatedState = finalUpdatedState ?? self.stateValue
|
||||
updatedState.items[index] = EngineStoryItem(
|
||||
updatedState.items[index] = State.Item(storyItem: EngineStoryItem(
|
||||
id: item.id,
|
||||
timestamp: item.timestamp,
|
||||
expirationTimestamp: item.expirationTimestamp,
|
||||
|
|
@ -991,7 +1061,7 @@ public final class PeerStoryListContext {
|
|||
myReaction: item.myReaction,
|
||||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
|
||||
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) }
|
||||
)
|
||||
), peer: nil)
|
||||
finalUpdatedState = updatedState
|
||||
} else {
|
||||
var updatedState = finalUpdatedState ?? self.stateValue
|
||||
|
|
@ -1007,7 +1077,7 @@ public final class PeerStoryListContext {
|
|||
if item.isPinned {
|
||||
if let media = item.media {
|
||||
var updatedState = finalUpdatedState ?? self.stateValue
|
||||
updatedState.items.append(EngineStoryItem(
|
||||
updatedState.items.append(State.Item(storyItem: EngineStoryItem(
|
||||
id: item.id,
|
||||
timestamp: item.timestamp,
|
||||
expirationTimestamp: item.expirationTimestamp,
|
||||
|
|
@ -1042,10 +1112,10 @@ public final class PeerStoryListContext {
|
|||
myReaction: item.myReaction,
|
||||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
|
||||
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) }
|
||||
))
|
||||
), peer: nil))
|
||||
updatedState.items.sort(by: { lhs, rhs in
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.id)
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.storyItem.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.storyItem.id)
|
||||
if lhsPinned != rhsPinned {
|
||||
if lhsPinned {
|
||||
return true
|
||||
|
|
@ -1053,7 +1123,7 @@ public final class PeerStoryListContext {
|
|||
return false
|
||||
}
|
||||
}
|
||||
return lhs.timestamp > rhs.timestamp
|
||||
return lhs.storyItem.timestamp > rhs.storyItem.timestamp
|
||||
})
|
||||
finalUpdatedState = updatedState
|
||||
}
|
||||
|
|
@ -1063,7 +1133,7 @@ public final class PeerStoryListContext {
|
|||
if case let .item(item) = item {
|
||||
if let media = item.media {
|
||||
var updatedState = finalUpdatedState ?? self.stateValue
|
||||
updatedState.items.append(EngineStoryItem(
|
||||
updatedState.items.append(State.Item(storyItem: EngineStoryItem(
|
||||
id: item.id,
|
||||
timestamp: item.timestamp,
|
||||
expirationTimestamp: item.expirationTimestamp,
|
||||
|
|
@ -1098,10 +1168,10 @@ public final class PeerStoryListContext {
|
|||
myReaction: item.myReaction,
|
||||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
|
||||
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) }
|
||||
))
|
||||
), peer: nil))
|
||||
updatedState.items.sort(by: { lhs, rhs in
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.id)
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.storyItem.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.storyItem.id)
|
||||
if lhsPinned != rhsPinned {
|
||||
if lhsPinned {
|
||||
return true
|
||||
|
|
@ -1109,7 +1179,7 @@ public final class PeerStoryListContext {
|
|||
return false
|
||||
}
|
||||
}
|
||||
return lhs.timestamp > rhs.timestamp
|
||||
return lhs.storyItem.timestamp > rhs.storyItem.timestamp
|
||||
})
|
||||
finalUpdatedState = updatedState
|
||||
}
|
||||
|
|
@ -1126,8 +1196,8 @@ public final class PeerStoryListContext {
|
|||
var updatedState = finalUpdatedState ?? self.stateValue
|
||||
updatedState.pinnedIds = Set(ids)
|
||||
updatedState.items.sort(by: { lhs, rhs in
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.id)
|
||||
let lhsPinned = updatedState.pinnedIds.contains(lhs.storyItem.id)
|
||||
let rhsPinned = updatedState.pinnedIds.contains(rhs.storyItem.id)
|
||||
if lhsPinned != rhsPinned {
|
||||
if lhsPinned {
|
||||
return true
|
||||
|
|
@ -1135,7 +1205,7 @@ public final class PeerStoryListContext {
|
|||
return false
|
||||
}
|
||||
}
|
||||
return lhs.timestamp > rhs.timestamp
|
||||
return lhs.storyItem.timestamp > rhs.storyItem.timestamp
|
||||
})
|
||||
finalUpdatedState = updatedState
|
||||
}
|
||||
|
|
@ -1153,7 +1223,7 @@ public final class PeerStoryListContext {
|
|||
let key = ValueBoxKey(length: 8 + 1)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
key.setInt8(8, value: isArchived ? 1 : 0)
|
||||
if let entry = CodableEntry(CachedPeerStoryListHead(items: items.prefix(100).map { .item($0.asStoryItem()) }, pinnedIds: Array(pinnedIds), totalCount: Int32(totalCount))) {
|
||||
if let entry = CodableEntry(CachedPeerStoryListHead(items: items.prefix(100).map { .item($0.storyItem.asStoryItem()) }, pinnedIds: Array(pinnedIds), totalCount: Int32(totalCount))) {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerStoryListHeads, key: key), entry: entry)
|
||||
}
|
||||
}).start()
|
||||
|
|
@ -1165,37 +1235,6 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
}
|
||||
|
||||
public struct State: Equatable {
|
||||
public var peerReference: PeerReference?
|
||||
public var items: [EngineStoryItem]
|
||||
public var pinnedIds: Set<Int32>
|
||||
public var totalCount: Int
|
||||
public var loadMoreToken: Int?
|
||||
public var isCached: Bool
|
||||
public var hasCache: Bool
|
||||
public var allEntityFiles: [MediaId: TelegramMediaFile]
|
||||
|
||||
public init(
|
||||
peerReference: PeerReference?,
|
||||
items: [EngineStoryItem],
|
||||
pinnedIds: Set<Int32>,
|
||||
totalCount: Int,
|
||||
loadMoreToken: Int?,
|
||||
isCached: Bool,
|
||||
hasCache: Bool,
|
||||
allEntityFiles: [MediaId: TelegramMediaFile]
|
||||
) {
|
||||
self.peerReference = peerReference
|
||||
self.items = items
|
||||
self.pinnedIds = pinnedIds
|
||||
self.totalCount = totalCount
|
||||
self.loadMoreToken = loadMoreToken
|
||||
self.isCached = isCached
|
||||
self.hasCache = hasCache
|
||||
self.allEntityFiles = allEntityFiles
|
||||
}
|
||||
}
|
||||
|
||||
public var state: Signal<State, NoError> {
|
||||
return impl.signalWith { impl, subscriber in
|
||||
return impl.state.start(next: subscriber.putNext)
|
||||
|
|
@ -1220,6 +1259,217 @@ public final class PeerStoryListContext {
|
|||
}
|
||||
}
|
||||
|
||||
public final class SearchStoryListContext: StoryListContext {
|
||||
private final class Impl {
|
||||
private let queue: Queue
|
||||
private let account: Account
|
||||
private let query: String
|
||||
|
||||
private let statePromise = Promise<State>()
|
||||
private var stateValue: State {
|
||||
didSet {
|
||||
self.statePromise.set(.single(self.stateValue))
|
||||
}
|
||||
}
|
||||
var state: Signal<State, NoError> {
|
||||
return self.statePromise.get()
|
||||
}
|
||||
|
||||
private var isLoadingMore: Bool = false
|
||||
private var requestDisposable: Disposable?
|
||||
|
||||
private var updatesDisposable: Disposable?
|
||||
|
||||
private var completionCallbacksByToken: [AnyHashable: [() -> Void]] = [:]
|
||||
|
||||
init(queue: Queue, account: Account, query: String) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.query = query
|
||||
|
||||
self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: AnyHashable(""), isCached: false, hasCache: false, allEntityFiles: [:])
|
||||
self.statePromise.set(.single(self.stateValue))
|
||||
|
||||
self.loadMore(completion: nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.requestDisposable?.dispose()
|
||||
}
|
||||
|
||||
func loadMore(completion: (() -> Void)?) {
|
||||
guard let loadMoreTokenValue = self.stateValue.loadMoreToken, let loadMoreToken = loadMoreTokenValue.base as? String else {
|
||||
return
|
||||
}
|
||||
|
||||
if let completion = completion {
|
||||
if self.completionCallbacksByToken[loadMoreToken] == nil {
|
||||
self.completionCallbacksByToken[loadMoreToken] = []
|
||||
}
|
||||
self.completionCallbacksByToken[loadMoreToken]?.append(completion)
|
||||
}
|
||||
|
||||
if self.isLoadingMore {
|
||||
return
|
||||
}
|
||||
|
||||
self.isLoadingMore = true
|
||||
|
||||
let limit = 100
|
||||
|
||||
let account = self.account
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
let searchHashtag: String
|
||||
if self.query.hasPrefix("#") {
|
||||
searchHashtag = String(self.query[self.query.index(after: self.query.startIndex)...])
|
||||
} else {
|
||||
searchHashtag = self.query
|
||||
}
|
||||
|
||||
self.requestDisposable = (account.network.request(Api.functions.stories.searchPosts(hashtag: searchHashtag, offset: "", limit: Int32(limit)))
|
||||
|> map { result -> Api.stories.FoundStories? in
|
||||
return result
|
||||
}
|
||||
|> `catch` { _ -> Signal<Api.stories.FoundStories?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<([State.Item], Int, String?), NoError> in
|
||||
guard let result else {
|
||||
return .single(([], 0, nil))
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> ([State.Item], Int, String?) in
|
||||
var storyItems: [State.Item] = []
|
||||
var totalCount: Int = 0
|
||||
var nextOffsetValue: String?
|
||||
|
||||
switch result {
|
||||
case let .foundStories(_, count, stories, nextOffset, chats, users):
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(transaction: transaction, chats: chats, users: users))
|
||||
|
||||
totalCount = Int(count)
|
||||
nextOffsetValue = nextOffset
|
||||
|
||||
for story in stories {
|
||||
switch story {
|
||||
case let .foundStory(peer, story):
|
||||
if let storedItem = Stories.StoredItem(apiStoryItem: story, peerId: peer.peerId, transaction: transaction) {
|
||||
if case let .item(item) = storedItem, let media = item.media {
|
||||
let mappedItem = EngineStoryItem(
|
||||
id: item.id,
|
||||
timestamp: item.timestamp,
|
||||
expirationTimestamp: item.expirationTimestamp,
|
||||
media: EngineMedia(media),
|
||||
alternativeMedia: item.alternativeMedia.flatMap(EngineMedia.init),
|
||||
mediaAreas: item.mediaAreas,
|
||||
text: item.text,
|
||||
entities: item.entities,
|
||||
views: item.views.flatMap { views in
|
||||
return EngineStoryItem.Views(
|
||||
seenCount: views.seenCount,
|
||||
reactedCount: views.reactedCount,
|
||||
forwardCount: views.forwardCount,
|
||||
seenPeers: views.seenPeerIds.compactMap { id -> EnginePeer? in
|
||||
return transaction.getPeer(id).flatMap(EnginePeer.init)
|
||||
},
|
||||
reactions: views.reactions,
|
||||
hasList: views.hasList
|
||||
)
|
||||
},
|
||||
privacy: item.privacy.flatMap(EngineStoryPrivacy.init),
|
||||
isPinned: item.isPinned,
|
||||
isExpired: item.isExpired,
|
||||
isPublic: item.isPublic,
|
||||
isPending: false,
|
||||
isCloseFriends: item.isCloseFriends,
|
||||
isContacts: item.isContacts,
|
||||
isSelectedContacts: item.isSelectedContacts,
|
||||
isForwardingDisabled: item.isForwardingDisabled,
|
||||
isEdited: item.isEdited,
|
||||
isMy: item.isMy,
|
||||
myReaction: item.myReaction,
|
||||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
|
||||
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) }
|
||||
)
|
||||
storyItems.append(State.Item(
|
||||
storyItem: mappedItem,
|
||||
peer: transaction.getPeer(peer.peerId).flatMap(EnginePeer.init)
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (storyItems, totalCount, nextOffsetValue)
|
||||
}
|
||||
}
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] storyItems, totalCount, nextOffset in
|
||||
guard let `self` = self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.isLoadingMore = false
|
||||
|
||||
var updatedState = self.stateValue
|
||||
updatedState.hasCache = true
|
||||
|
||||
var existingIds = Set(updatedState.items.map { $0.storyItem.id })
|
||||
for item in storyItems {
|
||||
if existingIds.contains(item.storyItem.id) {
|
||||
continue
|
||||
}
|
||||
existingIds.insert(item.storyItem.id)
|
||||
|
||||
updatedState.items.append(item)
|
||||
}
|
||||
|
||||
if let nextOffset {
|
||||
updatedState.loadMoreToken = AnyHashable(nextOffset)
|
||||
} else {
|
||||
updatedState.loadMoreToken = nil
|
||||
}
|
||||
if updatedState.loadMoreToken != nil {
|
||||
updatedState.totalCount = max(totalCount, updatedState.items.count)
|
||||
} else {
|
||||
updatedState.totalCount = updatedState.items.count
|
||||
}
|
||||
self.stateValue = updatedState
|
||||
|
||||
if let callbacks = self.completionCallbacksByToken.removeValue(forKey: loadMoreToken) {
|
||||
for f in callbacks {
|
||||
f()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public var state: Signal<State, NoError> {
|
||||
return impl.signalWith { impl, subscriber in
|
||||
return impl.state.start(next: subscriber.putNext)
|
||||
}
|
||||
}
|
||||
|
||||
private let queue: Queue
|
||||
private let impl: QueueLocalObject<Impl>
|
||||
|
||||
public init(account: Account, query: String) {
|
||||
let queue = Queue.mainQueue()
|
||||
self.queue = queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return Impl(queue: queue, account: account, query: query)
|
||||
})
|
||||
}
|
||||
|
||||
public func loadMore(completion: (() -> Void)? = nil) {
|
||||
self.impl.with { impl in
|
||||
impl.loadMore(completion : completion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class PeerExpiringStoryListContext {
|
||||
private final class Impl {
|
||||
private let queue: Queue
|
||||
|
|
|
|||
|
|
@ -1475,7 +1475,7 @@ public extension TelegramEngine {
|
|||
return .single(false)
|
||||
}
|
||||
|
||||
return self.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: id, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 44, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: [])
|
||||
return self.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: id, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 44, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: [])
|
||||
|> map { view -> Bool in
|
||||
for entry in view.0.entries {
|
||||
if entry.message.flags.contains(.Incoming) {
|
||||
|
|
|
|||
|
|
@ -334,8 +334,8 @@ final class PeerInfoScreenData {
|
|||
let groupsInCommon: GroupsInCommonContext?
|
||||
let linkedDiscussionPeer: Peer?
|
||||
let members: PeerInfoMembersData?
|
||||
let storyListContext: PeerStoryListContext?
|
||||
let storyArchiveListContext: PeerStoryListContext?
|
||||
let storyListContext: StoryListContext?
|
||||
let storyArchiveListContext: StoryListContext?
|
||||
let encryptionKeyFingerprint: SecretChatKeyFingerprint?
|
||||
let globalSettings: TelegramGlobalSettings?
|
||||
let invitations: PeerExportedInvitationsState?
|
||||
|
|
@ -375,8 +375,8 @@ final class PeerInfoScreenData {
|
|||
groupsInCommon: GroupsInCommonContext?,
|
||||
linkedDiscussionPeer: Peer?,
|
||||
members: PeerInfoMembersData?,
|
||||
storyListContext: PeerStoryListContext?,
|
||||
storyArchiveListContext: PeerStoryListContext?,
|
||||
storyListContext: StoryListContext?,
|
||||
storyArchiveListContext: StoryListContext?,
|
||||
encryptionKeyFingerprint: SecretChatKeyFingerprint?,
|
||||
globalSettings: TelegramGlobalSettings?,
|
||||
invitations: PeerExportedInvitationsState?,
|
||||
|
|
@ -635,7 +635,7 @@ private func peerInfoPersonalChannel(context: AccountContext, peerId: EnginePeer
|
|||
)
|
||||
|
||||
return combineLatest(
|
||||
context.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: channelPeer.id, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 10, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: []),
|
||||
context.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: channelPeer.id, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, clipHoles: false, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: []),
|
||||
context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Peer.StoryStats(id: channelPeer.id)
|
||||
),
|
||||
|
|
@ -1071,7 +1071,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||
|> distinctUntilChanged
|
||||
|
||||
let hasStoryArchive: Signal<Bool?, NoError>
|
||||
var storyArchiveListContext: PeerStoryListContext?
|
||||
var storyArchiveListContext: StoryListContext?
|
||||
if isMyProfile {
|
||||
let storyArchiveListContextValue = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: true)
|
||||
storyArchiveListContext = storyArchiveListContextValue
|
||||
|
|
@ -1556,7 +1556,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||
let requestsContextPromise = Promise<PeerInvitationImportersContext?>(nil)
|
||||
let requestsStatePromise = Promise<PeerInvitationImportersState?>(nil)
|
||||
|
||||
let storyListContext: PeerStoryListContext?
|
||||
let storyListContext: StoryListContext?
|
||||
let hasStories: Signal<Bool?, NoError>
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
storyListContext = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: false)
|
||||
|
|
|
|||
|
|
@ -435,7 +435,7 @@ private final class DurationLayer: SimpleLayer {
|
|||
avatarLayer.contents = other.avatarLayer?.contents
|
||||
}
|
||||
|
||||
func update(directMediaImageCache: DirectMediaImageCache, author: EnginePeer, synchronous: SparseItemGrid.Synchronous) {
|
||||
func update(directMediaImageCache: DirectMediaImageCache, author: EnginePeer, constrainedWidth: CGFloat, synchronous: SparseItemGrid.Synchronous) {
|
||||
let avatarLayer: SimpleLayer
|
||||
if let current = self.avatarLayer {
|
||||
avatarLayer = current
|
||||
|
|
@ -451,7 +451,7 @@ private final class DurationLayer: SimpleLayer {
|
|||
|
||||
if self.authorPeerId != author.id {
|
||||
let string = NSAttributedString(string: author.debugDisplayTitle, font: durationFont, textColor: .white)
|
||||
let bounds = string.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil)
|
||||
let bounds = string.boundingRect(with: CGSize(width: constrainedWidth - 20.0, height: 20.0), options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
|
||||
let textSize = CGSize(width: ceil(bounds.width), height: ceil(bounds.height))
|
||||
let sideInset: CGFloat = 6.0
|
||||
let verticalInset: CGFloat = 2.0
|
||||
|
|
@ -463,7 +463,7 @@ private final class DurationLayer: SimpleLayer {
|
|||
context.setShadow(offset: CGSize(width: 0.0, height: 0.0), blur: 2.5, color: UIColor(rgb: 0x000000, alpha: 0.22).cgColor)
|
||||
|
||||
UIGraphicsPushContext(context)
|
||||
string.draw(in: bounds.offsetBy(dx: sideInset, dy: verticalInset))
|
||||
string.draw(with: bounds.offsetBy(dx: sideInset, dy: verticalInset), options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
|
||||
UIGraphicsPopContext()
|
||||
})
|
||||
self.contents = image?.cgImage
|
||||
|
|
@ -552,7 +552,7 @@ private final class ItemLayer: CALayer, SparseItemGridLayer {
|
|||
self.item = item
|
||||
}
|
||||
|
||||
func updateDuration(viewCount: Int32?, duration: Int32?, topRightIcon: ItemTopRightIcon?, author: EnginePeer?, isMin: Bool, minFactor: CGFloat, directMediaImageCache: DirectMediaImageCache, synchronous: SparseItemGrid.Synchronous) {
|
||||
func updateDuration(size: CGSize, viewCount: Int32?, duration: Int32?, topRightIcon: ItemTopRightIcon?, author: EnginePeer?, isMin: Bool, minFactor: CGFloat, directMediaImageCache: DirectMediaImageCache, synchronous: SparseItemGrid.Synchronous) {
|
||||
self.minFactor = minFactor
|
||||
|
||||
if let viewCount {
|
||||
|
|
@ -607,11 +607,11 @@ private final class ItemLayer: CALayer, SparseItemGridLayer {
|
|||
|
||||
if let author {
|
||||
if let authorLayer = self.authorLayer {
|
||||
authorLayer.update(directMediaImageCache: directMediaImageCache, author: author, synchronous: synchronous)
|
||||
authorLayer.update(directMediaImageCache: directMediaImageCache, author: author, constrainedWidth: size.width, synchronous: synchronous)
|
||||
} else {
|
||||
let authorLayer = DurationLayer()
|
||||
authorLayer.contentsGravity = .bottomLeft
|
||||
authorLayer.update(directMediaImageCache: directMediaImageCache, author: author, synchronous: synchronous)
|
||||
authorLayer.update(directMediaImageCache: directMediaImageCache, author: author, constrainedWidth: size.width, synchronous: synchronous)
|
||||
self.addSublayer(authorLayer)
|
||||
authorLayer.frame = CGRect(origin: CGPoint(x: 17.0, y: 3.0), size: CGSize())
|
||||
authorLayer.transform = CATransform3DMakeScale(minFactor, minFactor, 1.0)
|
||||
|
|
@ -1292,7 +1292,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding {
|
|||
isMin = layer.bounds.width < 80.0
|
||||
}
|
||||
|
||||
layer.updateDuration(viewCount: viewCount, duration: duration, topRightIcon: topRightIcon, author: item.authorPeer, isMin: isMin, minFactor: min(1.0, layer.bounds.height / 74.0), directMediaImageCache: self.directMediaImageCache, synchronous: synchronous)
|
||||
layer.updateDuration(size: layer.bounds.size, viewCount: viewCount, duration: duration, topRightIcon: topRightIcon, author: item.authorPeer, isMin: isMin, minFactor: min(1.0, layer.bounds.height / 74.0), directMediaImageCache: self.directMediaImageCache, synchronous: synchronous)
|
||||
}
|
||||
|
||||
func unbindLayer(layer: SparseItemGridLayer) {
|
||||
|
|
@ -1468,7 +1468,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
private var animationTimer: SwiftSignalKit.Timer?
|
||||
|
||||
public private(set) var calendarSource: SparseMessageCalendar?
|
||||
private var listSource: PeerStoryListContext
|
||||
private var listSource: StoryListContext
|
||||
|
||||
public var openCurrentDate: (() -> Void)?
|
||||
public var paneDidScroll: (() -> Void)?
|
||||
|
|
@ -1484,14 +1484,14 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
|
||||
private weak var pendingOpenListContext: PeerStoryListContentContextImpl?
|
||||
|
||||
private var preloadArchiveListContext: PeerStoryListContext?
|
||||
private var preloadArchiveListContext: StoryListContext?
|
||||
|
||||
private var emptyStateView: ComponentView<Empty>?
|
||||
|
||||
private weak var contextControllerToDismissOnSelection: ContextControllerProtocol?
|
||||
private weak var tempContextContentItemNode: TempExtractedItemNode?
|
||||
|
||||
public init(context: AccountContext, peerId: PeerId?, searchQuery: String? = nil, contentType: ContentType, captureProtected: Bool, isSaved: Bool, isArchive: Bool, isProfileEmbedded: Bool, canManageStories: Bool, navigationController: @escaping () -> NavigationController?, listContext: PeerStoryListContext?) {
|
||||
public init(context: AccountContext, peerId: PeerId?, searchQuery: String? = nil, contentType: ContentType, captureProtected: Bool, isSaved: Bool, isArchive: Bool, isProfileEmbedded: Bool, canManageStories: Bool, navigationController: @escaping () -> NavigationController?, listContext: StoryListContext?) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.searchQuery = searchQuery
|
||||
|
|
@ -1518,7 +1518,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
displayPrivacy: isProfileEmbedded
|
||||
)
|
||||
|
||||
self.listSource = listContext ?? PeerStoryListContext(account: context.account, peerId: peerId ?? context.account.peerId, isArchived: self.isArchive)
|
||||
if let listContext {
|
||||
self.listSource = listContext
|
||||
} else if let searchQuery {
|
||||
self.listSource = SearchStoryListContext(account: context.account, query: searchQuery)
|
||||
} else {
|
||||
self.listSource = PeerStoryListContext(account: context.account, peerId: peerId ?? context.account.peerId, isArchived: self.isArchive)
|
||||
}
|
||||
self.calendarSource = nil
|
||||
|
||||
super.init()
|
||||
|
|
@ -2237,37 +2243,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
var firstTime = true
|
||||
let queue = Queue()
|
||||
|
||||
let authorPeer: Signal<EnginePeer?, NoError>
|
||||
if self.searchQuery != nil {
|
||||
authorPeer = self.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)
|
||||
)
|
||||
} else {
|
||||
authorPeer = .single(nil)
|
||||
}
|
||||
|
||||
var state = self.listSource.state
|
||||
if self.peerId == nil && self.listDisposable == nil {
|
||||
state = .single(PeerStoryListContext.State(
|
||||
peerReference: nil,
|
||||
items: [],
|
||||
pinnedIds: Set(),
|
||||
totalCount: 0,
|
||||
loadMoreToken: 0,
|
||||
isCached: false,
|
||||
hasCache: false,
|
||||
allEntityFiles: [:]
|
||||
)) |> then(state |> delay(2.0, queue: .mainQueue()))
|
||||
}
|
||||
let state = self.listSource.state
|
||||
|
||||
self.listDisposable?.dispose()
|
||||
self.listDisposable = nil
|
||||
|
||||
self.listDisposable = (combineLatest(
|
||||
state,
|
||||
authorPeer
|
||||
)
|
||||
|> deliverOn(queue)).startStrict(next: { [weak self] state, authorPeer in
|
||||
self.listDisposable = (state
|
||||
|> deliverOn(queue)).startStrict(next: { [weak self] state in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -2291,20 +2273,28 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
var mappedItems: [SparseItemGrid.Item] = []
|
||||
var mappedHoles: [SparseItemGrid.HoleAnchor] = []
|
||||
var totalCount: Int = 0
|
||||
if let peerReference = state.peerReference {
|
||||
for item in state.items {
|
||||
mappedItems.append(VisualMediaItem(
|
||||
index: mappedItems.count,
|
||||
peer: peerReference,
|
||||
story: item,
|
||||
authorPeer: authorPeer,
|
||||
isPinned: state.pinnedIds.contains(item.id),
|
||||
localMonthTimestamp: Month(localTimestamp: item.timestamp + timezoneOffset).packedValue
|
||||
))
|
||||
for item in state.items {
|
||||
var peerReference: PeerReference?
|
||||
if let value = state.peerReference {
|
||||
peerReference = value
|
||||
} else if let peer = item.peer {
|
||||
peerReference = PeerReference(peer._asPeer())
|
||||
}
|
||||
if mappedItems.count < state.totalCount, let lastItem = state.items.last, let loadMoreToken = state.loadMoreToken {
|
||||
mappedHoles.append(VisualMediaHoleAnchor(index: mappedItems.count, storyId: Int32(loadMoreToken), localMonthTimestamp: Month(localTimestamp: lastItem.timestamp + timezoneOffset).packedValue))
|
||||
guard let peerReference else {
|
||||
continue
|
||||
}
|
||||
|
||||
mappedItems.append(VisualMediaItem(
|
||||
index: mappedItems.count,
|
||||
peer: peerReference,
|
||||
story: item.storyItem,
|
||||
authorPeer: item.peer,
|
||||
isPinned: state.pinnedIds.contains(item.storyItem.id),
|
||||
localMonthTimestamp: Month(localTimestamp: item.storyItem.timestamp + timezoneOffset).packedValue
|
||||
))
|
||||
}
|
||||
if mappedItems.count < state.totalCount, let lastItem = state.items.last, let _ = state.loadMoreToken {
|
||||
mappedHoles.append(VisualMediaHoleAnchor(index: mappedItems.count, storyId: Int32.max, localMonthTimestamp: Month(localTimestamp: lastItem.storyItem.timestamp + timezoneOffset).packedValue))
|
||||
}
|
||||
totalCount = state.totalCount
|
||||
totalCount = max(mappedItems.count, totalCount)
|
||||
|
|
@ -2833,7 +2823,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
|
||||
transition.updateFrame(node: self.contextGestureContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
|
||||
if let items = self.items, items.items.isEmpty, items.count == 0 {
|
||||
if self.searchQuery == nil, let items = self.items, items.items.isEmpty, items.count == 0 {
|
||||
let emptyStateView: ComponentView<Empty>
|
||||
var emptyStateTransition = Transition(transition)
|
||||
if let current = self.emptyStateView {
|
||||
|
|
|
|||
|
|
@ -678,58 +678,67 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
}, reportPeerIrrelevantGeoLocation: {
|
||||
}, displaySlowmodeTooltip: { _, _ in
|
||||
}, displaySendMessageOptions: { [weak self] node, gesture in
|
||||
guard let strongSelf = self, let textInputPanelNode = strongSelf.textInputPanelNode else {
|
||||
return
|
||||
}
|
||||
textInputPanelNode.loadTextInputNodeIfNeeded()
|
||||
guard let textInputNode = textInputPanelNode.textInputNode else {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
var hasEntityKeyboard = false
|
||||
if case .media = strongSelf.presentationInterfaceState.inputMode {
|
||||
hasEntityKeyboard = true
|
||||
}
|
||||
|
||||
let controller = makeChatSendMessageActionSheetController(
|
||||
context: strongSelf.context,
|
||||
peerId: strongSelf.presentationInterfaceState.chatLocation.peerId,
|
||||
params: .sendMessage(SendMessageActionSheetControllerParams.SendMessage(
|
||||
isScheduledMessages: false,
|
||||
mediaPreview: nil,
|
||||
mediaCaptionIsAbove: nil,
|
||||
attachment: false,
|
||||
canSendWhenOnline: false,
|
||||
forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
)),
|
||||
hasEntityKeyboard: hasEntityKeyboard,
|
||||
gesture: gesture,
|
||||
sourceSendButton: node,
|
||||
textInputView: textInputNode.textView,
|
||||
emojiViewProvider: textInputPanelNode.emojiViewProvider,
|
||||
completion: {
|
||||
},
|
||||
sendMessage: { [weak textInputPanelNode] mode, messageEffect in
|
||||
switch mode {
|
||||
case .generic:
|
||||
textInputPanelNode?.sendMessage(.generic, messageEffect)
|
||||
case .silently:
|
||||
textInputPanelNode?.sendMessage(.silent, messageEffect)
|
||||
case .whenOnline:
|
||||
textInputPanelNode?.sendMessage(.whenOnline, messageEffect)
|
||||
}
|
||||
},
|
||||
schedule: { [weak textInputPanelNode] messageEffect in
|
||||
textInputPanelNode?.sendMessage(.schedule, messageEffect)
|
||||
},
|
||||
openPremiumPaywall: { [weak controller] c in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
controller.push(c)
|
||||
let _ = (ChatSendMessageContextScreen.initialData(context: strongSelf.context, currentMessageEffectId: nil)
|
||||
|> deliverOnMainQueue).start(next: { initialData in
|
||||
guard let strongSelf = self, let textInputPanelNode = strongSelf.textInputPanelNode else {
|
||||
return
|
||||
}
|
||||
)
|
||||
strongSelf.presentInGlobalOverlay(controller, nil)
|
||||
textInputPanelNode.loadTextInputNodeIfNeeded()
|
||||
guard let textInputNode = textInputPanelNode.textInputNode else {
|
||||
return
|
||||
}
|
||||
|
||||
var hasEntityKeyboard = false
|
||||
if case .media = strongSelf.presentationInterfaceState.inputMode {
|
||||
hasEntityKeyboard = true
|
||||
}
|
||||
|
||||
let controller = makeChatSendMessageActionSheetController(
|
||||
initialData: initialData,
|
||||
context: strongSelf.context,
|
||||
peerId: strongSelf.presentationInterfaceState.chatLocation.peerId,
|
||||
params: .sendMessage(SendMessageActionSheetControllerParams.SendMessage(
|
||||
isScheduledMessages: false,
|
||||
mediaPreview: nil,
|
||||
mediaCaptionIsAbove: nil,
|
||||
messageEffect: nil,
|
||||
attachment: false,
|
||||
canSendWhenOnline: false,
|
||||
forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
)),
|
||||
hasEntityKeyboard: hasEntityKeyboard,
|
||||
gesture: gesture,
|
||||
sourceSendButton: node,
|
||||
textInputView: textInputNode.textView,
|
||||
emojiViewProvider: textInputPanelNode.emojiViewProvider,
|
||||
completion: {
|
||||
},
|
||||
sendMessage: { [weak textInputPanelNode] mode, messageEffect in
|
||||
switch mode {
|
||||
case .generic:
|
||||
textInputPanelNode?.sendMessage(.generic, messageEffect)
|
||||
case .silently:
|
||||
textInputPanelNode?.sendMessage(.silent, messageEffect)
|
||||
case .whenOnline:
|
||||
textInputPanelNode?.sendMessage(.whenOnline, messageEffect)
|
||||
}
|
||||
},
|
||||
schedule: { [weak textInputPanelNode] messageEffect in
|
||||
textInputPanelNode?.sendMessage(.schedule, messageEffect)
|
||||
},
|
||||
openPremiumPaywall: { [weak controller] c in
|
||||
guard let controller else {
|
||||
return
|
||||
}
|
||||
controller.push(c)
|
||||
}
|
||||
)
|
||||
strongSelf.presentInGlobalOverlay(controller, nil)
|
||||
})
|
||||
}, openScheduledMessages: {
|
||||
}, openPeersNearby: {
|
||||
}, displaySearchResultsTooltip: { _, _ in
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public extension StoryContainerScreen {
|
|||
|> take(1)
|
||||
|> mapToSignal { state -> Signal<Void, NoError> in
|
||||
if let slice = state.slice {
|
||||
return waitUntilStoryMediaPreloaded(context: context, peerId: slice.peer.id, storyItem: slice.item.storyItem)
|
||||
return waitUntilStoryMediaPreloaded(context: context, peerId: slice.effectivePeer.id, storyItem: slice.item.storyItem)
|
||||
|> timeout(4.0, queue: .mainQueue(), alternate: .complete())
|
||||
|> map { _ -> Void in
|
||||
}
|
||||
|
|
@ -185,7 +185,7 @@ public extension StoryContainerScreen {
|
|||
}
|
||||
#endif
|
||||
|
||||
return waitUntilStoryMediaPreloaded(context: context, peerId: slice.peer.id, storyItem: slice.item.storyItem)
|
||||
return waitUntilStoryMediaPreloaded(context: context, peerId: slice.effectivePeer.id, storyItem: slice.item.storyItem)
|
||||
|> timeout(4.0, queue: .mainQueue(), alternate: .complete())
|
||||
|> map { _ -> StoryContentContextState in
|
||||
}
|
||||
|
|
|
|||
|
|
@ -444,7 +444,8 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||
dayCounters: nil,
|
||||
peerId: peer.id,
|
||||
storyItem: item,
|
||||
entityFiles: extractItemEntityFiles(item: item, allEntityFiles: allEntityFiles)
|
||||
entityFiles: extractItemEntityFiles(item: item, allEntityFiles: allEntityFiles),
|
||||
itemPeer: nil
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -457,7 +458,8 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||
dayCounters: nil,
|
||||
peerId: peer.id,
|
||||
storyItem: mappedItem,
|
||||
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles)
|
||||
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles),
|
||||
itemPeer: nil
|
||||
),
|
||||
totalCount: totalCount,
|
||||
previousItemId: previousItemId,
|
||||
|
|
@ -1344,7 +1346,8 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
|||
dayCounters: nil,
|
||||
peerId: peer.id,
|
||||
storyItem: mappedItem,
|
||||
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles)
|
||||
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles),
|
||||
itemPeer: nil
|
||||
)
|
||||
let stateValue = StoryContentContextState(
|
||||
slice: StoryContentContextState.FocusedSlice(
|
||||
|
|
@ -1421,7 +1424,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
private var requestedStoryKeys = Set<StoryKey>()
|
||||
private var requestStoryDisposables = DisposableSet()
|
||||
|
||||
private var listState: PeerStoryListContext.State?
|
||||
private var listState: StoryListContext.State?
|
||||
|
||||
private var focusedId: Int32?
|
||||
private var focusedIdUpdated = Promise<Void>(Void())
|
||||
|
|
@ -1429,7 +1432,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
private var preloadStoryResourceDisposables: [EngineMedia.Id: Disposable] = [:]
|
||||
private var pollStoryMetadataDisposables = DisposableSet()
|
||||
|
||||
public init(context: AccountContext, peerId: EnginePeer.Id, listContext: PeerStoryListContext, initialId: Int32?) {
|
||||
public init(context: AccountContext, peerId: EnginePeer.Id, listContext: StoryListContext, initialId: Int32?) {
|
||||
self.context = context
|
||||
|
||||
context.engine.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: [peerId])
|
||||
|
|
@ -1494,9 +1497,9 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
|
||||
let focusedIndex: Int?
|
||||
if let current = self.focusedId {
|
||||
if let index = state.items.firstIndex(where: { $0.id == current }) {
|
||||
if let index = state.items.firstIndex(where: { $0.storyItem.id == current }) {
|
||||
focusedIndex = index
|
||||
} else if let index = state.items.firstIndex(where: { $0.id <= current }) {
|
||||
} else if let index = state.items.firstIndex(where: { $0.storyItem.id <= current }) {
|
||||
focusedIndex = index
|
||||
} else if !state.items.isEmpty {
|
||||
focusedIndex = 0
|
||||
|
|
@ -1504,9 +1507,9 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
focusedIndex = nil
|
||||
}
|
||||
} else if let initialId = initialId {
|
||||
if let index = state.items.firstIndex(where: { $0.id == initialId }) {
|
||||
if let index = state.items.firstIndex(where: { $0.storyItem.id == initialId }) {
|
||||
focusedIndex = index
|
||||
} else if let index = state.items.firstIndex(where: { $0.id <= initialId }) {
|
||||
} else if let index = state.items.firstIndex(where: { $0.storyItem.id <= initialId }) {
|
||||
focusedIndex = index
|
||||
} else {
|
||||
focusedIndex = nil
|
||||
|
|
@ -1536,7 +1539,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
let stateValue: StoryContentContextState
|
||||
if let focusedIndex = focusedIndex {
|
||||
let item = state.items[focusedIndex]
|
||||
self.focusedId = item.id
|
||||
self.focusedId = item.storyItem.id
|
||||
|
||||
var allItems: [StoryContentItem] = []
|
||||
|
||||
|
|
@ -1549,11 +1552,12 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
position: i,
|
||||
dayCounters: nil,
|
||||
peerId: peer.id,
|
||||
storyItem: stateItem,
|
||||
entityFiles: extractItemEntityFiles(item: stateItem, allEntityFiles: state.allEntityFiles)
|
||||
storyItem: stateItem.storyItem,
|
||||
entityFiles: extractItemEntityFiles(item: stateItem.storyItem, allEntityFiles: state.allEntityFiles),
|
||||
itemPeer: stateItem.peer
|
||||
))
|
||||
|
||||
let day = DayIndex(timestamp: stateItem.timestamp)
|
||||
let day = DayIndex(timestamp: stateItem.storyItem.timestamp)
|
||||
let dayCount: Int
|
||||
if let current = dayCounts[day] {
|
||||
dayCount = current + 1
|
||||
|
|
@ -1562,11 +1566,11 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
dayCount = 1
|
||||
dayCounts[day] = dayCount
|
||||
}
|
||||
itemDayIndices[stateItem.id] = (dayCount - 1, day)
|
||||
itemDayIndices[stateItem.storyItem.id] = (dayCount - 1, day)
|
||||
}
|
||||
|
||||
var dayCounters: StoryContentItem.DayCounters?
|
||||
if let (offset, day) = itemDayIndices[item.id], let dayCount = dayCounts[day] {
|
||||
if let (offset, day) = itemDayIndices[item.storyItem.id], let dayCount = dayCounts[day] {
|
||||
dayCounters = StoryContentItem.DayCounters(
|
||||
position: offset,
|
||||
totalCount: dayCount
|
||||
|
|
@ -1581,12 +1585,13 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
position: focusedIndex,
|
||||
dayCounters: dayCounters,
|
||||
peerId: peer.id,
|
||||
storyItem: item,
|
||||
entityFiles: extractItemEntityFiles(item: item, allEntityFiles: state.allEntityFiles)
|
||||
storyItem: item.storyItem,
|
||||
entityFiles: extractItemEntityFiles(item: item.storyItem, allEntityFiles: state.allEntityFiles),
|
||||
itemPeer: item.peer
|
||||
),
|
||||
totalCount: state.totalCount,
|
||||
previousItemId: focusedIndex == 0 ? nil : state.items[focusedIndex - 1].id,
|
||||
nextItemId: (focusedIndex == state.items.count - 1) ? nil : state.items[focusedIndex + 1].id,
|
||||
previousItemId: focusedIndex == 0 ? nil : state.items[focusedIndex - 1].storyItem.id,
|
||||
nextItemId: (focusedIndex == state.items.count - 1) ? nil : state.items[focusedIndex + 1].storyItem.id,
|
||||
allItems: allItems,
|
||||
forwardInfoStories: [:]
|
||||
),
|
||||
|
|
@ -1612,7 +1617,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
var pollItems: [StoryKey] = []
|
||||
|
||||
if let focusedIndex, let slice = stateValue.slice {
|
||||
var possibleItems: [(EnginePeer, EngineStoryItem)] = []
|
||||
var possibleItems: [(EnginePeer, StoryListContext.State.Item)] = []
|
||||
if peer.id == self.context.account.peerId {
|
||||
pollItems.append(StoryKey(peerId: peer.id, id: slice.item.storyItem.id))
|
||||
}
|
||||
|
|
@ -1623,7 +1628,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
}
|
||||
|
||||
if slice.peer.id == self.context.account.peerId {
|
||||
pollItems.append(StoryKey(peerId: slice.peer.id, id: state.items[i].id))
|
||||
pollItems.append(StoryKey(peerId: slice.peer.id, id: state.items[i].storyItem.id))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1631,9 +1636,9 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
for i in 0 ..< min(possibleItems.count, 3) {
|
||||
let peer = possibleItems[i].0
|
||||
let item = possibleItems[i].1
|
||||
if let peerReference = PeerReference(peer._asPeer()), let mediaId = item.media.id {
|
||||
if let peerReference = PeerReference(peer._asPeer()), let mediaId = item.storyItem.media.id {
|
||||
var reactions: [MessageReaction.Reaction] = []
|
||||
for mediaArea in item.mediaAreas {
|
||||
for mediaArea in item.storyItem.mediaAreas {
|
||||
if case let .reaction(_, reaction, _) = mediaArea {
|
||||
if !reactions.contains(reaction) {
|
||||
reactions.append(reaction)
|
||||
|
|
@ -1642,15 +1647,15 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
}
|
||||
|
||||
var selectedMedia: EngineMedia
|
||||
if let alternativeMedia = item.alternativeMedia, (!preferHighQualityStories && !item.isMy) {
|
||||
if let alternativeMedia = item.storyItem.alternativeMedia, (!preferHighQualityStories && !item.storyItem.isMy) {
|
||||
selectedMedia = alternativeMedia
|
||||
} else {
|
||||
selectedMedia = item.media
|
||||
selectedMedia = item.storyItem.media
|
||||
}
|
||||
|
||||
resultResources[mediaId] = StoryPreloadInfo(
|
||||
peer: peerReference,
|
||||
storyId: item.id,
|
||||
storyId: item.storyItem.id,
|
||||
media: selectedMedia,
|
||||
reactions: reactions,
|
||||
priority: .top(position: nextPriority)
|
||||
|
|
@ -1721,13 +1726,13 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
case .previous:
|
||||
indexDifference = -1
|
||||
case let .id(id):
|
||||
if let listState = self.listState, let focusedId = self.focusedId, let index = listState.items.firstIndex(where: { $0.id == focusedId }), let nextIndex = listState.items.firstIndex(where: { $0.id == id }) {
|
||||
if let listState = self.listState, let focusedId = self.focusedId, let index = listState.items.firstIndex(where: { $0.storyItem.id == focusedId }), let nextIndex = listState.items.firstIndex(where: { $0.storyItem.id == id }) {
|
||||
indexDifference = nextIndex - index
|
||||
}
|
||||
}
|
||||
|
||||
if let indexDifference, let listState = self.listState, let focusedId = self.focusedId {
|
||||
if let index = listState.items.firstIndex(where: { $0.id == focusedId }) {
|
||||
if let index = listState.items.firstIndex(where: { $0.storyItem.id == focusedId }) {
|
||||
var nextIndex = index + indexDifference
|
||||
if nextIndex < 0 {
|
||||
nextIndex = 0
|
||||
|
|
@ -1736,7 +1741,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
|
|||
nextIndex = listState.items.count - 1
|
||||
}
|
||||
if nextIndex != index {
|
||||
self.focusedId = listState.items[nextIndex].id
|
||||
self.focusedId = listState.items[nextIndex].storyItem.id
|
||||
self.focusedIdUpdated.set(.single(Void()))
|
||||
}
|
||||
}
|
||||
|
|
@ -2516,7 +2521,8 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
|||
dayCounters: nil,
|
||||
peerId: peer.id,
|
||||
storyItem: item,
|
||||
entityFiles: extractItemEntityFiles(item: item, allEntityFiles: allEntityFiles)
|
||||
entityFiles: extractItemEntityFiles(item: item, allEntityFiles: allEntityFiles),
|
||||
itemPeer: nil
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -2529,7 +2535,8 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
|||
dayCounters: nil,
|
||||
peerId: peer.id,
|
||||
storyItem: mappedItem,
|
||||
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles)
|
||||
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles),
|
||||
itemPeer: nil
|
||||
),
|
||||
totalCount: totalCount,
|
||||
previousItemId: previousItemId,
|
||||
|
|
|
|||
|
|
@ -104,19 +104,22 @@ public final class StoryContentItem: Equatable {
|
|||
public let peerId: EnginePeer.Id?
|
||||
public let storyItem: EngineStoryItem
|
||||
public let entityFiles: [EngineMedia.Id: TelegramMediaFile]
|
||||
public let itemPeer: EnginePeer?
|
||||
|
||||
public init(
|
||||
position: Int?,
|
||||
dayCounters: DayCounters?,
|
||||
peerId: EnginePeer.Id?,
|
||||
storyItem: EngineStoryItem,
|
||||
entityFiles: [EngineMedia.Id: TelegramMediaFile]
|
||||
entityFiles: [EngineMedia.Id: TelegramMediaFile],
|
||||
itemPeer: EnginePeer?
|
||||
) {
|
||||
self.position = position
|
||||
self.dayCounters = dayCounters
|
||||
self.peerId = peerId
|
||||
self.storyItem = storyItem
|
||||
self.entityFiles = entityFiles
|
||||
self.itemPeer = itemPeer
|
||||
}
|
||||
|
||||
public static func ==(lhs: StoryContentItem, rhs: StoryContentItem) -> Bool {
|
||||
|
|
@ -135,6 +138,9 @@ public final class StoryContentItem: Equatable {
|
|||
if lhs.entityFiles != rhs.entityFiles {
|
||||
return false
|
||||
}
|
||||
if lhs.itemPeer != rhs.itemPeer {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -209,6 +215,10 @@ public final class StoryContentContextState {
|
|||
public let allItems: [StoryContentItem]
|
||||
public let forwardInfoStories: [StoryId: Promise<EngineStoryItem?>]
|
||||
|
||||
var effectivePeer: EnginePeer {
|
||||
return self.item.itemPeer ?? self.peer
|
||||
}
|
||||
|
||||
public init(
|
||||
peer: EnginePeer,
|
||||
additionalPeerData: AdditionalPeerData,
|
||||
|
|
|
|||
|
|
@ -1231,9 +1231,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
self.component?.controller()?.dismiss()
|
||||
} else if translation.y < -200.0 || (translation.y < -100.0 && velocity.y < -100.0) {
|
||||
var displayViewLists = false
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
displayViewLists = true
|
||||
} else if case let .channel(channel) = component.slice.peer, channel.flags.contains(.isCreator) || component.slice.additionalPeerData.canViewStats {
|
||||
} else if case let .channel(channel) = component.slice.effectivePeer, channel.flags.contains(.isCreator) || component.slice.additionalPeerData.canViewStats {
|
||||
displayViewLists = true
|
||||
}
|
||||
|
||||
|
|
@ -1563,7 +1563,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
component: AnyComponent(StoryItemContentComponent(
|
||||
context: component.context,
|
||||
strings: component.strings,
|
||||
peer: component.slice.peer,
|
||||
peer: component.slice.effectivePeer,
|
||||
item: item.storyItem,
|
||||
availableReactions: component.availableReactions,
|
||||
entityFiles: item.entityFiles,
|
||||
|
|
@ -1661,7 +1661,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
var isChannel = false
|
||||
var canShare = true
|
||||
var displayFooter = false
|
||||
if case let .channel(channel) = component.slice.peer {
|
||||
if case let .channel(channel) = component.slice.effectivePeer {
|
||||
isChannel = true
|
||||
if channel.addressName == nil {
|
||||
canShare = false
|
||||
|
|
@ -1678,7 +1678,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
displayFooter = true
|
||||
}
|
||||
}
|
||||
} else if component.slice.peer.id == component.context.account.peerId {
|
||||
} else if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
displayFooter = true
|
||||
} else if component.slice.item.storyItem.isPending {
|
||||
displayFooter = true
|
||||
|
|
@ -1723,7 +1723,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
context: component.context,
|
||||
theme: component.theme,
|
||||
strings: component.strings,
|
||||
peer: component.slice.peer,
|
||||
peer: component.slice.effectivePeer,
|
||||
storyItem: item.storyItem,
|
||||
myReaction: item.storyItem.myReaction.flatMap { value -> StoryFooterPanelComponent.MyReaction? in
|
||||
var centerAnimation: TelegramMediaFile?
|
||||
|
|
@ -1931,9 +1931,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
var displayViewLists = false
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
displayViewLists = true
|
||||
} else if case let .channel(channel) = component.slice.peer, channel.flags.contains(.isCreator) || component.slice.additionalPeerData.canViewStats {
|
||||
} else if case let .channel(channel) = component.slice.effectivePeer, channel.flags.contains(.isCreator) || component.slice.additionalPeerData.canViewStats {
|
||||
displayViewLists = true
|
||||
}
|
||||
|
||||
|
|
@ -1946,12 +1946,12 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return true
|
||||
} else {
|
||||
var canReply = false
|
||||
if case .user = component.slice.peer {
|
||||
if case .user = component.slice.effectivePeer {
|
||||
canReply = true
|
||||
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
canReply = false
|
||||
} else if component.slice.peer.isService {
|
||||
} else if component.slice.effectivePeer.isService {
|
||||
canReply = false
|
||||
} else if case .unsupported = component.slice.item.storyItem.media {
|
||||
canReply = false
|
||||
|
|
@ -1974,12 +1974,12 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
var canReply = false
|
||||
if case .user = component.slice.peer {
|
||||
if case .user = component.slice.effectivePeer {
|
||||
canReply = true
|
||||
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
canReply = false
|
||||
} else if component.slice.peer.isService {
|
||||
} else if component.slice.effectivePeer.isService {
|
||||
canReply = false
|
||||
} else if case .unsupported = component.slice.item.storyItem.media {
|
||||
canReply = false
|
||||
|
|
@ -2515,7 +2515,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
if likeButtonView.alpha == 0.0 {
|
||||
return
|
||||
}
|
||||
if component.slice.peer.isService {
|
||||
if component.slice.effectivePeer.isService {
|
||||
return
|
||||
} else if case .unsupported = component.slice.item.storyItem.media {
|
||||
return
|
||||
|
|
@ -2558,7 +2558,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
let previousInput = inputPanelView.getSendMessageInput()
|
||||
switch previousInput {
|
||||
case let .text(value):
|
||||
component.storyItemSharedState.replyDrafts[StoryId(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)] = value
|
||||
component.storyItemSharedState.replyDrafts[StoryId(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id)] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2608,10 +2608,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
resetInputContents = .text(NSAttributedString())
|
||||
|
||||
self.saveDraft()
|
||||
if let draft = component.storyItemSharedState.replyDrafts[StoryId(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)] {
|
||||
if let draft = component.storyItemSharedState.replyDrafts[StoryId(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id)] {
|
||||
resetInputContents = .text(draft)
|
||||
}
|
||||
component.storyItemSharedState.replyDrafts.removeValue(forKey: StoryId(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id))
|
||||
component.storyItemSharedState.replyDrafts.removeValue(forKey: StoryId(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id))
|
||||
|
||||
if let tooltipScreen = self.sendMessageContext.tooltipScreen {
|
||||
if let tooltipScreen = tooltipScreen as? UndoOverlayController, let tag = tooltipScreen.tag as? String, tag == "no_auto_dismiss" {
|
||||
|
|
@ -2761,7 +2761,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
var isGroup = false
|
||||
var showMessageInputPanel = true
|
||||
var isGroupCommentRestricted = false
|
||||
if case let .channel(channel) = component.slice.peer {
|
||||
if case let .channel(channel) = component.slice.effectivePeer {
|
||||
switch channel.info {
|
||||
case .broadcast:
|
||||
isChannel = true
|
||||
|
|
@ -2777,7 +2777,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
isGroup = true
|
||||
}
|
||||
} else {
|
||||
showMessageInputPanel = component.slice.peer.id != component.context.account.peerId
|
||||
showMessageInputPanel = component.slice.effectivePeer.id != component.context.account.peerId
|
||||
}
|
||||
|
||||
var isUnsupported = false
|
||||
|
|
@ -2788,10 +2788,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
self?.presentBoostToUnrestrict()
|
||||
})
|
||||
} else if component.slice.additionalPeerData.isPremiumRequiredForMessaging {
|
||||
disabledPlaceholder = .premiumRequired(title: component.strings.Story_MessagingRestrictedPlaceholder(component.slice.peer.compactDisplayTitle).string, subtitle: component.strings.Story_MessagingRestrictedPlaceholderAction, action: { [weak self] in
|
||||
disabledPlaceholder = .premiumRequired(title: component.strings.Story_MessagingRestrictedPlaceholder(component.slice.effectivePeer.compactDisplayTitle).string, subtitle: component.strings.Story_MessagingRestrictedPlaceholderAction, action: { [weak self] in
|
||||
self?.presentPremiumRequiredForMessaging()
|
||||
})
|
||||
} else if component.slice.peer.isService {
|
||||
} else if component.slice.effectivePeer.isService {
|
||||
disabledPlaceholder = .text(component.strings.Story_FooterReplyUnavailable)
|
||||
} else if case .unsupported = component.slice.item.storyItem.media {
|
||||
isUnsupported = true
|
||||
|
|
@ -2860,10 +2860,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
|
||||
if showMessageInputPanel {
|
||||
var haveLikeOptions = false
|
||||
if case .user = component.slice.peer {
|
||||
if case .user = component.slice.effectivePeer {
|
||||
haveLikeOptions = true
|
||||
|
||||
if component.slice.peer.isService {
|
||||
if component.slice.effectivePeer.isService {
|
||||
haveLikeOptions = false
|
||||
}
|
||||
}
|
||||
|
|
@ -2945,7 +2945,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
self.sendMessageContext.videoRecorderValue?.dismissVideo()
|
||||
self.sendMessageContext.discardMediaRecordingPreview(view: self)
|
||||
},
|
||||
attachmentAction: component.slice.peer.isService ? nil : { [weak self] in
|
||||
attachmentAction: component.slice.effectivePeer.isService ? nil : { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -2975,7 +2975,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
|
||||
return MessageInputPanelComponent.MyReaction(reaction: value, file: centerAnimation, animationFileId: animationFileId)
|
||||
},
|
||||
likeAction: component.slice.peer.isService ? nil : { [weak self] in
|
||||
likeAction: component.slice.effectivePeer.isService ? nil : { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -3018,7 +3018,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
let rect = view.convert(view.bounds, to: nil)
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text = presentationData.strings.Conversation_VoiceMessagesRestricted(component.slice.peer.compactDisplayTitle).string
|
||||
let text = presentationData.strings.Conversation_VoiceMessagesRestricted(component.slice.effectivePeer.compactDisplayTitle).string
|
||||
let controller = TooltipController(content: .text(text), baseFontSize: presentationData.listsFontSize.baseDisplaySize, isBlurred: true, padding: 2.0)
|
||||
controller.dismissed = { [weak self] _ in
|
||||
if let self {
|
||||
|
|
@ -3176,9 +3176,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
var validViewListIds: [Int32] = []
|
||||
|
||||
var displayViewLists = false
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
displayViewLists = true
|
||||
} else if case let .channel(channel) = component.slice.peer, channel.flags.contains(.isCreator) || component.slice.additionalPeerData.canViewStats {
|
||||
} else if case let .channel(channel) = component.slice.effectivePeer, channel.flags.contains(.isCreator) || component.slice.additionalPeerData.canViewStats {
|
||||
displayViewLists = true
|
||||
}
|
||||
|
||||
|
|
@ -3210,15 +3210,15 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
for (id, views) in preloadViewListIds {
|
||||
if component.sharedViewListsContext.viewLists[StoryId(peerId: component.slice.peer.id, id: id)] == nil {
|
||||
if component.sharedViewListsContext.viewLists[StoryId(peerId: component.slice.effectivePeer.id, id: id)] == nil {
|
||||
let defaultSortMode: EngineStoryViewListContext.SortMode
|
||||
if component.slice.peer.id.isGroupOrChannel {
|
||||
if component.slice.effectivePeer.id.isGroupOrChannel {
|
||||
defaultSortMode = .repostsFirst
|
||||
} else {
|
||||
defaultSortMode = .reactionsFirst
|
||||
}
|
||||
let viewList = component.context.engine.messages.storyViewList(peerId: component.slice.peer.id, id: id, views: views, listMode: .everyone, sortMode: defaultSortMode)
|
||||
component.sharedViewListsContext.viewLists[StoryId(peerId: component.slice.peer.id, id: id)] = viewList
|
||||
let viewList = component.context.engine.messages.storyViewList(peerId: component.slice.effectivePeer.id, id: id, views: views, listMode: .everyone, sortMode: defaultSortMode)
|
||||
component.sharedViewListsContext.viewLists[StoryId(peerId: component.slice.effectivePeer.id, id: id)] = viewList
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3304,7 +3304,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
safeInsets.bottom = max(safeInsets.bottom, component.inputHeight)
|
||||
|
||||
var hasPremium = false
|
||||
if case let .user(user) = component.slice.peer {
|
||||
if case let .user(user) = component.slice.effectivePeer {
|
||||
hasPremium = user.isPremium
|
||||
}
|
||||
|
||||
|
|
@ -3320,7 +3320,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
theme: component.theme,
|
||||
strings: component.strings,
|
||||
sharedListsContext: component.sharedViewListsContext,
|
||||
peerId: component.slice.peer.id,
|
||||
peerId: component.slice.effectivePeer.id,
|
||||
safeInsets: safeInsets,
|
||||
storyItem: item.storyItem,
|
||||
hasPremium: hasPremium,
|
||||
|
|
@ -3438,7 +3438,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
action: { _ in return false }
|
||||
), nil)
|
||||
})))
|
||||
} else {
|
||||
} else if isContact {
|
||||
itemList.append(.action(ContextMenuActionItem(text: component.strings.Story_ContextHideStoriesFrom(peer.compactDisplayTitle).string, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Stories"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, f in
|
||||
|
|
@ -3903,14 +3903,14 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
let storyPrivacyIcon: StoryPrivacyIconComponent.Privacy?
|
||||
if case .user = component.slice.peer {
|
||||
if case .user = component.slice.effectivePeer {
|
||||
if component.slice.item.storyItem.isCloseFriends {
|
||||
storyPrivacyIcon = .closeFriends
|
||||
} else if component.slice.item.storyItem.isContacts {
|
||||
storyPrivacyIcon = .contacts
|
||||
} else if component.slice.item.storyItem.isSelectedContacts {
|
||||
storyPrivacyIcon = .selectedContacts
|
||||
} else if component.slice.peer.id == component.context.account.peerId {
|
||||
} else if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
storyPrivacyIcon = .everyone
|
||||
} else {
|
||||
storyPrivacyIcon = nil
|
||||
|
|
@ -3935,7 +3935,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
content: AnyComponent(
|
||||
StoryPrivacyIconComponent(
|
||||
privacy: storyPrivacyIcon,
|
||||
isEditable: component.slice.peer.id == component.context.account.peerId
|
||||
isEditable: component.slice.effectivePeer.id == component.context.account.peerId
|
||||
)
|
||||
),
|
||||
effectAlignment: .center,
|
||||
|
|
@ -3943,7 +3943,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
self.openItemPrivacySettings()
|
||||
return
|
||||
}
|
||||
|
|
@ -3953,11 +3953,11 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
let tooltipText: String
|
||||
switch storyPrivacyIcon {
|
||||
case .closeFriends:
|
||||
tooltipText = component.strings.Story_TooltipPrivacyCloseFriends2(component.slice.peer.compactDisplayTitle).string
|
||||
tooltipText = component.strings.Story_TooltipPrivacyCloseFriends2(component.slice.effectivePeer.compactDisplayTitle).string
|
||||
case .contacts:
|
||||
tooltipText = component.strings.Story_TooltipPrivacyContacts(component.slice.peer.compactDisplayTitle).string
|
||||
tooltipText = component.strings.Story_TooltipPrivacyContacts(component.slice.effectivePeer.compactDisplayTitle).string
|
||||
case .selectedContacts:
|
||||
tooltipText = component.strings.Story_TooltipPrivacySelectedContacts(component.slice.peer.compactDisplayTitle).string
|
||||
tooltipText = component.strings.Story_TooltipPrivacySelectedContacts(component.slice.effectivePeer.compactDisplayTitle).string
|
||||
case .everyone:
|
||||
tooltipText = ""
|
||||
}
|
||||
|
|
@ -4011,7 +4011,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
|
||||
var currentLeftInfoItem: InfoItem?
|
||||
if focusedItem != nil {
|
||||
let leftInfoComponent = AnyComponent(StoryAvatarInfoComponent(context: component.context, peer: component.slice.peer))
|
||||
let leftInfoComponent = AnyComponent(StoryAvatarInfoComponent(context: component.context, peer: component.slice.effectivePeer))
|
||||
if let leftInfoItem = self.leftInfoItem, leftInfoItem.component == leftInfoComponent {
|
||||
currentLeftInfoItem = leftInfoItem
|
||||
} else {
|
||||
|
|
@ -4042,7 +4042,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
let centerInfoComponent = AnyComponent(StoryAuthorInfoComponent(
|
||||
context: component.context,
|
||||
strings: component.strings,
|
||||
peer: component.slice.peer,
|
||||
peer: component.slice.effectivePeer,
|
||||
forwardInfo: component.slice.item.storyItem.forwardInfo,
|
||||
author: component.slice.item.storyItem.author,
|
||||
timestamp: component.slice.item.storyItem.timestamp,
|
||||
|
|
@ -4085,10 +4085,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
self.navigateToPeer(peer: author, chat: false)
|
||||
}
|
||||
} else {
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
self.navigateToMyStories()
|
||||
} else {
|
||||
self.navigateToPeer(peer: component.slice.peer, chat: false)
|
||||
self.navigateToPeer(peer: component.slice.effectivePeer, chat: false)
|
||||
}
|
||||
}
|
||||
})),
|
||||
|
|
@ -4120,10 +4120,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
self.navigateToMyStories()
|
||||
} else {
|
||||
self.navigateToPeer(peer: component.slice.peer, chat: false)
|
||||
self.navigateToPeer(peer: component.slice.effectivePeer, chat: false)
|
||||
}
|
||||
})),
|
||||
environment: {},
|
||||
|
|
@ -4157,7 +4157,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
if let inputPanelSize {
|
||||
let inputPanelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - inputPanelSize.width) / 2.0), y: availableSize.height - inputPanelBottomInset - inputPanelSize.height), size: inputPanelSize)
|
||||
inputPanelFrameValue = inputPanelFrame
|
||||
var inputPanelAlpha: CGFloat = (component.slice.peer.id == component.context.account.peerId || component.hideUI || self.isEditingStory || component.slice.item.storyItem.isPending) ? 0.0 : 1.0
|
||||
var inputPanelAlpha: CGFloat = (component.slice.effectivePeer.id == component.context.account.peerId || component.hideUI || self.isEditingStory || component.slice.item.storyItem.isPending) ? 0.0 : 1.0
|
||||
if case .regular = component.metrics.widthClass {
|
||||
inputPanelAlpha *= component.visibilityFraction
|
||||
}
|
||||
|
|
@ -4169,7 +4169,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
var inputPanelOffset: CGFloat = 0.0
|
||||
if component.slice.peer.id != component.context.account.peerId && !self.inputPanelExternalState.isEditing {
|
||||
if component.slice.effectivePeer.id != component.context.account.peerId && !self.inputPanelExternalState.isEditing {
|
||||
let bandingOffset = scrollingRubberBandingOffset(offset: verticalPanFraction * availableSize.height, bandingStart: 0.0, range: 10.0)
|
||||
inputPanelOffset = -max(0.0, min(10.0, bandingOffset))
|
||||
}
|
||||
|
|
@ -4203,8 +4203,8 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
var enableEntities = true
|
||||
if case .user = component.slice.peer {
|
||||
if !component.slice.peer.isService && !component.slice.peer.isPremium {
|
||||
if case .user = component.slice.effectivePeer {
|
||||
if !component.slice.effectivePeer.isService && !component.slice.effectivePeer.isPremium {
|
||||
enableEntities = false
|
||||
}
|
||||
}
|
||||
|
|
@ -4220,7 +4220,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
strings: component.strings,
|
||||
theme: component.theme,
|
||||
text: component.slice.item.storyItem.text,
|
||||
author: component.slice.peer,
|
||||
author: component.slice.effectivePeer,
|
||||
forwardInfo: component.slice.item.storyItem.forwardInfo,
|
||||
forwardInfoStory: forwardInfoStory,
|
||||
entities: enableEntities ? component.slice.item.storyItem.entities : [],
|
||||
|
|
@ -4231,7 +4231,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
switch action {
|
||||
case let .url(url, concealed):
|
||||
let _ = openUserGeneratedUrl(context: component.context, peerId: component.slice.peer.id, url: url, concealed: concealed, skipUrlAuth: false, skipConcealedAlert: false, forceDark: true, present: { [weak self] c in
|
||||
let _ = openUserGeneratedUrl(context: component.context, peerId: component.slice.effectivePeer.id, url: url, concealed: concealed, skipUrlAuth: false, skipConcealedAlert: false, forceDark: true, present: { [weak self] c in
|
||||
guard let self, let component = self.component, let controller = component.controller() else {
|
||||
return
|
||||
}
|
||||
|
|
@ -4265,7 +4265,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
self.sendMessageContext.presentTextEntityActions(view: self, action: action, openUrl: { [weak self] url, concealed in
|
||||
let _ = openUserGeneratedUrl(context: component.context, peerId: component.slice.peer.id, url: url, concealed: concealed, skipUrlAuth: false, skipConcealedAlert: false, present: { [weak self] c in
|
||||
let _ = openUserGeneratedUrl(context: component.context, peerId: component.slice.effectivePeer.id, url: url, concealed: concealed, skipUrlAuth: false, skipConcealedAlert: false, present: { [weak self] c in
|
||||
guard let self, let component = self.component, let controller = component.controller() else {
|
||||
return
|
||||
}
|
||||
|
|
@ -4325,7 +4325,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
if let story {
|
||||
let context = component.context
|
||||
let peerId = component.slice.peer.id
|
||||
let peerId = component.slice.effectivePeer.id
|
||||
let currentResult: ResolvedUrl = .story(peerId: peerId, id: component.slice.item.storyItem.id)
|
||||
|
||||
self.sendMessageContext.openResolved(view: self, result: .story(peerId: peer.id, id: story.id), completion: { [weak self] in
|
||||
|
|
@ -4535,7 +4535,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
|
||||
if self.displayLikeReactions {
|
||||
if component.slice.item.storyItem.myReaction == updateReaction.reaction {
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: nil).startStandalone()
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id, reaction: nil).startStandalone()
|
||||
self.displayLikeReactions = false
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
|
||||
} else {
|
||||
|
|
@ -4546,7 +4546,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
|
||||
|
||||
self.waitingForReactionAnimateOutToLike = updateReaction.reaction
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: updateReaction.reaction).startStandalone()
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id, reaction: updateReaction.reaction).startStandalone()
|
||||
}
|
||||
} else {
|
||||
let _ = (component.context.engine.stickers.availableReactions()
|
||||
|
|
@ -4630,7 +4630,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
mediaReference: nil,
|
||||
threadId: nil,
|
||||
replyToMessageId: nil,
|
||||
replyToStoryId: StoryId(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id),
|
||||
replyToStoryId: StoryId(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id),
|
||||
localGroupingKey: nil,
|
||||
correlationId: nil,
|
||||
bubbleUpEmojiOrStickersets: []
|
||||
|
|
@ -4639,7 +4639,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
let context = component.context
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
|
||||
let presentController = component.presentController
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
|
||||
let _ = (enqueueMessages(account: context.account, peerId: peer.id, messages: [message])
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] messageIds in
|
||||
|
|
@ -4938,7 +4938,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
component.externalState.derivedMediaSize = contentFrame.size
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
component.externalState.derivedBottomInset = availableSize.height - itemsContainerFrame.maxY
|
||||
} else if let inputPanelFrameValue {
|
||||
component.externalState.derivedBottomInset = availableSize.height - min(inputPanelFrameValue.minY, contentFrame.maxY)
|
||||
|
|
@ -5291,7 +5291,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
let context = component.context
|
||||
let storyContent = RepostStoriesContentContextImpl(context: context, originalPeerId: component.slice.peer.id, originalStory: component.slice.item.storyItem, focusedStoryId: StoryId(peerId: peer.id, id: id), viewListContext: viewListContext, readGlobally: false)
|
||||
let storyContent = RepostStoriesContentContextImpl(context: context, originalPeerId: component.slice.effectivePeer.id, originalStory: component.slice.item.storyItem, focusedStoryId: StoryId(peerId: peer.id, id: id), viewListContext: viewListContext, readGlobally: false)
|
||||
let _ = (storyContent.state
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak controller, weak viewListView, weak sourceView] _ in
|
||||
|
|
@ -5374,7 +5374,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
|
||||
guard let controller = MediaEditorScreen.makeEditStoryController(
|
||||
context: component.context,
|
||||
peer: component.slice.peer,
|
||||
peer: component.slice.effectivePeer,
|
||||
storyItem: component.slice.item.storyItem,
|
||||
videoPlaybackPosition: videoPlaybackPosition,
|
||||
repost: repost,
|
||||
|
|
@ -5497,7 +5497,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
HapticFeedback().impact()
|
||||
|
||||
let _ = combineLatest(queue: Queue.mainQueue(),
|
||||
component.context.engine.peers.getChannelBoostStatus(peerId: component.slice.peer.id),
|
||||
component.context.engine.peers.getChannelBoostStatus(peerId: component.slice.effectivePeer.id),
|
||||
component.context.engine.peers.getMyBoostStatus()
|
||||
).startStandalone(next: { [weak self] boostStatus, myBoostStatus in
|
||||
guard let self, let component = self.component, let boostStatus, let myBoostStatus else {
|
||||
|
|
@ -5505,7 +5505,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
let boostController = PremiumBoostLevelsScreen(
|
||||
context: component.context,
|
||||
peerId: component.slice.peer.id,
|
||||
peerId: component.slice.effectivePeer.id,
|
||||
mode: .user(mode: .unrestrict(Int(boostsToUnrestrict))),
|
||||
status: boostStatus,
|
||||
myBoostStatus: myBoostStatus,
|
||||
|
|
@ -5586,7 +5586,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
private func requestSave() {
|
||||
guard let component = self.component, let peerReference = PeerReference(component.slice.peer._asPeer()) else {
|
||||
guard let component = self.component, let peerReference = PeerReference(component.slice.effectivePeer._asPeer()) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -5625,9 +5625,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
guard let component = self.component else {
|
||||
return
|
||||
}
|
||||
if component.slice.peer.id == component.context.account.peerId {
|
||||
if component.slice.effectivePeer.id == component.context.account.peerId {
|
||||
self.performMyMoreAction(sourceView: sourceView, gesture: gesture)
|
||||
} else if case let .channel(channel) = component.slice.peer {
|
||||
} else if case let .channel(channel) = component.slice.effectivePeer {
|
||||
var canPerformStoryActions = false
|
||||
|
||||
if channel.hasPermission(.editStories) {
|
||||
|
|
@ -5681,7 +5681,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: component.slice.item.storyItem.myReaction == nil ? .builtin("❤") : nil).startStandalone()
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id, reaction: component.slice.item.storyItem.myReaction == nil ? .builtin("❤") : nil).startStandalone()
|
||||
|
||||
if component.slice.item.storyItem.myReaction != nil {
|
||||
return
|
||||
|
|
@ -5808,7 +5808,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
}
|
||||
|
||||
if !emojiFileIds.isEmpty || hasLinkedStickers, let peerReference = PeerReference(component.slice.peer._asPeer()) {
|
||||
if !emojiFileIds.isEmpty || hasLinkedStickers, let peerReference = PeerReference(component.slice.effectivePeer._asPeer()) {
|
||||
let context = component.context
|
||||
|
||||
tip = .animatedEmoji(text: nil, arguments: nil, file: nil, action: nil)
|
||||
|
|
@ -6081,7 +6081,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.peer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).startStandalone()
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.effectivePeer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).startStandalone()
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
|
||||
if component.slice.item.storyItem.isPinned {
|
||||
|
|
@ -6117,7 +6117,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
self.requestSave()
|
||||
})))
|
||||
|
||||
if case let .user(accountUser) = component.slice.peer {
|
||||
if case let .user(accountUser) = component.slice.effectivePeer {
|
||||
items.append(.action(ContextMenuActionItem(text: component.strings.Story_ContextStealthMode, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: accountUser.isPremium ? "Chat/Context Menu/Eye" : "Chat/Context Menu/EyeLocked"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, a in
|
||||
|
|
@ -6134,7 +6134,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
})))
|
||||
}
|
||||
|
||||
if component.slice.item.storyItem.isPublic && (component.slice.peer.addressName != nil || !component.slice.peer._asPeer().usernames.isEmpty) && (component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) || component.slice.item.storyItem.isPinned) {
|
||||
if component.slice.item.storyItem.isPublic && (component.slice.effectivePeer.addressName != nil || !component.slice.effectivePeer._asPeer().usernames.isEmpty) && (component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) || component.slice.item.storyItem.isPinned) {
|
||||
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_CopyLink, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, a in
|
||||
|
|
@ -6144,7 +6144,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] link in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
|
|
@ -6197,7 +6197,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
guard let component = self.component, let controller = component.controller() else {
|
||||
return
|
||||
}
|
||||
guard case let .channel(channel) = component.slice.peer else {
|
||||
guard case let .channel(channel) = component.slice.effectivePeer else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -6270,10 +6270,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.peer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).startStandalone()
|
||||
let _ = component.context.engine.messages.updateStoriesArePinned(peerId: component.slice.effectivePeer.id, ids: [component.slice.item.storyItem.id: component.slice.item.storyItem], isPinned: !component.slice.item.storyItem.isPinned).startStandalone()
|
||||
|
||||
var isGroup = false
|
||||
if case let .channel(channel) = component.slice.peer, case .group = channel.info {
|
||||
if case let .channel(channel) = component.slice.effectivePeer, case .group = channel.info {
|
||||
isGroup = true
|
||||
}
|
||||
|
||||
|
|
@ -6313,7 +6313,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
let statsController = component.context.sharedContext.makeStoryStatsController(
|
||||
context: component.context,
|
||||
updatedPresentationData: (presentationData, .single(presentationData)),
|
||||
peerId: component.slice.peer.id,
|
||||
peerId: component.slice.effectivePeer.id,
|
||||
storyId: component.slice.item.storyItem.id,
|
||||
storyItem: component.slice.item.storyItem,
|
||||
fromStory: true
|
||||
|
|
@ -6334,7 +6334,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
self.requestSave()
|
||||
})))
|
||||
|
||||
if component.slice.item.storyItem.isPublic && (component.slice.peer.addressName != nil || !component.slice.peer._asPeer().usernames.isEmpty) && (component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) || component.slice.item.storyItem.isPinned) {
|
||||
if component.slice.item.storyItem.isPublic && (component.slice.effectivePeer.addressName != nil || !component.slice.effectivePeer._asPeer().usernames.isEmpty) && (component.slice.item.storyItem.expirationTimestamp > Int32(Date().timeIntervalSince1970) || component.slice.item.storyItem.isPinned) {
|
||||
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_CopyLink, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, a in
|
||||
|
|
@ -6344,7 +6344,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] link in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
|
|
@ -6376,7 +6376,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
var isHidden = false
|
||||
if case let .channel(channel) = component.slice.peer, let storiesHidden = channel.storiesHidden {
|
||||
if case let .channel(channel) = component.slice.effectivePeer, let storiesHidden = channel.storiesHidden {
|
||||
isHidden = storiesHidden
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: isHidden ? component.strings.StoryFeed_ContextUnarchive : component.strings.StoryFeed_ContextArchive, icon: { theme in
|
||||
|
|
@ -6388,20 +6388,20 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: !isHidden)
|
||||
let _ = component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.effectivePeer.id, isHidden: !isHidden)
|
||||
|
||||
let text = !isHidden ? component.strings.StoryFeed_TooltipArchive(component.slice.peer.compactDisplayTitle).string : component.strings.StoryFeed_TooltipUnarchive(component.slice.peer.compactDisplayTitle).string
|
||||
let text = !isHidden ? component.strings.StoryFeed_TooltipArchive(component.slice.effectivePeer.compactDisplayTitle).string : component.strings.StoryFeed_TooltipUnarchive(component.slice.effectivePeer.compactDisplayTitle).string
|
||||
let tooltipScreen = TooltipScreen(
|
||||
context: component.context,
|
||||
account: component.context.account,
|
||||
sharedContext: component.context.sharedContext,
|
||||
text: .markdown(text: text),
|
||||
style: .customBlur(UIColor(rgb: 0x1c1c1c), 0.0),
|
||||
icon: .peer(peer: component.slice.peer, isStory: true),
|
||||
icon: .peer(peer: component.slice.effectivePeer, isStory: true),
|
||||
action: TooltipScreen.Action(
|
||||
title: component.strings.Undo_Undo,
|
||||
action: {
|
||||
component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: isHidden)
|
||||
component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.effectivePeer.id, isHidden: isHidden)
|
||||
}
|
||||
),
|
||||
location: .bottom,
|
||||
|
|
@ -6503,10 +6503,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
let _ = (combineLatest(
|
||||
queue: Queue.mainQueue(),
|
||||
component.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: component.slice.peer.id),
|
||||
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: component.slice.effectivePeer.id),
|
||||
TelegramEngine.EngineData.Item.NotificationSettings.Global(),
|
||||
TelegramEngine.EngineData.Item.Contacts.Top(),
|
||||
TelegramEngine.EngineData.Item.Peer.IsContact(id: component.slice.peer.id),
|
||||
TelegramEngine.EngineData.Item.Peer.IsContact(id: component.slice.effectivePeer.id),
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: component.context.account.peerId)
|
||||
),
|
||||
translationSettings,
|
||||
|
|
@ -6558,9 +6558,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
items.append(.separator)
|
||||
}
|
||||
|
||||
let isMuted = resolvedAreStoriesMuted(globalSettings: globalSettings._asGlobalNotificationSettings(), peer: component.slice.peer._asPeer(), peerSettings: settings._asNotificationSettings(), topSearchPeers: topSearchPeers)
|
||||
let isMuted = resolvedAreStoriesMuted(globalSettings: globalSettings._asGlobalNotificationSettings(), peer: component.slice.effectivePeer._asPeer(), peerSettings: settings._asNotificationSettings(), topSearchPeers: topSearchPeers)
|
||||
|
||||
if !component.slice.peer.isService && isContact {
|
||||
if !component.slice.effectivePeer.isService && isContact {
|
||||
items.append(.action(ContextMenuActionItem(text: isMuted ? component.strings.StoryFeed_ContextNotifyOn : component.strings.StoryFeed_ContextNotifyOff, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: component.slice.additionalPeerData.isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, a in
|
||||
|
|
@ -6570,7 +6570,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.peers.togglePeerStoriesMuted(peerId: component.slice.peer.id).startStandalone()
|
||||
let _ = component.context.engine.peers.togglePeerStoriesMuted(peerId: component.slice.effectivePeer.id).startStandalone()
|
||||
|
||||
let iconColor = UIColor.white
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
|
||||
|
|
@ -6583,7 +6583,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
"Bottom.Group 1.Fill 1": iconColor,
|
||||
"EXAMPLE.Group 1.Fill 1": iconColor,
|
||||
"Line.Group 1.Stroke 1": iconColor
|
||||
], title: nil, text: component.strings.StoryFeed_TooltipNotifyOn(component.slice.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string, customUndoText: nil, timeout: nil),
|
||||
], title: nil, text: component.strings.StoryFeed_TooltipNotifyOn(component.slice.effectivePeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string, customUndoText: nil, timeout: nil),
|
||||
elevatedLayout: false,
|
||||
animateInAsReplacement: false,
|
||||
blurred: true,
|
||||
|
|
@ -6598,7 +6598,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
"Bottom.Group 1.Fill 1": iconColor,
|
||||
"EXAMPLE.Group 1.Fill 1": iconColor,
|
||||
"Line.Group 1.Stroke 1": iconColor
|
||||
], title: nil, text: component.strings.StoryFeed_TooltipNotifyOff(component.slice.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string, customUndoText: nil, timeout: nil),
|
||||
], title: nil, text: component.strings.StoryFeed_TooltipNotifyOff(component.slice.effectivePeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string, customUndoText: nil, timeout: nil),
|
||||
elevatedLayout: false,
|
||||
animateInAsReplacement: false,
|
||||
blurred: true,
|
||||
|
|
@ -6608,7 +6608,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
})))
|
||||
}
|
||||
|
||||
if !component.slice.peer.isService && component.slice.item.storyItem.isPublic && (component.slice.peer.addressName != nil || !component.slice.peer._asPeer().usernames.isEmpty) {
|
||||
if !component.slice.effectivePeer.isService && component.slice.item.storyItem.isPublic && (component.slice.effectivePeer.addressName != nil || !component.slice.effectivePeer._asPeer().usernames.isEmpty) {
|
||||
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_CopyLink, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, a in
|
||||
|
|
@ -6618,7 +6618,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] link in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
|
|
@ -6688,9 +6688,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
|
||||
var isHidden = false
|
||||
if case let .user(user) = component.slice.peer, let storiesHidden = user.storiesHidden {
|
||||
if case let .user(user) = component.slice.effectivePeer, let storiesHidden = user.storiesHidden {
|
||||
isHidden = storiesHidden
|
||||
} else if case let .channel(channel) = component.slice.peer, let storiesHidden = channel.storiesHidden {
|
||||
} else if case let .channel(channel) = component.slice.effectivePeer, let storiesHidden = channel.storiesHidden {
|
||||
isHidden = storiesHidden
|
||||
}
|
||||
|
||||
|
|
@ -6698,9 +6698,9 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
if isHidden {
|
||||
canArchive = true
|
||||
} else {
|
||||
if case .user = component.slice.peer, !component.slice.peer.isService {
|
||||
if case .user = component.slice.effectivePeer, !component.slice.effectivePeer.isService {
|
||||
canArchive = true
|
||||
} else if case .channel = component.slice.peer {
|
||||
} else if case .channel = component.slice.effectivePeer {
|
||||
canArchive = true
|
||||
}
|
||||
}
|
||||
|
|
@ -6715,20 +6715,20 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: !isHidden)
|
||||
let _ = component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.effectivePeer.id, isHidden: !isHidden)
|
||||
|
||||
let text = !isHidden ? component.strings.StoryFeed_TooltipArchive(component.slice.peer.compactDisplayTitle).string : component.strings.StoryFeed_TooltipUnarchive(component.slice.peer.compactDisplayTitle).string
|
||||
let text = !isHidden ? component.strings.StoryFeed_TooltipArchive(component.slice.effectivePeer.compactDisplayTitle).string : component.strings.StoryFeed_TooltipUnarchive(component.slice.effectivePeer.compactDisplayTitle).string
|
||||
let tooltipScreen = TooltipScreen(
|
||||
context: component.context,
|
||||
account: component.context.account,
|
||||
sharedContext: component.context.sharedContext,
|
||||
text: .markdown(text: text),
|
||||
style: .customBlur(UIColor(rgb: 0x1c1c1c), 0.0),
|
||||
icon: .peer(peer: component.slice.peer, isStory: true),
|
||||
icon: .peer(peer: component.slice.effectivePeer, isStory: true),
|
||||
action: TooltipScreen.Action(
|
||||
title: component.strings.Undo_Undo,
|
||||
action: {
|
||||
component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.peer.id, isHidden: isHidden)
|
||||
component.context.engine.peers.updatePeerStoriesHidden(id: component.slice.effectivePeer.id, isHidden: isHidden)
|
||||
}
|
||||
),
|
||||
location: .bottom,
|
||||
|
|
@ -6767,7 +6767,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
})))
|
||||
}
|
||||
|
||||
if case .user = component.slice.peer {
|
||||
if case .user = component.slice.effectivePeer {
|
||||
items.append(.action(ContextMenuActionItem(text: component.strings.Story_ContextStealthMode, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: accountUser.isPremium ? "Chat/Context Menu/Eye" : "Chat/Context Menu/EyeLocked"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] _, a in
|
||||
|
|
@ -6797,7 +6797,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
let statsController = component.context.sharedContext.makeStoryStatsController(
|
||||
context: component.context,
|
||||
updatedPresentationData: (presentationData, .single(presentationData)),
|
||||
peerId: component.slice.peer.id,
|
||||
peerId: component.slice.effectivePeer.id,
|
||||
storyId: component.slice.item.storyItem.id,
|
||||
storyItem: component.slice.item.storyItem,
|
||||
fromStory: true
|
||||
|
|
@ -6822,7 +6822,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
}
|
||||
}
|
||||
|
||||
if !component.slice.peer.isService {
|
||||
if !component.slice.effectivePeer.isService {
|
||||
items.append(.action(ContextMenuActionItem(text: component.strings.Story_Context_Report, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Report"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] c, a in
|
||||
|
|
@ -6836,7 +6836,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
parent: controller,
|
||||
contextController: c,
|
||||
backAction: { _ in },
|
||||
subject: .story(component.slice.peer.id, component.slice.item.storyItem.id),
|
||||
subject: .story(component.slice.effectivePeer.id, component.slice.item.storyItem.id),
|
||||
options: options,
|
||||
passthrough: true,
|
||||
forceTheme: defaultDarkPresentationTheme,
|
||||
|
|
@ -6851,7 +6851,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||
guard let self, let component = self.component, let controller = component.controller(), let reason else {
|
||||
return
|
||||
}
|
||||
let _ = component.context.engine.peers.reportPeerStory(peerId: component.slice.peer.id, storyId: component.slice.item.storyItem.id, reason: reason, message: "").startStandalone()
|
||||
let _ = component.context.engine.peers.reportPeerStory(peerId: component.slice.effectivePeer.id, storyId: component.slice.item.storyItem.id, reason: reason, message: "").startStandalone()
|
||||
controller.present(
|
||||
UndoOverlayController(
|
||||
presentationData: presentationData,
|
||||
|
|
|
|||
|
|
@ -571,7 +571,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
guard let inputPanelView = view.inputPanel.view as? MessageInputPanelComponent.View else {
|
||||
return
|
||||
}
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
|
||||
let controller = component.controller() as? StoryContainerScreen
|
||||
|
||||
|
|
@ -638,7 +638,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
return
|
||||
}
|
||||
let focusedStoryId = StoryId(peerId: peerId, id: focusedItem.storyItem.id)
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
|
||||
let controller = component.controller() as? StoryContainerScreen
|
||||
|
||||
|
|
@ -692,7 +692,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
return
|
||||
}
|
||||
let focusedStoryId = StoryId(peerId: peerId, id: focusedItem.storyItem.id)
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
|
||||
let controller = component.controller() as? StoryContainerScreen
|
||||
|
||||
|
|
@ -740,7 +740,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
guard let component = view.component else {
|
||||
return
|
||||
}
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
let _ = (legacyEnqueueGifMessage(account: component.context.account, data: data) |> deliverOnMainQueue).start(next: { [weak self, weak view] message in
|
||||
if let self, let view {
|
||||
self.sendMessages(view: view, peer: peer, messages: [message])
|
||||
|
|
@ -752,7 +752,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
guard let component = view.component else {
|
||||
return
|
||||
}
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
|
||||
let size = image.size.aspectFitted(CGSize(width: 512.0, height: 512.0))
|
||||
|
||||
|
|
@ -1013,7 +1013,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
component.presentController(actionSheet, nil)
|
||||
} else {
|
||||
var preferredAction: ShareControllerPreferredAction?
|
||||
if focusedItem.storyItem.isPublic && !component.slice.peer.isService {
|
||||
if focusedItem.storyItem.isPublic && !component.slice.effectivePeer.isService {
|
||||
preferredAction = .custom(action: ShareControllerAction(title: component.strings.Story_Context_CopyLink, action: {
|
||||
let _ = ((component.context.engine.messages.exportStoryLink(peerId: peerId, id: focusedItem.storyItem.id))
|
||||
|> deliverOnMainQueue).start(next: { link in
|
||||
|
|
@ -1170,7 +1170,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
guard let self, let view else {
|
||||
return
|
||||
}
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
|
||||
let _ = self
|
||||
|
||||
|
|
@ -1260,7 +1260,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
return
|
||||
}
|
||||
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id)
|
||||
let _ = (component.context.engine.messages.exportStoryLink(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id)
|
||||
|> deliverOnMainQueue).start(next: { [weak view] link in
|
||||
guard let view, let component = view.component else {
|
||||
return
|
||||
|
|
@ -2214,7 +2214,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
inputText = text
|
||||
}
|
||||
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
let theme = defaultDarkPresentationTheme
|
||||
let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>) = (component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: theme), component.context.sharedContext.presentationData |> map { $0.withUpdated(theme: theme) })
|
||||
let controller = mediaPasteboardScreen(
|
||||
|
|
@ -2283,7 +2283,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
return
|
||||
}
|
||||
let context = component.context
|
||||
let peer = component.slice.peer
|
||||
let peer = component.slice.effectivePeer
|
||||
let storyId = component.slice.item.storyItem.id
|
||||
|
||||
let theme = component.theme
|
||||
|
|
@ -2669,7 +2669,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||
let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
|
||||
let peerId = component.slice.peer.id
|
||||
let peerId = component.slice.effectivePeer.id
|
||||
component.context.sharedContext.openResolvedUrl(
|
||||
result,
|
||||
context: component.context,
|
||||
|
|
@ -2851,7 +2851,7 @@ final class StoryItemSetContainerSendMessage {
|
|||
return
|
||||
}
|
||||
|
||||
let peerId = component.slice.peer.id
|
||||
let peerId = component.slice.effectivePeer.id
|
||||
|
||||
var resolveSignal: Signal<Peer?, NoError>
|
||||
if let peerName = peerName {
|
||||
|
|
@ -2918,13 +2918,13 @@ final class StoryItemSetContainerSendMessage {
|
|||
return
|
||||
}
|
||||
if !hashtag.isEmpty {
|
||||
/*if !"".isEmpty {
|
||||
if peerName == nil {
|
||||
let searchController = component.context.sharedContext.makeStorySearchController(context: component.context, query: hashtag)
|
||||
navigationController.pushViewController(searchController)
|
||||
} else {*/
|
||||
} else {
|
||||
let searchController = component.context.sharedContext.makeHashtagSearchController(context: component.context, peer: peer.flatMap(EnginePeer.init), query: hashtag, all: true)
|
||||
navigationController.pushViewController(searchController)
|
||||
//}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
|
@ -3485,8 +3485,8 @@ final class StoryItemSetContainerSendMessage {
|
|||
guard let view, let component = view.component else {
|
||||
return
|
||||
}
|
||||
if component.slice.peer.id != component.context.account.peerId {
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id, reaction: reaction).start()
|
||||
if component.slice.effectivePeer.id != component.context.account.peerId {
|
||||
let _ = component.context.engine.messages.setStoryReaction(peerId: component.slice.effectivePeer.id, id: component.slice.item.storyItem.id, reaction: reaction).start()
|
||||
}
|
||||
|
||||
let targetFrame = reactionView.convert(reactionView.bounds, to: view)
|
||||
|
|
|
|||
|
|
@ -1779,7 +1779,7 @@ extension ChatControllerImpl {
|
|||
})
|
||||
}
|
||||
} else {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil) }) }, completion: { t in
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }) }, completion: { t in
|
||||
completion(t, {})
|
||||
})
|
||||
}
|
||||
|
|
@ -2497,7 +2497,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -2521,7 +2521,7 @@ extension ChatControllerImpl {
|
|||
}
|
||||
|
||||
self.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
})
|
||||
|
||||
if !self.presentationInterfaceState.isPremium {
|
||||
|
|
@ -2537,7 +2537,7 @@ extension ChatControllerImpl {
|
|||
return
|
||||
}
|
||||
self.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
})
|
||||
}, nil)
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ extension ChatControllerImpl {
|
|||
self.chatDisplayNode.collapseInput()
|
||||
|
||||
self.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedMediaDraftState(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedMediaDraftState(nil) }
|
||||
})
|
||||
}
|
||||
}, usedCorrelationId ? correlationId : nil)
|
||||
|
|
@ -336,7 +336,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, usedCorrelationId ? correlationId : nil)
|
||||
|
|
@ -506,7 +506,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedMediaDraftState(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedMediaDraftState(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
|
||||
strongSelf.updateDownButtonVisibility()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -67,7 +67,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -97,7 +97,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -115,7 +115,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
|
|||
|
|
@ -471,7 +471,7 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||
}
|
||||
var replySubject = replySubject
|
||||
replySubject.quote = nil
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil).withoutSelectionState() }).updatedSearch(nil) })
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withoutSelectionState() }).updatedSearch(nil) })
|
||||
})))
|
||||
}
|
||||
|
||||
|
|
@ -646,7 +646,7 @@ func moveReplyMessageToAnotherChat(selfController: ChatControllerImpl, replySubj
|
|||
guard let selfController else {
|
||||
return
|
||||
}
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil).withoutSelectionState() }) })
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withoutSelectionState() }) })
|
||||
|
||||
let navigationController: NavigationController?
|
||||
if let parentController = selfController.parentController {
|
||||
|
|
|
|||
|
|
@ -64,14 +64,22 @@ func chatMessageDisplaySendMessageOptions(selfController: ChatControllerImpl, no
|
|||
editMessages = .single([])
|
||||
}
|
||||
|
||||
var currentMessageEffect: ChatSendMessageActionSheetControllerSendParameters.Effect?
|
||||
if selfController.presentationInterfaceState.interfaceState.editMessage == nil {
|
||||
if let sendMessageEffect = selfController.presentationInterfaceState.interfaceState.sendMessageEffect {
|
||||
currentMessageEffect = ChatSendMessageActionSheetControllerSendParameters.Effect(id: sendMessageEffect)
|
||||
}
|
||||
}
|
||||
|
||||
let _ = (combineLatest(
|
||||
selfController.context.account.viewTracker.peerView(peerId) |> take(1),
|
||||
effectItems,
|
||||
availableMessageEffects,
|
||||
hasPremium,
|
||||
editMessages
|
||||
editMessages,
|
||||
ChatSendMessageContextScreen.initialData(context: selfController.context, currentMessageEffectId: currentMessageEffect?.id)
|
||||
)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak selfController] peerView, effectItems, availableMessageEffects, hasPremium, editMessages in
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak selfController] peerView, effectItems, availableMessageEffects, hasPremium, editMessages, initialData in
|
||||
guard let selfController, let peer = peerViewMainPeer(peerView) else {
|
||||
return
|
||||
}
|
||||
|
|
@ -112,6 +120,7 @@ func chatMessageDisplaySendMessageOptions(selfController: ChatControllerImpl, no
|
|||
}
|
||||
|
||||
let controller = makeChatSendMessageActionSheetController(
|
||||
initialData: initialData,
|
||||
context: selfController.context,
|
||||
updatedPresentationData: selfController.updatedPresentationData,
|
||||
peerId: selfController.presentationInterfaceState.chatLocation.peerId,
|
||||
|
|
@ -200,6 +209,7 @@ func chatMessageDisplaySendMessageOptions(selfController: ChatControllerImpl, no
|
|||
}
|
||||
|
||||
let controller = makeChatSendMessageActionSheetController(
|
||||
initialData: initialData,
|
||||
context: selfController.context,
|
||||
updatedPresentationData: selfController.updatedPresentationData,
|
||||
peerId: selfController.presentationInterfaceState.chatLocation.peerId,
|
||||
|
|
@ -207,6 +217,16 @@ func chatMessageDisplaySendMessageOptions(selfController: ChatControllerImpl, no
|
|||
isScheduledMessages: false,
|
||||
mediaPreview: mediaPreview,
|
||||
mediaCaptionIsAbove: nil,
|
||||
messageEffect: (currentMessageEffect, { [weak selfController] updatedEffect in
|
||||
guard let selfController else {
|
||||
return
|
||||
}
|
||||
selfController.updateChatPresentationInterfaceState(transition: .immediate, interactive: true, { presentationInterfaceState in
|
||||
return presentationInterfaceState.updatedInterfaceState { interfaceState in
|
||||
return interfaceState.withUpdatedSendMessageEffect(updatedEffect?.id)
|
||||
}
|
||||
})
|
||||
}),
|
||||
attachment: false,
|
||||
canSendWhenOnline: sendWhenOnlineAvailable,
|
||||
forwardMessageIds: selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
|
|
@ -238,7 +258,7 @@ func chatMessageDisplaySendMessageOptions(selfController: ChatControllerImpl, no
|
|||
return
|
||||
}
|
||||
selfController.updateChatPresentationInterfaceState(animated: true, interactive: false, saveInterfaceState: selfController.presentationInterfaceState.subject != .scheduledMessages, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
||||
})
|
||||
selfController.openScheduledMessages()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1792,7 +1792,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -1850,7 +1850,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
var current = current
|
||||
current = current.updatedInterfaceState { interfaceState in
|
||||
var interfaceState = interfaceState
|
||||
interfaceState = interfaceState.withUpdatedReplyMessageSubject(nil)
|
||||
interfaceState = interfaceState.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil)
|
||||
if clearInput {
|
||||
interfaceState = interfaceState.withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString()))
|
||||
}
|
||||
|
|
@ -1982,7 +1982,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }.updatedInputMode { current in
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }.updatedInputMode { current in
|
||||
if case let .media(mode, maybeExpanded, focused) = current, maybeExpanded != nil {
|
||||
return .media(mode: mode, expanded: nil, focused: focused)
|
||||
}
|
||||
|
|
@ -2426,7 +2426,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -3390,7 +3390,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}) { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, saveInterfaceState: strongSelf.presentationInterfaceState.subject != .scheduledMessages, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
||||
})
|
||||
|
||||
if strongSelf.presentationInterfaceState.subject != .scheduledMessages && time != scheduleWhenOnlineTimestamp {
|
||||
|
|
@ -3572,7 +3572,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
completion(nil)
|
||||
}
|
||||
} else {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil) }) }, completion: completion)
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }) }, completion: completion)
|
||||
}
|
||||
}
|
||||
}, displayImportedMessageTooltip: { [weak self] _ in
|
||||
|
|
@ -7236,7 +7236,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
chatLocation = .peer(id: peerId)
|
||||
}
|
||||
|
||||
return (chatHistoryViewForLocation(ChatHistoryLocationInput(content: location, id: 0), ignoreMessagesInTimestampRange: nil, context: context, chatLocation: chatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), scheduled: false, fixedCombinedReadStates: nil, tag: .tag(MessageTags.pinned), appendMessagesFromTheSameGroup: false, additionalData: [], orderStatistics: .combinedLocation)
|
||||
return (chatHistoryViewForLocation(ChatHistoryLocationInput(content: location, id: 0), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), context: context, chatLocation: chatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), scheduled: false, fixedCombinedReadStates: nil, tag: .tag(MessageTags.pinned), appendMessagesFromTheSameGroup: false, additionalData: [], orderStatistics: .combinedLocation)
|
||||
|> castError(Bool.self)
|
||||
|> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in
|
||||
switch update {
|
||||
|
|
@ -8103,7 +8103,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
interfaceState = interfaceState.withUpdatedInputLanguage(self.chatDisplayNode.currentTextInputLanguage)
|
||||
if case .peer = self.chatLocation, let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.flags.contains(.isForum) {
|
||||
interfaceState = interfaceState.withUpdatedComposeInputState(ChatTextInputState()).withUpdatedReplyMessageSubject(nil)
|
||||
interfaceState = interfaceState.withUpdatedComposeInputState(ChatTextInputState()).withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil)
|
||||
}
|
||||
let _ = ChatInterfaceState.update(engine: self.context.engine, peerId: peerId, threadId: threadId, { _ in
|
||||
return interfaceState
|
||||
|
|
@ -8881,7 +8881,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -9135,6 +9135,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
attributes.append(SendAsMessageAttribute(peerId: sendAsPeerId))
|
||||
}
|
||||
}
|
||||
if let sendMessageEffect = self.presentationInterfaceState.interfaceState.sendMessageEffect {
|
||||
if attributes.first(where: { $0 is EffectMessageAttribute }) == nil {
|
||||
attributes.append(EffectMessageAttribute(id: sendMessageEffect))
|
||||
}
|
||||
}
|
||||
return attributes
|
||||
}
|
||||
}
|
||||
|
|
@ -9304,7 +9309,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
completionImpl?()
|
||||
|
|
@ -9348,7 +9353,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
if resetTextInputState {
|
||||
state = state.updatedInterfaceState { interfaceState in
|
||||
var interfaceState = interfaceState
|
||||
interfaceState = interfaceState.withUpdatedReplyMessageSubject(nil)
|
||||
interfaceState = interfaceState.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil)
|
||||
interfaceState = interfaceState.withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: "")))
|
||||
interfaceState = interfaceState.withUpdatedComposeDisableUrlPreviews([])
|
||||
return interfaceState
|
||||
|
|
|
|||
|
|
@ -319,88 +319,31 @@ extension ChatControllerImpl {
|
|||
))
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
func beginDeleteMessagesWithUndo(messageIds: Set<MessageId>, type: InteractiveMessagesDeletionType) {
|
||||
self.chatDisplayNode.historyNode.ignoreMessageIds = Set(messageIds)
|
||||
|
||||
/*do {
|
||||
self.navigationActionDisposable.set((self.context.engine.peers.fetchChannelParticipant(peerId: peerId, participantId: author.id)
|
||||
|> deliverOnMainQueue).startStrict(next: {
|
||||
if let strongSelf = self {
|
||||
if "".isEmpty {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let canBan = participant?.canBeBannedBy(peerId: accountPeerId) ?? true
|
||||
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
var items: [ActionSheetItem] = []
|
||||
|
||||
var actions = Set<Int>([0])
|
||||
|
||||
let toggleCheck: (Int, Int) -> Void = { [weak actionSheet] category, itemIndex in
|
||||
if actions.contains(category) {
|
||||
actions.remove(category)
|
||||
} else {
|
||||
actions.insert(category)
|
||||
}
|
||||
actionSheet?.updateItem(groupIndex: 0, itemIndex: itemIndex, { item in
|
||||
if let item = item as? ActionSheetCheckboxItem {
|
||||
return ActionSheetCheckboxItem(title: item.title, label: item.label, value: !item.value, action: item.action)
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
|
||||
var itemIndex = 0
|
||||
var categories: [Int] = [0]
|
||||
if canBan {
|
||||
categories.append(1)
|
||||
}
|
||||
categories.append(contentsOf: [2, 3])
|
||||
|
||||
for categoryId in categories as [Int] {
|
||||
var title = ""
|
||||
if categoryId == 0 {
|
||||
title = strongSelf.presentationData.strings.Conversation_Moderate_Delete
|
||||
} else if categoryId == 1 {
|
||||
title = strongSelf.presentationData.strings.Conversation_Moderate_Ban
|
||||
} else if categoryId == 2 {
|
||||
title = strongSelf.presentationData.strings.Conversation_Moderate_Report
|
||||
} else if categoryId == 3 {
|
||||
title = strongSelf.presentationData.strings.Conversation_Moderate_DeleteAllMessages(EnginePeer(author).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string
|
||||
}
|
||||
let index = itemIndex
|
||||
items.append(ActionSheetCheckboxItem(title: title, label: "", value: actions.contains(categoryId), action: { value in
|
||||
toggleCheck(categoryId, index)
|
||||
}))
|
||||
itemIndex += 1
|
||||
}
|
||||
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Done, action: { [weak self, weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
if actions.contains(3) {
|
||||
let _ = strongSelf.context.engine.messages.deleteAllMessagesWithAuthor(peerId: peerId, authorId: author.id, namespace: Namespaces.Message.Cloud).startStandalone()
|
||||
let _ = strongSelf.context.engine.messages.clearAuthorHistory(peerId: peerId, memberId: author.id).startStandalone()
|
||||
} else if actions.contains(0) {
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
}
|
||||
if actions.contains(1) {
|
||||
let _ = strongSelf.context.engine.peers.removePeerMember(peerId: peerId, memberId: author.id).startStandalone()
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
})
|
||||
])])
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
}
|
||||
}))
|
||||
}*/
|
||||
//TODO:localize
|
||||
let undoTitle: String
|
||||
if messageIds.count == 1 {
|
||||
undoTitle = "Message Deleted"
|
||||
} else {
|
||||
undoTitle = "\(messageIds.count) Messages Deleted"
|
||||
}
|
||||
self.present(UndoOverlayController(presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(title: undoTitle, text: nil), elevatedLayout: false, position: .top, action: { [weak self] value in
|
||||
guard let self else {
|
||||
return false
|
||||
}
|
||||
if value == .commit {
|
||||
let _ = self.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: type).startStandalone()
|
||||
return true
|
||||
} else if value == .undo {
|
||||
self.chatDisplayNode.historyNode.ignoreMessageIds = Set()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), in: .current)
|
||||
}
|
||||
|
||||
func presentDeleteMessageOptions(messageIds: Set<MessageId>, options: ChatAvailableMessageActionOptions, contextController: ContextControllerProtocol?, completion: @escaping (ContextMenuActionResult) -> Void) {
|
||||
|
|
@ -429,7 +372,7 @@ extension ChatControllerImpl {
|
|||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
strongSelf.beginDeleteMessagesWithUndo(messageIds: messageIds, type: .forEveryone)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
|
@ -466,7 +409,8 @@ extension ChatControllerImpl {
|
|||
}
|
||||
let commit = {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
|
||||
strongSelf.beginDeleteMessagesWithUndo(messageIds: messageIds, type: .forEveryone)
|
||||
}
|
||||
if let giveaway {
|
||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||
|
|
@ -501,7 +445,8 @@ extension ChatControllerImpl {
|
|||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: .forEveryone).startStandalone()
|
||||
|
||||
strongSelf.beginDeleteMessagesWithUndo(messageIds: messageIds, type: .forEveryone)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
|
@ -534,7 +479,7 @@ extension ChatControllerImpl {
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).startStandalone()
|
||||
strongSelf.beginDeleteMessagesWithUndo(messageIds: messageIds, type: unsendPersonalMessages ? .forEveryone : .forLocalPeer)
|
||||
}
|
||||
|
||||
if "".isEmpty {
|
||||
|
|
@ -553,8 +498,8 @@ extension ChatControllerImpl {
|
|||
actionSheet?.dismissAnimated()
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
|
||||
let _ = strongSelf.context.engine.messages.deleteMessagesInteractively(messageIds: Array(messageIds), type: unsendPersonalMessages ? .forEveryone : .forLocalPeer).startStandalone()
|
||||
|
||||
strongSelf.beginDeleteMessagesWithUndo(messageIds: messageIds, type: unsendPersonalMessages ? .forEveryone : .forLocalPeer)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2705,6 +2705,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||
return chatHistoryViewForLocation(
|
||||
input,
|
||||
ignoreMessagesInTimestampRange: nil,
|
||||
ignoreMessageIds: Set(),
|
||||
context: context,
|
||||
chatLocation: chatLocation,
|
||||
chatLocationContextHolder: Atomic(value: nil),
|
||||
|
|
@ -4123,7 +4124,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||
|
||||
strongSelf.ignoreUpdateHeight = true
|
||||
textInputPanelNode.text = ""
|
||||
strongSelf.requestUpdateChatInterfaceState(.immediate, true, { $0.withUpdatedReplyMessageSubject(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeDisableUrlPreviews([]) })
|
||||
strongSelf.requestUpdateChatInterfaceState(.immediate, true, { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeDisableUrlPreviews([]) })
|
||||
strongSelf.ignoreUpdateHeight = false
|
||||
}
|
||||
}, usedCorrelationId)
|
||||
|
|
|
|||
|
|
@ -384,7 +384,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -448,7 +448,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -520,7 +520,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -551,7 +551,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -616,7 +616,7 @@ extension ChatControllerImpl {
|
|||
controller.completion = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}
|
||||
|
|
@ -1116,7 +1116,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -1491,7 +1491,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -1540,7 +1540,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -1601,7 +1601,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
@ -1621,7 +1621,7 @@ extension ChatControllerImpl {
|
|||
strongSelf.chatDisplayNode.collapseInput()
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil) }
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedSendMessageEffect(nil) }
|
||||
})
|
||||
}
|
||||
}, nil)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func chatShareToSavedMessagesAdditionalView(_ chatController: ChatControllerImpl
|
|||
return
|
||||
}
|
||||
|
||||
let _ = (chatController.context.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: chatController.context.account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 45, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: [])
|
||||
let _ = (chatController.context.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: chatController.context.account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 45, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allNonRegular), orderStatistics: [])
|
||||
|> map { view, _, _ -> [EngineMessage.Id] in
|
||||
let messageIds = correlationIds.compactMap { correlationId in
|
||||
return chatController.context.engine.messages.synchronouslyLookupCorrelationId(correlationId: correlationId)
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ struct ChatHistoryView {
|
|||
let id: Int32
|
||||
let locationInput: ChatHistoryLocationInput?
|
||||
let ignoreMessagesInTimestampRange: ClosedRange<Int32>?
|
||||
let ignoreMessageIds: Set<MessageId>
|
||||
}
|
||||
|
||||
enum ChatHistoryViewTransitionReason {
|
||||
|
|
@ -536,6 +537,15 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
}
|
||||
}
|
||||
|
||||
private let ignoreMessageIdsPromise = ValuePromise<Set<EngineMessage.Id>>(Set())
|
||||
var ignoreMessageIds: Set<EngineMessage.Id> = Set() {
|
||||
didSet {
|
||||
if self.ignoreMessageIds != oldValue {
|
||||
self.ignoreMessageIdsPromise.set(self.ignoreMessageIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let chatHasBotsPromise = ValuePromise<Bool>(false)
|
||||
var chatHasBots: Bool = false {
|
||||
didSet {
|
||||
|
|
@ -1263,7 +1273,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
|
||||
let currentViewVersion = self.currentViewVersion
|
||||
|
||||
let historyViewUpdate: Signal<(ChatHistoryViewUpdate, Int, ChatHistoryLocationInput?, ClosedRange<Int32>?), NoError>
|
||||
let historyViewUpdate: Signal<(ChatHistoryViewUpdate, Int, ChatHistoryLocationInput?, ClosedRange<Int32>?, Set<MessageId>), NoError>
|
||||
var isFirstTime = true
|
||||
var updateAllOnEachVersion = false
|
||||
if case let .custom(messages, at, quote, _) = self.source {
|
||||
|
|
@ -1286,12 +1296,13 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
scrollPosition = nil
|
||||
}
|
||||
|
||||
return (ChatHistoryViewUpdate.HistoryView(view: MessageHistoryView(tag: nil, namespaces: .all, entries: messages.reversed().map { MessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: hasMore, holeLater: false, isLoading: false), type: .Generic(type: version > 0 ? ViewUpdateType.Generic : ViewUpdateType.Initial), scrollPosition: scrollPosition, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: nil, buttonKeyboardMessage: nil, cachedData: nil, cachedDataMessages: nil, readStateData: nil), id: 0), version, nil, nil)
|
||||
return (ChatHistoryViewUpdate.HistoryView(view: MessageHistoryView(tag: nil, namespaces: .all, entries: messages.reversed().map { MessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: hasMore, holeLater: false, isLoading: false), type: .Generic(type: version > 0 ? ViewUpdateType.Generic : ViewUpdateType.Initial), scrollPosition: scrollPosition, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: nil, buttonKeyboardMessage: nil, cachedData: nil, cachedDataMessages: nil, readStateData: nil), id: 0), version, nil, nil, Set())
|
||||
}
|
||||
} else if case let .customView(historyView) = self.source {
|
||||
historyViewUpdate = combineLatest(queue: .mainQueue(),
|
||||
self.chatHistoryLocationPromise.get(),
|
||||
self.ignoreMessagesInTimestampRangePromise.get()
|
||||
self.ignoreMessagesInTimestampRangePromise.get(),
|
||||
self.ignoreMessageIdsPromise.get()
|
||||
)
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
if lhs.0 != rhs.0 {
|
||||
|
|
@ -1300,9 +1311,12 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
if lhs.1 != rhs.1 {
|
||||
return false
|
||||
}
|
||||
if lhs.2 != rhs.2 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|> mapToSignal { location, _ -> Signal<((MessageHistoryView, ViewUpdateType), ChatHistoryLocationInput?), NoError> in
|
||||
|> mapToSignal { location, _, _ -> Signal<((MessageHistoryView, ViewUpdateType), ChatHistoryLocationInput?), NoError> in
|
||||
return historyView
|
||||
|> map { historyView in
|
||||
return (historyView, location)
|
||||
|
|
@ -1347,13 +1361,15 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
),
|
||||
version,
|
||||
location,
|
||||
nil
|
||||
nil,
|
||||
Set()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
historyViewUpdate = combineLatest(queue: .mainQueue(),
|
||||
self.chatHistoryLocationPromise.get(),
|
||||
self.ignoreMessagesInTimestampRangePromise.get()
|
||||
self.ignoreMessagesInTimestampRangePromise.get(),
|
||||
self.ignoreMessageIdsPromise.get()
|
||||
)
|
||||
|> distinctUntilChanged(isEqual: { lhs, rhs in
|
||||
if lhs.0 != rhs.0 {
|
||||
|
|
@ -1362,10 +1378,13 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
if lhs.1 != rhs.1 {
|
||||
return false
|
||||
}
|
||||
if lhs.2 != rhs.2 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|> mapToSignal { location, ignoreMessagesInTimestampRange in
|
||||
return chatHistoryViewForLocation(location, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduledMessages, fixedCombinedReadStates: fixedCombinedReadStates.with { $0 }, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, additionalData: additionalData, orderStatistics: [], useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
|> mapToSignal { location, ignoreMessagesInTimestampRange, ignoreMessageIds in
|
||||
return chatHistoryViewForLocation(location, ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduledMessages, fixedCombinedReadStates: fixedCombinedReadStates.with { $0 }, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, additionalData: additionalData, orderStatistics: [], useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
|> beforeNext { viewUpdate in
|
||||
switch viewUpdate {
|
||||
case let .HistoryView(view, _, _, _, _, _, _):
|
||||
|
|
@ -1374,7 +1393,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
break
|
||||
}
|
||||
}
|
||||
|> map { view -> (ChatHistoryViewUpdate, Int, ChatHistoryLocationInput?, ClosedRange<Int32>?) in
|
||||
|> map { view -> (ChatHistoryViewUpdate, Int, ChatHistoryLocationInput?, ClosedRange<Int32>?, Set<MessageId>) in
|
||||
let version = currentViewVersion.modify({ value in
|
||||
if let value = value {
|
||||
return value + 1
|
||||
|
|
@ -1382,7 +1401,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
return 0
|
||||
}
|
||||
})!
|
||||
return (view, version, location, ignoreMessagesInTimestampRange)
|
||||
return (view, version, location, ignoreMessagesInTimestampRange, ignoreMessageIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1675,7 +1694,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
|
||||
if resetScrolling, let previousViewValue = previousView.with({ $0 })?.0 {
|
||||
let filteredEntries: [ChatHistoryEntry] = []
|
||||
let processedView = ChatHistoryView(originalView: MessageHistoryView(tag: nil, namespaces: .all, entries: [], holeEarlier: false, holeLater: false, isLoading: true), filteredEntries: filteredEntries, associatedData: previousViewValue.associatedData, lastHeaderId: 0, id: previousViewValue.id, locationInput: previousViewValue.locationInput, ignoreMessagesInTimestampRange: nil)
|
||||
let processedView = ChatHistoryView(originalView: MessageHistoryView(tag: nil, namespaces: .all, entries: [], holeEarlier: false, holeLater: false, isLoading: true), filteredEntries: filteredEntries, associatedData: previousViewValue.associatedData, lastHeaderId: 0, id: previousViewValue.id, locationInput: previousViewValue.locationInput, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set())
|
||||
let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages, allAdMessages.version))
|
||||
let previous = previousValueAndVersion?.0
|
||||
let previousSelectedMessages = previousValueAndVersion?.2
|
||||
|
|
@ -1847,7 +1866,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
dynamicAdMessages: allAdMessages.opportunistic
|
||||
)
|
||||
let lastHeaderId = filteredEntries.last.flatMap { listMessageDateHeaderId(timestamp: $0.index.timestamp) } ?? 0
|
||||
let processedView = ChatHistoryView(originalView: view, filteredEntries: filteredEntries, associatedData: associatedData, lastHeaderId: lastHeaderId, id: id, locationInput: update.2, ignoreMessagesInTimestampRange: update.3)
|
||||
let processedView = ChatHistoryView(originalView: view, filteredEntries: filteredEntries, associatedData: associatedData, lastHeaderId: lastHeaderId, id: id, locationInput: update.2, ignoreMessagesInTimestampRange: update.3, ignoreMessageIds: update.4)
|
||||
let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages, allAdMessages.version))
|
||||
let previous = previousValueAndVersion?.0
|
||||
let previousSelectedMessages = previousValueAndVersion?.2
|
||||
|
|
@ -1877,6 +1896,9 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
} else if let previous = previous, previous.id == processedView.id, previous.originalView.entries == processedView.originalView.entries {
|
||||
reason = ChatHistoryViewTransitionReason.InteractiveChanges
|
||||
updatedScrollPosition = nil
|
||||
} else if let previous = previous, previous.id == processedView.id, previous.ignoreMessageIds != processedView.ignoreMessageIds {
|
||||
reason = ChatHistoryViewTransitionReason.InteractiveChanges
|
||||
updatedScrollPosition = nil
|
||||
} else {
|
||||
switch type {
|
||||
case let .Initial(fadeIn):
|
||||
|
|
@ -3423,6 +3445,14 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
}
|
||||
}
|
||||
}
|
||||
for id in self.ignoreMessageIds {
|
||||
inner: for (stableId, listId) in maybeRemovedInteractivelyMessageIds {
|
||||
if listId == id {
|
||||
expiredMessageStableIds.insert(stableId)
|
||||
break inner
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.currentDeleteAnimationCorrelationIds.formUnion(expiredMessageStableIds)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ func preloadedChatHistoryViewForLocation(_ location: ChatHistoryLocationInput, c
|
|||
tag = .tag(.pinned)
|
||||
}
|
||||
|
||||
return (chatHistoryViewForLocation(location, ignoreMessagesInTimestampRange: nil, context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduled, fixedCombinedReadStates: fixedCombinedReadStates, tag: tag, appendMessagesFromTheSameGroup: false, additionalData: additionalData, orderStatistics: orderStatistics)
|
||||
return (chatHistoryViewForLocation(location, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, scheduled: isScheduled, fixedCombinedReadStates: fixedCombinedReadStates, tag: tag, appendMessagesFromTheSameGroup: false, additionalData: additionalData, orderStatistics: orderStatistics)
|
||||
|> castError(Bool.self)
|
||||
|> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in
|
||||
switch update {
|
||||
|
|
@ -36,7 +36,21 @@ func preloadedChatHistoryViewForLocation(_ location: ChatHistoryLocationInput, c
|
|||
|> restartIfError
|
||||
}
|
||||
|
||||
func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMessagesInTimestampRange: ClosedRange<Int32>?, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, scheduled: Bool, fixedCombinedReadStates: MessageHistoryViewReadState?, tag: HistoryViewInputTag?, appendMessagesFromTheSameGroup: Bool, additionalData: [AdditionalMessageHistoryViewData], orderStatistics: MessageHistoryViewOrderStatistics = [], useRootInterfaceStateForThread: Bool = false) -> Signal<ChatHistoryViewUpdate, NoError> {
|
||||
func chatHistoryViewForLocation(
|
||||
_ location: ChatHistoryLocationInput,
|
||||
ignoreMessagesInTimestampRange: ClosedRange<Int32>?,
|
||||
ignoreMessageIds: Set<EngineMessage.Id>,
|
||||
context: AccountContext,
|
||||
chatLocation: ChatLocation,
|
||||
chatLocationContextHolder: Atomic<ChatLocationContextHolder?>,
|
||||
scheduled: Bool,
|
||||
fixedCombinedReadStates: MessageHistoryViewReadState?,
|
||||
tag: HistoryViewInputTag?,
|
||||
appendMessagesFromTheSameGroup: Bool,
|
||||
additionalData: [AdditionalMessageHistoryViewData],
|
||||
orderStatistics: MessageHistoryViewOrderStatistics = [],
|
||||
useRootInterfaceStateForThread: Bool = false
|
||||
) -> Signal<ChatHistoryViewUpdate, NoError> {
|
||||
let account = context.account
|
||||
if scheduled {
|
||||
var first = true
|
||||
|
|
@ -93,9 +107,9 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
|
|||
}
|
||||
|
||||
if requestAroundId {
|
||||
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, index: .upperBound, anchorIndex: .upperBound, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: preFixedReadState, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, index: .upperBound, anchorIndex: .upperBound, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: preFixedReadState, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
} else {
|
||||
signal = account.viewTracker.aroundMessageOfInterestHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
signal = account.viewTracker.aroundMessageOfInterestHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
}
|
||||
|
||||
let isPossibleIntroLoaded: Signal<Bool, NoError>
|
||||
|
|
@ -220,9 +234,9 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
|
|||
let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>
|
||||
switch searchLocationSubject.location {
|
||||
case let .index(index):
|
||||
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, index: .message(index), anchorIndex: .message(index), count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: nil, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
signal = account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, index: .message(index), anchorIndex: .message(index), count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: nil, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
case let .id(id):
|
||||
signal = account.viewTracker.aroundIdMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: id, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
signal = account.viewTracker.aroundIdMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, count: count, ignoreRelatedChats: ignoreRelatedChats, messageId: id, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
}
|
||||
|
||||
return signal |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
|
||||
|
|
@ -271,7 +285,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
|
|||
}
|
||||
case let .Navigation(index, anchorIndex, count, _):
|
||||
var first = true
|
||||
return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, index: index, anchorIndex: anchorIndex, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread) |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
|
||||
return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, index: index, anchorIndex: anchorIndex, count: count, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread) |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
|
||||
let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation)
|
||||
|
||||
let genericType: ViewUpdateType
|
||||
|
|
@ -287,7 +301,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
|
|||
let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > subject.index ? .Down : .Up
|
||||
let chatScrollPosition = ChatHistoryViewScrollPosition.index(subject: subject, position: scrollPosition, directionHint: directionHint, animated: animated, highlight: highlight, displayLink: false)
|
||||
var first = true
|
||||
return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, index: subject.index, anchorIndex: anchorIndex, count: 128, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
return account.viewTracker.aroundMessageHistoryViewForLocation(context.chatLocationInput(for: chatLocation, contextHolder: chatLocationContextHolder), ignoreMessagesInTimestampRange: ignoreMessagesInTimestampRange, ignoreMessageIds: ignoreMessageIds, index: subject.index, anchorIndex: anchorIndex, count: 128, ignoreRelatedChats: ignoreRelatedChats, fixedCombinedReadStates: fixedCombinedReadStates, tag: tag, appendMessagesFromTheSameGroup: appendMessagesFromTheSameGroup, orderStatistics: orderStatistics, additionalData: additionalData, useRootInterfaceStateForThread: useRootInterfaceStateForThread)
|
||||
|> map { view, updateType, initialData -> ChatHistoryViewUpdate in
|
||||
let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,121 @@ import ChatControllerInteraction
|
|||
import AccountContext
|
||||
import ChatTextInputMediaRecordingButton
|
||||
import ChatSendButtonRadialStatusNode
|
||||
import ChatSendMessageActionUI
|
||||
import ComponentFlow
|
||||
|
||||
final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
||||
private final class EffectBadgeView: UIView {
|
||||
private let context: AccountContext
|
||||
private var currentEffectId: Int64?
|
||||
|
||||
private let backgroundView: UIImageView
|
||||
|
||||
private var theme: PresentationTheme?
|
||||
|
||||
private var effect: AvailableMessageEffects.MessageEffect?
|
||||
private var effectIcon: ComponentView<Empty>?
|
||||
|
||||
private let effectDisposable = MetaDisposable()
|
||||
|
||||
init(context: AccountContext) {
|
||||
self.context = context
|
||||
self.backgroundView = UIImageView()
|
||||
|
||||
super.init(frame: CGRect())
|
||||
|
||||
self.isUserInteractionEnabled = false
|
||||
|
||||
self.addSubview(self.backgroundView)
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.effectDisposable.dispose()
|
||||
}
|
||||
|
||||
func update(size: CGSize, theme: PresentationTheme, effectId: Int64) {
|
||||
if self.theme !== theme {
|
||||
self.theme = theme
|
||||
self.backgroundView.image = generateFilledCircleImage(diameter: size.width, color: theme.list.plainBackgroundColor, strokeColor: nil, strokeWidth: nil, backgroundColor: nil)
|
||||
self.backgroundView.layer.shadowPath = UIBezierPath(ovalIn: CGRect(origin: CGPoint(), size: size)).cgPath
|
||||
self.backgroundView.layer.shadowColor = UIColor(white: 0.0, alpha: 1.0).cgColor
|
||||
self.backgroundView.layer.shadowOpacity = 0.14
|
||||
self.backgroundView.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
|
||||
self.backgroundView.layer.shadowRadius = 1.0
|
||||
}
|
||||
|
||||
self.backgroundView.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
if self.currentEffectId != effectId {
|
||||
self.currentEffectId = effectId
|
||||
|
||||
let messageEffect = self.context.engine.stickers.availableMessageEffects()
|
||||
|> take(1)
|
||||
|> map { availableMessageEffects -> AvailableMessageEffects.MessageEffect? in
|
||||
guard let availableMessageEffects else {
|
||||
return nil
|
||||
}
|
||||
for messageEffect in availableMessageEffects.messageEffects {
|
||||
if messageEffect.id == effectId || messageEffect.effectSticker.fileId.id == effectId {
|
||||
return messageEffect
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
self.effectDisposable.set((messageEffect |> deliverOnMainQueue).start(next: { [weak self] effect in
|
||||
guard let self, let effect else {
|
||||
return
|
||||
}
|
||||
self.effect = effect
|
||||
self.updateIcon()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
private func updateIcon() {
|
||||
guard let effect else {
|
||||
return
|
||||
}
|
||||
|
||||
let effectIcon: ComponentView<Empty>
|
||||
if let current = self.effectIcon {
|
||||
effectIcon = current
|
||||
} else {
|
||||
effectIcon = ComponentView()
|
||||
self.effectIcon = effectIcon
|
||||
}
|
||||
let effectIconContent: ChatSendMessageScreenEffectIcon.Content
|
||||
if let staticIcon = effect.staticIcon {
|
||||
effectIconContent = .file(staticIcon)
|
||||
} else {
|
||||
effectIconContent = .text(effect.emoticon)
|
||||
}
|
||||
let effectIconSize = effectIcon.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(ChatSendMessageScreenEffectIcon(
|
||||
context: self.context,
|
||||
content: effectIconContent
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 8.0, height: 8.0)
|
||||
)
|
||||
|
||||
let size = CGSize(width: 16.0, height: 16.0)
|
||||
if let effectIconView = effectIcon.view {
|
||||
if effectIconView.superview == nil {
|
||||
self.addSubview(effectIconView)
|
||||
}
|
||||
effectIconView.frame = CGRect(origin: CGPoint(x: floor((size.width - effectIconSize.width) * 0.5), y: floor((size.height - effectIconSize.height) * 0.5)), size: effectIconSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessageActionSheetControllerSourceSendButtonNode {
|
||||
private let context: AccountContext
|
||||
private let presentationContext: ChatPresentationContext?
|
||||
private let strings: PresentationStrings
|
||||
|
||||
|
|
@ -26,6 +139,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
|||
var sendButtonHasApplyIcon = false
|
||||
var animatingSendButton = false
|
||||
let expandMediaInputButton: HighlightableButtonNode
|
||||
private var effectBadgeView: EffectBadgeView?
|
||||
|
||||
var sendButtonLongPressed: ((ASDisplayNode, ContextGesture) -> Void)?
|
||||
|
||||
|
|
@ -42,6 +156,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
|||
private var validLayout: CGSize?
|
||||
|
||||
init(context: AccountContext, presentationInterfaceState: ChatPresentationInterfaceState, presentationContext: ChatPresentationContext?, presentController: @escaping (ViewController) -> Void) {
|
||||
self.context = context
|
||||
self.presentationContext = presentationContext
|
||||
let theme = presentationInterfaceState.theme
|
||||
let strings = presentationInterfaceState.strings
|
||||
|
|
@ -145,7 +260,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, isMediaInputExpanded: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) {
|
||||
func updateLayout(size: CGSize, isMediaInputExpanded: Bool, currentMessageEffectId: Int64?, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) {
|
||||
self.validLayout = size
|
||||
transition.updateFrame(layer: self.micButton.layer, frame: CGRect(origin: CGPoint(), size: size))
|
||||
self.micButton.layoutItems()
|
||||
|
|
@ -154,7 +269,8 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
|||
transition.updateFrame(node: self.sendContainerNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
let backgroundSize = CGSize(width: 33.0, height: 33.0)
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize))
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize)
|
||||
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
|
||||
self.backgroundNode.cornerRadius = backgroundSize.width / 2.0
|
||||
|
||||
transition.updateFrame(node: self.backdropNode, frame: CGRect(origin: CGPoint(x: -2.0, y: -2.0), size: CGSize(width: size.width + 12.0, height: size.height + 2.0)))
|
||||
|
|
@ -162,42 +278,31 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
|||
self.backdropNode.update(rect: rect, within: containerSize)
|
||||
}
|
||||
|
||||
// var isScheduledMessages = false
|
||||
// if case .scheduledMessages = interfaceState.subject {
|
||||
// isScheduledMessages = true
|
||||
// }
|
||||
//
|
||||
// if let slowmodeState = interfaceState.slowmodeState, !isScheduledMessages && interfaceState.editMessageState == nil {
|
||||
// let sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode
|
||||
// if let current = self.sendButtonRadialStatusNode {
|
||||
// sendButtonRadialStatusNode = current
|
||||
// } else {
|
||||
// sendButtonRadialStatusNode = ChatSendButtonRadialStatusNode(color: interfaceState.theme.chat.inputPanel.panelControlAccentColor)
|
||||
// sendButtonRadialStatusNode.alpha = self.sendContainerNode.alpha
|
||||
// self.sendButtonRadialStatusNode = sendButtonRadialStatusNode
|
||||
// self.addSubnode(sendButtonRadialStatusNode)
|
||||
// }
|
||||
//
|
||||
// transition.updateSublayerTransformScale(layer: self.sendContainerNode.layer, scale: CGPoint(x: 0.7575, y: 0.7575))
|
||||
//
|
||||
// let defaultSendButtonSize: CGFloat = 25.0
|
||||
// let defaultOriginX = floorToScreenPixels((self.sendButton.bounds.width - defaultSendButtonSize) / 2.0)
|
||||
// let defaultOriginY = floorToScreenPixels((self.sendButton.bounds.height - defaultSendButtonSize) / 2.0)
|
||||
//
|
||||
// let radialStatusFrame = CGRect(origin: CGPoint(x: defaultOriginX - 4.0, y: defaultOriginY - 4.0), size: CGSize(width: 33.0, height: 33.0))
|
||||
// sendButtonRadialStatusNode.frame = radialStatusFrame
|
||||
// sendButtonRadialStatusNode.slowmodeState = slowmodeState
|
||||
// } else {
|
||||
// if let sendButtonRadialStatusNode = self.sendButtonRadialStatusNode {
|
||||
// self.sendButtonRadialStatusNode = nil
|
||||
// sendButtonRadialStatusNode.removeFromSupernode()
|
||||
// }
|
||||
// transition.updateSublayerTransformScale(layer: self.sendContainerNode.layer, scale: CGPoint(x: 1.0, y: 1.0))
|
||||
// }
|
||||
|
||||
transition.updateFrame(node: self.expandMediaInputButton, frame: CGRect(origin: CGPoint(), size: size))
|
||||
let expanded = isMediaInputExpanded
|
||||
transition.updateSublayerTransformScale(node: self.expandMediaInputButton, scale: CGPoint(x: 1.0, y: expanded ? 1.0 : -1.0))
|
||||
|
||||
if let currentMessageEffectId {
|
||||
let effectBadgeView: EffectBadgeView
|
||||
if let current = self.effectBadgeView {
|
||||
effectBadgeView = current
|
||||
} else {
|
||||
effectBadgeView = EffectBadgeView(context: self.context)
|
||||
self.effectBadgeView = effectBadgeView
|
||||
self.sendContainerNode.view.addSubview(effectBadgeView)
|
||||
|
||||
effectBadgeView.alpha = 0.0
|
||||
transition.updateAlpha(layer: effectBadgeView.layer, alpha: 1.0)
|
||||
}
|
||||
let badgeSize = CGSize(width: 16.0, height: 16.0)
|
||||
effectBadgeView.frame = CGRect(origin: CGPoint(x: backgroundFrame.minX + backgroundSize.width + 3.0 - badgeSize.width, y: backgroundFrame.minY + backgroundSize.height + 3.0 - badgeSize.height), size: badgeSize)
|
||||
effectBadgeView.update(size: badgeSize, theme: interfaceState.theme, effectId: currentMessageEffectId)
|
||||
} else if let effectBadgeView = self.effectBadgeView {
|
||||
self.effectBadgeView = nil
|
||||
transition.updateAlpha(layer: effectBadgeView.layer, alpha: 0.0, completion: { [weak effectBadgeView] _ in
|
||||
effectBadgeView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func updateAccessibility() {
|
||||
|
|
@ -216,4 +321,17 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
|||
self.accessibilityHint = nil
|
||||
}
|
||||
}
|
||||
|
||||
func makeCustomContents() -> UIView? {
|
||||
if self.sendButtonHasApplyIcon {
|
||||
let result = UIView()
|
||||
result.frame = self.bounds
|
||||
if let copyView = self.sendContainerNode.view.snapshotView(afterScreenUpdates: false) {
|
||||
copyView.frame = self.sendContainerNode.frame
|
||||
result.addSubview(copyView)
|
||||
}
|
||||
return result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2483,7 +2483,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
|||
}
|
||||
|
||||
if let presentationInterfaceState = self.presentationInterfaceState {
|
||||
self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, transition: transition, interfaceState: presentationInterfaceState)
|
||||
self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState)
|
||||
}
|
||||
|
||||
let slowModeButtonFrame = CGRect(origin: CGPoint(x: hideOffset.x + width - rightInset - 5.0 - slowModeButtonSize.width + composeButtonsOffset, y: hideOffset.y + panelHeight - minimalHeight + 6.0), size: slowModeButtonSize)
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
|
|||
return .single(nil)
|
||||
}
|
||||
|
||||
return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic<ChatLocationContextHolder?>(value: nil)), anchor: .index(message.index), ignoreMessagesInTimestampRange: nil, count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [])
|
||||
return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic<ChatLocationContextHolder?>(value: nil)), anchor: .index(message.index), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [])
|
||||
|> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in
|
||||
if let (message, aroundMessages, _) = navigatedMessageFromView(view.0, anchorIndex: message.index, position: .exact, reversed: reversed) {
|
||||
return .single((message, aroundMessages))
|
||||
|
|
@ -678,7 +678,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
|
|||
guard let inputIndex = inputIndex else {
|
||||
return .single(nil)
|
||||
}
|
||||
return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic<ChatLocationContextHolder?>(value: nil)), anchor: .index(inputIndex), ignoreMessagesInTimestampRange: nil, count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [])
|
||||
return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic<ChatLocationContextHolder?>(value: nil)), anchor: .index(inputIndex), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [])
|
||||
|> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in
|
||||
let position: NavigatedMessageFromViewPosition
|
||||
switch navigation {
|
||||
|
|
@ -708,7 +708,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
|
|||
} else {
|
||||
viewIndex = .lowerBound
|
||||
}
|
||||
return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic<ChatLocationContextHolder?>(value: nil)), anchor: viewIndex, ignoreMessagesInTimestampRange: nil, count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [])
|
||||
return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic<ChatLocationContextHolder?>(value: nil)), anchor: viewIndex, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: [])
|
||||
|> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in
|
||||
let position: NavigatedMessageFromViewPosition
|
||||
switch navigation {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue