mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
7d5815f329
56 changed files with 3526 additions and 3497 deletions
|
|
@ -188,7 +188,6 @@
|
|||
09FDAEE62140477F00BF856F /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09FDAEE52140477F00BF856F /* MtProtoKitDynamic.framework */; };
|
||||
D000CACF21FB6E380011B15D /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D000CAC821FB6E370011B15D /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
D001D5AA1F878DA300DF975A /* PhoneCountries.txt in Resources */ = {isa = PBXBuildFile; fileRef = D001D5A91F878DA300DF975A /* PhoneCountries.txt */; };
|
||||
D008184E22B5796E008A895F /* BuildConfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D008184D22B5796E008A895F /* BuildConfig.framework */; };
|
||||
D008185022B5797A008A895F /* BuildConfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D008184F22B5797A008A895F /* BuildConfig.framework */; };
|
||||
D008185222B57986008A895F /* BuildConfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D008185122B57986008A895F /* BuildConfig.framework */; };
|
||||
D008185422B57994008A895F /* BuildConfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D008185322B57994008A895F /* BuildConfig.framework */; };
|
||||
|
|
@ -205,7 +204,6 @@
|
|||
D015E04D225D2D8F00CB9E8A /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D015E04C225D2D8F00CB9E8A /* WebP.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
D015E050225D303F00CB9E8A /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D015E04C225D2D8F00CB9E8A /* WebP.framework */; };
|
||||
D015E051225D303F00CB9E8A /* WebP.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D015E04C225D2D8F00CB9E8A /* WebP.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
D01A47551F4DBED700383CC1 /* HockeySDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D01A47541F4DBED700383CC1 /* HockeySDK.framework */; };
|
||||
D021D4D9219CAEDD0064BEBA /* Config-Fork.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = D021D4D8219CAEDD0064BEBA /* Config-Fork.xcconfig */; };
|
||||
D02CF5FD215D9ABF00E0F56A /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0AA1A671D568BA400152314 /* UserNotifications.framework */; };
|
||||
D02CF5FE215D9ABF00E0F56A /* UserNotificationsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0AA1A691D568BA400152314 /* UserNotificationsUI.framework */; };
|
||||
|
|
@ -1099,11 +1097,9 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D008184E22B5796E008A895F /* BuildConfig.framework in Frameworks */,
|
||||
D0CAD6A421C03BEB001E3055 /* FFMpeg.framework in Frameworks */,
|
||||
09C50E88217385CF009E676F /* WatchConnectivity.framework in Frameworks */,
|
||||
09FDAEE62140477F00BF856F /* MtProtoKitDynamic.framework in Frameworks */,
|
||||
D01A47551F4DBED700383CC1 /* HockeySDK.framework in Frameworks */,
|
||||
D0A18D631E149043004C6734 /* PushKit.framework in Frameworks */,
|
||||
D0B844601DACF561005F29E1 /* libc++.tbd in Frameworks */,
|
||||
D06706621D5118F500DED3E3 /* TelegramCore.framework in Frameworks */,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
|
|
@ -36,8 +38,8 @@
|
|||
ReferencedContainer = "container:Telegram-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "DebugAppStoreLLC"
|
||||
|
|
@ -59,9 +61,11 @@
|
|||
ReferencedContainer = "container:Telegram-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "ReleaseAppStoreLLC"
|
||||
buildConfiguration = "DebugAppStoreLLC"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
|
|
|
|||
|
|
@ -41,15 +41,6 @@
|
|||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D008599B1B28189D00EAF753"
|
||||
BuildableName = "Telegram.app"
|
||||
BlueprintName = "Telegram-iOS"
|
||||
ReferencedContainer = "container:Telegram-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
|
|
@ -72,6 +63,17 @@
|
|||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D008599B1B28189D00EAF753"
|
||||
BuildableName = "Telegram.app"
|
||||
BlueprintName = "Telegram-iOS"
|
||||
ReferencedContainer = "container:Telegram-iOS.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "DebugHockeyapp"
|
||||
|
|
@ -102,6 +104,8 @@
|
|||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "DebugHockeyapp"
|
||||
|
|
|
|||
|
|
@ -1614,7 +1614,10 @@
|
|||
"ShareMenu.Send" = "Send";
|
||||
|
||||
"Conversation.ReportSpam" = "Report Spam";
|
||||
"Conversation.ReportSpamAndLeave" = "Report Spam and Leave";
|
||||
"Conversation.ReportSpamConfirmation" = "Are you sure you want to report spam from this user?";
|
||||
"Conversation.ReportSpamGroupConfirmation" = "Are you sure you want to report spam from this group?";
|
||||
"Conversation.ReportSpamChannelConfirmation" = "Are you sure you want to report spam from this channel?";
|
||||
"SharedMedia.EmptyMusicText" = "All music shared in this chat will appear here.";
|
||||
|
||||
"ChatSettings.AutoPlayAnimations" = "Autoplay GIFs";
|
||||
|
|
@ -4348,6 +4351,7 @@ Any member of this group will be able to see messages in the channel.";
|
|||
"Appearance.ThemeCarouselNight" = "Monochrome";
|
||||
|
||||
"Notification.Exceptions.DeleteAll" = "Delete All";
|
||||
"Notification.Exceptions.DeleteAllConfirmation" = "Are you sure you want to delete all exceptions?";
|
||||
"Notification.Exceptions.Add" = "Add";
|
||||
"Exceptions.AddToExceptions" = "ADD TO EXCEPTIONS";
|
||||
|
||||
|
|
@ -4358,6 +4362,7 @@ Any member of this group will be able to see messages in the channel.";
|
|||
"Conversation.Block" = "Block";
|
||||
"Conversation.BlockUser" = "Block User";
|
||||
"Conversation.ShareMyPhoneNumber" = "Share My Phone Number";
|
||||
"Conversation.ShareMyPhoneNumberConfirmation" = "Are you sure you want to share your phone number %1$@ with %2$@?";
|
||||
"Conversation.AddToContacts" = "Add to Contacts";
|
||||
"Conversation.AddNameToContacts" = "Add %@ to Contacts";
|
||||
|
||||
|
|
|
|||
|
|
@ -759,7 +759,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||
return additionalInverseTopInset
|
||||
}
|
||||
|
||||
private func snapToBounds(snapTopItem: Bool, stackFromBottom: Bool, updateSizeAndInsets: ListViewUpdateSizeAndInsets? = nil, scrollToItem: ListViewScrollToItem? = nil) -> (snappedTopInset: CGFloat, offset: CGFloat) {
|
||||
private func snapToBounds(snapTopItem: Bool, stackFromBottom: Bool, updateSizeAndInsets: ListViewUpdateSizeAndInsets? = nil, scrollToItem: ListViewScrollToItem? = nil, isExperimentalSnapToScrollToItem: Bool = false) -> (snappedTopInset: CGFloat, offset: CGFloat) {
|
||||
if self.itemNodes.count == 0 {
|
||||
return (0.0, 0.0)
|
||||
}
|
||||
|
|
@ -819,7 +819,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||
|
||||
var transition: ContainedViewLayoutTransition = .immediate
|
||||
if let updateSizeAndInsets = updateSizeAndInsets {
|
||||
if !updateSizeAndInsets.duration.isZero {
|
||||
if !updateSizeAndInsets.duration.isZero && !isExperimentalSnapToScrollToItem {
|
||||
switch updateSizeAndInsets.curve {
|
||||
case let .Spring(duration):
|
||||
transition = .animated(duration: duration, curve: .spring)
|
||||
|
|
@ -828,15 +828,17 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||
}
|
||||
}
|
||||
} else if let scrollToItem = scrollToItem {
|
||||
switch scrollToItem.curve {
|
||||
case let .Spring(duration):
|
||||
transition = .animated(duration: duration, curve: .spring)
|
||||
case let .Default(duration):
|
||||
if let duration = duration, duration.isZero {
|
||||
transition = .immediate
|
||||
} else {
|
||||
transition = .animated(duration: duration ?? 0.3, curve: .easeInOut)
|
||||
}
|
||||
if scrollToItem.animated {
|
||||
switch scrollToItem.curve {
|
||||
case let .Spring(duration):
|
||||
transition = .animated(duration: duration, curve: .spring)
|
||||
case let .Default(duration):
|
||||
if let duration = duration, duration.isZero {
|
||||
transition = .immediate
|
||||
} else {
|
||||
transition = .animated(duration: duration ?? 0.3, curve: .easeInOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2484,7 +2486,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||
itemNode.position = CGPoint(x: position.x, y: position.y + offsetFix)
|
||||
}
|
||||
|
||||
let (snappedTopInset, snapToBoundsOffset) = self.snapToBounds(snapTopItem: scrollToItem != nil, stackFromBottom: self.stackFromBottom, updateSizeAndInsets: updateSizeAndInsets)
|
||||
let (snappedTopInset, snapToBoundsOffset) = self.snapToBounds(snapTopItem: scrollToItem != nil, stackFromBottom: self.stackFromBottom, updateSizeAndInsets: updateSizeAndInsets, isExperimentalSnapToScrollToItem: isExperimentalSnapToScrollToItem)
|
||||
|
||||
if !snappedTopInset.isZero && (previousVisibleSize.height.isZero || previousApparentFrames.isEmpty) {
|
||||
offsetFix += snappedTopInset
|
||||
|
|
@ -2504,7 +2506,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||
sizeAndInsetsOffset = offsetFix
|
||||
completeOffset += snapToBoundsOffset
|
||||
|
||||
if !updateSizeAndInsets.duration.isZero {
|
||||
if !updateSizeAndInsets.duration.isZero && !isExperimentalSnapToScrollToItem {
|
||||
let animation: CABasicAnimation
|
||||
switch updateSizeAndInsets.curve {
|
||||
case let .Spring(duration):
|
||||
|
|
|
|||
|
|
@ -54,6 +54,5 @@ final class CachedPeerDataTable: Table {
|
|||
}
|
||||
|
||||
self.updatedPeerIds.removeAll()
|
||||
self.cachedDatas.removeAll()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ public struct MessageId: Hashable, Comparable, CustomStringConvertible {
|
|||
|
||||
public var description: String {
|
||||
get {
|
||||
return "\(namespace):\(id)"
|
||||
return "\(namespace)_\(id)"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -478,36 +478,6 @@ final class MutableMessageHistoryView {
|
|||
self.sampledState = self.state.sample(postbox: postbox)
|
||||
}
|
||||
|
||||
/*for operationSet in operations {
|
||||
for operation in operationSet {
|
||||
switch operation {
|
||||
case let .InsertMessage(intermediateMessage):
|
||||
for i in 0 ..< self.entries.count {
|
||||
switch self.entries[i] {
|
||||
case let .MessageEntry(value):
|
||||
let message = value.message
|
||||
if message.associatedMessageIds.count != message.associatedMessages.count {
|
||||
if message.associatedMessageIds.contains(intermediateMessage.id) && message.associatedMessages[intermediateMessage.id] == nil {
|
||||
var updatedAssociatedMessages = message.associatedMessages
|
||||
let renderedMessage = renderIntermediateMessage(intermediateMessage)
|
||||
updatedAssociatedMessages[intermediateMessage.id] = renderedMessage
|
||||
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: updatedAssociatedMessages, associatedMessageIds: message.associatedMessageIds)
|
||||
self.entries[i] = .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes))
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
for operationSet in operations {
|
||||
for operation in operationSet {
|
||||
switch operation {
|
||||
|
|
@ -786,150 +756,6 @@ public final class MessageHistoryView {
|
|||
self.isLoading = isLoading
|
||||
}
|
||||
|
||||
|
||||
/*var entries: [MessageHistoryEntry] = []
|
||||
if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates {
|
||||
for entry in mutableView.entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(value):
|
||||
let read: Bool
|
||||
if value.message.flags.contains(.Incoming) {
|
||||
read = false
|
||||
} else if let readState = states[value.message.id.peerId] {
|
||||
read = readState.isOutgoingMessageIndexRead(value.message.index)
|
||||
} else {
|
||||
read = false
|
||||
}
|
||||
entries.append(MessageHistoryEntry(message: value.message, isRead: read, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes))
|
||||
case .IntermediateMessageEntry:
|
||||
assertionFailure("unexpected IntermediateMessageEntry in MessageHistoryView.init()")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for entry in mutableView.entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(value):
|
||||
entries.append(MessageHistoryEntry(message: value.message, isRead: false, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes))
|
||||
case .IntermediateMessageEntry:
|
||||
assertionFailure("unexpected IntermediateMessageEntry in MessageHistoryView.init()")
|
||||
}
|
||||
}
|
||||
}
|
||||
var holeEarlier = false
|
||||
var holeLater = false
|
||||
if mutableView.clipHoles {
|
||||
if entries.isEmpty {
|
||||
if !mutableView.holes.isEmpty {
|
||||
holeEarlier = true
|
||||
holeLater = true
|
||||
}
|
||||
} else {
|
||||
var clearAllEntries = false
|
||||
if case let .message(index) = self.anchorIndex {
|
||||
for (holeKey, indices) in mutableView.holes {
|
||||
if holeKey.peerId == index.id.peerId && holeKey.namespace == index.id.namespace && indices.contains(Int(index.id.id)) {
|
||||
entries.removeAll()
|
||||
earlierId = nil
|
||||
holeEarlier = true
|
||||
laterId = nil
|
||||
holeLater = true
|
||||
clearAllEntries = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !clearAllEntries {
|
||||
var referenceIndex = entries.count - 1
|
||||
for i in 0 ..< entries.count {
|
||||
if self.anchorIndex.isLessOrEqual(to: entries[i].index) {
|
||||
referenceIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
var groupStart: (Int, MessageGroupInfo)?
|
||||
for i in referenceIndex ..< entries.count {
|
||||
let id = entries[i].message.id
|
||||
if let holeIndices = mutableView.holes[PeerIdAndNamespace(peerId: id.peerId, namespace: id.namespace)] {
|
||||
if holeIndices.contains(Int(id.id)) {
|
||||
if let groupStart = groupStart {
|
||||
entries.removeSubrange(groupStart.0 ..< entries.count)
|
||||
} else {
|
||||
entries.removeSubrange(i ..< entries.count)
|
||||
}
|
||||
laterId = nil
|
||||
holeLater = true
|
||||
break
|
||||
}
|
||||
}
|
||||
/*if let groupStart = groupStart {
|
||||
entries.removeSubrange(groupStart.0 ..< entries.count)
|
||||
laterId = nil
|
||||
} else {
|
||||
if i != entries.count - 1 {
|
||||
entries.removeSubrange(i + 1 ..< entries.count)
|
||||
laterId = nil
|
||||
}
|
||||
}*/
|
||||
if let groupInfo = entries[i].message.groupInfo {
|
||||
if let groupStart = groupStart, groupStart.1 == groupInfo {
|
||||
} else {
|
||||
groupStart = (i, groupInfo)
|
||||
}
|
||||
} else {
|
||||
groupStart = nil
|
||||
}
|
||||
}
|
||||
if let groupStart = groupStart, laterId != nil {
|
||||
entries.removeSubrange(groupStart.0 ..< entries.count)
|
||||
}
|
||||
|
||||
groupStart = nil
|
||||
if !entries.isEmpty {
|
||||
for i in (0 ... min(referenceIndex, entries.count - 1)).reversed() {
|
||||
let id = entries[i].message.id
|
||||
if let holeIndices = mutableView.holes[PeerIdAndNamespace(peerId: id.peerId, namespace: id.namespace)] {
|
||||
if holeIndices.contains(Int(id.id)) {
|
||||
if let groupStart = groupStart {
|
||||
entries.removeSubrange(0 ..< groupStart.0 + 1)
|
||||
} else {
|
||||
entries.removeSubrange(0 ... i)
|
||||
}
|
||||
earlierId = nil
|
||||
holeEarlier = true
|
||||
break
|
||||
}
|
||||
}
|
||||
/*if let groupStart = groupStart {
|
||||
entries.removeSubrange(0 ..< groupStart.0 + 1)
|
||||
earlierId = nil
|
||||
} else {
|
||||
if i != 0 {
|
||||
entries.removeSubrange(0 ..< i)
|
||||
earlierId = nil
|
||||
}
|
||||
}
|
||||
break
|
||||
*/
|
||||
if let groupInfo = entries[i].message.groupInfo {
|
||||
if let groupStart = groupStart, groupStart.1 == groupInfo {
|
||||
} else {
|
||||
groupStart = (i, groupInfo)
|
||||
}
|
||||
} else {
|
||||
groupStart = nil
|
||||
}
|
||||
}
|
||||
if let groupStart = groupStart, earlierId != nil {
|
||||
entries.removeSubrange(0 ..< groupStart.0 + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.holeEarlier = holeEarlier
|
||||
self.holeLater = holeLater
|
||||
self.entries = entries*/
|
||||
|
||||
var topTaggedMessages: [Message] = []
|
||||
for (_, message) in mutableView.topTaggedMessages {
|
||||
if let message = message {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@ struct PeerIdAndNamespace: Hashable {
|
|||
let namespace: MessageId.Namespace
|
||||
}
|
||||
|
||||
private func canContainHoles(_ peerIdAndNamespace: PeerIdAndNamespace, seedConfiguration: SeedConfiguration) -> Bool {
|
||||
guard let messageNamespaces = seedConfiguration.messageHoles[peerIdAndNamespace.peerId.namespace] else {
|
||||
return false
|
||||
}
|
||||
return messageNamespaces[peerIdAndNamespace.namespace] != nil
|
||||
}
|
||||
|
||||
private struct MessageMonthIndex: Equatable {
|
||||
let year: Int32
|
||||
let month: Int32
|
||||
|
|
@ -279,7 +286,7 @@ private func isIndex(index: MessageIndex, closerTo anchor: HistoryViewAnchor, th
|
|||
}
|
||||
}
|
||||
|
||||
private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries], holes: HistoryViewHoles, anchor: HistoryViewAnchor, tag: MessageTags?, halfLimit: Int) -> (clipRanges: [ClosedRange<MessageIndex>], sampledHole: SampledHistoryViewHole?) {
|
||||
private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries], holes: HistoryViewHoles, anchor: HistoryViewAnchor, tag: MessageTags?, halfLimit: Int, seedConfiguration: SeedConfiguration) -> (clipRanges: [ClosedRange<MessageIndex>], sampledHole: SampledHistoryViewHole?) {
|
||||
var clipRanges: [ClosedRange<MessageIndex>] = []
|
||||
var sampledHole: (distanceFromAnchor: Int?, hole: SampledHistoryViewHole)?
|
||||
|
||||
|
|
@ -287,6 +294,7 @@ private func sampleHoleRanges(orderedEntriesBySpace: [PeerIdAndNamespace: Ordere
|
|||
if indices.isEmpty {
|
||||
continue
|
||||
}
|
||||
assert(canContainHoles(space, seedConfiguration: seedConfiguration))
|
||||
switch anchor {
|
||||
case .lowerBound, .upperBound:
|
||||
break
|
||||
|
|
@ -628,11 +636,11 @@ struct OrderedHistoryViewEntries {
|
|||
var lowerOrAtAnchor: [MutableMessageHistoryEntry]
|
||||
var higherThanAnchor: [MutableMessageHistoryEntry]
|
||||
|
||||
mutating func fixMonotonity() {
|
||||
mutating func fixMonotony() {
|
||||
if self.lowerOrAtAnchor.count > 1 {
|
||||
for i in 1 ..< self.lowerOrAtAnchor.count {
|
||||
if self.lowerOrAtAnchor[i].index < self.lowerOrAtAnchor[i - 1].index {
|
||||
//assertionFailure()
|
||||
assertionFailure()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -640,7 +648,7 @@ struct OrderedHistoryViewEntries {
|
|||
if self.higherThanAnchor.count > 1 {
|
||||
for i in 1 ..< self.higherThanAnchor.count {
|
||||
if self.higherThanAnchor[i].index < self.higherThanAnchor[i - 1].index {
|
||||
// assertionFailure()
|
||||
assertionFailure()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -664,7 +672,7 @@ struct OrderedHistoryViewEntries {
|
|||
}
|
||||
}
|
||||
if fix {
|
||||
//assertionFailure()
|
||||
assertionFailure()
|
||||
self.lowerOrAtAnchor.sort(by: { $0.index.id.id < $1.index.id.id })
|
||||
self.higherThanAnchor.sort(by: { $0.index.id.id < $1.index.id.id })
|
||||
}
|
||||
|
|
@ -742,6 +750,7 @@ final class HistoryViewLoadedState {
|
|||
let tag: MessageTags?
|
||||
let statistics: MessageHistoryViewOrderStatistics
|
||||
let halfLimit: Int
|
||||
let seedConfiguration: SeedConfiguration
|
||||
var orderedEntriesBySpace: [PeerIdAndNamespace: OrderedHistoryViewEntries]
|
||||
var holes: HistoryViewHoles
|
||||
var spacesWithRemovals = Set<PeerIdAndNamespace>()
|
||||
|
|
@ -752,6 +761,7 @@ final class HistoryViewLoadedState {
|
|||
self.tag = tag
|
||||
self.statistics = statistics
|
||||
self.halfLimit = halfLimit
|
||||
self.seedConfiguration = postbox.seedConfiguration
|
||||
self.orderedEntriesBySpace = [:]
|
||||
self.holes = holes
|
||||
|
||||
|
|
@ -805,7 +815,7 @@ final class HistoryViewLoadedState {
|
|||
|
||||
if lowerOrAtAnchorMessages.count < self.halfLimit {
|
||||
let nextLowerIndex: (index: MessageIndex, includeFrom: Bool)
|
||||
if let lastMessage = lowerOrAtAnchorMessages.last {
|
||||
if let lastMessage = lowerOrAtAnchorMessages.min(by: { $0.index < $1.index }) {
|
||||
nextLowerIndex = (lastMessage.index, false)
|
||||
} else {
|
||||
nextLowerIndex = (anchorIndex, true)
|
||||
|
|
@ -814,7 +824,7 @@ final class HistoryViewLoadedState {
|
|||
}
|
||||
if higherThanAnchorMessages.count < self.halfLimit {
|
||||
let nextHigherIndex: MessageIndex
|
||||
if let lastMessage = higherThanAnchorMessages.last {
|
||||
if let lastMessage = higherThanAnchorMessages.max(by: { $0.index < $1.index }) {
|
||||
nextHigherIndex = lastMessage.index
|
||||
} else {
|
||||
nextHigherIndex = anchorIndex
|
||||
|
|
@ -872,15 +882,19 @@ final class HistoryViewLoadedState {
|
|||
}
|
||||
}
|
||||
|
||||
entries.fixMonotonity()
|
||||
if canContainHoles(space, seedConfiguration: self.seedConfiguration) {
|
||||
entries.fixMonotony()
|
||||
}
|
||||
self.orderedEntriesBySpace[space] = entries
|
||||
}
|
||||
|
||||
func insertHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> Bool {
|
||||
assert(canContainHoles(space, seedConfiguration: self.seedConfiguration))
|
||||
return self.holes.insertHole(space: space, range: range)
|
||||
}
|
||||
|
||||
func removeHole(space: PeerIdAndNamespace, range: ClosedRange<MessageId.Id>) -> Bool {
|
||||
assert(canContainHoles(space, seedConfiguration: self.seedConfiguration))
|
||||
return self.holes.removeHole(space: space, range: range)
|
||||
}
|
||||
|
||||
|
|
@ -1097,7 +1111,7 @@ final class HistoryViewLoadedState {
|
|||
self.spacesWithRemovals.removeAll()
|
||||
}
|
||||
let combinedSpacesAndIndicesByDirection = sampleEntries(orderedEntriesBySpace: self.orderedEntriesBySpace, anchor: self.anchor, halfLimit: self.halfLimit)
|
||||
let (clipRanges, sampledHole) = sampleHoleRanges(orderedEntriesBySpace: self.orderedEntriesBySpace, holes: self.holes, anchor: self.anchor, tag: self.tag, halfLimit: self.halfLimit)
|
||||
let (clipRanges, sampledHole) = sampleHoleRanges(orderedEntriesBySpace: self.orderedEntriesBySpace, holes: self.holes, anchor: self.anchor, tag: self.tag, halfLimit: self.halfLimit, seedConfiguration: self.seedConfiguration)
|
||||
|
||||
var holesToLower = false
|
||||
var holesToHigher = false
|
||||
|
|
@ -1164,20 +1178,22 @@ private func fetchHoles(postbox: Postbox, locations: MessageHistoryViewPeerIds,
|
|||
var holesBySpace: [PeerIdAndNamespace: IndexSet] = [:]
|
||||
var peerIds: [PeerId] = []
|
||||
switch locations {
|
||||
case let .single(peerId):
|
||||
peerIds.append(peerId)
|
||||
case let .associated(peerId, associatedId):
|
||||
peerIds.append(peerId)
|
||||
if let associatedId = associatedId {
|
||||
peerIds.append(associatedId.peerId)
|
||||
}
|
||||
case let .single(peerId):
|
||||
peerIds.append(peerId)
|
||||
case let .associated(peerId, associatedId):
|
||||
peerIds.append(peerId)
|
||||
if let associatedId = associatedId {
|
||||
peerIds.append(associatedId.peerId)
|
||||
}
|
||||
}
|
||||
let holeSpace = tag.flatMap(MessageHistoryHoleSpace.tag) ?? .everywhere
|
||||
for peerId in peerIds {
|
||||
for namespace in postbox.messageHistoryHoleIndexTable.existingNamespaces(peerId: peerId, holeSpace: holeSpace) {
|
||||
let indices = postbox.messageHistoryHoleIndexTable.closest(peerId: peerId, namespace: namespace, space: holeSpace, range: 1 ... (Int32.max - 1))
|
||||
if !indices.isEmpty {
|
||||
holesBySpace[PeerIdAndNamespace(peerId: peerId, namespace: namespace)] = indices
|
||||
let peerIdAndNamespace = PeerIdAndNamespace(peerId: peerId, namespace: namespace)
|
||||
assert(canContainHoles(peerIdAndNamespace, seedConfiguration: postbox.seedConfiguration))
|
||||
holesBySpace[peerIdAndNamespace] = indices
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1560,6 +1560,9 @@ public final class Postbox {
|
|||
|
||||
fileprivate func clearHistory(_ peerId: PeerId) {
|
||||
self.messageHistoryTable.clearHistory(peerId: peerId, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations, globalTagsOperations: &self.currentGlobalTagsOperations, pendingActionsOperations: &self.currentPendingMessageActionsOperations, updatedMessageActionsSummaries: &self.currentUpdatedMessageActionsSummaries, updatedMessageTagSummaries: &self.currentUpdatedMessageTagSummaries, invalidateMessageTagSummaries: &self.currentInvalidateMessageTagSummaries, localTagsOperations: &self.currentLocalTagsOperations)
|
||||
for namespace in self.messageHistoryHoleIndexTable.existingNamespaces(peerId: peerId, holeSpace: .everywhere) {
|
||||
self.messageHistoryHoleIndexTable.remove(peerId: peerId, namespace: namespace, space: .everywhere, range: 1 ... Int32.max - 1, operations: &self.currentPeerHoleOperations)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func removeAllMessagesWithAuthor(_ peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) {
|
||||
|
|
|
|||
|
|
@ -2424,6 +2424,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
|||
updatePeers(transaction: transaction, peers: peers, update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
updateContacts(transaction: transaction, apiUsers: users)
|
||||
case let .UpdatePeer(id, f):
|
||||
if let peer = f(transaction.getPeer(id)) {
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
|
|
|
|||
|
|
@ -32,87 +32,95 @@ func imageRepresentationsForApiChatPhoto(_ photo: Api.ChatPhoto) -> [TelegramMed
|
|||
|
||||
func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
|
||||
switch chat {
|
||||
case let .chat(flags, id, title, photo, participantsCount, date, version, migratedTo, adminRights, defaultBannedRights):
|
||||
let left = (flags & ((1 << 1) | (1 << 2))) != 0
|
||||
var migrationReference: TelegramGroupToChannelMigrationReference?
|
||||
if let migratedTo = migratedTo {
|
||||
switch migratedTo {
|
||||
case let .inputChannel(channelId, accessHash):
|
||||
migrationReference = TelegramGroupToChannelMigrationReference(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), accessHash: accessHash)
|
||||
case .inputChannelEmpty:
|
||||
break
|
||||
}
|
||||
case let .chat(flags, id, title, photo, participantsCount, date, version, migratedTo, adminRights, defaultBannedRights):
|
||||
let left = (flags & ((1 << 1) | (1 << 2))) != 0
|
||||
var migrationReference: TelegramGroupToChannelMigrationReference?
|
||||
if let migratedTo = migratedTo {
|
||||
switch migratedTo {
|
||||
case let .inputChannel(channelId, accessHash):
|
||||
migrationReference = TelegramGroupToChannelMigrationReference(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), accessHash: accessHash)
|
||||
case .inputChannelEmpty:
|
||||
break
|
||||
}
|
||||
var groupFlags = TelegramGroupFlags()
|
||||
var role: TelegramGroupRole = .member
|
||||
if (flags & (1 << 0)) != 0 {
|
||||
role = .creator
|
||||
} else if let adminRights = adminRights {
|
||||
role = .admin(TelegramChatAdminRights(apiAdminRights: adminRights))
|
||||
}
|
||||
var groupFlags = TelegramGroupFlags()
|
||||
var role: TelegramGroupRole = .member
|
||||
if (flags & (1 << 0)) != 0 {
|
||||
role = .creator
|
||||
} else if let adminRights = adminRights {
|
||||
role = .admin(TelegramChatAdminRights(apiAdminRights: adminRights))
|
||||
}
|
||||
if (flags & (1 << 5)) != 0 {
|
||||
groupFlags.insert(.deactivated)
|
||||
}
|
||||
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: imageRepresentationsForApiChatPhoto(photo), participantCount: Int(participantsCount), role: role, membership: left ? .Left : .Member, flags: groupFlags, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init(apiBannedRights:)), migrationReference: migrationReference, creationDate: date, version: Int(version))
|
||||
case let .chatEmpty(id):
|
||||
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
|
||||
case let .chatForbidden(id, title):
|
||||
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
|
||||
case let .channel(flags, id, accessHash, title, username, photo, date, version, restrictionReason, adminRights, bannedRights, defaultBannedRights, _):
|
||||
let isMin = (flags & (1 << 20)) != 0
|
||||
|
||||
let participationStatus: TelegramChannelParticipationStatus
|
||||
if (flags & Int32(1 << 1)) != 0 {
|
||||
participationStatus = .kicked
|
||||
} else if (flags & Int32(1 << 2)) != 0 {
|
||||
participationStatus = .left
|
||||
} else {
|
||||
participationStatus = .member
|
||||
}
|
||||
|
||||
let info: TelegramChannelInfo
|
||||
if (flags & Int32(1 << 8)) != 0 {
|
||||
let infoFlags = TelegramChannelGroupFlags()
|
||||
info = .group(TelegramChannelGroupInfo(flags: infoFlags))
|
||||
} else {
|
||||
var infoFlags = TelegramChannelBroadcastFlags()
|
||||
if (flags & Int32(1 << 11)) != 0 {
|
||||
infoFlags.insert(.messagesShouldHaveSignatures)
|
||||
}
|
||||
if (flags & (1 << 5)) != 0 {
|
||||
groupFlags.insert(.deactivated)
|
||||
if (flags & Int32(1 << 20)) != 0 {
|
||||
infoFlags.insert(.hasDiscussionGroup)
|
||||
}
|
||||
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: imageRepresentationsForApiChatPhoto(photo), participantCount: Int(participantsCount), role: role, membership: left ? .Left : .Member, flags: groupFlags, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init(apiBannedRights:)), migrationReference: migrationReference, creationDate: date, version: Int(version))
|
||||
case let .chatEmpty(id):
|
||||
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
|
||||
case let .chatForbidden(id, title):
|
||||
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: id), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
|
||||
case let .channel(flags, id, accessHash, title, username, photo, date, version, restrictionReason, adminRights, bannedRights, defaultBannedRights, _):
|
||||
let isMin = (flags & (1 << 20)) != 0
|
||||
|
||||
let participationStatus: TelegramChannelParticipationStatus
|
||||
if (flags & Int32(1 << 1)) != 0 {
|
||||
participationStatus = .kicked
|
||||
} else if (flags & Int32(1 << 2)) != 0 {
|
||||
participationStatus = .left
|
||||
info = .broadcast(TelegramChannelBroadcastInfo(flags: infoFlags))
|
||||
}
|
||||
|
||||
var channelFlags = TelegramChannelFlags()
|
||||
if (flags & Int32(1 << 0)) != 0 {
|
||||
channelFlags.insert(.isCreator)
|
||||
}
|
||||
if (flags & Int32(1 << 7)) != 0 {
|
||||
channelFlags.insert(.isVerified)
|
||||
}
|
||||
if (flags & Int32(1 << 19)) != 0 {
|
||||
channelFlags.insert(.isScam)
|
||||
}
|
||||
|
||||
let restrictionInfo: PeerAccessRestrictionInfo?
|
||||
if let restrictionReason = restrictionReason {
|
||||
restrictionInfo = PeerAccessRestrictionInfo(reason: restrictionReason)
|
||||
} else {
|
||||
restrictionInfo = nil
|
||||
}
|
||||
|
||||
let accessHashValue = accessHash.flatMap { value -> TelegramPeerAccessHash in
|
||||
if isMin {
|
||||
return .genericPublic(value)
|
||||
} else {
|
||||
participationStatus = .member
|
||||
return .personal(value)
|
||||
}
|
||||
|
||||
let info: TelegramChannelInfo
|
||||
if (flags & Int32(1 << 8)) != 0 {
|
||||
let infoFlags = TelegramChannelGroupFlags()
|
||||
info = .group(TelegramChannelGroupInfo(flags: infoFlags))
|
||||
} else {
|
||||
var infoFlags = TelegramChannelBroadcastFlags()
|
||||
if (flags & Int32(1 << 11)) != 0 {
|
||||
infoFlags.insert(.messagesShouldHaveSignatures)
|
||||
}
|
||||
if (flags & Int32(1 << 20)) != 0 {
|
||||
infoFlags.insert(.hasDiscussionGroup)
|
||||
}
|
||||
info = .broadcast(TelegramChannelBroadcastInfo(flags: infoFlags))
|
||||
}
|
||||
|
||||
var channelFlags = TelegramChannelFlags()
|
||||
if (flags & Int32(1 << 0)) != 0 {
|
||||
channelFlags.insert(.isCreator)
|
||||
}
|
||||
if (flags & Int32(1 << 7)) != 0 {
|
||||
channelFlags.insert(.isVerified)
|
||||
}
|
||||
if (flags & Int32(1 << 19)) != 0 {
|
||||
channelFlags.insert(.isScam)
|
||||
}
|
||||
|
||||
let restrictionInfo: PeerAccessRestrictionInfo?
|
||||
if let restrictionReason = restrictionReason {
|
||||
restrictionInfo = PeerAccessRestrictionInfo(reason: restrictionReason)
|
||||
} else {
|
||||
restrictionInfo = nil
|
||||
}
|
||||
|
||||
return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: id), accessHash: accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: date, version: version, participationStatus: participationStatus, info: info, flags: channelFlags, restrictionInfo: restrictionInfo, adminRights: adminRights.flatMap(TelegramChatAdminRights.init), bannedRights: bannedRights.flatMap(TelegramChatBannedRights.init), defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init))
|
||||
case let .channelForbidden(flags, id, accessHash, title, untilDate):
|
||||
let info: TelegramChannelInfo
|
||||
if (flags & Int32(1 << 8)) != 0 {
|
||||
info = .group(TelegramChannelGroupInfo(flags: []))
|
||||
} else {
|
||||
info = .broadcast(TelegramChannelBroadcastInfo(flags: []))
|
||||
}
|
||||
|
||||
return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: id), accessHash: accessHash, title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil)
|
||||
}
|
||||
|
||||
return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: id), accessHash: accessHashValue, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: date, version: version, participationStatus: participationStatus, info: info, flags: channelFlags, restrictionInfo: restrictionInfo, adminRights: adminRights.flatMap(TelegramChatAdminRights.init), bannedRights: bannedRights.flatMap(TelegramChatBannedRights.init), defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init))
|
||||
case let .channelForbidden(flags, id, accessHash, title, untilDate):
|
||||
let info: TelegramChannelInfo
|
||||
if (flags & Int32(1 << 8)) != 0 {
|
||||
info = .group(TelegramChannelGroupInfo(flags: []))
|
||||
} else {
|
||||
info = .broadcast(TelegramChannelBroadcastInfo(flags: []))
|
||||
}
|
||||
|
||||
return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: id), accessHash: .personal(accessHash), title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +129,8 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
|
|||
case .chat, .chatEmpty, .chatForbidden, .channelForbidden:
|
||||
return parseTelegramGroupOrChannel(chat: rhs)
|
||||
case let .channel(flags, _, accessHash, title, username, photo, _, _, _, _, _, defaultBannedRights, _/*feed*//*, feedId*/):
|
||||
if accessHash != nil && (flags & (1 << 12)) == 0 {
|
||||
let isMin = (flags & (1 << 12)) != 0
|
||||
if accessHash != nil && !isMin {
|
||||
return parseTelegramGroupOrChannel(chat: rhs)
|
||||
} else if let lhs = lhs as? TelegramChannel {
|
||||
var channelFlags = lhs.flags
|
||||
|
|
@ -132,11 +141,11 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
|
|||
}
|
||||
var info = lhs.info
|
||||
switch info {
|
||||
case .broadcast:
|
||||
break
|
||||
case .group:
|
||||
let infoFlags = TelegramChannelGroupFlags()
|
||||
info = .group(TelegramChannelGroupInfo(flags: infoFlags))
|
||||
case .broadcast:
|
||||
break
|
||||
case .group:
|
||||
let infoFlags = TelegramChannelGroupFlags()
|
||||
info = .group(TelegramChannelGroupInfo(flags: infoFlags))
|
||||
}
|
||||
return TelegramChannel(id: lhs.id, accessHash: lhs.accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: lhs.creationDate, version: lhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: lhs.restrictionInfo, adminRights: lhs.adminRights, bannedRights: lhs.bannedRights, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public enum PeerReference: PostboxCoding, Hashable, Equatable {
|
|||
switch peer {
|
||||
case let user as TelegramUser:
|
||||
if let accessHash = user.accessHash {
|
||||
self = .user(id: user.id.id, accessHash: accessHash)
|
||||
self = .user(id: user.id.id, accessHash: accessHash.value)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ public enum PeerReference: PostboxCoding, Hashable, Equatable {
|
|||
self = .group(id: group.id.id)
|
||||
case let channel as TelegramChannel:
|
||||
if let accessHash = channel.accessHash {
|
||||
self = .channel(id: channel.id.id, accessHash: accessHash)
|
||||
self = .channel(id: channel.id.id, accessHash: accessHash.value)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -104,12 +104,12 @@ public enum PeerReference: PostboxCoding, Hashable, Equatable {
|
|||
func forceApiInputPeer(_ peer: Peer) -> Api.InputPeer? {
|
||||
switch peer {
|
||||
case let user as TelegramUser:
|
||||
return Api.InputPeer.inputPeerUser(userId: user.id.id, accessHash: user.accessHash ?? 0)
|
||||
return Api.InputPeer.inputPeerUser(userId: user.id.id, accessHash: user.accessHash?.value ?? 0)
|
||||
case let group as TelegramGroup:
|
||||
return Api.InputPeer.inputPeerChat(chatId: group.id.id)
|
||||
case let channel as TelegramChannel:
|
||||
if let accessHash = channel.accessHash {
|
||||
return Api.InputPeer.inputPeerChannel(channelId: channel.id.id, accessHash: accessHash)
|
||||
return Api.InputPeer.inputPeerChannel(channelId: channel.id.id, accessHash: accessHash.value)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -121,12 +121,12 @@ func forceApiInputPeer(_ peer: Peer) -> Api.InputPeer? {
|
|||
func apiInputPeer(_ peer: Peer) -> Api.InputPeer? {
|
||||
switch peer {
|
||||
case let user as TelegramUser where user.accessHash != nil:
|
||||
return Api.InputPeer.inputPeerUser(userId: user.id.id, accessHash: user.accessHash!)
|
||||
return Api.InputPeer.inputPeerUser(userId: user.id.id, accessHash: user.accessHash!.value)
|
||||
case let group as TelegramGroup:
|
||||
return Api.InputPeer.inputPeerChat(chatId: group.id.id)
|
||||
case let channel as TelegramChannel:
|
||||
if let accessHash = channel.accessHash {
|
||||
return Api.InputPeer.inputPeerChannel(channelId: channel.id.id, accessHash: accessHash)
|
||||
return Api.InputPeer.inputPeerChannel(channelId: channel.id.id, accessHash: accessHash.value)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -137,7 +137,7 @@ func apiInputPeer(_ peer: Peer) -> Api.InputPeer? {
|
|||
|
||||
func apiInputChannel(_ peer: Peer) -> Api.InputChannel? {
|
||||
if let channel = peer as? TelegramChannel, let accessHash = channel.accessHash {
|
||||
return Api.InputChannel.inputChannel(channelId: channel.id.id, accessHash: accessHash)
|
||||
return Api.InputChannel.inputChannel(channelId: channel.id.id, accessHash: accessHash.value)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -145,7 +145,7 @@ func apiInputChannel(_ peer: Peer) -> Api.InputChannel? {
|
|||
|
||||
func apiInputUser(_ peer: Peer) -> Api.InputUser? {
|
||||
if let user = peer as? TelegramUser, let accessHash = user.accessHash {
|
||||
return Api.InputUser.inputUser(userId: user.id.id, accessHash: accessHash)
|
||||
return Api.InputUser.inputUser(userId: user.id.id, accessHash: accessHash.value)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ private final class HistoryPreloadViewContext {
|
|||
|
||||
private enum ChatHistoryPreloadEntity: Hashable {
|
||||
case peer(PeerId)
|
||||
//case group(PeerGroupId)
|
||||
}
|
||||
|
||||
private struct ChatHistoryPreloadIndex {
|
||||
|
|
@ -317,7 +316,9 @@ final class ChatHistoryPreloadManager {
|
|||
return
|
||||
}
|
||||
#if DEBUG
|
||||
//return;
|
||||
if true {
|
||||
//return
|
||||
}
|
||||
#endif
|
||||
var indices: [(ChatHistoryPreloadIndex, Bool, Bool)] = []
|
||||
for entry in view.0.entries {
|
||||
|
|
|
|||
21
submodules/TelegramCore/TelegramCore/DeleteAccount.swift
Normal file
21
submodules/TelegramCore/TelegramCore/DeleteAccount.swift
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import Foundation
|
||||
#if os(macOS)
|
||||
import SwiftSignalKitMac
|
||||
import PostboxMac
|
||||
#else
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
#endif
|
||||
import TelegramApi
|
||||
|
||||
public enum DeleteAccountError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func deleteAccount(account: Account) -> Signal<Never, DeleteAccountError> {
|
||||
return account.network.request(Api.functions.account.deleteAccount(reason: "GDPR"))
|
||||
|> mapError { _ -> DeleteAccountError in
|
||||
return .generic
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
import Foundation
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
import TelegramApi
|
||||
|
||||
public func availableGroupFeedPeers(postbox: Postbox, network: Network, groupId: PeerGroupId) -> Signal<[(Peer, Bool)], NoError> {
|
||||
/*feed*/
|
||||
return .single([])
|
||||
/*return network.request(Api.functions.channels.getFeedSources(flags: 0, feedId: groupId.rawValue, hash: 0))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<[(Peer, Bool)], NoError> in
|
||||
return postbox.transaction { transaction -> [(Peer, Bool)] in
|
||||
switch result {
|
||||
case .feedSourcesNotModified:
|
||||
return []
|
||||
case let .feedSources(_, newlyJoinedFeed, feeds, chats, users):
|
||||
var includedPeerIds = Set<PeerId>()
|
||||
var excludedPeerIds = Set<PeerId>()
|
||||
for feedsInfo in feeds {
|
||||
switch feedsInfo {
|
||||
case let .feedBroadcasts(feedId, channels):
|
||||
if feedId == groupId.rawValue {
|
||||
for id in channels {
|
||||
includedPeerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: id))
|
||||
}
|
||||
}
|
||||
case let .feedBroadcastsUngrouped(channels):
|
||||
for id in channels {
|
||||
excludedPeerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: id))
|
||||
}
|
||||
}
|
||||
}
|
||||
var peers: [(Peer, Bool)] = []
|
||||
for peerId in includedPeerIds {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
peers.append((peer, true))
|
||||
}
|
||||
}
|
||||
for peerId in excludedPeerIds {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
peers.append((peer, false))
|
||||
}
|
||||
}
|
||||
return peers
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: M
|
|||
return account.postbox.transaction { transaction -> Signal<Peer?, NoError> in
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let user = peer as? TelegramUser {
|
||||
if user.accessHash != 0 {
|
||||
if let accessHash = user.accessHash, accessHash.value != 0 {
|
||||
return .single(user)
|
||||
} else {
|
||||
let messageSignal: Signal<Api.messages.Messages?, NoError>?
|
||||
|
|
@ -50,7 +50,7 @@ public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: M
|
|||
|
||||
for user in apiUsers {
|
||||
let telegramUser = TelegramUser(user: user)
|
||||
if telegramUser.id == peerId && telegramUser.accessHash != 0 {
|
||||
if telegramUser.id == peerId, let accessHash = telegramUser.accessHash, accessHash.value != 0 {
|
||||
if let presence = TelegramUserPresence(apiUser: user) {
|
||||
updatePeerPresences(transaction: transaction, accountPeerId: account.peerId, peerPresences: [telegramUser.id: presence])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,12 @@ func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Mes
|
|||
|
||||
if let peer = peers[id.peerId] {
|
||||
messagePeers[peer.id] = peer
|
||||
|
||||
if let group = peer as? TelegramGroup, let migrationReference = group.migrationReference {
|
||||
if let channelPeer = peers[migrationReference.peerId] {
|
||||
messagePeers[channelPeer.id] = channelPeer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for media in message.media {
|
||||
|
|
|
|||
|
|
@ -22,12 +22,15 @@ public final class NotificationExceptionsList: Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
public func notificationExceptionsList(network: Network) -> Signal<NotificationExceptionsList, NoError> {
|
||||
return network.request(Api.functions.account.getNotifyExceptions(flags: 1 << 1, peer: nil)) |> retryRequest |> map { result in
|
||||
switch result {
|
||||
public func notificationExceptionsList(postbox: Postbox, network: Network) -> Signal<NotificationExceptionsList, NoError> {
|
||||
return network.request(Api.functions.account.getNotifyExceptions(flags: 1 << 1, peer: nil))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<NotificationExceptionsList, NoError> in
|
||||
return postbox.transaction { transaction -> NotificationExceptionsList in
|
||||
switch result {
|
||||
case let .updates(updates, users, chats, _, _):
|
||||
var peers:[PeerId: Peer] = [:]
|
||||
var settings:[PeerId : TelegramPeerNotificationSettings] = [:]
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
var settings: [PeerId: TelegramPeerNotificationSettings] = [:]
|
||||
|
||||
for user in users {
|
||||
let peer = TelegramUser(user: user)
|
||||
|
|
@ -39,32 +42,35 @@ public func notificationExceptionsList(network: Network) -> Signal<NotificationE
|
|||
}
|
||||
}
|
||||
|
||||
updatePeers(transaction: transaction, peers: Array(peers.values), update: { _, updated in updated })
|
||||
|
||||
for update in updates {
|
||||
switch update {
|
||||
case let .updateNotifySettings(apiPeer, notifySettings):
|
||||
switch apiPeer {
|
||||
case let .notifyPeer(notifyPeer):
|
||||
let peerId: PeerId
|
||||
switch notifyPeer {
|
||||
case let .peerUser(userId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .peerChat(chatId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
|
||||
case let .peerChannel(channelId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
}
|
||||
settings[peerId] = TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||
default:
|
||||
break
|
||||
case let .updateNotifySettings(apiPeer, notifySettings):
|
||||
switch apiPeer {
|
||||
case let .notifyPeer(notifyPeer):
|
||||
let peerId: PeerId
|
||||
switch notifyPeer {
|
||||
case let .peerUser(userId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
case let .peerChat(chatId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
|
||||
case let .peerChannel(channelId):
|
||||
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
}
|
||||
settings[peerId] = TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||
default:
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return NotificationExceptionsList(peers: peers, settings: settings)
|
||||
default:
|
||||
return NotificationExceptionsList(peers: [:], settings: [:])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,13 @@ import Foundation
|
|||
public enum TelegramPeerAccessHash: Hashable {
|
||||
case personal(Int64)
|
||||
case genericPublic(Int64)
|
||||
|
||||
public var value: Int64 {
|
||||
switch self {
|
||||
case let .personal(personal):
|
||||
return personal
|
||||
case let .genericPublic(genericPublic):
|
||||
return genericPublic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,10 +275,8 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
|
|||
}
|
||||
return combineLatest(peerMessages, additionalPeerMessages)
|
||||
}
|
||||
case let .group(groupId):
|
||||
case .group:
|
||||
remoteSearchResult = .single((nil, nil))
|
||||
/*remoteSearchResult = account.network.request(Api.functions.channels.searchFeed(feedId: groupId.rawValue, q: query, offsetDate: 0, offsetPeer: Api.InputPeer.inputPeerEmpty, offsetId: 0, limit: 64), automaticFloodWait: false)
|
||||
|> mapError { _ in } |> map(Optional.init)*/
|
||||
case .general:
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> (Int32, MessageIndex?, Api.InputPeer) in
|
||||
var lowerBound: MessageIndex?
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ public struct TelegramChannelFlags: OptionSet {
|
|||
|
||||
public final class TelegramChannel: Peer {
|
||||
public let id: PeerId
|
||||
public let accessHash: Int64?
|
||||
public let accessHash: TelegramPeerAccessHash?
|
||||
public let title: String
|
||||
public let username: String?
|
||||
public let photo: [TelegramMediaImageRepresentation]
|
||||
|
|
@ -169,7 +169,7 @@ public final class TelegramChannel: Peer {
|
|||
public let associatedPeerId: PeerId? = nil
|
||||
public let notificationSettingsPeerId: PeerId? = nil
|
||||
|
||||
public init(id: PeerId, accessHash: Int64?, title: String, username: String?, photo: [TelegramMediaImageRepresentation], creationDate: Int32, version: Int32, participationStatus: TelegramChannelParticipationStatus, info: TelegramChannelInfo, flags: TelegramChannelFlags, restrictionInfo: PeerAccessRestrictionInfo?, adminRights: TelegramChatAdminRights?, bannedRights: TelegramChatBannedRights?, defaultBannedRights: TelegramChatBannedRights?) {
|
||||
public init(id: PeerId, accessHash: TelegramPeerAccessHash?, title: String, username: String?, photo: [TelegramMediaImageRepresentation], creationDate: Int32, version: Int32, participationStatus: TelegramChannelParticipationStatus, info: TelegramChannelInfo, flags: TelegramChannelFlags, restrictionInfo: PeerAccessRestrictionInfo?, adminRights: TelegramChatAdminRights?, bannedRights: TelegramChatBannedRights?, defaultBannedRights: TelegramChatBannedRights?) {
|
||||
self.id = id
|
||||
self.accessHash = accessHash
|
||||
self.title = title
|
||||
|
|
@ -188,7 +188,17 @@ public final class TelegramChannel: Peer {
|
|||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
self.accessHash = decoder.decodeOptionalInt64ForKey("ah")
|
||||
let accessHash = decoder.decodeOptionalInt64ForKey("ah")
|
||||
let accessHashType: Int32 = decoder.decodeInt32ForKey("aht", orElse: 0)
|
||||
if let accessHash = accessHash {
|
||||
if accessHashType == 0 {
|
||||
self.accessHash = .personal(accessHash)
|
||||
} else {
|
||||
self.accessHash = .genericPublic(accessHash)
|
||||
}
|
||||
} else {
|
||||
self.accessHash = nil
|
||||
}
|
||||
self.title = decoder.decodeStringForKey("t", orElse: "")
|
||||
self.username = decoder.decodeOptionalStringForKey("un")
|
||||
self.photo = decoder.decodeObjectArrayForKey("ph")
|
||||
|
|
@ -206,7 +216,14 @@ public final class TelegramChannel: Peer {
|
|||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt64(self.id.toInt64(), forKey: "i")
|
||||
if let accessHash = self.accessHash {
|
||||
encoder.encodeInt64(accessHash, forKey: "ah")
|
||||
switch accessHash {
|
||||
case let .personal(value):
|
||||
encoder.encodeInt64(value, forKey: "ah")
|
||||
encoder.encodeInt32(0, forKey: "aht")
|
||||
case let .genericPublic(value):
|
||||
encoder.encodeInt64(value, forKey: "ah")
|
||||
encoder.encodeInt32(1, forKey: "aht")
|
||||
}
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "ah")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,15 +61,11 @@ public struct BotUserInfo: PostboxCoding, Equatable {
|
|||
encoder.encodeNil(forKey: "ip")
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: BotUserInfo, rhs: BotUserInfo) -> Bool {
|
||||
return lhs.flags == rhs.flags && lhs.inlinePlaceholder == rhs.inlinePlaceholder
|
||||
}
|
||||
}
|
||||
|
||||
public final class TelegramUser: Peer {
|
||||
public let id: PeerId
|
||||
public let accessHash: Int64?
|
||||
public let accessHash: TelegramPeerAccessHash?
|
||||
public let firstName: String?
|
||||
public let lastName: String?
|
||||
public let username: String?
|
||||
|
|
@ -100,7 +96,7 @@ public final class TelegramUser: Peer {
|
|||
public let associatedPeerId: PeerId? = nil
|
||||
public let notificationSettingsPeerId: PeerId? = nil
|
||||
|
||||
public init(id: PeerId, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: [TelegramMediaImageRepresentation], botInfo: BotUserInfo?, restrictionInfo: PeerAccessRestrictionInfo?, flags: UserInfoFlags) {
|
||||
public init(id: PeerId, accessHash: TelegramPeerAccessHash?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: [TelegramMediaImageRepresentation], botInfo: BotUserInfo?, restrictionInfo: PeerAccessRestrictionInfo?, flags: UserInfoFlags) {
|
||||
self.id = id
|
||||
self.accessHash = accessHash
|
||||
self.firstName = firstName
|
||||
|
|
@ -117,8 +113,13 @@ public final class TelegramUser: Peer {
|
|||
self.id = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
|
||||
|
||||
let accessHash: Int64 = decoder.decodeInt64ForKey("ah", orElse: 0)
|
||||
let accessHashType: Int32 = decoder.decodeInt32ForKey("aht", orElse: 0)
|
||||
if accessHash != 0 {
|
||||
self.accessHash = accessHash
|
||||
if accessHashType == 0 {
|
||||
self.accessHash = .personal(accessHash)
|
||||
} else {
|
||||
self.accessHash = .genericPublic(accessHash)
|
||||
}
|
||||
} else {
|
||||
self.accessHash = nil
|
||||
}
|
||||
|
|
@ -146,7 +147,14 @@ public final class TelegramUser: Peer {
|
|||
encoder.encodeInt64(self.id.toInt64(), forKey: "i")
|
||||
|
||||
if let accessHash = self.accessHash {
|
||||
encoder.encodeInt64(accessHash, forKey: "ah")
|
||||
switch accessHash {
|
||||
case let .personal(value):
|
||||
encoder.encodeInt64(value, forKey: "ah")
|
||||
encoder.encodeInt32(0, forKey: "aht")
|
||||
case let .genericPublic(value):
|
||||
encoder.encodeInt64(value, forKey: "ah")
|
||||
encoder.encodeInt32(1, forKey: "aht")
|
||||
}
|
||||
}
|
||||
|
||||
if let firstName = self.firstName {
|
||||
|
|
@ -242,7 +250,7 @@ public final class TelegramUser: Peer {
|
|||
func parsedTelegramProfilePhoto(_ photo: Api.UserProfilePhoto) -> [TelegramMediaImageRepresentation] {
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
switch photo {
|
||||
case let .userProfilePhoto(photoId, photoSmall, photoBig, dcId):
|
||||
case let .userProfilePhoto(_, photoSmall, photoBig, dcId):
|
||||
let smallResource: TelegramMediaResource
|
||||
let fullSizeResource: TelegramMediaResource
|
||||
switch photoSmall {
|
||||
|
|
@ -267,6 +275,15 @@ extension TelegramUser {
|
|||
case let .user(flags, id, accessHash, firstName, lastName, username, phone, photo, _, _, restrictionReason, botInlinePlaceholder, _):
|
||||
let representations: [TelegramMediaImageRepresentation] = photo.flatMap(parsedTelegramProfilePhoto) ?? []
|
||||
|
||||
let isMin = (flags & (1 << 20)) != 0
|
||||
let accessHashValue = accessHash.flatMap { value -> TelegramPeerAccessHash in
|
||||
if isMin {
|
||||
return .genericPublic(value)
|
||||
} else {
|
||||
return .personal(value)
|
||||
}
|
||||
}
|
||||
|
||||
var userFlags: UserInfoFlags = []
|
||||
if (flags & (1 << 17)) != 0 {
|
||||
userFlags.insert(.isVerified)
|
||||
|
|
@ -295,7 +312,7 @@ extension TelegramUser {
|
|||
|
||||
let restrictionInfo: PeerAccessRestrictionInfo? = restrictionReason.flatMap(PeerAccessRestrictionInfo.init)
|
||||
|
||||
self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: id), accessHash: accessHash, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags)
|
||||
self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: id), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags)
|
||||
case let .userEmpty(id):
|
||||
self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: id), accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])
|
||||
}
|
||||
|
|
@ -303,7 +320,7 @@ extension TelegramUser {
|
|||
|
||||
static func merge(_ lhs: TelegramUser?, rhs: Api.User) -> TelegramUser? {
|
||||
switch rhs {
|
||||
case let .user(flags, _, _, _, _, username, _, photo, _, _, restrictionReason, botInlinePlaceholder, _):
|
||||
case let .user(flags, _, rhsAccessHash, _, _, username, _, photo, _, _, restrictionReason, botInlinePlaceholder, _):
|
||||
let isMin = (flags & (1 << 20)) != 0
|
||||
if !isMin {
|
||||
return TelegramUser(user: rhs)
|
||||
|
|
@ -338,7 +355,22 @@ extension TelegramUser {
|
|||
|
||||
let restrictionInfo: PeerAccessRestrictionInfo? = restrictionReason.flatMap(PeerAccessRestrictionInfo.init)
|
||||
|
||||
return TelegramUser(id: lhs.id, accessHash: lhs.accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags)
|
||||
let rhsAccessHashValue = rhsAccessHash.flatMap { value -> TelegramPeerAccessHash in
|
||||
if isMin {
|
||||
return .genericPublic(value)
|
||||
} else {
|
||||
return .personal(value)
|
||||
}
|
||||
}
|
||||
|
||||
let accessHash: TelegramPeerAccessHash?
|
||||
if let rhsAccessHashValue = rhsAccessHashValue, case .personal = rhsAccessHashValue {
|
||||
accessHash = rhsAccessHashValue
|
||||
} else {
|
||||
accessHash = lhs.accessHash ?? rhsAccessHashValue
|
||||
}
|
||||
|
||||
return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags)
|
||||
} else {
|
||||
return TelegramUser(user: rhs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import Foundation
|
|||
#else
|
||||
import Postbox
|
||||
#endif
|
||||
import TelegramApi
|
||||
|
||||
func updatePeerChatInclusionWithMinTimestamp(transaction: Transaction, id: PeerId, minTimestamp: Int32, forceRootGroupIfNotExists: Bool) {
|
||||
let currentInclusion = transaction.getPeerChatListInclusion(id)
|
||||
|
|
@ -136,3 +137,34 @@ func updatePeerPresenceLastActivities(transaction: Transaction, accountPeerId: P
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func updateContacts(transaction: Transaction, apiUsers: [Api.User]) {
|
||||
if apiUsers.isEmpty {
|
||||
return
|
||||
}
|
||||
var contactIds = transaction.getContactPeerIds()
|
||||
var updated = false
|
||||
for user in apiUsers {
|
||||
let isContact: Bool
|
||||
switch user {
|
||||
case let .user(user):
|
||||
isContact = (user.flags & (1 << 11)) != 0
|
||||
case .userEmpty:
|
||||
isContact = false
|
||||
}
|
||||
if isContact {
|
||||
if !contactIds.contains(user.peerId) {
|
||||
contactIds.insert(user.peerId)
|
||||
updated = true
|
||||
}
|
||||
} else {
|
||||
if contactIds.contains(user.peerId) {
|
||||
contactIds.remove(user.peerId)
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if updated {
|
||||
transaction.replaceContactPeerIds(contactIds)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -400,6 +400,8 @@
|
|||
D0575AF21E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575AF01E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift */; };
|
||||
D0575AF41E9FFDDE006F2541 /* ManagedSynchronizeSavedGifsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575AF31E9FFDDD006F2541 /* ManagedSynchronizeSavedGifsOperations.swift */; };
|
||||
D0575AF51E9FFDDE006F2541 /* ManagedSynchronizeSavedGifsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575AF31E9FFDDD006F2541 /* ManagedSynchronizeSavedGifsOperations.swift */; };
|
||||
D0575C2D22B922DF00A71A0E /* DeleteAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575C2C22B922DF00A71A0E /* DeleteAccount.swift */; };
|
||||
D0575C2E22B922DF00A71A0E /* DeleteAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0575C2C22B922DF00A71A0E /* DeleteAccount.swift */; };
|
||||
D058E0D11E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */; };
|
||||
D058E0D21E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */; };
|
||||
D05A32E11E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */; };
|
||||
|
|
@ -770,8 +772,6 @@
|
|||
D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B843961DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift */; };
|
||||
D0F7B1EB1E045C87007EB8A5 /* ResolvePeerByName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F3CC7C1DDE289E008148FA /* ResolvePeerByName.swift */; };
|
||||
D0F7B1EC1E045C87007EB8A5 /* SearchPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07827BA1E00451F00071108 /* SearchPeers.swift */; };
|
||||
D0F8C39D20178B9B00236FC5 /* GroupFeedPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F8C39C20178B9B00236FC5 /* GroupFeedPeers.swift */; };
|
||||
D0F8C39E20178B9B00236FC5 /* GroupFeedPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F8C39C20178B9B00236FC5 /* GroupFeedPeers.swift */; };
|
||||
D0F8C3A02017AF2700236FC5 /* GlobalTelegramCoreConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F8C39F2017AF2700236FC5 /* GlobalTelegramCoreConfiguration.swift */; };
|
||||
D0F8C3A12017AF2700236FC5 /* GlobalTelegramCoreConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F8C39F2017AF2700236FC5 /* GlobalTelegramCoreConfiguration.swift */; };
|
||||
D0FA08BB2046B37900DD23FC /* ContentPrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FA08BA2046B37900DD23FC /* ContentPrivacySettings.swift */; };
|
||||
|
|
@ -1025,6 +1025,7 @@
|
|||
D0561DE91E5754FA00E6B9E9 /* ChannelAdmins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelAdmins.swift; sourceTree = "<group>"; };
|
||||
D0575AF01E9FFA5D006F2541 /* SynchronizeSavedGifsOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeSavedGifsOperation.swift; sourceTree = "<group>"; };
|
||||
D0575AF31E9FFDDD006F2541 /* ManagedSynchronizeSavedGifsOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeSavedGifsOperations.swift; sourceTree = "<group>"; };
|
||||
D0575C2C22B922DF00A71A0E /* DeleteAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteAccount.swift; sourceTree = "<group>"; };
|
||||
D058E0D01E8AD65C00A442DE /* StandaloneSendMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StandaloneSendMessage.swift; sourceTree = "<group>"; };
|
||||
D05A32E01E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatedAccountPrivacySettings.swift; sourceTree = "<group>"; };
|
||||
D05A32E31E6F0B2E002760B4 /* RecentAccountSessions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentAccountSessions.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -1226,7 +1227,6 @@
|
|||
D0F760D722202FE20074F7E5 /* ChannelStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelStats.swift; sourceTree = "<group>"; };
|
||||
D0F7AB2B1DCE889D009AD9A1 /* EditedMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditedMessageAttribute.swift; sourceTree = "<group>"; };
|
||||
D0F7AB2E1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyMarkupMessageAttribute.swift; sourceTree = "<group>"; };
|
||||
D0F8C39C20178B9B00236FC5 /* GroupFeedPeers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupFeedPeers.swift; sourceTree = "<group>"; };
|
||||
D0F8C39F2017AF2700236FC5 /* GlobalTelegramCoreConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalTelegramCoreConfiguration.swift; sourceTree = "<group>"; };
|
||||
D0FA08BA2046B37900DD23FC /* ContentPrivacySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentPrivacySettings.swift; sourceTree = "<group>"; };
|
||||
D0FA0ABC1E76C908005BB9B7 /* TwoStepVerification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwoStepVerification.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -1637,6 +1637,7 @@
|
|||
D01843A72190C28100278AFF /* ConfirmTwoStepRecoveryEmail.swift */,
|
||||
D02B198F21FB1D520094A764 /* RegisterNotificationToken.swift */,
|
||||
D0338742223BD532007A2CE4 /* InitializeAccountAfterLogin.swift */,
|
||||
D0575C2C22B922DF00A71A0E /* DeleteAccount.swift */,
|
||||
);
|
||||
name = Account;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1975,7 +1976,6 @@
|
|||
D0DA1D311F7043D50034E892 /* ManagedPendingPeerNotificationSettings.swift */,
|
||||
D02395D51F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift */,
|
||||
D0C44B601FC616E200227BE0 /* SearchGroupMembers.swift */,
|
||||
D0F8C39C20178B9B00236FC5 /* GroupFeedPeers.swift */,
|
||||
D018EE042045E95000CBB130 /* CheckPeerChatServiceActions.swift */,
|
||||
9F06830F21A40DEC001D8EDB /* NotificationExceptionsList.swift */,
|
||||
D0F760D722202FE20074F7E5 /* ChannelStats.swift */,
|
||||
|
|
@ -2543,7 +2543,6 @@
|
|||
C2366C861E4F403C0097CCFF /* AddressNames.swift in Sources */,
|
||||
D0529D2421A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift in Sources */,
|
||||
D0FA08BB2046B37900DD23FC /* ContentPrivacySettings.swift in Sources */,
|
||||
D0F8C39D20178B9B00236FC5 /* GroupFeedPeers.swift in Sources */,
|
||||
D0B843C11DA7FF30005F29E1 /* NBPhoneMetaData.m in Sources */,
|
||||
D0528E601E65B94E00E2FEF5 /* SingleMessageView.swift in Sources */,
|
||||
D08CAA841ED8164B0000FDA8 /* Localization.swift in Sources */,
|
||||
|
|
@ -2564,6 +2563,7 @@
|
|||
D054649A20738760002ECC1E /* SecureIdRentalAgreementValue.swift in Sources */,
|
||||
D0B843BF1DA7FF30005F29E1 /* NBNumberFormat.m in Sources */,
|
||||
D0E305A71E5B5CBE00D7A3A2 /* PeerAdmins.swift in Sources */,
|
||||
D0575C2D22B922DF00A71A0E /* DeleteAccount.swift in Sources */,
|
||||
D0B843C51DA7FF30005F29E1 /* NBPhoneNumber.m in Sources */,
|
||||
D03B0D0D1D62255C00955575 /* SynchronizePeerReadState.swift in Sources */,
|
||||
D03B0D081D62255C00955575 /* ChannelState.swift in Sources */,
|
||||
|
|
@ -2803,7 +2803,6 @@
|
|||
D0529D2521A4123400D7C3C4 /* SynchronizeRecentlyUsedMediaOperations.swift in Sources */,
|
||||
D06ECFC920B810D300C576C2 /* TermsOfService.swift in Sources */,
|
||||
9F06831121A40DEC001D8EDB /* NotificationExceptionsList.swift in Sources */,
|
||||
D0F8C39E20178B9B00236FC5 /* GroupFeedPeers.swift in Sources */,
|
||||
D0AB262C21C3CE80008F6685 /* Polls.swift in Sources */,
|
||||
D073CE6C1DCBCF17007511FD /* TextEntitiesMessageAttribute.swift in Sources */,
|
||||
D03C53751DAD5CA9004C17B3 /* TelegramUserPresence.swift in Sources */,
|
||||
|
|
@ -2844,6 +2843,7 @@
|
|||
D08F4A671E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */,
|
||||
D05A32E81E6F0B5C002760B4 /* RecentAccountSession.swift in Sources */,
|
||||
D0F7B1E31E045C7B007EB8A5 /* RichText.swift in Sources */,
|
||||
D0575C2E22B922DF00A71A0E /* DeleteAccount.swift in Sources */,
|
||||
D0FA8BB11E1FEC7E001E855B /* SecretChatEncryptionConfig.swift in Sources */,
|
||||
D0B418AA1D7E0597004562A4 /* Download.swift in Sources */,
|
||||
D001F3F41E128A1C007A8C60 /* UpdatesApiUtils.swift in Sources */,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -28,6 +28,7 @@ private func encodeText(_ string: String, _ key: Int) -> String {
|
|||
}
|
||||
|
||||
private let statusBarRootViewClass: AnyClass = NSClassFromString("UIStatusBar")!
|
||||
private let statusBarPlaceholderClass: AnyClass? = NSClassFromString("UIStatusBar_Placeholder")
|
||||
private let cutoutStatusBarForegroundClass: AnyClass? = NSClassFromString("_UIStatusBar")
|
||||
private let keyboardViewClass: AnyClass? = NSClassFromString(encodeText("VJJoqvuTfuIptuWjfx", -1))!
|
||||
private let keyboardViewContainerClass: AnyClass? = NSClassFromString(encodeText("VJJoqvuTfuDpoubjofsWjfx", -1))!
|
||||
|
|
@ -65,6 +66,12 @@ private class ApplicationStatusBarHost: StatusBarHost {
|
|||
if containerView.isKind(of: statusBarRootViewClass) {
|
||||
return containerView
|
||||
}
|
||||
if let statusBarPlaceholderClass = statusBarPlaceholderClass {
|
||||
if containerView.isKind(of: statusBarPlaceholderClass) {
|
||||
return containerView
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for subview in containerView.subviews {
|
||||
if let cutoutStatusBarForegroundClass = cutoutStatusBarForegroundClass, subview.isKind(of: cutoutStatusBarForegroundClass) {
|
||||
|
|
|
|||
|
|
@ -323,10 +323,18 @@ final class AuthorizedApplicationContext {
|
|||
}))
|
||||
|
||||
let accountId = context.account.id
|
||||
self.loggedOutDisposable.set(context.account.loggedOut.start(next: { value in
|
||||
self.loggedOutDisposable.set((context.account.loggedOut
|
||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
if value {
|
||||
Logger.shared.log("ApplicationContext", "account logged out")
|
||||
let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: false).start()
|
||||
if let strongSelf = self {
|
||||
strongSelf.rootController.currentWindow?.forEachController { controller in
|
||||
if let controller = controller as? TermsOfServiceController {
|
||||
controller.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
|
|
@ -486,15 +494,23 @@ final class AuthorizedApplicationContext {
|
|||
})
|
||||
}
|
||||
|
||||
declineImpl = {
|
||||
declineImpl = { [weak controller] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId)
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
if let phone = (peer as? TelegramUser)?.phone {
|
||||
UIApplication.shared.openURL(URL(string: "https://telegram.org/deactivate?phone=\(phone)")!)
|
||||
let accountId = strongSelf.context.account.id
|
||||
let accountManager = strongSelf.context.sharedContext.accountManager
|
||||
let _ = (deleteAccount(account: strongSelf.context.account)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = textAlertController(context: strongSelf.context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
|
||||
(strongSelf.rootController.viewControllers.last as? ViewController)?.present(controller, in: .window(.root))
|
||||
}, completed: {
|
||||
controller?.dismiss()
|
||||
let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: true).start()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1573,7 +1573,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
}
|
||||
|
||||
var didDisplayActionsPanel = false
|
||||
if let contactStatus = strongSelf.presentationInterfaceState.contactStatus, let peerStatusSettings = contactStatus.peerStatusSettings {
|
||||
if let contactStatus = strongSelf.presentationInterfaceState.contactStatus, !contactStatus.isEmpty, let peerStatusSettings = contactStatus.peerStatusSettings {
|
||||
if !peerStatusSettings.isEmpty {
|
||||
if contactStatus.canAddContact && peerStatusSettings.contains(.canAddContact) {
|
||||
didDisplayActionsPanel = true
|
||||
|
|
@ -1588,7 +1588,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
}
|
||||
|
||||
var displayActionsPanel = false
|
||||
if let contactStatus = contactStatus, let peerStatusSettings = contactStatus.peerStatusSettings {
|
||||
if let contactStatus = contactStatus, !contactStatus.isEmpty, let peerStatusSettings = contactStatus.peerStatusSettings {
|
||||
if !peerStatusSettings.isEmpty {
|
||||
if contactStatus.canAddContact && peerStatusSettings.contains(.canAddContact) {
|
||||
displayActionsPanel = true
|
||||
|
|
@ -2258,7 +2258,10 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
insertItems.append(ListViewInsertItem(index: item.index, previousIndex: item.previousIndex, item: item.item, directionHint: item.directionHint == .Down ? .Up : nil))
|
||||
}
|
||||
|
||||
let scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: 0.2), directionHint: .Up)
|
||||
var scrollToItem: ListViewScrollToItem?
|
||||
if transition.historyView.originalView.laterId == nil {
|
||||
scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: 0.2), directionHint: .Up)
|
||||
}
|
||||
|
||||
var stationaryItemRange: (Int, Int)?
|
||||
if let maxInsertedItem = maxInsertedItem {
|
||||
|
|
@ -2280,7 +2283,8 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
if let strongSelf = self, case let .peer(peerId) = strongSelf.chatLocation {
|
||||
strongSelf.commitPurposefulAction()
|
||||
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: strongSelf.transformEnqueueMessages(messages)) |> deliverOnMainQueue).start(next: { _ in
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: strongSelf.transformEnqueueMessages(messages))
|
||||
|> deliverOnMainQueue).start(next: { _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}
|
||||
|
|
@ -5391,6 +5395,14 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
self.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}
|
||||
|
||||
func updateTextInputState(_ textInputState: ChatTextInputState) {
|
||||
self.updateChatPresentationInterfaceState(interactive: false, { state in
|
||||
state.updatedInterfaceState({ state in
|
||||
state.withUpdatedComposeInputState(textInputState)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public func navigateToMessage(messageLocation: NavigateToMessageLocation, animated: Bool, forceInCurrentChat: Bool = false, completion: (() -> Void)? = nil, customPresentProgress: ((ViewController, Any?) -> Void)? = nil) {
|
||||
self.navigateToMessage(from: nil, to: messageLocation, rememberInStack: false, forceInCurrentChat: forceInCurrentChat, animated: animated, completion: completion, customPresentProgress: customPresentProgress)
|
||||
}
|
||||
|
|
@ -5698,8 +5710,8 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
})
|
||||
})
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
(strongSelf.navigationController as? NavigationController)?.pushViewController(ChatController(context: strongSelf.context, chatLocation: .peer(peerId), messageId: messageId))
|
||||
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), messageId: messageId, updateTextInputState: textInputState)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
|
@ -5920,9 +5932,15 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
let title: String
|
||||
var infoString: String?
|
||||
if let _ = peer as? TelegramGroup {
|
||||
title = self.presentationData.strings.Conversation_ReportSpam
|
||||
} else if let _ = peer as? TelegramChannel {
|
||||
title = self.presentationData.strings.Conversation_ReportSpam
|
||||
title = self.presentationData.strings.Conversation_ReportSpamAndLeave
|
||||
infoString = self.presentationData.strings.Conversation_ReportSpamGroupConfirmation
|
||||
} else if let channel = peer as? TelegramChannel {
|
||||
title = self.presentationData.strings.Conversation_ReportSpamAndLeave
|
||||
if case .group = channel.info {
|
||||
infoString = self.presentationData.strings.Conversation_ReportSpamGroupConfirmation
|
||||
} else {
|
||||
infoString = self.presentationData.strings.Conversation_ReportSpamChannelConfirmation
|
||||
}
|
||||
} else {
|
||||
title = self.presentationData.strings.Conversation_ReportSpam
|
||||
infoString = self.presentationData.strings.Conversation_ReportSpamConfirmation
|
||||
|
|
@ -5955,25 +5973,42 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let _ = accountPeer as? TelegramUser else {
|
||||
guard let user = accountPeer as? TelegramUser, let phoneNumber = user.phone else {
|
||||
return
|
||||
}
|
||||
guard let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramUser else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = (acceptAndShareContact(account: strongSelf.context.account, peerId: peer.id)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetTextItem(title: strongSelf.presentationData.strings.Conversation_ShareMyPhoneNumberConfirmation(formatPhoneNumber(phoneNumber), peer.compactDisplayTitle).0))
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ShareMyPhoneNumber, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}, completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.present(OverlayStatusController(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, type: .genericSuccess(strongSelf.presentationData.strings.Conversation_ShareMyPhoneNumber_StatusSuccess(peer.compactDisplayTitle).0, true)), in: .window(.root))
|
||||
})
|
||||
let _ = (acceptAndShareContact(account: strongSelf.context.account, peerId: peer.id)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}, completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.present(OverlayStatusController(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, type: .genericSuccess(strongSelf.presentationData.strings.Conversation_ShareMyPhoneNumber_StatusSuccess(peer.compactDisplayTitle).0, true)), in: .window(.root))
|
||||
})
|
||||
}))
|
||||
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
})
|
||||
])])
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,15 +21,13 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView,
|
|||
|
||||
var groupBucket: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes)] = []
|
||||
loop: for entry in view.entries {
|
||||
if entry.message.id.peerId.namespace == Namespaces.Peer.CloudChannel || entry.message.id.peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
for media in entry.message.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
switch action.action {
|
||||
case .channelMigratedFromGroup, .groupMigratedToChannel, .historyCleared:
|
||||
continue loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
for media in entry.message.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
switch action.action {
|
||||
case .channelMigratedFromGroup, .groupMigratedToChannel, .historyCleared:
|
||||
continue loop
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -82,7 +80,9 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView,
|
|||
let unreadEntry: ChatHistoryEntry = .UnreadEntry(maxReadIndex, presentationData)
|
||||
for entry in entries {
|
||||
if entry > unreadEntry {
|
||||
entries.insert(unreadEntry, at: i)
|
||||
if i != 0 {
|
||||
entries.insert(unreadEntry, at: i)
|
||||
}
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
|
|
@ -100,38 +100,39 @@ func chatHistoryEntriesForView(location: ChatLocation, view: MessageHistoryView,
|
|||
}
|
||||
if let cachedPeerData = cachedPeerData as? CachedUserData, let botInfo = cachedPeerData.botInfo, !botInfo.description.isEmpty {
|
||||
entries.insert(.ChatInfoEntry(botInfo.description, presentationData), at: 0)
|
||||
}
|
||||
var isEmpty = true
|
||||
if entries.count <= 3 {
|
||||
loop: for entry in view.entries {
|
||||
var isEmptyMedia = false
|
||||
for media in entry.message.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
switch action.action {
|
||||
case .groupCreated, .photoUpdated, .channelMigratedFromGroup, .groupMigratedToChannel:
|
||||
isEmptyMedia = true
|
||||
default:
|
||||
break
|
||||
} else {
|
||||
var isEmpty = true
|
||||
if entries.count <= 3 {
|
||||
loop: for entry in view.entries {
|
||||
var isEmptyMedia = false
|
||||
for media in entry.message.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
switch action.action {
|
||||
case .groupCreated, .photoUpdated, .channelMigratedFromGroup, .groupMigratedToChannel:
|
||||
isEmptyMedia = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
var isCreator = false
|
||||
if let peer = entry.message.peers[entry.message.id.peerId] as? TelegramGroup, case .creator = peer.role {
|
||||
isCreator = true
|
||||
} else if let peer = entry.message.peers[entry.message.id.peerId] as? TelegramChannel, case .group = peer.info, peer.flags.contains(.isCreator) {
|
||||
isCreator = true
|
||||
}
|
||||
if isEmptyMedia && isCreator {
|
||||
} else {
|
||||
isEmpty = false
|
||||
break loop
|
||||
}
|
||||
}
|
||||
var isCreator = false
|
||||
if let peer = entry.message.peers[entry.message.id.peerId] as? TelegramGroup, case .creator = peer.role {
|
||||
isCreator = true
|
||||
} else if let peer = entry.message.peers[entry.message.id.peerId] as? TelegramChannel, case .group = peer.info, peer.flags.contains(.isCreator) {
|
||||
isCreator = true
|
||||
}
|
||||
if isEmptyMedia && isCreator {
|
||||
} else {
|
||||
isEmpty = false
|
||||
break loop
|
||||
}
|
||||
} else {
|
||||
isEmpty = false
|
||||
}
|
||||
if isEmpty {
|
||||
entries.removeAll()
|
||||
}
|
||||
} else {
|
||||
isEmpty = false
|
||||
}
|
||||
if isEmpty {
|
||||
entries.removeAll()
|
||||
}
|
||||
}
|
||||
} else if includeSearchEntry {
|
||||
|
|
|
|||
|
|
@ -530,12 +530,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||
if let filteredEntries = historyView?.filteredEntries, let visibleRange = displayRange.visibleRange {
|
||||
let lastEntry = filteredEntries[filteredEntries.count - 1 - visibleRange.lastIndex]
|
||||
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0)
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
} else {
|
||||
if let messageId = messageId {
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: 0)
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
} else {
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Initial(count: 60), id: 0)
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Initial(count: 60), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -993,11 +993,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||
|
||||
if let loaded = displayedRange.loadedRange, let firstEntry = historyView.filteredEntries.first, let lastEntry = historyView.filteredEntries.last {
|
||||
if loaded.firstIndex < 5 && historyView.originalView.laterId != nil {
|
||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: 0)
|
||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: (self.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
} else if loaded.firstIndex < 5, historyView.originalView.laterId == nil, !historyView.originalView.holeLater, let chatHistoryLocationValue = self.chatHistoryLocationValue, !chatHistoryLocationValue.isAtUpperBound, historyView.originalView.anchorIndex != .upperBound {
|
||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .upperBound, anchorIndex: .upperBound, count: historyMessageCount), id: 0)
|
||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .upperBound, anchorIndex: .upperBound, count: historyMessageCount), id: (self.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
} else if loaded.lastIndex >= historyView.filteredEntries.count - 5 && historyView.originalView.earlierId != nil {
|
||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(firstEntry.index), anchorIndex: .message(firstEntry.index), count: historyMessageCount), id: 0)
|
||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(firstEntry.index), anchorIndex: .message(firstEntry.index), count: historyMessageCount), id: (self.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,23 +58,6 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
|||
|
||||
var displayInputTextPanel = false
|
||||
|
||||
/*if case .group = chatPresentationInterfaceState.chatLocation {
|
||||
if chatPresentationInterfaceState.interfaceState.editMessage != nil {
|
||||
displayInputTextPanel = true
|
||||
} else {
|
||||
if let currentPanel = currentPanel as? ChatFeedNavigationInputPanelNode {
|
||||
currentPanel.interfaceInteraction = interfaceInteraction
|
||||
currentPanel.updateThemeAndStrings(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = ChatFeedNavigationInputPanelNode(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
|
||||
panel.context = context
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
return panel
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if let peer = chatPresentationInterfaceState.renderedPeer?.peer {
|
||||
if let secretChat = peer as? TelegramSecretChat {
|
||||
switch secretChat.embeddedState {
|
||||
|
|
@ -100,7 +83,24 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
|||
break
|
||||
}
|
||||
} else if let channel = peer as? TelegramChannel {
|
||||
if channel.hasBannedPermission(.banSendMessages) != nil {
|
||||
var isMember: Bool = false
|
||||
switch channel.participationStatus {
|
||||
case .kicked:
|
||||
if let currentPanel = currentPanel as? DeleteChatInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = DeleteChatInputPanelNode()
|
||||
panel.context = context
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
return panel
|
||||
}
|
||||
case .member:
|
||||
isMember = true
|
||||
case .left:
|
||||
break
|
||||
}
|
||||
|
||||
if isMember && channel.hasBannedPermission(.banSendMessages) != nil {
|
||||
if let currentPanel = currentPanel as? ChatRestrictedInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
|
|
@ -111,61 +111,48 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
|||
}
|
||||
}
|
||||
|
||||
switch channel.participationStatus {
|
||||
case .kicked:
|
||||
if let currentPanel = currentPanel as? DeleteChatInputPanelNode {
|
||||
switch channel.info {
|
||||
case .broadcast:
|
||||
if chatPresentationInterfaceState.interfaceState.editMessage != nil, channel.hasPermission(.editAllMessages) {
|
||||
displayInputTextPanel = true
|
||||
} else if !channel.hasPermission(.sendMessages) {
|
||||
if let currentPanel = currentPanel as? ChatChannelSubscriberInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = DeleteChatInputPanelNode()
|
||||
panel.context = context
|
||||
let panel = ChatChannelSubscriberInputPanelNode()
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
panel.context = context
|
||||
return panel
|
||||
}
|
||||
case .member, .left:
|
||||
}
|
||||
case .group:
|
||||
switch channel.participationStatus {
|
||||
case .kicked, .left:
|
||||
if let currentPanel = currentPanel as? ChatChannelSubscriberInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = ChatChannelSubscriberInputPanelNode()
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
panel.context = context
|
||||
return panel
|
||||
}
|
||||
case .member:
|
||||
break
|
||||
}
|
||||
switch channel.info {
|
||||
case .broadcast:
|
||||
if chatPresentationInterfaceState.interfaceState.editMessage != nil, channel.hasPermission(.editAllMessages) {
|
||||
displayInputTextPanel = true
|
||||
} else if !channel.hasPermission(.sendMessages) {
|
||||
if let currentPanel = currentPanel as? ChatChannelSubscriberInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = ChatChannelSubscriberInputPanelNode()
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
panel.context = context
|
||||
return panel
|
||||
}
|
||||
}
|
||||
case .group:
|
||||
switch channel.participationStatus {
|
||||
case .kicked, .left:
|
||||
if let currentPanel = currentPanel as? ChatChannelSubscriberInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = ChatChannelSubscriberInputPanelNode()
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
panel.context = context
|
||||
return panel
|
||||
}
|
||||
case .member:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
switch group.membership {
|
||||
case .Removed, .Left:
|
||||
if let currentPanel = currentPanel as? DeleteChatInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = DeleteChatInputPanelNode()
|
||||
panel.context = context
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
return panel
|
||||
}
|
||||
case .Member:
|
||||
break
|
||||
case .Removed, .Left:
|
||||
if let currentPanel = currentPanel as? DeleteChatInputPanelNode {
|
||||
return currentPanel
|
||||
} else {
|
||||
let panel = DeleteChatInputPanelNode()
|
||||
panel.context = context
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
return panel
|
||||
}
|
||||
case .Member:
|
||||
break
|
||||
}
|
||||
|
||||
if group.hasBannedPermission(.banSendMessages) {
|
||||
|
|
|
|||
|
|
@ -11,32 +11,6 @@ import TelegramUIPreferences
|
|||
private enum ChatListRecentEntryStableId: Hashable {
|
||||
case topPeers
|
||||
case peerId(PeerId)
|
||||
|
||||
static func ==(lhs: ChatListRecentEntryStableId, rhs: ChatListRecentEntryStableId) -> Bool {
|
||||
switch lhs {
|
||||
case .topPeers:
|
||||
if case .topPeers = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .peerId(peerId):
|
||||
if case .peerId(peerId) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var hashValue: Int {
|
||||
switch self {
|
||||
case .topPeers:
|
||||
return 0
|
||||
case let .peerId(peerId):
|
||||
return peerId.hashValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum ChatListRecentEntry: Comparable, Identifiable {
|
||||
|
|
@ -251,7 +225,7 @@ enum ChatListSearchEntryStableId: Hashable {
|
|||
enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
case localPeer(Peer, Peer?, UnreadSearchBadge?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder)
|
||||
case globalPeer(FoundPeer, UnreadSearchBadge?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder)
|
||||
case message(Message, CombinedPeerReadState?, ChatListPresentationData)
|
||||
case message(Message, RenderedPeer, CombinedPeerReadState?, ChatListPresentationData)
|
||||
case addContact(String, PresentationTheme, PresentationStrings)
|
||||
|
||||
var stableId: ChatListSearchEntryStableId {
|
||||
|
|
@ -260,7 +234,7 @@ enum ChatListSearchEntry: Comparable, Identifiable {
|
|||
return .localPeerId(peer.id)
|
||||
case let .globalPeer(peer, _, _, _, _, _, _):
|
||||
return .globalPeerId(peer.peer.id)
|
||||
case let .message(message, _, _):
|
||||
case let .message(message, _, _, _):
|
||||
return .messageId(message.id)
|
||||
case .addContact:
|
||||
return .addContact
|
||||
|
|
@ -281,14 +255,17 @@ enum ChatListSearchEntry: Comparable, Identifiable {
|
|||
} else {
|
||||
return false
|
||||
}
|
||||
case let .message(lhsMessage, lhsCombinedPeerReadState, lhsPresentationData):
|
||||
if case let .message(rhsMessage, rhsCombinedPeerReadState, rhsPresentationData) = rhs {
|
||||
case let .message(lhsMessage, lhsPeer, lhsCombinedPeerReadState, lhsPresentationData):
|
||||
if case let .message(rhsMessage, rhsPeer, rhsCombinedPeerReadState, rhsPresentationData) = rhs {
|
||||
if lhsMessage.id != rhsMessage.id {
|
||||
return false
|
||||
}
|
||||
if lhsMessage.stableVersion != rhsMessage.stableVersion {
|
||||
return false
|
||||
}
|
||||
if lhsPeer != rhsPeer {
|
||||
return false
|
||||
}
|
||||
if lhsPresentationData !== rhsPresentationData {
|
||||
return false
|
||||
}
|
||||
|
|
@ -334,8 +311,8 @@ enum ChatListSearchEntry: Comparable, Identifiable {
|
|||
case .message, .addContact:
|
||||
return true
|
||||
}
|
||||
case let .message(lhsMessage, _, _):
|
||||
if case let .message(rhsMessage, _, _) = rhs {
|
||||
case let .message(lhsMessage, _, _, _):
|
||||
if case let .message(rhsMessage, _, _, _) = rhs {
|
||||
return lhsMessage.index < rhsMessage.index
|
||||
} else if case .addContact = rhs {
|
||||
return true
|
||||
|
|
@ -448,8 +425,8 @@ enum ChatListSearchEntry: Comparable, Identifiable {
|
|||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .addressName(suffixString), badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
interaction.peerSelected(peer.peer)
|
||||
})
|
||||
case let .message(message, readState, presentationData):
|
||||
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: RenderedPeer(message: message), combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true), editing: false, hasActiveRevealControls: false, selected: false, header: enableHeaders ? ChatListSearchItemHeader(type: .messages, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
case let .message(message, peer, readState, presentationData):
|
||||
return ChatListItem(presentationData: presentationData, context: context, peerGroupId: .root, index: ChatListIndex(pinningIndex: nil, messageIndex: message.index), content: .peer(message: message, peer: peer, combinedReadState: readState, notificationSettings: nil, presence: nil, summaryInfo: ChatListMessageTagSummaryInfo(), embeddedState: nil, inputActivities: nil, isAd: false, ignoreUnreadBadge: true), editing: false, hasActiveRevealControls: false, selected: false, header: enableHeaders ? ChatListSearchItemHeader(type: .messages, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||
case let .addContact(phoneNumber, theme, strings):
|
||||
return ContactsAddItem(theme: theme, strings: strings, phoneNumber: phoneNumber, header: ChatListSearchItemHeader(type: .phoneNumber, theme: theme, strings: strings, actionTitle: nil, action: nil), action: {
|
||||
interaction.addContact(phoneNumber)
|
||||
|
|
@ -813,7 +790,13 @@ final class ChatListSearchContainerNode: SearchDisplayControllerContentNode {
|
|||
if !foundRemotePeers.2 {
|
||||
index = 0
|
||||
for message in foundRemoteMessages.0.0 {
|
||||
entries.append(.message(message, foundRemoteMessages.0.1[message.id.peerId], presentationData))
|
||||
var peer = RenderedPeer(message: message)
|
||||
if let group = message.peers[message.id.peerId] as? TelegramGroup, let migrationReference = group.migrationReference {
|
||||
if let channelPeer = message.peers[migrationReference.peerId] {
|
||||
peer = RenderedPeer(peer: channelPeer)
|
||||
}
|
||||
}
|
||||
entries.append(.message(message, peer, foundRemoteMessages.0.1[message.id.peerId], presentationData))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,6 +323,16 @@ final class ChatRecordedMediaPreview: Equatable {
|
|||
struct ChatContactStatus: Equatable {
|
||||
var canAddContact: Bool
|
||||
var peerStatusSettings: PeerStatusSettings?
|
||||
|
||||
var isEmpty: Bool {
|
||||
guard var peerStatusSettings = self.peerStatusSettings else {
|
||||
return false
|
||||
}
|
||||
if !self.canAddContact {
|
||||
peerStatusSettings.remove(.canAddContact)
|
||||
}
|
||||
return peerStatusSettings.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatPresentationInterfaceState: Equatable {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ private enum ChatReportPeerTitleButton: Equatable {
|
|||
case .shareMyPhoneNumber:
|
||||
return strings.Conversation_ShareMyPhoneNumber
|
||||
case .reportSpam:
|
||||
return strings.Conversation_ReportSpam
|
||||
return strings.Conversation_ReportSpamAndLeave
|
||||
case .reportIrrelevantGeoLocation:
|
||||
return strings.Conversation_ReportGroupLocation
|
||||
}
|
||||
|
|
@ -131,11 +131,12 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
|
|||
let view = UIButton()
|
||||
view.setTitle(button.title(strings: interfaceState.strings), for: [])
|
||||
view.titleLabel?.font = Font.regular(16.0)
|
||||
if case .block = button {
|
||||
switch button {
|
||||
case .block, .reportSpam:
|
||||
view.setTitleColor(interfaceState.theme.chat.inputPanel.panelControlDestructiveColor, for: [])
|
||||
view.setTitleColor(interfaceState.theme.chat.inputPanel.panelControlDestructiveColor.withAlphaComponent(0.7), for: [.highlighted])
|
||||
} else {
|
||||
view.setTitleColor(interfaceState.theme.rootController.navigationBar.accentTextColor, for: [])
|
||||
default:
|
||||
view.setTitleColor(interfaceState.theme.rootController.navigationBar.accentTextColor, for: [])
|
||||
view.setTitleColor(interfaceState.theme.rootController.navigationBar.accentTextColor.withAlphaComponent(0.7), for: [.highlighted])
|
||||
}
|
||||
view.addTarget(self, action: #selector(self.buttonPressed(_:)), for: [.touchUpInside])
|
||||
|
|
@ -154,7 +155,7 @@ final class ChatReportPeerTitlePanelNode: ChatTitleAccessoryPanelNode {
|
|||
nextButtonOrigin += buttonWidth
|
||||
}
|
||||
} else {
|
||||
let additionalRightInset: CGFloat = 18.0
|
||||
let additionalRightInset: CGFloat = 36.0
|
||||
let areaWidth = width - maxInset * 2.0 - additionalRightInset
|
||||
let maxButtonWidth = floor(areaWidth / CGFloat(self.buttons.count))
|
||||
let buttonSizes = self.buttons.map { button -> CGFloat in
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
let textInputContainer: ASDisplayNode
|
||||
var textInputNode: EditableTextNode?
|
||||
|
||||
let textInputBackgroundView: UIImageView
|
||||
let textInputBackgroundNode: ASImageNode
|
||||
let actionButtons: ChatTextInputActionButtonsNode
|
||||
var mediaRecordingAccessibilityArea: AccessibilityAreaNode?
|
||||
|
||||
|
|
@ -322,7 +322,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
self.textInputContainer.clipsToBounds = true
|
||||
self.textInputContainer.backgroundColor = theme.chat.inputPanel.inputBackgroundColor
|
||||
|
||||
self.textInputBackgroundView = UIImageView()
|
||||
self.textInputBackgroundNode = ASImageNode()
|
||||
self.textInputBackgroundNode.displaysAsynchronously = false
|
||||
self.textInputBackgroundNode.displayWithoutProcessing = true
|
||||
self.textPlaceholderNode = ImmediateTextNode()
|
||||
self.textPlaceholderNode.maximumNumberOfLines = 1
|
||||
self.textPlaceholderNode.isUserInteractionEnabled = false
|
||||
|
|
@ -407,21 +409,21 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
self.searchLayoutClearButton.addSubview(self.searchLayoutProgressView)
|
||||
|
||||
self.addSubnode(self.textInputContainer)
|
||||
self.view.addSubview(self.textInputBackgroundView)
|
||||
self.addSubnode(self.textInputBackgroundNode)
|
||||
|
||||
self.addSubnode(self.textPlaceholderNode)
|
||||
|
||||
self.view.addSubview(self.searchLayoutClearButton)
|
||||
|
||||
self.textInputBackgroundView.clipsToBounds = true
|
||||
self.textInputBackgroundNode.clipsToBounds = true
|
||||
let recognizer = TouchDownGestureRecognizer(target: self, action: #selector(self.textInputBackgroundViewTap(_:)))
|
||||
recognizer.touchDown = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.ensureFocused()
|
||||
}
|
||||
}
|
||||
self.textInputBackgroundView.addGestureRecognizer(recognizer)
|
||||
self.textInputBackgroundView.isUserInteractionEnabled = true
|
||||
self.textInputBackgroundNode.isUserInteractionEnabled = true
|
||||
self.textInputBackgroundNode.view.addGestureRecognizer(recognizer)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
|
|
@ -490,8 +492,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
textInputNode.frame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right + accessoryButtonsWidth), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - self.textInputViewInternalInsets.bottom))
|
||||
}
|
||||
|
||||
self.textInputBackgroundView.isUserInteractionEnabled = false
|
||||
self.textInputBackgroundView.removeGestureRecognizer(self.textInputBackgroundView.gestureRecognizers![0])
|
||||
self.textInputBackgroundNode.isUserInteractionEnabled = false
|
||||
self.textInputBackgroundNode.view.removeGestureRecognizer(self.textInputBackgroundNode.view.gestureRecognizers![0])
|
||||
|
||||
let recognizer = TouchDownGestureRecognizer(target: self, action: #selector(self.textInputBackgroundViewTap(_:)))
|
||||
recognizer.touchDown = { [weak self] in
|
||||
|
|
@ -647,7 +649,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
|
||||
let textFieldMinHeight = calclulateTextFieldMinHeight(interfaceState, metrics: metrics)
|
||||
let minimalInputHeight: CGFloat = 2.0 + textFieldMinHeight
|
||||
self.textInputBackgroundView.image = textInputBackgroundImage(backgroundColor: interfaceState.theme.chat.inputPanel.panelBackgroundColor, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight)
|
||||
self.textInputBackgroundNode.image = textInputBackgroundImage(backgroundColor: interfaceState.theme.chat.inputPanel.panelBackgroundColor, strokeColor: interfaceState.theme.chat.inputPanel.inputStrokeColor, diameter: minimalInputHeight)
|
||||
|
||||
self.searchLayoutClearButton.setImage(PresentationResourcesChat.chatInputTextFieldClearImage(interfaceState.theme), for: [])
|
||||
|
||||
|
|
@ -799,7 +801,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
var audioRecordingItemsVerticalOffset: CGFloat = 0.0
|
||||
if let mediaRecordingState = interfaceState.inputTextPanelState.mediaRecordingState {
|
||||
audioRecordingItemsVerticalOffset = panelHeight * 2.0
|
||||
transition.updateAlpha(layer: self.textInputBackgroundView.layer, alpha: 0.0)
|
||||
transition.updateAlpha(layer: self.textInputBackgroundNode.layer, alpha: 0.0)
|
||||
if let textInputNode = self.textInputNode {
|
||||
transition.updateAlpha(node: textInputNode, alpha: 0.0)
|
||||
}
|
||||
|
|
@ -908,7 +910,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
} else {
|
||||
self.actionButtons.micButton.audioRecorder = nil
|
||||
self.actionButtons.micButton.videoRecordingStatus = nil
|
||||
transition.updateAlpha(layer: self.textInputBackgroundView.layer, alpha: 1.0)
|
||||
transition.updateAlpha(layer: self.textInputBackgroundNode.layer, alpha: 1.0)
|
||||
if let textInputNode = self.textInputNode {
|
||||
transition.updateAlpha(node: textInputNode, alpha: 1.0)
|
||||
}
|
||||
|
|
@ -1056,7 +1058,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
|
||||
transition.updateFrame(node: self.textPlaceholderNode, frame: CGRect(origin: CGPoint(x: leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: textFieldInsets.top + self.textInputViewInternalInsets.top + self.textInputViewRealInsets.top + audioRecordingItemsVerticalOffset + UIScreenPixel), size: self.textPlaceholderNode.frame.size))
|
||||
|
||||
transition.updateFrame(layer: self.textInputBackgroundView.layer, frame: CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top + audioRecordingItemsVerticalOffset, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom))
|
||||
transition.updateFrame(layer: self.textInputBackgroundNode.layer, frame: CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top + audioRecordingItemsVerticalOffset, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom))
|
||||
|
||||
var nextButtonTopRight = CGPoint(x: width - rightInset - textFieldInsets.right - accessoryButtonInset, y: panelHeight - textFieldInsets.bottom - minimalInputHeight + audioRecordingItemsVerticalOffset)
|
||||
for (_, button) in self.accessoryItemButtons.reversed() {
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
|||
if peerView.peerId == self.account.peerId {
|
||||
string = NSAttributedString(string: self.strings.Conversation_SavedMessages, font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
} else {
|
||||
if !peerView.peerIsContact, let user = peer as? TelegramUser, let phone = user.phone, !phone.isEmpty {
|
||||
if !peerView.peerIsContact, let user = peer as? TelegramUser, !user.flags.contains(.isSupport), user.botInfo == nil, let phone = user.phone, !phone.isEmpty {
|
||||
string = NSAttributedString(string: formatPhoneNumber(phone), font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
} else {
|
||||
string = NSAttributedString(string: peer.displayTitle(strings: self.strings, displayOrder: self.nameDisplayOrder), font: Font.medium(17.0), textColor: self.theme.rootController.navigationBar.primaryTextColor)
|
||||
|
|
|
|||
|
|
@ -1009,7 +1009,7 @@ final class ContactListNode: ASDisplayNode {
|
|||
|> map { ($0.0, $0.1) }
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
let foundDeviceContacts: Signal<[DeviceContactStableId: DeviceContactBasicData], NoError>
|
||||
let foundDeviceContacts: Signal<[DeviceContactStableId: (DeviceContactBasicData, PeerId?)], NoError>
|
||||
if searchDeviceContacts {
|
||||
foundDeviceContacts = context.sharedContext.contactDataManager?.search(query: query) ?? .single([:])
|
||||
} else {
|
||||
|
|
@ -1106,13 +1106,18 @@ final class ContactListNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
outer: for (stableId, contact) in deviceContacts {
|
||||
inner: for phoneNumber in contact.phoneNumbers {
|
||||
inner: for phoneNumber in contact.0.phoneNumbers {
|
||||
let normalizedNumber = DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phoneNumber.value))
|
||||
if existingNormalizedPhoneNumbers.contains(normalizedNumber) {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
peers.append(.deviceContact(stableId, contact))
|
||||
if let peerId = contact.1 {
|
||||
if existingPeerIds.contains(peerId) {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
peers.append(.deviceContact(stableId, contact.0))
|
||||
}
|
||||
|
||||
let entries = contactListNodeEntries(accountPeer: nil, peers: peers, presences: localPeersAndStatuses.1, presentation: presentation, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, dateTimeFormat: themeAndStrings.2, sortOrder: themeAndStrings.3, displayOrder: themeAndStrings.4, disabledPeerIds: disabledPeerIds, authorizationStatus: .allowed, warningSuppressed: (true, true), displaySortOptions: false)
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ final class ContactsSearchContainerNode: SearchDisplayControllerContentNode {
|
|||
foundRemoteContacts = .single(([], []))
|
||||
}
|
||||
let searchDeviceContacts = categories.contains(.deviceContacts)
|
||||
let foundDeviceContacts: Signal<[DeviceContactStableId: DeviceContactBasicData]?, NoError>
|
||||
let foundDeviceContacts: Signal<[DeviceContactStableId: (DeviceContactBasicData, PeerId?)]?, NoError>
|
||||
if searchDeviceContacts, let contactDataManager = context.sharedContext.contactDataManager {
|
||||
foundDeviceContacts = contactDataManager.search(query: query)
|
||||
|> map(Optional.init)
|
||||
|
|
@ -271,13 +271,18 @@ final class ContactsSearchContainerNode: SearchDisplayControllerContentNode {
|
|||
}
|
||||
if let _ = remotePeers, let deviceContacts = deviceContacts {
|
||||
outer: for (stableId, contact) in deviceContacts {
|
||||
inner: for phoneNumber in contact.phoneNumbers {
|
||||
inner: for phoneNumber in contact.0.phoneNumbers {
|
||||
let normalizedNumber = DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phoneNumber.value))
|
||||
if existingNormalizedPhoneNumbers.contains(normalizedNumber) {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
entries.append(ContactListSearchEntry(index: index, theme: themeAndStrings.0, strings: themeAndStrings.1, peer: .deviceContact(stableId, contact), presence: nil, group: .deviceContacts, enabled: true))
|
||||
if let peerId = contact.1 {
|
||||
if existingPeerIds.contains(peerId) {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
entries.append(ContactListSearchEntry(index: index, theme: themeAndStrings.0, strings: themeAndStrings.1, peer: .deviceContact(stableId, contact.0), presence: nil, group: .deviceContacts, enabled: true))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -485,6 +485,7 @@ private final class DeviceContactDataManagerImpl {
|
|||
private var stableIdToBasicContactData: [DeviceContactStableId: DeviceContactBasicData] = [:]
|
||||
private var normalizedPhoneNumberToStableId: [DeviceContactNormalizedPhoneNumber: [DeviceContactStableId]] = [:]
|
||||
private var appSpecificReferences: [PeerId: DeviceContactBasicDataWithReference] = [:]
|
||||
private var stableIdToAppSpecificReference: [DeviceContactStableId: PeerId] = [:]
|
||||
|
||||
private var importableContacts: [DeviceContactNormalizedPhoneNumber: ImportableDeviceContactData] = [:]
|
||||
|
||||
|
|
@ -616,6 +617,11 @@ private final class DeviceContactDataManagerImpl {
|
|||
|
||||
private func updateAppSpecificReferences(appSpecificReferences: [PeerId: DeviceContactBasicDataWithReference]) {
|
||||
self.appSpecificReferences = appSpecificReferences
|
||||
var stableIdToAppSpecificReference: [DeviceContactStableId: PeerId] = [:]
|
||||
for (peerId, value) in appSpecificReferences {
|
||||
stableIdToAppSpecificReference[value.stableId] = peerId
|
||||
}
|
||||
self.stableIdToAppSpecificReference = stableIdToAppSpecificReference
|
||||
for f in self.appSpecificReferencesSubscribers.copyItems() {
|
||||
f(appSpecificReferences)
|
||||
}
|
||||
|
|
@ -721,12 +727,12 @@ private final class DeviceContactDataManagerImpl {
|
|||
}
|
||||
}
|
||||
|
||||
func search(query: String, updated: @escaping ([DeviceContactStableId: DeviceContactBasicData]) -> Void) -> Disposable {
|
||||
func search(query: String, updated: @escaping ([DeviceContactStableId: (DeviceContactBasicData, PeerId?)]) -> Void) -> Disposable {
|
||||
let normalizedQuery = query.lowercased()
|
||||
var result: [DeviceContactStableId: DeviceContactBasicData] = [:]
|
||||
var result: [DeviceContactStableId: (DeviceContactBasicData, PeerId?)] = [:]
|
||||
for (stableId, basicData) in self.stableIdToBasicContactData {
|
||||
if basicData.firstName.lowercased().hasPrefix(normalizedQuery) || basicData.lastName.lowercased().hasPrefix(normalizedQuery) {
|
||||
result[stableId] = basicData
|
||||
result[stableId] = (basicData, self.stableIdToAppSpecificReference[stableId])
|
||||
}
|
||||
}
|
||||
updated(result)
|
||||
|
|
@ -837,7 +843,7 @@ public final class DeviceContactDataManager {
|
|||
}
|
||||
}
|
||||
|
||||
public func search(query: String) -> Signal<[DeviceContactStableId: DeviceContactBasicData], NoError> {
|
||||
public func search(query: String) -> Signal<[DeviceContactStableId: (DeviceContactBasicData, PeerId?)], NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
self.impl.with({ impl in
|
||||
|
|
|
|||
|
|
@ -414,9 +414,9 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
|||
arguments.setPhoneIdWithRevealedOptions(lhs, rhs)
|
||||
}, updated: { value in
|
||||
arguments.updatePhone(id, value)
|
||||
}, selectLabel: {
|
||||
}, selectLabel: nil /*{
|
||||
arguments.updatePhoneLabel(id, label)
|
||||
}, delete: {
|
||||
}*/, delete: {
|
||||
arguments.deletePhone(id)
|
||||
}, tag: DeviceContactInfoEntryTag.editingPhone(id))
|
||||
case let .addPhoneNumber(_, theme, title):
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ final class HashtagSearchController: TelegramController {
|
|||
let search = searchMessages(account: context.account, location: location, query: query, state: nil)
|
||||
let foundMessages: Signal<[ChatListSearchEntry], NoError> = search
|
||||
|> map { result, _ in
|
||||
return result.messages.map({ .message($0, result.readStates[$0.id.peerId], chatListPresentationData) })
|
||||
return result.messages.map({ .message($0, RenderedPeer(message: $0), result.readStates[$0.id.peerId], chatListPresentationData) })
|
||||
}
|
||||
let interaction = ChatListNodeInteraction(activateSearch: {
|
||||
}, peerSelected: { peer in
|
||||
|
|
|
|||
|
|
@ -351,20 +351,22 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
|||
self?.requestShareTelegram?()
|
||||
})
|
||||
|
||||
let existingNumbers: Signal<Set<String>, NoError> = account.postbox.contactPeersView(accountPeerId: nil, includePresences: false)
|
||||
|> map { view -> Set<String> in
|
||||
let existingNumbers: Signal<(Set<String>, Set<PeerId>), NoError> = account.postbox.contactPeersView(accountPeerId: nil, includePresences: false)
|
||||
|> map { view -> (Set<String>, Set<PeerId>) in
|
||||
var existingNumbers = Set<String>()
|
||||
var existingPeerIds = Set<PeerId>()
|
||||
for peer in view.peers {
|
||||
if let peer = peer as? TelegramUser, let phone = peer.phone {
|
||||
existingNumbers.insert(formatPhoneNumber(phone))
|
||||
}
|
||||
existingPeerIds.insert(peer.id)
|
||||
}
|
||||
return existingNumbers
|
||||
return (existingNumbers, existingPeerIds)
|
||||
}
|
||||
|
||||
let currentSortedContacts = self.currentSortedContacts
|
||||
let sortedContacts: Signal<[(DeviceContactStableId, DeviceContactBasicData, Int32)], NoError> = combineLatest(existingNumbers, (context.sharedContext.contactDataManager?.basicData() ?? .single([:])) |> take(1))
|
||||
|> mapToSignal { existingNumbers, contacts -> Signal<[(DeviceContactStableId, DeviceContactBasicData, Int32)], NoError> in
|
||||
|> mapToSignal { existingNumbersAndPeerIds, contacts -> Signal<[(DeviceContactStableId, DeviceContactBasicData, Int32)], NoError> in
|
||||
var mappedContacts: [(String, [DeviceContactNormalizedPhoneNumber])] = []
|
||||
for (id, basicData) in contacts {
|
||||
mappedContacts.append((id: id, basicData.phoneNumbers.map({ phoneNumber in
|
||||
|
|
@ -378,7 +380,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
|||
for (id, basicData) in contacts {
|
||||
var found = false
|
||||
for number in basicData.phoneNumbers {
|
||||
if existingNumbers.contains(formatPhoneNumber(number.value)) {
|
||||
if existingNumbersAndPeerIds.0.contains(formatPhoneNumber(number.value)) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func loadLegacyUser(database: SqliteInterface, id: Int32) -> (TelegramUser, Tele
|
|||
photo.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: 600.0, height: 600.0), resource: resource))
|
||||
}
|
||||
|
||||
let user = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: cursor.getInt32(at: 0)), accessHash: accessHash == 0 ? nil : accessHash, firstName: firstName.isEmpty ? nil : firstName, lastName: lastName.isEmpty ? nil : lastName, username: username.isEmpty ? nil : username, phone: phone.isEmpty ? nil : phone, photo: photo, botInfo: nil, restrictionInfo: nil, flags: [])
|
||||
let user = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: cursor.getInt32(at: 0)), accessHash: accessHash == 0 ? nil : .personal(accessHash), firstName: firstName.isEmpty ? nil : firstName, lastName: lastName.isEmpty ? nil : lastName, username: username.isEmpty ? nil : username, phone: phone.isEmpty ? nil : phone, photo: photo, botInfo: nil, restrictionInfo: nil, flags: [])
|
||||
|
||||
let status: UserPresenceStatus
|
||||
let lastSeen = cursor.getInt32(at: 7)
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@ public enum NavigateToChatKeepStack {
|
|||
case never
|
||||
}
|
||||
|
||||
public func navigateToChatController(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, messageId: MessageId? = nil, botStart: ChatControllerInitialBotStart? = nil, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, animated: Bool = true, parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) {
|
||||
public func navigateToChatController(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, messageId: MessageId? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, animated: Bool = true, parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) {
|
||||
var found = false
|
||||
var isFirst = true
|
||||
for controller in navigationController.viewControllers.reversed() {
|
||||
if let controller = controller as? ChatController, controller.chatLocation == chatLocation {
|
||||
if let updateTextInputState = updateTextInputState {
|
||||
controller.updateTextInputState(updateTextInputState)
|
||||
}
|
||||
if let messageId = messageId {
|
||||
controller.navigateToMessage(messageLocation: .id(messageId), animated: isFirst, completion: { [weak navigationController, weak controller] in
|
||||
if let navigationController = navigationController, let controller = controller {
|
||||
|
|
|
|||
|
|
@ -883,6 +883,7 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
|
|||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: presentationData.strings.Notification_Exceptions_DeleteAllConfirmation),
|
||||
ActionSheetButtonItem(title: presentationData.strings.Notification_Exceptions_DeleteAll, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
|
||||
|
|
|
|||
|
|
@ -219,27 +219,36 @@ func playSound(context: AccountContext, sound: PeerMessageSound, defaultSound: P
|
|||
var currentPlayer: AudioPlayerWrapper?
|
||||
var deactivateImpl: (() -> Void)?
|
||||
let session = context.sharedContext.mediaManager.audioSession.push(audioSessionType: .play, activate: { _ in
|
||||
if let url = Bundle.main.url(forResource: fileNameForNotificationSound(sound, defaultSound: defaultSound), withExtension: "m4a") {
|
||||
currentPlayer = AudioPlayerWrapper(url: url, completed: {
|
||||
deactivateImpl?()
|
||||
})
|
||||
currentPlayer?.play()
|
||||
Queue.mainQueue().async {
|
||||
if let url = Bundle.main.url(forResource: fileNameForNotificationSound(sound, defaultSound: defaultSound), withExtension: "m4a") {
|
||||
currentPlayer = AudioPlayerWrapper(url: url, completed: {
|
||||
deactivateImpl?()
|
||||
})
|
||||
currentPlayer?.play()
|
||||
}
|
||||
}
|
||||
}, deactivate: {
|
||||
currentPlayer?.stop()
|
||||
currentPlayer = nil
|
||||
|
||||
return .complete()
|
||||
return Signal { subscriber in
|
||||
Queue.mainQueue().async {
|
||||
currentPlayer?.stop()
|
||||
currentPlayer = nil
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
return EmptyDisposable
|
||||
}
|
||||
})
|
||||
deactivateImpl = {
|
||||
session.dispose()
|
||||
}
|
||||
return ActionDisposable {
|
||||
session.dispose()
|
||||
currentPlayer?.stop()
|
||||
currentPlayer = nil
|
||||
Queue.mainQueue().async {
|
||||
currentPlayer?.stop()
|
||||
currentPlayer = nil
|
||||
}
|
||||
}
|
||||
} |> runOn(Queue.mainQueue())
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1002,7 +1002,7 @@ public func notificationsAndSoundsController(context: AccountContext, exceptions
|
|||
let sharedData = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.inAppNotificationSettings])
|
||||
let preferences = context.account.postbox.preferencesView(keys: [PreferencesKeys.globalNotifications])
|
||||
|
||||
let exceptionsSignal = Signal<NotificationExceptionsList?, NoError>.single(exceptionsList) |> then(notificationExceptionsList(network: context.account.network) |> map(Optional.init))
|
||||
let exceptionsSignal = Signal<NotificationExceptionsList?, NoError>.single(exceptionsList) |> then(notificationExceptionsList(postbox: context.account.postbox, network: context.account.network) |> map(Optional.init))
|
||||
|
||||
notificationExceptions.set(exceptionsSignal |> map { list -> (NotificationExceptionMode, NotificationExceptionMode, NotificationExceptionMode) in
|
||||
var users:[PeerId : NotificationExceptionWrapper] = [:]
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1074,7 +1074,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||
|> mapToSignal { context -> Signal<NotificationExceptionsList?, NoError> in
|
||||
return .single(NotificationExceptionsList(peers: [:], settings: [:]))
|
||||
|> then(
|
||||
notificationExceptionsList(network: context.account.network)
|
||||
notificationExceptionsList(postbox: context.account.postbox, network: context.account.network)
|
||||
|> map(Optional.init)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode {
|
|||
strongSelf.leftActionTextNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
self.leftActionNode.highligthedChanged = { [weak self] highlighted in
|
||||
self.rightActionNode.highligthedChanged = { [weak self] highlighted in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -773,6 +773,7 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
|
|||
var botAddToGroupImpl: (() -> Void)?
|
||||
var shareBotImpl: (() -> Void)?
|
||||
var dismissInputImpl: (() -> Void)?
|
||||
var dismissImpl: (() -> Void)?
|
||||
|
||||
let actionsDisposable = DisposableSet()
|
||||
|
||||
|
|
@ -1066,7 +1067,9 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
|
|||
}
|
||||
|
||||
updatePeerBlockedDisposable.set((deleteSignal
|
||||
|> deliverOnMainQueue).start())
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
dismissImpl?()
|
||||
}))
|
||||
})
|
||||
})
|
||||
]),
|
||||
|
|
@ -1288,6 +1291,12 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Us
|
|||
pushControllerImpl = { [weak controller] value in
|
||||
(controller?.navigationController as? NavigationController)?.pushViewController(value)
|
||||
}
|
||||
dismissImpl = { [weak controller] in
|
||||
guard let controller = controller else {
|
||||
return
|
||||
}
|
||||
(controller.navigationController as? NavigationController)?.filterController(controller, animated: true)
|
||||
}
|
||||
presentControllerImpl = { [weak controller] value, presentationArguments in
|
||||
controller?.present(value, in: .window(.root), with: presentationArguments, blockInteraction: true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@ class UserInfoEditingPhoneItem: ListViewItem, ItemListItem {
|
|||
let sectionId: ItemListSectionId
|
||||
let setPhoneIdWithRevealedOptions: (Int64?, Int64?) -> Void
|
||||
let updated: (String) -> Void
|
||||
let selectLabel: () -> Void
|
||||
let selectLabel: (() -> Void)?
|
||||
let delete: () -> Void
|
||||
let tag: ItemListItemTag?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, id: Int64, label: String, value: String, editing: UserInfoEditingPhoneItemEditing, sectionId: ItemListSectionId, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, updated: @escaping (String) -> Void, selectLabel: @escaping () -> Void, delete: @escaping () -> Void, tag: ItemListItemTag?) {
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, id: Int64, label: String, value: String, editing: UserInfoEditingPhoneItemEditing, sectionId: ItemListSectionId, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, updated: @escaping (String) -> Void, selectLabel: (() -> Void)?, delete: @escaping () -> Void, tag: ItemListItemTag?) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.id = id
|
||||
|
|
@ -237,6 +237,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
|||
let labelFrame = CGRect(origin: CGPoint(x: revealOffset + leftInset + 30.0, y: 12.0), size: labelLayout.size)
|
||||
strongSelf.labelNode.frame = labelFrame
|
||||
strongSelf.labelButtonNode.frame = labelFrame
|
||||
strongSelf.labelButtonNode.isUserInteractionEnabled = item.selectLabel != nil
|
||||
strongSelf.labelSeparatorNode.frame = CGRect(origin: CGPoint(x: labelFrame.maxX + 8.0, y: 0.0), size: CGSize(width: UIScreenPixel, height: layout.contentSize.height))
|
||||
|
||||
let phoneX = labelFrame.maxX + 16.0
|
||||
|
|
@ -293,7 +294,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
|||
}
|
||||
|
||||
@objc func labelPressed() {
|
||||
self.item?.selectLabel()
|
||||
self.item?.selectLabel?()
|
||||
}
|
||||
|
||||
func focus() {
|
||||
|
|
|
|||
|
|
@ -317,6 +317,7 @@
|
|||
D02D60B1206C189900FEFE1E /* SecureIdPlaintextFormController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02D60B0206C189900FEFE1E /* SecureIdPlaintextFormController.swift */; };
|
||||
D02D60B3206C18A600FEFE1E /* SecureIdPlaintextFormControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02D60B2206C18A600FEFE1E /* SecureIdPlaintextFormControllerNode.swift */; };
|
||||
D02D60C8206E705D00FEFE1E /* SecureIdValueFormPhoneItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02D60C7206E705D00FEFE1E /* SecureIdValueFormPhoneItem.swift */; };
|
||||
D02D634A22B85B94006BE519 /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D02D634922B85B94006BE519 /* PushKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
D02F4AE91FCF370B004DFBAE /* ChatMessageInteractiveMediaBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02F4AE81FCF370B004DFBAE /* ChatMessageInteractiveMediaBadge.swift */; };
|
||||
D02F4AF01FD4C46D004DFBAE /* SystemVideoContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02F4AEF1FD4C46D004DFBAE /* SystemVideoContent.swift */; };
|
||||
D035734B22B5CCCA00F0920D /* LegacyBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035734A22B5CCCA00F0920D /* LegacyBuffer.swift */; };
|
||||
|
|
@ -332,6 +333,8 @@
|
|||
D03AA4DF202DBF6F0056C405 /* ChatContextResultPeekContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03AA4DE202DBF6F0056C405 /* ChatContextResultPeekContentNode.swift */; };
|
||||
D03AA4E5202DF8840056C405 /* StickerPreviewPeekContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03AA4E4202DF8840056C405 /* StickerPreviewPeekContent.swift */; };
|
||||
D03AA4E7202DFB160056C405 /* ItemListEditableReorderControlNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03AA4E6202DFB160056C405 /* ItemListEditableReorderControlNode.swift */; };
|
||||
D03AE67322B9459C0078411C /* HockeySDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03AE67222B9459C0078411C /* HockeySDK.framework */; };
|
||||
D03AE67522B945D30078411C /* BuildConfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D03AE67422B945D30078411C /* BuildConfig.framework */; };
|
||||
D04203152037162700490EA5 /* MediaInputPaneTrendingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04203142037162700490EA5 /* MediaInputPaneTrendingItem.swift */; };
|
||||
D04281ED200E3B28009DDE36 /* ItemListControllerSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04281EC200E3B28009DDE36 /* ItemListControllerSearch.swift */; };
|
||||
D04281EF200E3D88009DDE36 /* GroupInfoSearchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04281EE200E3D88009DDE36 /* GroupInfoSearchItem.swift */; };
|
||||
|
|
@ -1574,6 +1577,7 @@
|
|||
D02D60B0206C189900FEFE1E /* SecureIdPlaintextFormController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdPlaintextFormController.swift; sourceTree = "<group>"; };
|
||||
D02D60B2206C18A600FEFE1E /* SecureIdPlaintextFormControllerNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdPlaintextFormControllerNode.swift; sourceTree = "<group>"; };
|
||||
D02D60C7206E705D00FEFE1E /* SecureIdValueFormPhoneItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdValueFormPhoneItem.swift; sourceTree = "<group>"; };
|
||||
D02D634922B85B94006BE519 /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = System/Library/Frameworks/PushKit.framework; sourceTree = SDKROOT; };
|
||||
D02DADBE2138D76F00116225 /* Vision.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vision.framework; path = System/Library/Frameworks/Vision.framework; sourceTree = SDKROOT; };
|
||||
D02F4AE81FCF370B004DFBAE /* ChatMessageInteractiveMediaBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMessageInteractiveMediaBadge.swift; sourceTree = "<group>"; };
|
||||
D02F4AEF1FD4C46D004DFBAE /* SystemVideoContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemVideoContent.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -1599,6 +1603,8 @@
|
|||
D03ADB4A1D70443F005A521C /* ReplyAccessoryPanelNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReplyAccessoryPanelNode.swift; sourceTree = "<group>"; };
|
||||
D03ADB4C1D7045C9005A521C /* ChatInterfaceStateAccessoryPanels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatInterfaceStateAccessoryPanels.swift; sourceTree = "<group>"; };
|
||||
D03ADB4E1D70546B005A521C /* AccessoryPanelNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessoryPanelNode.swift; sourceTree = "<group>"; };
|
||||
D03AE67222B9459C0078411C /* HockeySDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = HockeySDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03AE67422B945D30078411C /* BuildConfig.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = BuildConfig.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D03E5E081E55C49C0029569A /* DebugAccountsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugAccountsController.swift; sourceTree = "<group>"; };
|
||||
D03E5E0E1E55F8B90029569A /* ChannelVisibilityController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelVisibilityController.swift; sourceTree = "<group>"; };
|
||||
D04203142037162700490EA5 /* MediaInputPaneTrendingItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaInputPaneTrendingItem.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -2383,6 +2389,9 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D03AE67522B945D30078411C /* BuildConfig.framework in Frameworks */,
|
||||
D03AE67322B9459C0078411C /* HockeySDK.framework in Frameworks */,
|
||||
D02D634A22B85B94006BE519 /* PushKit.framework in Frameworks */,
|
||||
D00818CD22B595CB008A895F /* LightweightAccountData.framework in Frameworks */,
|
||||
D008184A22B57225008A895F /* WatchCommon.framework in Frameworks */,
|
||||
D0750C7A22B2A14300BE5F6E /* DeviceAccess.framework in Frameworks */,
|
||||
|
|
@ -3489,6 +3498,9 @@
|
|||
D08D45281D5E340200A7428A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D03AE67422B945D30078411C /* BuildConfig.framework */,
|
||||
D03AE67222B9459C0078411C /* HockeySDK.framework */,
|
||||
D02D634922B85B94006BE519 /* PushKit.framework */,
|
||||
D00818CC22B595CB008A895F /* LightweightAccountData.framework */,
|
||||
D008184922B57225008A895F /* WatchCommon.framework */,
|
||||
D0750C7922B2A14300BE5F6E /* DeviceAccess.framework */,
|
||||
|
|
|
|||
|
|
@ -733,11 +733,12 @@
|
|||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
|
|
@ -764,12 +765,14 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "-DTARGET_OS_WATCH=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.WatchCommonWatch;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
|
|
@ -778,7 +781,7 @@
|
|||
TARGETED_DEVICE_FAMILY = 4;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 5.1;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.2;
|
||||
};
|
||||
name = DebugAppStoreLLC;
|
||||
};
|
||||
|
|
@ -816,11 +819,12 @@
|
|||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
|
|
@ -841,11 +845,13 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_CFLAGS = "-DTARGET_OS_WATCH=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.WatchCommonWatch;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
|
@ -855,7 +861,7 @@
|
|||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 5.1;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.2;
|
||||
};
|
||||
name = ReleaseAppStoreLLC;
|
||||
};
|
||||
|
|
@ -984,11 +990,12 @@
|
|||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
|
|
@ -1015,12 +1022,14 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "-DTARGET_OS_WATCH=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.WatchCommonWatch;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
|
|
@ -1029,7 +1038,7 @@
|
|||
TARGETED_DEVICE_FAMILY = 4;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 5.1;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.2;
|
||||
};
|
||||
name = DebugHockeyapp;
|
||||
};
|
||||
|
|
@ -1152,11 +1161,12 @@
|
|||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
|
|
@ -1177,11 +1187,13 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACH_O_TYPE = staticlib;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
OTHER_CFLAGS = "-DTARGET_OS_WATCH=1";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.telegram.WatchCommonWatch;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
|
@ -1191,7 +1203,7 @@
|
|||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 5.1;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.2;
|
||||
};
|
||||
name = ReleaseHockeyappInternal;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Lottie.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>4</integer>
|
||||
</dict>
|
||||
<key>Lottie_iOS.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>44</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
Loading…
Add table
Add a link
Reference in a new issue