mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
937eae7081
34 changed files with 250 additions and 154 deletions
4
.bazelrc
4
.bazelrc
|
|
@ -27,9 +27,9 @@ build:swift_profile --local_cpu_resources=1
|
|||
build:swift_profile --features=-swift.enable_batch_mode
|
||||
build:swift_profile --experimental_ui_max_stdouterr_bytes=104857600
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-Xfrontend
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-debug-time-function-bodies
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-warn-long-function-bodies=350
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-Xfrontend
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-debug-time-expression-type-checking
|
||||
build:swift_profile --@build_bazel_rules_swift//swift:copt=-warn-long-expression-type-checking=350
|
||||
|
||||
common:index_build --experimental_convenience_symlinks=ignore
|
||||
common:index_build --bes_backend= --bes_results_url=
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ def remote_build_tart(macos_version, bazel_cache_host, configuration, build_inpu
|
|||
else:
|
||||
guest_build_sh += '--cacheHost="$CACHE_HOST" \\'
|
||||
guest_build_sh += 'build \\'
|
||||
guest_build_sh += '--lock \\'
|
||||
#guest_build_sh += '--lock \\'
|
||||
guest_build_sh += '--buildNumber={} \\'.format(build_number)
|
||||
guest_build_sh += '--configuration={} \\'.format(configuration)
|
||||
guest_build_sh += '--configurationPath=$HOME/telegram-build-input/configuration.json \\'
|
||||
|
|
|
|||
|
|
@ -2545,13 +2545,25 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||
guard let strongSelf, currentValues.contains(.setupPasskey) else {
|
||||
return
|
||||
}
|
||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
let controller = strongSelf.context.sharedContext.makePasskeySetupController(context: strongSelf.context, displaySkip: true, navigationController: navigationController, completion: {
|
||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
|
||||
}, dismiss: {
|
||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
|
||||
})
|
||||
navigationController.pushViewController(controller)
|
||||
|
||||
Task { @MainActor [weak strongSelf] in
|
||||
guard let strongSelf else {
|
||||
return
|
||||
}
|
||||
|
||||
let passkeysData = await strongSelf.context.engine.auth.passkeysData().get()
|
||||
if !passkeysData.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
let controller = strongSelf.context.sharedContext.makePasskeySetupController(context: strongSelf.context, displaySkip: true, navigationController: navigationController, completion: {
|
||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
|
||||
}, dismiss: {
|
||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
|
||||
})
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -788,6 +788,9 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
let topInset = navigationBarHeight
|
||||
|
||||
var filtersInsets = UIEdgeInsets(top: 0.0, left: 12.0, bottom: layout.insets(options: [.input]).bottom, right: 12.0)
|
||||
if filtersInsets.bottom == 84.0 {
|
||||
filtersInsets.bottom -= 6.0
|
||||
}
|
||||
if layout.insets(options: [.input]).bottom <= 30.0 {
|
||||
filtersInsets = ContainerViewLayout.concentricInsets(bottomInset: layout.insets(options: [.input]).bottom, innerDiameter: 40.0, sideInset: 32.0)
|
||||
} else if layout.insets(options: [.input]).bottom <= 84.0 {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ final class MutableDeletedMessagesView: MutablePostboxView {
|
|||
for operation in operations {
|
||||
switch operation {
|
||||
case let .Remove(indices):
|
||||
for (index, _) in indices {
|
||||
for (index, _, _) in indices {
|
||||
testMessageIds.append(index.id)
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ final class MutableHistoryTagInfoView: MutablePostboxView {
|
|||
}
|
||||
case let .Remove(indicesAndTags):
|
||||
if self.currentIndex != nil {
|
||||
for (index, tags) in indicesAndTags {
|
||||
for (index, tags, _) in indicesAndTags {
|
||||
if tags.contains(self.tag) {
|
||||
if index == self.currentIndex {
|
||||
self.currentIndex = nil
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
|
||||
enum MessageHistoryOperation {
|
||||
case InsertMessage(IntermediateMessage)
|
||||
case Remove([(MessageIndex, MessageTags)])
|
||||
case Remove([(MessageIndex, MessageTags, Int64?)])
|
||||
case UpdateReadState(PeerId, CombinedPeerReadState)
|
||||
case UpdateEmbeddedMedia(MessageIndex, ReadBuffer)
|
||||
case UpdateTimestamp(MessageIndex, Int32)
|
||||
|
|
|
|||
|
|
@ -197,19 +197,19 @@ final class MessageHistoryTable: Table {
|
|||
|
||||
let buckets = self.continuousIndexIntervalsForRemoving(accumulatedRemoveIndices)
|
||||
for bucket in buckets {
|
||||
var indicesWithMetadata: [(MessageIndex, MessageTags)] = []
|
||||
var indicesWithMetadata: [(MessageIndex, MessageTags, Int64?)] = []
|
||||
var globalIndicesWithMetadata: [(GlobalMessageTags, MessageIndex)] = []
|
||||
|
||||
for index in bucket {
|
||||
let tagsAndGlobalTags = self.justRemove(index, unsentMessageOperations: &unsentMessageOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: ×tampBasedMessageAttributesOperations)
|
||||
if let (tags, globalTags) = tagsAndGlobalTags {
|
||||
indicesWithMetadata.append((index, tags))
|
||||
if let (tags, globalTags, threadId) = tagsAndGlobalTags {
|
||||
indicesWithMetadata.append((index, tags, threadId))
|
||||
|
||||
if !globalTags.isEmpty {
|
||||
globalIndicesWithMetadata.append((globalTags, index))
|
||||
}
|
||||
} else {
|
||||
indicesWithMetadata.append((index, MessageTags()))
|
||||
indicesWithMetadata.append((index, MessageTags(), nil))
|
||||
}
|
||||
}
|
||||
assert(bucket.count == indicesWithMetadata.count)
|
||||
|
|
@ -352,8 +352,8 @@ final class MessageHistoryTable: Table {
|
|||
processIndexOperationsCommitAccumulatedRemoveIndices(peerId: peerId, accumulatedRemoveIndices: &accumulatedRemoveIndices, updatedCombinedState: &updatedCombinedState, invalidateReadState: &invalidateReadState, unsentMessageOperations: &unsentMessageOperations, outputOperations: &outputOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: ×tampBasedMessageAttributesOperations)
|
||||
|
||||
var updatedGroupInfos: [MessageId: MessageGroupInfo] = [:]
|
||||
if let (message, previousTags) = self.justUpdate(storeMessage.index, message: storeMessage, keepLocalTags: true, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: ×tampBasedMessageAttributesOperations, updatedMedia: &updatedMedia) {
|
||||
outputOperations.append(.Remove([(storeMessage.index, previousTags)]))
|
||||
if let (message, previousTags, previousThreadId) = self.justUpdate(storeMessage.index, message: storeMessage, keepLocalTags: true, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: ×tampBasedMessageAttributesOperations, updatedMedia: &updatedMedia) {
|
||||
outputOperations.append(.Remove([(storeMessage.index, previousTags, previousThreadId)]))
|
||||
outputOperations.append(.InsertMessage(message))
|
||||
if !updatedGroupInfos.isEmpty {
|
||||
outputOperations.append(.UpdateGroupInfos(updatedGroupInfos))
|
||||
|
|
@ -367,8 +367,8 @@ final class MessageHistoryTable: Table {
|
|||
processIndexOperationsCommitAccumulatedRemoveIndices(peerId: peerId, accumulatedRemoveIndices: &accumulatedRemoveIndices, updatedCombinedState: &updatedCombinedState, invalidateReadState: &invalidateReadState, unsentMessageOperations: &unsentMessageOperations, outputOperations: &outputOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: ×tampBasedMessageAttributesOperations)
|
||||
|
||||
var updatedGroupInfos: [MessageId: MessageGroupInfo] = [:]
|
||||
if let (message, previousTags) = self.justUpdate(index, message: storeMessage, keepLocalTags: false, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: ×tampBasedMessageAttributesOperations, updatedMedia: &updatedMedia) {
|
||||
outputOperations.append(.Remove([(index, previousTags)]))
|
||||
if let (message, previousTags, previousThreadId) = self.justUpdate(index, message: storeMessage, keepLocalTags: false, sharedKey: sharedKey, sharedBuffer: sharedBuffer, sharedEncoder: sharedEncoder, unsentMessageOperations: &unsentMessageOperations, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, updatedGroupInfos: &updatedGroupInfos, localTagsOperations: &localTagsOperations, timestampBasedMessageAttributesOperations: ×tampBasedMessageAttributesOperations, updatedMedia: &updatedMedia) {
|
||||
outputOperations.append(.Remove([(index, previousTags, previousThreadId)]))
|
||||
outputOperations.append(.InsertMessage(message))
|
||||
if !updatedGroupInfos.isEmpty {
|
||||
outputOperations.append(.UpdateGroupInfos(updatedGroupInfos))
|
||||
|
|
@ -944,7 +944,7 @@ final class MessageHistoryTable: Table {
|
|||
self.storeIntermediateMessage(updatedMessage, sharedKey: self.key(MessageIndex.absoluteLowerBound()))
|
||||
|
||||
let operations: [MessageHistoryOperation] = [
|
||||
.Remove([(index, message.tags)]),
|
||||
.Remove([(index, message.tags, message.threadId)]),
|
||||
.InsertMessage(updatedMessage)
|
||||
]
|
||||
if operationsByPeerId[message.id.peerId] == nil {
|
||||
|
|
@ -1352,7 +1352,7 @@ final class MessageHistoryTable: Table {
|
|||
return result
|
||||
}
|
||||
|
||||
private func justRemove(_ index: MessageIndex, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation], timestampBasedMessageAttributesOperations: inout [TimestampBasedMessageAttributesOperation]) -> (MessageTags, GlobalMessageTags)? {
|
||||
private func justRemove(_ index: MessageIndex, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation], timestampBasedMessageAttributesOperations: inout [TimestampBasedMessageAttributesOperation]) -> (MessageTags, GlobalMessageTags, Int64?)? {
|
||||
let key = self.key(index)
|
||||
if let value = self.valueBox.get(self.table, key: key) {
|
||||
let resultTags: MessageTags
|
||||
|
|
@ -1440,7 +1440,7 @@ final class MessageHistoryTable: Table {
|
|||
resultGlobalTags = message.globalTags
|
||||
|
||||
self.valueBox.remove(self.table, key: key, secure: true)
|
||||
return (resultTags, resultGlobalTags)
|
||||
return (resultTags, resultGlobalTags, message.threadId)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1544,7 +1544,7 @@ final class MessageHistoryTable: Table {
|
|||
})
|
||||
}
|
||||
|
||||
private func justUpdate(_ index: MessageIndex, message: InternalStoreMessage, keepLocalTags: Bool, sharedKey: ValueBoxKey, sharedBuffer: WriteBuffer, sharedEncoder: PostboxEncoder, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], updatedGroupInfos: inout [MessageId: MessageGroupInfo], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation], timestampBasedMessageAttributesOperations: inout [TimestampBasedMessageAttributesOperation], updatedMedia: inout [MediaId: Media?]) -> (IntermediateMessage, MessageTags)? {
|
||||
private func justUpdate(_ index: MessageIndex, message: InternalStoreMessage, keepLocalTags: Bool, sharedKey: ValueBoxKey, sharedBuffer: WriteBuffer, sharedEncoder: PostboxEncoder, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], updatedGroupInfos: inout [MessageId: MessageGroupInfo], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation], timestampBasedMessageAttributesOperations: inout [TimestampBasedMessageAttributesOperation], updatedMedia: inout [MediaId: Media?]) -> (IntermediateMessage, MessageTags, Int64?)? {
|
||||
if let previousMessage = self.getMessage(index) {
|
||||
var mediaToUpdate: [Media] = []
|
||||
|
||||
|
|
@ -2037,7 +2037,7 @@ final class MessageHistoryTable: Table {
|
|||
|
||||
self.valueBox.set(self.table, key: self.key(message.index, key: sharedKey), value: sharedBuffer)
|
||||
|
||||
let result = (IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: flags, tags: tags, globalTags: message.globalTags, localTags: updatedLocalTags, customTags: message.customTags, forwardInfo: intermediateForwardInfo, authorId: message.authorId, text: message.text, attributesData: attributesBuffer.makeReadBufferAndReset(), embeddedMediaData: embeddedMediaBuffer.makeReadBufferAndReset(), referencedMedia: referencedMedia), previousMessage.tags)
|
||||
let result = (IntermediateMessage(stableId: stableId, stableVersion: stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: flags, tags: tags, globalTags: message.globalTags, localTags: updatedLocalTags, customTags: message.customTags, forwardInfo: intermediateForwardInfo, authorId: message.authorId, text: message.text, attributesData: attributesBuffer.makeReadBufferAndReset(), embeddedMediaData: embeddedMediaBuffer.makeReadBufferAndReset(), referencedMedia: referencedMedia), previousMessage.tags, previousMessage.threadId)
|
||||
|
||||
for media in mediaToUpdate {
|
||||
if let id = media.id {
|
||||
|
|
|
|||
|
|
@ -676,7 +676,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
}
|
||||
}
|
||||
case let .Remove(indicesAndTags):
|
||||
for (index, _) in indicesAndTags {
|
||||
for (index, _, _) in indicesAndTags {
|
||||
if self.namespaces.contains(index.id.namespace) {
|
||||
if loadedState.remove(index: index) {
|
||||
hasChanges = true
|
||||
|
|
@ -821,7 +821,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
}
|
||||
case let .Remove(indices):
|
||||
if !self.topTaggedMessages.isEmpty {
|
||||
for (index, _) in indices {
|
||||
for (index, _, _) in indices {
|
||||
if let maybeCurrentTopMessage = self.topTaggedMessages[index.id.namespace], let currentTopMessage = maybeCurrentTopMessage, index.id == currentTopMessage.id {
|
||||
let item: MessageHistoryTopTaggedMessage? = nil
|
||||
self.topTaggedMessages[index.id.namespace] = item
|
||||
|
|
@ -873,7 +873,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
break findOperation
|
||||
}
|
||||
case let .Remove(indices):
|
||||
for (index, _) in indices {
|
||||
for (index, _, _) in indices {
|
||||
if currentIds.contains(index.id) {
|
||||
updateMessage = true
|
||||
break findOperation
|
||||
|
|
@ -956,7 +956,7 @@ final class MutableMessageHistoryView: MutablePostboxView {
|
|||
break outer
|
||||
}
|
||||
case let .Remove(indicesWithTags):
|
||||
for (index, _) in indicesWithTags {
|
||||
for (index, _, _) in indicesWithTags {
|
||||
if cachedData.messageIds.contains(index.id) {
|
||||
updatedCachedPeerDataMessages = true
|
||||
break outer
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ final class MutableMessageView {
|
|||
case let .Remove(indices):
|
||||
if let message = self.message {
|
||||
let messageIndex = message.index
|
||||
for (index, _) in indices {
|
||||
for (index, _, _) in indices {
|
||||
if index == messageIndex {
|
||||
self.message = nil
|
||||
updated = true
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Foundation
|
||||
|
||||
private struct PeerChatTopTaggedUpdateRecord: Equatable, Hashable {
|
||||
let peerId: PeerId
|
||||
let peerAndThreadId: PeerAndThreadId
|
||||
let namespace: MessageId.Namespace
|
||||
}
|
||||
|
||||
|
|
@ -10,71 +10,85 @@ final class PeerChatTopTaggedMessageIdsTable: Table {
|
|||
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: true)
|
||||
}
|
||||
|
||||
private var cachedTopIds: [PeerId: [MessageId.Namespace: MessageId?]] = [:]
|
||||
private var cachedTopIds: [PeerAndThreadId: [MessageId.Namespace: MessageId?]] = [:]
|
||||
private var updatedPeerIds = Set<PeerChatTopTaggedUpdateRecord>()
|
||||
|
||||
private let sharedKey = ValueBoxKey(length: 8 + 4)
|
||||
private let sharedKeyNoThreadId = ValueBoxKey(length: 8 + 4)
|
||||
private let sharedKeyWithThreadId = ValueBoxKey(length: 8 + 4 + 8)
|
||||
|
||||
private func key(peerId: PeerId, namespace: MessageId.Namespace) -> ValueBoxKey {
|
||||
self.sharedKey.setInt64(0, value: peerId.toInt64())
|
||||
self.sharedKey.setInt32(8, value: namespace)
|
||||
return self.sharedKey
|
||||
private func key(combinedId: PeerAndThreadId, namespace: MessageId.Namespace) -> ValueBoxKey {
|
||||
if let threadId = combinedId.threadId {
|
||||
self.sharedKeyWithThreadId.setInt64(0, value: combinedId.peerId.toInt64())
|
||||
self.sharedKeyWithThreadId.setInt32(8, value: namespace)
|
||||
self.sharedKeyWithThreadId.setInt64(8 + 4, value: threadId)
|
||||
|
||||
return self.sharedKeyWithThreadId
|
||||
} else {
|
||||
self.sharedKeyNoThreadId.setInt64(0, value: combinedId.peerId.toInt64())
|
||||
self.sharedKeyNoThreadId.setInt32(8, value: namespace)
|
||||
|
||||
return self.sharedKeyNoThreadId
|
||||
}
|
||||
}
|
||||
|
||||
func get(peerId: PeerId, namespace: MessageId.Namespace) -> MessageId? {
|
||||
if let cachedDict = self.cachedTopIds[peerId] {
|
||||
func get(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace) -> MessageId? {
|
||||
let combinedId = PeerAndThreadId(peerId: peerId, threadId: threadId)
|
||||
|
||||
if let cachedDict = self.cachedTopIds[combinedId] {
|
||||
if let maybeCachedId = cachedDict[namespace] {
|
||||
return maybeCachedId
|
||||
} else {
|
||||
if let value = self.valueBox.get(self.table, key: self.key(peerId: peerId, namespace: namespace)) {
|
||||
if let value = self.valueBox.get(self.table, key: self.key(combinedId: combinedId, namespace: namespace)) {
|
||||
var messageIdId: Int32 = 0
|
||||
value.read(&messageIdId, offset: 0, length: 4)
|
||||
self.cachedTopIds[peerId]![namespace] = MessageId(peerId: peerId, namespace: namespace, id: messageIdId)
|
||||
self.cachedTopIds[combinedId]![namespace] = MessageId(peerId: peerId, namespace: namespace, id: messageIdId)
|
||||
return MessageId(peerId: peerId, namespace: namespace, id: messageIdId)
|
||||
} else {
|
||||
let item: MessageId? = nil
|
||||
self.cachedTopIds[peerId]![namespace] = item
|
||||
self.cachedTopIds[combinedId]![namespace] = item
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let value = self.valueBox.get(self.table, key: self.key(peerId: peerId, namespace: namespace)) {
|
||||
if let value = self.valueBox.get(self.table, key: self.key(combinedId: combinedId, namespace: namespace)) {
|
||||
var messageIdId: Int32 = 0
|
||||
value.read(&messageIdId, offset: 0, length: 4)
|
||||
self.cachedTopIds[peerId] = [namespace: MessageId(peerId: peerId, namespace: namespace, id: messageIdId)]
|
||||
self.cachedTopIds[combinedId] = [namespace: MessageId(peerId: peerId, namespace: namespace, id: messageIdId)]
|
||||
return MessageId(peerId: peerId, namespace: namespace, id: messageIdId)
|
||||
} else {
|
||||
let item: MessageId? = nil
|
||||
self.cachedTopIds[peerId] = [namespace: item]
|
||||
self.cachedTopIds[combinedId] = [namespace: item]
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func set(peerId: PeerId, namespace: MessageId.Namespace, id: MessageId?) {
|
||||
if let _ = self.cachedTopIds[peerId] {
|
||||
self.cachedTopIds[peerId]![namespace] = id
|
||||
private func set(peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace, id: MessageId?) {
|
||||
let combinedId = PeerAndThreadId(peerId: peerId, threadId: threadId)
|
||||
|
||||
if let _ = self.cachedTopIds[combinedId] {
|
||||
self.cachedTopIds[combinedId]![namespace] = id
|
||||
} else {
|
||||
self.cachedTopIds[peerId] = [namespace: id]
|
||||
self.cachedTopIds[combinedId] = [namespace: id]
|
||||
}
|
||||
self.updatedPeerIds.insert(PeerChatTopTaggedUpdateRecord(peerId: peerId, namespace: namespace))
|
||||
self.updatedPeerIds.insert(PeerChatTopTaggedUpdateRecord(peerAndThreadId: combinedId, namespace: namespace))
|
||||
}
|
||||
|
||||
func replay(historyOperationsByPeerId: [PeerId : [MessageHistoryOperation]]) {
|
||||
func replay(historyOperationsByPeerId: [PeerId: [MessageHistoryOperation]]) {
|
||||
for (_, operations) in historyOperationsByPeerId {
|
||||
for operation in operations {
|
||||
switch operation {
|
||||
case let .InsertMessage(message):
|
||||
if message.flags.contains(.TopIndexable) {
|
||||
let currentTopMessageId = self.get(peerId: message.id.peerId, namespace: message.id.namespace)
|
||||
let currentTopMessageId = self.get(peerId: message.id.peerId, threadId: message.threadId, namespace: message.id.namespace)
|
||||
if currentTopMessageId == nil || currentTopMessageId! < message.id {
|
||||
self.set(peerId: message.id.peerId, namespace: message.id.namespace, id: message.id)
|
||||
self.set(peerId: message.id.peerId, threadId: message.threadId, namespace: message.id.namespace, id: message.id)
|
||||
}
|
||||
}
|
||||
case let .Remove(indices):
|
||||
for (index, _) in indices {
|
||||
if let messageId = self.get(peerId: index.id.peerId, namespace: index.id.namespace), index.id == messageId {
|
||||
self.set(peerId: index.id.peerId, namespace: index.id.namespace, id: nil)
|
||||
for (index, _, threadId) in indices {
|
||||
if let messageId = self.get(peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace), index.id == messageId {
|
||||
self.set(peerId: index.id.peerId, threadId: threadId, namespace: index.id.namespace, id: nil)
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
|
@ -92,12 +106,12 @@ final class PeerChatTopTaggedMessageIdsTable: Table {
|
|||
override func beforeCommit() {
|
||||
if !self.updatedPeerIds.isEmpty {
|
||||
for record in self.updatedPeerIds {
|
||||
if let cachedDict = self.cachedTopIds[record.peerId], let maybeMessageId = cachedDict[record.namespace] {
|
||||
if let cachedDict = self.cachedTopIds[record.peerAndThreadId], let maybeMessageId = cachedDict[record.namespace] {
|
||||
if let maybeMessageId = maybeMessageId {
|
||||
var messageIdId: Int32 = maybeMessageId.id
|
||||
self.valueBox.set(self.table, key: self.key(peerId: record.peerId, namespace: record.namespace), value: MemoryBuffer(memory: &messageIdId, capacity: 4, length: 4, freeWhenDone: false))
|
||||
self.valueBox.set(self.table, key: self.key(combinedId: record.peerAndThreadId, namespace: record.namespace), value: MemoryBuffer(memory: &messageIdId, capacity: 4, length: 4, freeWhenDone: false))
|
||||
} else {
|
||||
self.valueBox.remove(self.table, key: self.key(peerId: record.peerId, namespace: record.namespace), secure: false)
|
||||
self.valueBox.remove(self.table, key: self.key(combinedId: record.peerAndThreadId, namespace: record.namespace), secure: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ final class MutablePeerView: MutablePostboxView {
|
|||
break outer
|
||||
}
|
||||
case let .Remove(indicesWithTags):
|
||||
for (index, _) in indicesWithTags {
|
||||
for (index, _, _) in indicesWithTags {
|
||||
if cachedData.messageIds.contains(index.id) {
|
||||
updateMessages = true
|
||||
break outer
|
||||
|
|
|
|||
|
|
@ -3494,20 +3494,20 @@ final class PostboxImpl {
|
|||
useRootInterfaceStateForThread: Bool
|
||||
) -> Disposable {
|
||||
var topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?] = [:]
|
||||
var mainPeerIdForTopTaggedMessages: PeerId?
|
||||
switch peerIds {
|
||||
var mainPeerIdForTopTaggedMessages: (peerId: PeerId, threadId: Int64?)?
|
||||
if tag == nil {
|
||||
switch peerIds {
|
||||
case let .single(id, threadId):
|
||||
if threadId == nil {
|
||||
mainPeerIdForTopTaggedMessages = id
|
||||
}
|
||||
mainPeerIdForTopTaggedMessages = (id, threadId)
|
||||
case let .associated(id, _):
|
||||
mainPeerIdForTopTaggedMessages = id
|
||||
mainPeerIdForTopTaggedMessages = (id, nil)
|
||||
case .external:
|
||||
mainPeerIdForTopTaggedMessages = nil
|
||||
}
|
||||
}
|
||||
if let peerId = mainPeerIdForTopTaggedMessages {
|
||||
for namespace in topTaggedMessageIdNamespaces {
|
||||
if let messageId = self.peerChatTopTaggedMessageIdsTable.get(peerId: peerId, namespace: namespace) {
|
||||
if let messageId = self.peerChatTopTaggedMessageIdsTable.get(peerId: peerId.peerId, threadId: peerId.threadId, namespace: namespace) {
|
||||
if let index = self.messageHistoryIndexTable.getIndex(messageId) {
|
||||
if let message = self.messageHistoryTable.getMessage(index) {
|
||||
topTaggedMessages[namespace] = MessageHistoryTopTaggedMessage.intermediate(message)
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ final class TabBarControllerNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
return params.layout.size.height - tabBarFrame.minY - 6.0
|
||||
return params.layout.size.height - tabBarFrame.minY
|
||||
}
|
||||
|
||||
func frameForControllerTab(at index: Int) -> CGRect? {
|
||||
|
|
|
|||
|
|
@ -2173,7 +2173,7 @@ public final class AccountViewTracker {
|
|||
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))
|
||||
])]),
|
||||
topTaggedMessageIdNamespaces: [],
|
||||
topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud],
|
||||
tag: tag,
|
||||
appendMessagesFromTheSameGroup: false,
|
||||
namespaces: .not(Namespaces.Message.allNonRegular),
|
||||
|
|
@ -2201,7 +2201,7 @@ public final class AccountViewTracker {
|
|||
count: count,
|
||||
trackHoles: trackHoles,
|
||||
fixedCombinedReadStates: nil,
|
||||
topTaggedMessageIdNamespaces: [],
|
||||
topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud],
|
||||
tag: tag,
|
||||
appendMessagesFromTheSameGroup: false,
|
||||
namespaces: .not(Namespaces.Message.allNonRegular),
|
||||
|
|
|
|||
|
|
@ -479,6 +479,26 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
|
|||
|> `catch` { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
} else if let threadId = operation.threadId {
|
||||
guard let inputPeer = apiInputPeer(peer) else {
|
||||
return .complete()
|
||||
}
|
||||
return network.request(Api.functions.messages.deleteTopicHistory(peer: inputPeer, topMsgId: Int32(clamping: threadId)))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.AffectedHistory?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
if let result = result {
|
||||
switch result {
|
||||
case let .affectedHistory(pts, ptsCount, _):
|
||||
stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)])
|
||||
return .complete()
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return requestClearHistory(postbox: postbox, network: network, stateManager: stateManager, inputPeer: inputPeer, maxId: operation.topMessageId.id, justClear: true, minTimestamp: operation.minTimestamp, maxTimestamp: operation.maxTimestamp, type: operation.type)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme
|
|||
panelBackgroundColor: mainBackgroundColor?.withAlphaComponent(0.9),
|
||||
panelSeparatorColor: mainSeparatorColor,
|
||||
panelControlAccentColor: accentColor,
|
||||
panelControlColor: mainSecondaryTextColor?.withAlphaComponent(0.5),
|
||||
panelControlColor: UIColor(rgb: 0xffffff),
|
||||
inputBackgroundColor: inputBackgroundColor,
|
||||
inputStrokeColor: accentColor?.withMultiplied(hue: 1.038, saturation: 0.463, brightness: 0.26),
|
||||
inputPlaceholderColor: mainSecondaryTextColor?.withAlphaComponent(0.4),
|
||||
|
|
@ -874,7 +874,7 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres
|
|||
panelBackgroundColorNoWallpaper: accentColor.withMultiplied(hue: 1.024, saturation: 0.573, brightness: 0.18),
|
||||
panelSeparatorColor: mainSeparatorColor,
|
||||
panelControlAccentColor: accentColor,
|
||||
panelControlColor: mainSecondaryTextColor.withAlphaComponent(0.5),
|
||||
panelControlColor: UIColor(rgb: 0xffffff),
|
||||
panelControlDisabledColor: UIColor(rgb: 0x90979F, alpha: 0.5),
|
||||
panelControlDestructiveColor: UIColor(rgb: 0xff6767),
|
||||
inputBackgroundColor: inputBackgroundColor,
|
||||
|
|
|
|||
|
|
@ -59,45 +59,50 @@ public enum ChatHistoryEntry: Identifiable, Comparable {
|
|||
|
||||
public var stableId: UInt64 {
|
||||
switch self {
|
||||
case let .MessageEntry(message, _, _, _, _, attributes):
|
||||
let type: UInt64
|
||||
switch attributes.contentTypeHint {
|
||||
case .generic:
|
||||
type = 2
|
||||
case .largeEmoji:
|
||||
type = 3
|
||||
case .animatedEmoji:
|
||||
type = 4
|
||||
}
|
||||
return UInt64(message.stableId) | ((type << 40))
|
||||
case let .MessageGroupEntry(groupInfo, _, _):
|
||||
return UInt64(bitPattern: groupInfo) | ((UInt64(2) << 40))
|
||||
case .UnreadEntry:
|
||||
return UInt64(4) << 40
|
||||
case .ReplyCountEntry:
|
||||
return UInt64(5) << 40
|
||||
case .ChatInfoEntry:
|
||||
case let .MessageEntry(message, _, _, _, _, attributes):
|
||||
let type: UInt64
|
||||
switch attributes.contentTypeHint {
|
||||
case .generic:
|
||||
type = 2
|
||||
case .largeEmoji:
|
||||
type = 3
|
||||
case .animatedEmoji:
|
||||
type = 4
|
||||
}
|
||||
return UInt64(message.stableId) | ((type << 40))
|
||||
case let .MessageGroupEntry(groupInfo, _, _):
|
||||
return UInt64(bitPattern: groupInfo) | ((UInt64(2) << 40))
|
||||
case .UnreadEntry:
|
||||
return UInt64(4) << 40
|
||||
case .ReplyCountEntry:
|
||||
return UInt64(5) << 40
|
||||
case let .ChatInfoEntry(infoData, _):
|
||||
switch infoData {
|
||||
case .newThreadInfo:
|
||||
return UInt64(7) << 40
|
||||
default:
|
||||
return UInt64(6) << 40
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var index: MessageIndex {
|
||||
switch self {
|
||||
case let .MessageEntry(message, _, _, _, _, _):
|
||||
return message.index
|
||||
case let .MessageGroupEntry(_, messages, _):
|
||||
return messages[messages.count - 1].0.index
|
||||
case let .UnreadEntry(index, _):
|
||||
return index
|
||||
case let .ReplyCountEntry(index, _, _, _):
|
||||
return index
|
||||
case let .ChatInfoEntry(infoData, _):
|
||||
switch infoData {
|
||||
case .newThreadInfo:
|
||||
return MessageIndex.absoluteUpperBound()
|
||||
default:
|
||||
return MessageIndex.absoluteLowerBound()
|
||||
}
|
||||
case let .MessageEntry(message, _, _, _, _, _):
|
||||
return message.index
|
||||
case let .MessageGroupEntry(_, messages, _):
|
||||
return messages[messages.count - 1].0.index
|
||||
case let .UnreadEntry(index, _):
|
||||
return index
|
||||
case let .ReplyCountEntry(index, _, _, _):
|
||||
return index
|
||||
case let .ChatInfoEntry(infoData, _):
|
||||
switch infoData {
|
||||
case .newThreadInfo:
|
||||
return MessageIndex.absoluteUpperBound()
|
||||
default:
|
||||
return MessageIndex.absoluteLowerBound()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ public final class ChatTitleComponent: Component {
|
|||
private let contentContainer: UIView
|
||||
private let title = ComponentView<Empty>()
|
||||
private var subtitleNode: ChatTitleActivityNode?
|
||||
private var activityMeasureSubtitleNode: ChatTitleActivityNode?
|
||||
private var leftIcon: ComponentView<Empty>?
|
||||
private var rightIcon: ComponentView<Empty>?
|
||||
private var credibilityIcon: ComponentView<Empty>?
|
||||
|
|
@ -1003,9 +1004,25 @@ public final class ChatTitleComponent: Component {
|
|||
let _ = subtitleNode.transitionToState(state, animation: transition.animation.isImmediate ? .none : .slide)
|
||||
let subtitleSize = subtitleNode.updateLayout(CGSize(width: availableSize.width - containerSideInset * 2.0, height: 100.0), alignment: .center)
|
||||
|
||||
var minSubtitleWidth: CGFloat?
|
||||
let activityMeasureSubtitleNode: ChatTitleActivityNode
|
||||
if let current = self.activityMeasureSubtitleNode {
|
||||
activityMeasureSubtitleNode = current
|
||||
} else {
|
||||
activityMeasureSubtitleNode = ChatTitleActivityNode()
|
||||
self.activityMeasureSubtitleNode = activityMeasureSubtitleNode
|
||||
}
|
||||
let measureTypingTextString = NSAttributedString(string: component.strings.Conversation_typing, font: subtitleFont, textColor: .black)
|
||||
let _ = activityMeasureSubtitleNode.transitionToState(.typingText(measureTypingTextString, .black), animation: .none)
|
||||
let activityMeasureSubtitleSize = activityMeasureSubtitleNode.updateLayout(CGSize(width: availableSize.width - containerSideInset * 2.0, height: 100.0), alignment: .center)
|
||||
minSubtitleWidth = activityMeasureSubtitleSize.width
|
||||
|
||||
var contentSize = titleSize
|
||||
contentSize.width += titleLeftIconsWidth + titleRightIconsWidth
|
||||
contentSize.width = max(contentSize.width, subtitleSize.width)
|
||||
if let minSubtitleWidth {
|
||||
contentSize.width = max(contentSize.width, minSubtitleWidth)
|
||||
}
|
||||
contentSize.height += subtitleSize.height
|
||||
|
||||
let containerSize = CGSize(width: contentSize.width + containerSideInset * 2.0, height: 44.0)
|
||||
|
|
|
|||
|
|
@ -807,7 +807,7 @@ public extension GlassBackgroundView {
|
|||
}
|
||||
}
|
||||
|
||||
addShadow(context, true, CGPoint(), 30.0, 0.0, UIColor(white: 0.0, alpha: 0.075), .normal)
|
||||
addShadow(context, true, CGPoint(), 30.0, 0.0, UIColor(white: 0.0, alpha: 0.045), .normal)
|
||||
addShadow(context, true, CGPoint(), 20.0, 0.0, UIColor(white: 0.0, alpha: 0.01), .normal)
|
||||
|
||||
var a: CGFloat = 0.0
|
||||
|
|
|
|||
|
|
@ -239,13 +239,17 @@ public final class HeaderPanelContainerComponent: Component {
|
|||
self.panelViews.removeValue(forKey: key)
|
||||
}
|
||||
|
||||
transition.setFrame(view: self.backgroundContainer, frame: CGRect(origin: CGPoint(), size: size))
|
||||
self.backgroundContainer.update(size: size, isDark: component.theme.overallDarkAppearance, transition: transition)
|
||||
let backgroundSize = CGSize(width: size.width, height: max(40.0, size.height))
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: sideInset, y: 0.0), size: CGSize(width: size.width - sideInset * 2.0, height: size.height))
|
||||
transition.setFrame(view: self.backgroundContainer, frame: CGRect(origin: CGPoint(), size: backgroundSize))
|
||||
self.backgroundContainer.update(size: backgroundSize, isDark: component.theme.overallDarkAppearance, transition: transition)
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: sideInset, y: 0.0), size: CGSize(width: size.width - sideInset * 2.0, height: backgroundSize.height))
|
||||
transition.setFrame(view: self.backgroundView, frame: backgroundFrame)
|
||||
self.backgroundView.update(size: backgroundFrame.size, cornerRadius: 20.0, isDark: component.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: UIColor(white: component.theme.overallDarkAppearance ? 0.0 : 1.0, alpha: 0.6)), isInteractive: true, transition: transition)
|
||||
|
||||
transition.setAlpha(view: self.backgroundContainer, alpha: (component.tabs != nil || !component.panels.isEmpty) ? 1.0 : 0.0)
|
||||
|
||||
transition.setFrame(view: self.contentContainer, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||
self.contentContainer.layer.cornerRadius = 20.0
|
||||
|
||||
|
|
|
|||
|
|
@ -182,8 +182,6 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScro
|
|||
self.addSubnode(self.chatController.displayNode)
|
||||
self.chatController.displayNode.clipsToBounds = true
|
||||
|
||||
self.view.addSubview(self.coveringView)
|
||||
|
||||
self.chatController.stateUpdated = { [weak self] transition in
|
||||
guard let self else {
|
||||
return
|
||||
|
|
@ -276,9 +274,9 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScro
|
|||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, navigationHeight: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
|
||||
let fullHeight = navigationHeight + size.height
|
||||
let fullHeight = size.height - topInset
|
||||
|
||||
let chatFrame = CGRect(origin: CGPoint(x: 0.0, y: -navigationHeight), size: CGSize(width: size.width, height: fullHeight))
|
||||
let chatFrame = CGRect(origin: CGPoint(x: 0.0, y: topInset), size: CGSize(width: size.width, height: fullHeight))
|
||||
|
||||
if !self.chatController.displayNode.bounds.isEmpty {
|
||||
if let contextController = self.chatController.visibleContextController as? ContextController {
|
||||
|
|
@ -293,7 +291,7 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScro
|
|||
let combinedBottomInset = bottomInset
|
||||
transition.updateFrame(node: self.chatController.displayNode, frame: chatFrame)
|
||||
self.chatController.updateIsScrollingLockedAtTop(isScrollingLockedAtTop: isScrollingLockedAtTop)
|
||||
self.chatController.containerLayoutUpdated(ContainerViewLayout(size: chatFrame.size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact, orientation: nil), deviceMetrics: deviceMetrics, intrinsicInsets: UIEdgeInsets(top: topInset + navigationHeight, left: sideInset, bottom: combinedBottomInset, right: sideInset), safeInsets: UIEdgeInsets(top: navigationHeight + topInset + 4.0, left: sideInset, bottom: combinedBottomInset, right: sideInset), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||
self.chatController.containerLayoutUpdated(ContainerViewLayout(size: chatFrame.size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact, orientation: nil), deviceMetrics: deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: combinedBottomInset, right: sideInset), safeInsets: UIEdgeInsets(top: 0.0 + 4.0, left: sideInset, bottom: combinedBottomInset, right: sideInset), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
|
|
|
|||
|
|
@ -823,7 +823,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||
var scrollOffset: CGFloat = max(0.0, size.height - params.visibleHeight)
|
||||
|
||||
let effectiveBottomInset = max(buttonInsets.bottom, bottomInset)
|
||||
var bottomPanelHeight = effectiveBottomInset + panelButtonSize.height + 8.0
|
||||
let bottomPanelHeight = effectiveBottomInset + panelButtonSize.height + 8.0
|
||||
if params.visibleHeight < 110.0 {
|
||||
scrollOffset -= bottomPanelHeight
|
||||
}
|
||||
|
|
@ -838,8 +838,6 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||
panelTransition.setFrame(view: panelContentContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height - bottomPanelHeight), size: CGSize(width: size.width, height: bottomPanelHeight)))
|
||||
|
||||
if self.canManage {
|
||||
bottomPanelHeight -= 9.0
|
||||
|
||||
let panelCheck: ComponentView<Empty>
|
||||
if let current = self.panelCheck {
|
||||
panelCheck = current
|
||||
|
|
@ -904,7 +902,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||
if panelCheckView.superview == nil {
|
||||
panelContentContainer.addSubview(panelCheckView)
|
||||
}
|
||||
panelCheckView.frame = CGRect(origin: CGPoint(x: floor((size.width - panelCheckSize.width) / 2.0), y: 16.0), size: panelCheckSize)
|
||||
panelCheckView.frame = CGRect(origin: CGPoint(x: floor((size.width - panelCheckSize.width) / 2.0), y: 16.0 + 16.0), size: panelCheckSize)
|
||||
}
|
||||
if let panelButtonView = panelButton.view {
|
||||
panelButtonView.isHidden = true
|
||||
|
|
|
|||
|
|
@ -4749,12 +4749,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
} else {
|
||||
backgroundColor = presentationData.theme.list.blocksBackgroundColor
|
||||
}
|
||||
let _ = backgroundColor
|
||||
|
||||
if self.didUpdateItemsOnce {
|
||||
/*if self.didUpdateItemsOnce {
|
||||
ComponentTransition(animation: .curve(duration: 0.2, curve: .easeInOut)).setBackgroundColor(view: self.view, color: backgroundColor)
|
||||
} else {
|
||||
self.view.backgroundColor = backgroundColor
|
||||
}
|
||||
}*/
|
||||
} else if case let .peer(_, _, isArchived) = self.scope, self.canManageStories, !isArchived, self.isProfileEmbedded, let items = self.items, items.items.isEmpty, items.count == 0 {
|
||||
let emptyStateView: ComponentView<Empty>
|
||||
var emptyStateTransition = ComponentTransition(transition)
|
||||
|
|
@ -4852,7 +4853,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
}
|
||||
}
|
||||
|
||||
if self.isProfileEmbedded, case .botPreview = self.scope {
|
||||
/*if self.isProfileEmbedded, case .botPreview = self.scope {
|
||||
subTransition.setBackgroundColor(view: self.view, color: presentationData.theme.list.blocksBackgroundColor)
|
||||
} else if self.isProfileEmbedded, case let .peer(_, _, isArchived) = self.scope, ((self.canManageStories && !isArchived) || !self.currentStoryFolders.isEmpty), self.isProfileEmbedded {
|
||||
subTransition.setBackgroundColor(view: self.view, color: presentationData.theme.list.blocksBackgroundColor)
|
||||
|
|
@ -4860,7 +4861,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr
|
|||
subTransition.setBackgroundColor(view: self.view, color: presentationData.theme.list.blocksBackgroundColor)
|
||||
} else {
|
||||
subTransition.setBackgroundColor(view: self.view, color: presentationData.theme.list.blocksBackgroundColor)
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
/*if self.isProfileEmbedded, case .botPreview = self.scope {
|
||||
self.view.backgroundColor = presentationData.theme.list.blocksBackgroundColor
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ public final class PasskeysScreen: ViewControllerComponentContainer {
|
|||
public init(context: AccountContext, displaySkip: Bool, initialPasskeysData: [TelegramPasskey]?, passkeysDataUpdated: @escaping ([TelegramPasskey]) -> Void, completion: @escaping () -> Void, cancel: @escaping () -> Void) {
|
||||
self.context = context
|
||||
|
||||
super.init(context: context, component: PasskeysScreenComponent(context: context, displaySkip: displaySkip, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: passkeysDataUpdated, completion: completion, cancel: cancel), navigationBarAppearance: .default)
|
||||
super.init(context: context, component: PasskeysScreenComponent(context: context, displaySkip: displaySkip, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: passkeysDataUpdated, completion: completion, cancel: cancel), navigationBarAppearance: .transparent)
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
|
|
|
|||
|
|
@ -357,7 +357,9 @@ extension ChatControllerImpl {
|
|||
})))
|
||||
}
|
||||
|
||||
items.append(.separator)
|
||||
if !items.isEmpty {
|
||||
items.append(.separator)
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: strings.Conversation_Search, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Search"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak self] action in
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ func chatHistoryEntriesForView(
|
|||
currentState: ChatHistoryEntriesForViewState,
|
||||
context: AccountContext,
|
||||
location: ChatLocation,
|
||||
subject: ChatControllerSubject?,
|
||||
view: MessageHistoryView,
|
||||
includeUnreadEntry: Bool,
|
||||
includeEmptyEntry: Bool,
|
||||
|
|
@ -331,7 +332,10 @@ func chatHistoryEntriesForView(
|
|||
}
|
||||
}
|
||||
var attributes = attributes
|
||||
attributes.displayContinueThreadFooter = true
|
||||
if let subject, case .pinnedMessages = subject {
|
||||
} else {
|
||||
attributes.displayContinueThreadFooter = true
|
||||
}
|
||||
entries[i] = .MessageEntry(message, presentationData, isRead, location, selection, attributes)
|
||||
break outer
|
||||
default:
|
||||
|
|
@ -507,7 +511,12 @@ func chatHistoryEntriesForView(
|
|||
entries.insert(.ChatInfoEntry(.botInfo(title: "", text: presentationData.strings.VerificationCodes_DescriptionText, photo: nil, video: nil), presentationData), at: 0)
|
||||
} else if let cachedPeerData = cachedPeerData as? CachedUserData {
|
||||
if let botInfo = cachedPeerData.botInfo, !botInfo.description.isEmpty {
|
||||
entries.insert(.ChatInfoEntry(.botInfo(title: presentationData.strings.Bot_DescriptionTitle, text: botInfo.description, photo: botInfo.photo, video: botInfo.video), presentationData), at: 0)
|
||||
if location.threadId == nil {
|
||||
if let subject, case .pinnedMessages = subject {
|
||||
} else {
|
||||
entries.insert(.ChatInfoEntry(.botInfo(title: presentationData.strings.Bot_DescriptionTitle, text: botInfo.description, photo: botInfo.photo, video: botInfo.video), presentationData), at: 0)
|
||||
}
|
||||
}
|
||||
} else if let peerStatusSettings = cachedPeerData.peerStatusSettings, peerStatusSettings.registrationDate != nil || peerStatusSettings.phoneCountry != nil {
|
||||
if peerStatusSettings.flags.contains(.canAddContact) || peerStatusSettings.flags.contains(.canReport) || peerStatusSettings.flags.contains(.canBlock) {
|
||||
|
||||
|
|
@ -681,7 +690,10 @@ func chatHistoryEntriesForView(
|
|||
}
|
||||
}
|
||||
if addBotForumHeader {
|
||||
entries.append(.ChatInfoEntry(.newThreadInfo, presentationData))
|
||||
if let subject, case .pinnedMessages = subject {
|
||||
} else {
|
||||
entries.append(.ChatInfoEntry(.newThreadInfo, presentationData))
|
||||
}
|
||||
}
|
||||
if includeEmbeddedSavedChatInfo, let peerId = location.peerId {
|
||||
if !view.isLoading && view.laterId == nil {
|
||||
|
|
|
|||
|
|
@ -2090,6 +2090,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
currentState: previousChatHistoryEntriesForViewState,
|
||||
context: context,
|
||||
location: chatLocation,
|
||||
subject: subject,
|
||||
view: view,
|
||||
includeUnreadEntry: mode == .bubbles,
|
||||
includeEmptyEntry: mode == .bubbles && tag == nil,
|
||||
|
|
@ -2323,6 +2324,9 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
}
|
||||
|
||||
var keyboardButtonsMessage = view.topTaggedMessages.first
|
||||
if keyboardButtonsMessage != nil && keyboardButtonsMessage?.threadId != chatLocation.threadId {
|
||||
keyboardButtonsMessage = nil
|
||||
}
|
||||
if let keyboardButtonsMessageValue = keyboardButtonsMessage, keyboardButtonsMessageValue.isRestricted(platform: "ios", contentSettings: context.currentContentSettings.with({ $0 })) {
|
||||
keyboardButtonsMessage = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,21 +20,21 @@ enum ChatHistoryNavigationButtonType {
|
|||
|
||||
class ChatHistoryNavigationButtonNode: ContextControllerSourceNode {
|
||||
let containerNode: ContextExtractedContentContainingNode
|
||||
let buttonNode: HighlightTrackingButtonNode
|
||||
private let backgroundView: GlassBackgroundView
|
||||
let imageView: GlassBackgroundView.ContentImageView
|
||||
private let badgeBackgroundView: GlassBackgroundView
|
||||
private let badgeTextNode: ImmediateAnimatedCountLabelNode
|
||||
private var tapRecognizer: UITapGestureRecognizer?
|
||||
|
||||
var tapped: (() -> Void)? {
|
||||
didSet {
|
||||
if (oldValue != nil) != (self.tapped != nil) {
|
||||
if self.tapped != nil {
|
||||
self.buttonNode.addTarget(self, action: #selector(self.onTap), forControlEvents: .touchUpInside)
|
||||
} else {
|
||||
self.buttonNode.removeTarget(self, action: #selector(self.onTap), forControlEvents: .touchUpInside)
|
||||
}
|
||||
}
|
||||
self.tapRecognizer?.isEnabled = self.tapped != nil && self.isEnabled
|
||||
}
|
||||
}
|
||||
|
||||
var isEnabled: Bool = true {
|
||||
didSet {
|
||||
self.tapRecognizer?.isEnabled = self.tapped != nil && self.isEnabled
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +54,6 @@ class ChatHistoryNavigationButtonNode: ContextControllerSourceNode {
|
|||
self.type = type
|
||||
|
||||
self.containerNode = ContextExtractedContentContainingNode()
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
|
||||
self.backgroundView = GlassBackgroundView()
|
||||
|
||||
|
|
@ -80,7 +79,10 @@ class ChatHistoryNavigationButtonNode: ContextControllerSourceNode {
|
|||
|
||||
super.init()
|
||||
|
||||
self.targetNodeForActivationProgress = self.buttonNode
|
||||
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.onTapGesture(_:)))
|
||||
self.tapRecognizer = tapRecognizer
|
||||
self.backgroundView.contentView.addGestureRecognizer(tapRecognizer)
|
||||
tapRecognizer.isEnabled = false
|
||||
|
||||
self.addSubnode(self.containerNode)
|
||||
|
||||
|
|
@ -89,18 +91,16 @@ class ChatHistoryNavigationButtonNode: ContextControllerSourceNode {
|
|||
self.containerNode.contentNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.containerNode.contentRect = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
self.buttonNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.containerNode.contentNode.addSubnode(self.buttonNode)
|
||||
self.containerNode.contentNode.view.addSubview(self.backgroundView)
|
||||
|
||||
self.buttonNode.view.addSubview(self.backgroundView)
|
||||
self.backgroundView.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.backgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: .immediate)
|
||||
self.backgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), isInteractive: true, transition: .immediate)
|
||||
self.imageView.tintColor = theme.chat.inputPanel.panelControlColor
|
||||
|
||||
self.backgroundView.contentView.addSubview(self.imageView)
|
||||
self.imageView.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
self.buttonNode.view.addSubview(self.badgeBackgroundView)
|
||||
self.containerNode.contentNode.view.addSubview(self.badgeBackgroundView)
|
||||
self.badgeBackgroundView.contentView.addSubview(self.badgeTextNode.view)
|
||||
|
||||
self.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
|
@ -143,9 +143,11 @@ class ChatHistoryNavigationButtonNode: ContextControllerSourceNode {
|
|||
self.absoluteRect = (rect, containerSize)
|
||||
}
|
||||
|
||||
@objc func onTap() {
|
||||
if let tapped = self.tapped {
|
||||
tapped()
|
||||
@objc private func onTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
if let tapped = self.tapped {
|
||||
tapped()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ final class ChatHistoryNavigationButtons: ASDisplayNode {
|
|||
|
||||
if let down = self.directionButtonState.down {
|
||||
self.downButton.imageView.alpha = down.isEnabled ? 1.0 : 0.5
|
||||
self.downButton.buttonNode.isEnabled = down.isEnabled
|
||||
self.downButton.isEnabled = down.isEnabled
|
||||
|
||||
mentionsOffset += buttonSize.height + 12.0
|
||||
upOffset += buttonSize.height + 12.0
|
||||
|
|
@ -203,7 +203,7 @@ final class ChatHistoryNavigationButtons: ASDisplayNode {
|
|||
|
||||
if let up = self.directionButtonState.up {
|
||||
self.upButton.imageView.alpha = up.isEnabled ? 1.0 : 0.5
|
||||
self.upButton.buttonNode.isEnabled = up.isEnabled
|
||||
self.upButton.isEnabled = up.isEnabled
|
||||
|
||||
mentionsOffset += buttonSize.height + 12.0
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ swift_library(
|
|||
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
|
||||
"//submodules/Components/HierarchyTrackingLayer:HierarchyTrackingLayer",
|
||||
"//submodules/TelegramUI/Components/EdgeEffect",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
|
|
|||
|
|
@ -1044,7 +1044,7 @@ public final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgrou
|
|||
public private(set) var isDark: Bool?
|
||||
public var isDarkUpdated: (() -> Void)?
|
||||
|
||||
private func updateIsDark(_ isDark: Bool) {
|
||||
private func updateIsDark(_ isDark: Bool?) {
|
||||
if self.isDark != isDark {
|
||||
self.isDark = isDark
|
||||
self.isDarkUpdated?()
|
||||
|
|
@ -1205,8 +1205,7 @@ public final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgrou
|
|||
self.wallpaperDisposable.set(nil)
|
||||
|
||||
if case let .file(file) = wallpaper, file.isPattern {
|
||||
let intensity = CGFloat(file.settings.intensity ?? 50) / 100.0
|
||||
self.updateIsDark(intensity < 0)
|
||||
self.updateIsDark(nil)
|
||||
} else {
|
||||
self.updateIsDark(calculateWallpaperBrightness(from: gradientColors) <= 0.3)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import Display
|
|||
import GradientBackground
|
||||
import EdgeEffect
|
||||
import SwiftSignalKit
|
||||
import ComponentFlow
|
||||
import ComponentDisplayAdapters
|
||||
|
||||
final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEffectNode {
|
||||
private struct Params: Equatable {
|
||||
|
|
@ -116,6 +118,7 @@ final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEffectNode
|
|||
return
|
||||
}
|
||||
self.contentNode.contents = parentNode.contentNode.contents
|
||||
self.contentNode.backgroundColor = parentNode.contentNode.backgroundColor
|
||||
self.contentNode.alpha = parentNode.contentNode.alpha
|
||||
self.contentNode.isHidden = parentNode.contentNode.isHidden
|
||||
}
|
||||
|
|
@ -160,8 +163,8 @@ final class WallpaperEdgeEffectNodeImpl: ASDisplayNode, WallpaperEdgeEffectNode
|
|||
}
|
||||
|
||||
let maskFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: rect.size)
|
||||
transition.updatePosition(layer: self.maskView.layer, position: maskFrame.center)
|
||||
transition.updateBounds(layer: self.maskView.layer, bounds: CGRect(origin: CGPoint(), size: maskFrame.size))
|
||||
ComponentTransition(transition).setPosition(view: self.maskView, position: maskFrame.center)
|
||||
ComponentTransition(transition).setBounds(view: self.maskView, bounds: CGRect(origin: CGPoint(), size: maskFrame.size))
|
||||
if case .top = edge.edge {
|
||||
self.maskView.transform = CGAffineTransformMakeScale(1.0, -1.0)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"app": "12.3.1",
|
||||
"xcode": "26.0",
|
||||
"xcode": "26.2",
|
||||
"bazel": "8.4.2:45e9388abf21d1107e146ea366ad080eb93cb6a5f3a4a3b048f78de0bc3faffa",
|
||||
"macos": "26"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue