mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
86e3e2bc35
@ -818,9 +818,9 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let peersDisablingAddressNameAssignment = Promise<[Peer]?>()
|
let peersDisablingAddressNameAssignment = Promise<[Peer]?>()
|
||||||
peersDisablingAddressNameAssignment.set(.single(nil) |> then(channelAddressNameAssignmentAvailability(account: context.account, peerId: peerId.namespace == Namespaces.Peer.CloudChannel ? peerId : nil) |> mapToSignal { result -> Signal<[Peer]?, NoError> in
|
peersDisablingAddressNameAssignment.set(.single(nil) |> then(context.engine.peerNames.channelAddressNameAssignmentAvailability(peerId: peerId.namespace == Namespaces.Peer.CloudChannel ? peerId : nil) |> mapToSignal { result -> Signal<[Peer]?, NoError> in
|
||||||
if case .addressNameLimitReached = result {
|
if case .addressNameLimitReached = result {
|
||||||
return adminedPublicChannels(account: context.account, scope: .all)
|
return context.engine.peerNames.adminedPublicChannels(scope: .all)
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
} else {
|
} else {
|
||||||
return .single([])
|
return .single([])
|
||||||
@ -871,7 +871,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
|||||||
return state.withUpdatedEditingPublicLinkText(text)
|
return state.withUpdatedEditingPublicLinkText(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAddressNameDisposable.set((validateAddressNameInteractive(account: context.account, domain: .peer(peerId), name: text)
|
checkAddressNameDisposable.set((context.engine.peerNames.validateAddressNameInteractive(domain: .peer(peerId), name: text)
|
||||||
|> deliverOnMainQueue).start(next: { result in
|
|> deliverOnMainQueue).start(next: { result in
|
||||||
updateState { state in
|
updateState { state in
|
||||||
return state.withUpdatedAddressNameValidationStatus(result)
|
return state.withUpdatedAddressNameValidationStatus(result)
|
||||||
@ -893,7 +893,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
|||||||
return state.withUpdatedRevokingPeerId(peerId)
|
return state.withUpdatedRevokingPeerId(peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
revokeAddressNameDisposable.set((updateAddressName(account: context.account, domain: .peer(peerId), name: nil) |> deliverOnMainQueue).start(error: { _ in
|
revokeAddressNameDisposable.set((context.engine.peerNames.updateAddressName(domain: .peer(peerId), name: nil) |> deliverOnMainQueue).start(error: { _ in
|
||||||
updateState { state in
|
updateState { state in
|
||||||
return state.withUpdatedRevokingPeerId(nil)
|
return state.withUpdatedRevokingPeerId(nil)
|
||||||
}
|
}
|
||||||
@ -1101,7 +1101,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
|||||||
}
|
}
|
||||||
_ = ApplicationSpecificNotice.markAsSeenSetPublicChannelLink(accountManager: context.sharedContext.accountManager).start()
|
_ = ApplicationSpecificNotice.markAsSeenSetPublicChannelLink(accountManager: context.sharedContext.accountManager).start()
|
||||||
|
|
||||||
updateAddressNameDisposable.set((updateAddressName(account: context.account, domain: .peer(peerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic))
|
updateAddressNameDisposable.set((context.engine.peerNames.updateAddressName(domain: .peer(peerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic))
|
||||||
|> deliverOnMainQueue).start(error: { _ in
|
|> deliverOnMainQueue).start(error: { _ in
|
||||||
updateState { state in
|
updateState { state in
|
||||||
return state.withUpdatedUpdatingAddressName(false)
|
return state.withUpdatedUpdatingAddressName(false)
|
||||||
@ -1173,7 +1173,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
|||||||
|
|
||||||
let signal = convertGroupToSupergroup(account: context.account, peerId: peerId)
|
let signal = convertGroupToSupergroup(account: context.account, peerId: peerId)
|
||||||
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ConvertGroupToSupergroupError> in
|
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ConvertGroupToSupergroupError> in
|
||||||
return updateAddressName(account: context.account, domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
return context.engine.peerNames.updateAddressName(domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
||||||
|> `catch` { _ -> Signal<Void, NoError> in
|
|> `catch` { _ -> Signal<Void, NoError> in
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|
@ -512,7 +512,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
|
|||||||
cancelImpl = {
|
cancelImpl = {
|
||||||
checkCreationAvailabilityDisposable.set(nil)
|
checkCreationAvailabilityDisposable.set(nil)
|
||||||
}
|
}
|
||||||
checkCreationAvailabilityDisposable.set((checkPublicChannelCreationAvailability(account: context.account, location: true)
|
checkCreationAvailabilityDisposable.set((context.engine.peerNames.checkPublicChannelCreationAvailability(location: true)
|
||||||
|> afterDisposed {
|
|> afterDisposed {
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
progressDisposable.dispose()
|
progressDisposable.dispose()
|
||||||
|
@ -157,7 +157,7 @@ public func logoutOptionsController(context: AccountContext, navigationControlle
|
|||||||
dismissImpl?()
|
dismissImpl?()
|
||||||
}, contactSupport: { [weak navigationController] in
|
}, contactSupport: { [weak navigationController] in
|
||||||
let supportPeer = Promise<PeerId?>()
|
let supportPeer = Promise<PeerId?>()
|
||||||
supportPeer.set(supportPeerId(account: context.account))
|
supportPeer.set(context.engine.peerNames.supportPeerId())
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
var faqUrl = presentationData.strings.Settings_FAQ_URL
|
var faqUrl = presentationData.strings.Settings_FAQ_URL
|
||||||
|
@ -883,7 +883,7 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
|
|||||||
}
|
}
|
||||||
|
|
||||||
let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: synonyms(strings.SettingsSearch_Synonyms_Support), icon: .support, breadcrumbs: [], present: { context, _, present in
|
let support = SettingsSearchableItem(id: .support(0), title: strings.Settings_Support, alternate: synonyms(strings.SettingsSearch_Synonyms_Support), icon: .support, breadcrumbs: [], present: { context, _, present in
|
||||||
let _ = (supportPeerId(account: context.account)
|
let _ = (context.engine.peerNames.supportPeerId()
|
||||||
|> deliverOnMainQueue).start(next: { peerId in
|
|> deliverOnMainQueue).start(next: { peerId in
|
||||||
if let peerId = peerId {
|
if let peerId = peerId {
|
||||||
present(.push, context.sharedContext.makeChatController(context: context, chatLocation: .peer(peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
present(.push, context.sharedContext.makeChatController(context: context, chatLocation: .peer(peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
||||||
|
@ -260,7 +260,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController {
|
|||||||
return state.withUpdatedEditingPublicLinkText(text)
|
return state.withUpdatedEditingPublicLinkText(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAddressNameDisposable.set((validateAddressNameInteractive(account: context.account, domain: .account, name: text)
|
checkAddressNameDisposable.set((context.engine.peerNames.validateAddressNameInteractive(domain: .account, name: text)
|
||||||
|> deliverOnMainQueue).start(next: { result in
|
|> deliverOnMainQueue).start(next: { result in
|
||||||
updateState { state in
|
updateState { state in
|
||||||
return state.withUpdatedAddressNameValidationStatus(result)
|
return state.withUpdatedAddressNameValidationStatus(result)
|
||||||
@ -325,7 +325,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let updatedAddressNameValue = updatedAddressNameValue {
|
if let updatedAddressNameValue = updatedAddressNameValue {
|
||||||
updateAddressNameDisposable.set((updateAddressName(account: context.account, domain: .account, name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
updateAddressNameDisposable.set((context.engine.peerNames.updateAddressName(domain: .account, name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|
||||||
|> deliverOnMainQueue).start(error: { _ in
|
|> deliverOnMainQueue).start(error: { _ in
|
||||||
updateState { state in
|
updateState { state in
|
||||||
return state.withUpdatedUpdatingAddressName(false)
|
return state.withUpdatedUpdatingAddressName(false)
|
||||||
|
@ -202,7 +202,6 @@ private enum PreferencesKeyValues: Int32 {
|
|||||||
case globalNotifications = 0
|
case globalNotifications = 0
|
||||||
case suggestedLocalization = 3
|
case suggestedLocalization = 3
|
||||||
case limitsConfiguration = 4
|
case limitsConfiguration = 4
|
||||||
case coreSettings = 7
|
|
||||||
case contentPrivacySettings = 8
|
case contentPrivacySettings = 8
|
||||||
case networkSettings = 9
|
case networkSettings = 9
|
||||||
case remoteStorageConfiguration = 10
|
case remoteStorageConfiguration = 10
|
||||||
@ -251,12 +250,6 @@ public struct PreferencesKeys {
|
|||||||
return key
|
return key
|
||||||
}()
|
}()
|
||||||
|
|
||||||
public static let coreSettings: ValueBoxKey = {
|
|
||||||
let key = ValueBoxKey(length: 4)
|
|
||||||
key.setInt32(0, value: PreferencesKeyValues.coreSettings.rawValue)
|
|
||||||
return key
|
|
||||||
}()
|
|
||||||
|
|
||||||
public static let contentPrivacySettings: ValueBoxKey = {
|
public static let contentPrivacySettings: ValueBoxKey = {
|
||||||
let key = ValueBoxKey(length: 4)
|
let key = ValueBoxKey(length: 4)
|
||||||
key.setInt32(0, value: PreferencesKeyValues.contentPrivacySettings.rawValue)
|
key.setInt32(0, value: PreferencesKeyValues.contentPrivacySettings.rawValue)
|
||||||
|
@ -1,292 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import Postbox
|
|
||||||
import SwiftSignalKit
|
|
||||||
import TelegramApi
|
|
||||||
import MtProtoKit
|
|
||||||
|
|
||||||
import SyncCore
|
|
||||||
|
|
||||||
private struct LocalChatListEntryRange {
|
|
||||||
var entries: [ChatListNamespaceEntry]
|
|
||||||
var upperBound: ChatListIndex?
|
|
||||||
var lowerBound: ChatListIndex
|
|
||||||
var count: Int32
|
|
||||||
var hash: UInt32
|
|
||||||
|
|
||||||
var apiHash: Int32 {
|
|
||||||
return Int32(bitPattern: self.hash & UInt32(0x7FFFFFFF))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func combineHash(_ value: Int32, into hash: inout UInt32) {
|
|
||||||
let low = UInt32(bitPattern: value)
|
|
||||||
hash = (hash &* 20261) &+ low
|
|
||||||
}
|
|
||||||
|
|
||||||
private func combineChatListNamespaceEntryHash(index: ChatListIndex, readState: PeerReadState?, topMessageAttributes: [MessageAttribute], tagSummary: MessageHistoryTagNamespaceSummary?, interfaceState: PeerChatInterfaceState?, into hash: inout UInt32) {
|
|
||||||
/*
|
|
||||||
dialog.pinned ? 1 : 0,
|
|
||||||
dialog.unread_mark ? 1 : 0,
|
|
||||||
dialog.peer.channel_id || dialog.peer.chat_id || dialog.peer.user_id,
|
|
||||||
dialog.top_message.id,
|
|
||||||
top_message.edit_date || top_message.date,
|
|
||||||
dialog.read_inbox_max_id,
|
|
||||||
dialog.read_outbox_max_id,
|
|
||||||
dialog.unread_count,
|
|
||||||
dialog.unread_mentions_count,
|
|
||||||
draft.draft.date || 0
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
combineHash(index.pinningIndex != nil ? 1 : 0, into: &hash)
|
|
||||||
if let readState = readState, readState.markedUnread {
|
|
||||||
combineHash(1, into: &hash)
|
|
||||||
} else {
|
|
||||||
combineHash(0, into: &hash)
|
|
||||||
}
|
|
||||||
combineHash(index.messageIndex.id.peerId.id, into: &hash)
|
|
||||||
combineHash(index.messageIndex.id.id, into: &hash)
|
|
||||||
var timestamp = index.messageIndex.timestamp
|
|
||||||
for attribute in topMessageAttributes {
|
|
||||||
if let attribute = attribute as? EditedMessageAttribute {
|
|
||||||
timestamp = max(timestamp, attribute.date)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
combineHash(timestamp, into: &hash)
|
|
||||||
if let readState = readState, case let .idBased(maxIncomingReadId, maxOutgoingReadId, _, count, _) = readState {
|
|
||||||
combineHash(maxIncomingReadId, into: &hash)
|
|
||||||
combineHash(maxOutgoingReadId, into: &hash)
|
|
||||||
combineHash(count, into: &hash)
|
|
||||||
} else {
|
|
||||||
combineHash(0, into: &hash)
|
|
||||||
combineHash(0, into: &hash)
|
|
||||||
combineHash(0, into: &hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let tagSummary = tagSummary {
|
|
||||||
combineHash(tagSummary.count, into: &hash)
|
|
||||||
} else {
|
|
||||||
combineHash(0, into: &hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let embeddedState = interfaceState?.chatListEmbeddedState {
|
|
||||||
combineHash(embeddedState.timestamp, into: &hash)
|
|
||||||
} else {
|
|
||||||
combineHash(0, into: &hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func localChatListEntryRanges(_ entries: [ChatListNamespaceEntry], limit: Int) -> [LocalChatListEntryRange] {
|
|
||||||
var result: [LocalChatListEntryRange] = []
|
|
||||||
var currentRange: LocalChatListEntryRange?
|
|
||||||
for i in 0 ..< entries.count {
|
|
||||||
switch entries[i] {
|
|
||||||
case let .peer(index, readState, topMessageAttributes, tagSummary, interfaceState):
|
|
||||||
var updatedRange: LocalChatListEntryRange
|
|
||||||
if let current = currentRange {
|
|
||||||
updatedRange = current
|
|
||||||
} else {
|
|
||||||
updatedRange = LocalChatListEntryRange(entries: [], upperBound: result.last?.lowerBound, lowerBound: index, count: 0, hash: 0)
|
|
||||||
}
|
|
||||||
updatedRange.entries.append(entries[i])
|
|
||||||
updatedRange.lowerBound = index
|
|
||||||
updatedRange.count += 1
|
|
||||||
|
|
||||||
combineChatListNamespaceEntryHash(index: index, readState: readState, topMessageAttributes: topMessageAttributes, tagSummary: tagSummary, interfaceState: interfaceState, into: &updatedRange.hash)
|
|
||||||
|
|
||||||
if Int(updatedRange.count) >= limit {
|
|
||||||
result.append(updatedRange)
|
|
||||||
currentRange = nil
|
|
||||||
} else {
|
|
||||||
currentRange = updatedRange
|
|
||||||
}
|
|
||||||
case .hole:
|
|
||||||
if let currentRangeValue = currentRange {
|
|
||||||
result.append(currentRangeValue)
|
|
||||||
currentRange = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let currentRangeValue = currentRange {
|
|
||||||
result.append(currentRangeValue)
|
|
||||||
currentRange = nil
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct ResolvedChatListResetRange {
|
|
||||||
let head: Bool
|
|
||||||
let local: LocalChatListEntryRange
|
|
||||||
let remote: FetchedChatList
|
|
||||||
}
|
|
||||||
|
|
||||||
/*func accountStateReset(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Void, NoError> {
|
|
||||||
let pinnedChats: Signal<Api.messages.PeerDialogs, NoError> = network.request(Api.functions.messages.getPinnedDialogs(folderId: 0))
|
|
||||||
|> retryRequest
|
|
||||||
let state: Signal<Api.updates.State, NoError> = network.request(Api.functions.updates.getState())
|
|
||||||
|> retryRequest
|
|
||||||
|
|
||||||
return postbox.transaction { transaction -> [ChatListNamespaceEntry] in
|
|
||||||
return transaction.getChatListNamespaceEntries(groupId: .root, namespace: Namespaces.Message.Cloud, summaryTag: MessageTags.unseenPersonalMessage)
|
|
||||||
}
|
|
||||||
|> mapToSignal { localChatListEntries -> Signal<Void, NoError> in
|
|
||||||
let localRanges = localChatListEntryRanges(localChatListEntries, limit: 100)
|
|
||||||
var signal: Signal<ResolvedChatListResetRange?, NoError> = .complete()
|
|
||||||
for i in 0 ..< localRanges.count {
|
|
||||||
let upperBound: MessageIndex
|
|
||||||
let head = i == 0
|
|
||||||
let localRange = localRanges[i]
|
|
||||||
if let rangeUpperBound = localRange.upperBound {
|
|
||||||
upperBound = rangeUpperBound.messageIndex.predecessor()
|
|
||||||
} else {
|
|
||||||
upperBound = MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 0), timestamp: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
let rangeSignal: Signal<ResolvedChatListResetRange?, NoError> = fetchChatList(postbox: postbox, network: network, location: .general, upperBound: upperBound, hash: localRange.apiHash, limit: localRange.count)
|
|
||||||
|> map { remote -> ResolvedChatListResetRange? in
|
|
||||||
if let remote = remote {
|
|
||||||
return ResolvedChatListResetRange(head: head, local: localRange, remote: remote)
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signal = signal
|
|
||||||
|> then(rangeSignal)
|
|
||||||
}
|
|
||||||
let collectedResolvedRanges: Signal<[ResolvedChatListResetRange], NoError> = signal
|
|
||||||
|> map { next -> [ResolvedChatListResetRange] in
|
|
||||||
if let next = next {
|
|
||||||
return [next]
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|> reduceLeft(value: [], f: { list, next in
|
|
||||||
var list = list
|
|
||||||
list.append(contentsOf: next)
|
|
||||||
return list
|
|
||||||
})
|
|
||||||
|
|
||||||
return combineLatest(collectedResolvedRanges, state)
|
|
||||||
|> mapToSignal { collectedRanges, state -> Signal<Void, NoError> in
|
|
||||||
return postbox.transaction { transaction -> Void in
|
|
||||||
for range in collectedRanges {
|
|
||||||
let previousPeerIds = transaction.resetChatList(keepPeerNamespaces: [Namespaces.Peer.SecretChat], upperBound: range.local.upperBound ?? ChatListIndex.absoluteUpperBound, lowerBound: range.local.lowerBound)
|
|
||||||
#if DEBUG
|
|
||||||
for peerId in previousPeerIds {
|
|
||||||
print("pre \(peerId) [\(transaction.getPeer(peerId)?.debugDisplayTitle ?? "nil")]")
|
|
||||||
}
|
|
||||||
print("pre hash \(range.local.hash)")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
var preRecalculatedHash: UInt32 = 0
|
|
||||||
for entry in range.local.entries {
|
|
||||||
switch entry {
|
|
||||||
case let .peer(index, readState, topMessageAttributes, tagSummary, interfaceState):
|
|
||||||
print("val \(index.messageIndex.id.peerId) [\(transaction.getPeer(index.messageIndex.id.peerId)?.debugDisplayTitle ?? "nil")]")
|
|
||||||
combineChatListNamespaceEntryHash(index: index, readState: readState, topMessageAttributes: topMessageAttributes, tagSummary: nil, interfaceState: nil, into: &preRecalculatedHash)
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
print("pre recalculated hash \(preRecalculatedHash)")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
var hash: UInt32 = 0
|
|
||||||
range.remote.storeMessages.compactMap({ message -> MessageIndex? in
|
|
||||||
if case let .Id(id) = message.id {
|
|
||||||
if range.remote.topMessageIds[id.peerId] == id {
|
|
||||||
return message.index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}).sorted(by: { lhs, rhs in
|
|
||||||
return lhs > rhs
|
|
||||||
}).forEach({ index in
|
|
||||||
var topMessageAttributes: [MessageAttribute] = []
|
|
||||||
for message in range.remote.storeMessages {
|
|
||||||
if case let .Id(id) = message.id, id == index.id {
|
|
||||||
topMessageAttributes = message.attributes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
combineChatListNamespaceEntryHash(index: ChatListIndex(pinningIndex: nil, messageIndex: index), readState: range.remote.readStates[index.id.peerId]?[Namespaces.Message.Cloud], topMessageAttributes: topMessageAttributes, tagSummary: nil, interfaceState: nil, into: &hash)
|
|
||||||
print("upd \(index.id.peerId) [\(transaction.getPeer(index.id.peerId)?.debugDisplayTitle ?? "nil")]")
|
|
||||||
})
|
|
||||||
print("upd hash \(hash)")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
updatePeers(transaction: transaction, peers: range.remote.peers, update: { _, updated -> Peer in
|
|
||||||
return updated
|
|
||||||
})
|
|
||||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: range.remote.peerPresences)
|
|
||||||
|
|
||||||
transaction.updateCurrentPeerNotificationSettings(range.remote.notificationSettings)
|
|
||||||
|
|
||||||
var allPeersWithMessages = Set<PeerId>()
|
|
||||||
for message in range.remote.storeMessages {
|
|
||||||
allPeersWithMessages.insert(message.id.peerId)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (_, messageId) in range.remote.topMessageIds {
|
|
||||||
if messageId.id > 1 {
|
|
||||||
var skipHole = false
|
|
||||||
if let localTopId = transaction.getTopPeerMessageIndex(peerId: messageId.peerId, namespace: messageId.namespace)?.id {
|
|
||||||
if localTopId >= messageId {
|
|
||||||
skipHole = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !skipHole {
|
|
||||||
//transaction.addHole(MessageId(peerId: messageId.peerId, namespace: messageId.namespace, id: messageId.id - 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = transaction.addMessages(range.remote.storeMessages, location: .UpperHistoryBlock)
|
|
||||||
|
|
||||||
transaction.resetIncomingReadStates(range.remote.readStates)
|
|
||||||
|
|
||||||
for (peerId, chatState) in range.remote.chatStates {
|
|
||||||
if let chatState = chatState as? ChannelState {
|
|
||||||
if let current = transaction.getPeerChatState(peerId) as? ChannelState {
|
|
||||||
transaction.setPeerChatState(peerId, state: current.withUpdatedPts(chatState.pts))
|
|
||||||
} else {
|
|
||||||
transaction.setPeerChatState(peerId, state: chatState)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
transaction.setPeerChatState(peerId, state: chatState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (peerId, summary) in range.remote.mentionTagSummaries {
|
|
||||||
transaction.replaceMessageTagSummary(peerId: peerId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId)
|
|
||||||
}
|
|
||||||
|
|
||||||
let namespacesWithHoles: [PeerId.Namespace: [MessageId.Namespace]] = [
|
|
||||||
Namespaces.Peer.CloudUser: [Namespaces.Message.Cloud],
|
|
||||||
Namespaces.Peer.CloudGroup: [Namespaces.Message.Cloud],
|
|
||||||
Namespaces.Peer.CloudChannel: [Namespaces.Message.Cloud]
|
|
||||||
]
|
|
||||||
for peerId in previousPeerIds {
|
|
||||||
if !allPeersWithMessages.contains(peerId), let namespaces = namespacesWithHoles[peerId.namespace] {
|
|
||||||
for namespace in namespaces {
|
|
||||||
//transaction.addHole(MessageId(peerId: peerId, namespace: namespace, id: Int32.max - 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if range.head {
|
|
||||||
transaction.setPinnedItemIds(groupId: nil, itemIds: range.remote.pinnedItemIds ?? [])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let currentState = transaction.getState() as? AuthorizedAccountState, let embeddedState = currentState.state {
|
|
||||||
switch state {
|
|
||||||
case let .state(pts, _, _, seq, _):
|
|
||||||
transaction.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: embeddedState.qts, date: embeddedState.date, seq: seq)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
@ -57,7 +57,7 @@ public func addGroupMember(account: Account, peerId: PeerId, memberId: PeerId) -
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> mapError { _ -> AddGroupMemberError in return .generic }
|
|> mapError { _ -> AddGroupMemberError in }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
@ -65,7 +65,7 @@ public func addGroupMember(account: Account, peerId: PeerId, memberId: PeerId) -
|
|||||||
} else {
|
} else {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
} |> mapError { _ -> AddGroupMemberError in return .generic } |> switchToLatest
|
} |> mapError { _ -> AddGroupMemberError in } |> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AddChannelMemberError {
|
public enum AddChannelMemberError {
|
||||||
@ -82,7 +82,6 @@ public enum AddChannelMemberError {
|
|||||||
public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> {
|
public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> {
|
||||||
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
||||||
|> mapError { error -> AddChannelMemberError in
|
|> mapError { error -> AddChannelMemberError in
|
||||||
return .generic
|
|
||||||
}
|
}
|
||||||
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> in
|
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> in
|
||||||
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> in
|
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> in
|
||||||
@ -158,7 +157,7 @@ public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId)
|
|||||||
if let presence = transaction.getPeerPresence(peerId: memberPeer.id) {
|
if let presence = transaction.getPeerPresence(peerId: memberPeer.id) {
|
||||||
presences[memberPeer.id] = presence
|
presences[memberPeer.id] = presence
|
||||||
}
|
}
|
||||||
if case let .member(_, _, maybeAdminInfo, maybeBannedInfo, _) = updatedParticipant {
|
if case let .member(_, _, maybeAdminInfo, _, _) = updatedParticipant {
|
||||||
if let adminInfo = maybeAdminInfo {
|
if let adminInfo = maybeAdminInfo {
|
||||||
if let peer = transaction.getPeer(adminInfo.promotedBy) {
|
if let peer = transaction.getPeer(adminInfo.promotedBy) {
|
||||||
peers[peer.id] = peer
|
peers[peer.id] = peer
|
||||||
@ -167,7 +166,7 @@ public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId)
|
|||||||
}
|
}
|
||||||
return (currentParticipant, RenderedChannelParticipant(participant: updatedParticipant, peer: memberPeer, peers: peers, presences: presences))
|
return (currentParticipant, RenderedChannelParticipant(participant: updatedParticipant, peer: memberPeer, peers: peers, presences: presences))
|
||||||
}
|
}
|
||||||
|> mapError { _ -> AddChannelMemberError in return .generic }
|
|> mapError { _ -> AddChannelMemberError in }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
@ -176,7 +175,7 @@ public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId)
|
|||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> mapError { _ -> AddChannelMemberError in return .generic }
|
|> mapError { _ -> AddChannelMemberError in }
|
||||||
|> switchToLatest
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
SWIFT_INCLUDE_PATHS = $(SRCROOT)/TelegramCore
|
|
||||||
MODULEMAP_PRIVATE_FILE = $(SRCROOT)/TelegramCore/module.private.modulemap
|
|
@ -1,59 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import Postbox
|
|
||||||
import SwiftSignalKit
|
|
||||||
import MtProtoKit
|
|
||||||
|
|
||||||
import SyncCore
|
|
||||||
|
|
||||||
public final class CoreSettings: PreferencesEntry, Equatable {
|
|
||||||
public let fastForward: Bool
|
|
||||||
|
|
||||||
public static var defaultSettings = CoreSettings(fastForward: true)
|
|
||||||
|
|
||||||
public init(fastForward: Bool) {
|
|
||||||
self.fastForward = fastForward
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
|
||||||
self.fastForward = decoder.decodeInt32ForKey("fastForward", orElse: 0) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
|
||||||
encoder.encodeInt32(self.fastForward ? 1 : 0, forKey: "fastForward")
|
|
||||||
}
|
|
||||||
|
|
||||||
public func withUpdatedFastForward(_ fastForward: Bool) -> CoreSettings {
|
|
||||||
return CoreSettings(fastForward: fastForward)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func isEqual(to: PreferencesEntry) -> Bool {
|
|
||||||
guard let to = to as? CoreSettings else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return self == to
|
|
||||||
}
|
|
||||||
|
|
||||||
public static func ==(lhs: CoreSettings, rhs: CoreSettings) -> Bool {
|
|
||||||
if lhs.fastForward != rhs.fastForward {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func updateCoreSettings(postbox: Postbox, _ f: @escaping (CoreSettings) -> CoreSettings) -> Signal<Void, NoError> {
|
|
||||||
return postbox.transaction { transaction -> Void in
|
|
||||||
var updated: CoreSettings?
|
|
||||||
transaction.updatePreferencesEntry(key: PreferencesKeys.coreSettings, { current in
|
|
||||||
if let current = current as? CoreSettings {
|
|
||||||
updated = f(current)
|
|
||||||
return updated
|
|
||||||
} else {
|
|
||||||
updated = f(CoreSettings.defaultSettings)
|
|
||||||
return updated
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +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>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>en</string>
|
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>$(PRODUCT_NAME)</string>
|
|
||||||
<key>CFBundlePackageType</key>
|
|
||||||
<string>FMWK</string>
|
|
||||||
<key>CFBundleShortVersionString</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
|
||||||
<key>NSPrincipalClass</key>
|
|
||||||
<string></string>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
@ -1,119 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import MultipeerConnectivity
|
|
||||||
|
|
||||||
protocol ColorServiceManagerDelegate {
|
|
||||||
|
|
||||||
func connectedDevicesChanged(manager : ColorServiceManager, connectedDevices: [String])
|
|
||||||
func colorChanged(manager : ColorServiceManager, colorString: String)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class ColorServiceManager : NSObject {
|
|
||||||
private let ColorServiceType = "tg-p2p"
|
|
||||||
|
|
||||||
private let myPeerId = MCPeerID(displayName: UIDevice.current.name)
|
|
||||||
|
|
||||||
private let serviceAdvertiser : MCNearbyServiceAdvertiser
|
|
||||||
private let serviceBrowser : MCNearbyServiceBrowser
|
|
||||||
|
|
||||||
var delegate : ColorServiceManagerDelegate?
|
|
||||||
|
|
||||||
lazy var session : MCSession = {
|
|
||||||
let session = MCSession(peer: self.myPeerId, securityIdentity: nil, encryptionPreference: .required)
|
|
||||||
session.delegate = self
|
|
||||||
return session
|
|
||||||
}()
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
self.serviceAdvertiser = MCNearbyServiceAdvertiser(peer: myPeerId, discoveryInfo: nil, serviceType: ColorServiceType)
|
|
||||||
self.serviceBrowser = MCNearbyServiceBrowser(peer: myPeerId, serviceType: ColorServiceType)
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.serviceAdvertiser.delegate = self
|
|
||||||
self.serviceAdvertiser.startAdvertisingPeer()
|
|
||||||
|
|
||||||
self.serviceBrowser.delegate = self
|
|
||||||
self.serviceBrowser.startBrowsingForPeers()
|
|
||||||
}
|
|
||||||
|
|
||||||
func send(colorName : String) {
|
|
||||||
NSLog("%@", "sendColor: \(colorName) to \(session.connectedPeers.count) peers")
|
|
||||||
|
|
||||||
if session.connectedPeers.count > 0 {
|
|
||||||
do {
|
|
||||||
try self.session.send(colorName.data(using: .utf8)!, toPeers: session.connectedPeers, with: .reliable)
|
|
||||||
}
|
|
||||||
catch let error {
|
|
||||||
NSLog("%@", "Error for sending: \(error)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.serviceAdvertiser.stopAdvertisingPeer()
|
|
||||||
self.serviceBrowser.stopBrowsingForPeers()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ColorServiceManager : MCNearbyServiceAdvertiserDelegate {
|
|
||||||
|
|
||||||
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didNotStartAdvertisingPeer error: Error) {
|
|
||||||
NSLog("%@", "didNotStartAdvertisingPeer: \(error)")
|
|
||||||
}
|
|
||||||
|
|
||||||
func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
|
|
||||||
NSLog("%@", "didReceiveInvitationFromPeer \(peerID)")
|
|
||||||
invitationHandler(true, self.session)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ColorServiceManager : MCNearbyServiceBrowserDelegate {
|
|
||||||
|
|
||||||
func browser(_ browser: MCNearbyServiceBrowser, didNotStartBrowsingForPeers error: Error) {
|
|
||||||
NSLog("%@", "didNotStartBrowsingForPeers: \(error)")
|
|
||||||
}
|
|
||||||
|
|
||||||
func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
|
|
||||||
NSLog("%@", "foundPeer: \(peerID)")
|
|
||||||
NSLog("%@", "invitePeer: \(peerID)")
|
|
||||||
browser.invitePeer(peerID, to: self.session, withContext: nil, timeout: 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
|
|
||||||
NSLog("%@", "lostPeer: \(peerID)")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ColorServiceManager : MCSessionDelegate {
|
|
||||||
|
|
||||||
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
|
|
||||||
NSLog("%@", "peer \(peerID) didChangeState: \(state)")
|
|
||||||
self.delegate?.connectedDevicesChanged(manager: self, connectedDevices:
|
|
||||||
session.connectedPeers.map{$0.displayName})
|
|
||||||
}
|
|
||||||
|
|
||||||
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
|
|
||||||
NSLog("%@", "didReceiveData: \(data)")
|
|
||||||
let str = String(data: data, encoding: .utf8)!
|
|
||||||
self.delegate?.colorChanged(manager: self, colorString: str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
|
|
||||||
NSLog("%@", "didReceiveStream")
|
|
||||||
}
|
|
||||||
|
|
||||||
func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
|
|
||||||
NSLog("%@", "didStartReceivingResourceWithName")
|
|
||||||
}
|
|
||||||
|
|
||||||
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
|
|
||||||
NSLog("%@", "didFinishReceivingResourceWithName")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -63,7 +63,7 @@ extension PeerInputActivity {
|
|||||||
self = .uploadingInstantVideo(progress: progress)
|
self = .uploadingInstantVideo(progress: progress)
|
||||||
case .speakingInGroupCallAction:
|
case .speakingInGroupCallAction:
|
||||||
self = .speakingInGroupCall(timestamp: timestamp)
|
self = .speakingInGroupCall(timestamp: timestamp)
|
||||||
case let .sendMessageHistoryImportAction(progress):
|
case let .sendMessageHistoryImportAction:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ public func stickerPacksAttachedToMedia(account: Account, media: AnyMediaReferen
|
|||||||
|> mapToSignal { reference -> Signal<[Api.StickerSetCovered], MTRpcError> in
|
|> mapToSignal { reference -> Signal<[Api.StickerSetCovered], MTRpcError> in
|
||||||
let inputMedia: Api.InputStickeredMedia
|
let inputMedia: Api.InputStickeredMedia
|
||||||
if let resource = reference.updatedResource as? TelegramCloudMediaResourceWithFileReference, let updatedReference = resource.fileReference {
|
if let resource = reference.updatedResource as? TelegramCloudMediaResourceWithFileReference, let updatedReference = resource.fileReference {
|
||||||
if let imageReference = media.concrete(TelegramMediaImage.self), let reference = imageReference.media.reference, case let .cloud(imageId, accessHash, _) = reference, let representation = largestImageRepresentation(imageReference.media.representations) {
|
if let imageReference = media.concrete(TelegramMediaImage.self), let reference = imageReference.media.reference, case let .cloud(imageId, accessHash, _) = reference, let _ = largestImageRepresentation(imageReference.media.representations) {
|
||||||
inputMedia = .inputStickeredMediaPhoto(id: Api.InputPhoto.inputPhoto(id: imageId, accessHash: accessHash, fileReference: Buffer(data: updatedReference)))
|
inputMedia = .inputStickeredMediaPhoto(id: Api.InputPhoto.inputPhoto(id: imageId, accessHash: accessHash, fileReference: Buffer(data: updatedReference)))
|
||||||
} else if let fileReference = media.concrete(TelegramMediaFile.self), let resource = fileReference.media.resource as? CloudDocumentMediaResource {
|
} else if let fileReference = media.concrete(TelegramMediaFile.self), let resource = fileReference.media.resource as? CloudDocumentMediaResource {
|
||||||
inputMedia = .inputStickeredMediaDocument(id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: updatedReference)))
|
inputMedia = .inputStickeredMediaDocument(id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: updatedReference)))
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
//
|
|
||||||
// TelegramCore.h
|
|
||||||
// TelegramCore
|
|
||||||
//
|
|
||||||
// Created by Peter on 8/1/16.
|
|
||||||
// Copyright © 2016 Peter. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
|
|
||||||
//! Project version number for TelegramCore.
|
|
||||||
FOUNDATION_EXPORT double TelegramCoreVersionNumber;
|
|
||||||
|
|
||||||
//! Project version string for TelegramCore.
|
|
||||||
FOUNDATION_EXPORT const unsigned char TelegramCoreVersionString[];
|
|
||||||
|
|
||||||
#import <TelegramCore/FormatPhoneNumber.h>
|
|
||||||
#import <TelegramCore/Crypto.h>
|
|
||||||
#import <TelegramCore/NetworkLogging.h>
|
|
||||||
#import <TelegramCore/Reachability.h>
|
|
@ -5,17 +5,7 @@ import SyncCore
|
|||||||
import MtProtoKit
|
import MtProtoKit
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
|
||||||
public struct BankCardUrl {
|
func _internal_getBankCardInfo(account: Account, cardNumber: String) -> Signal<BankCardInfo?, NoError> {
|
||||||
public let title: String
|
|
||||||
public let url: String
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct BankCardInfo {
|
|
||||||
public let title: String
|
|
||||||
public let urls: [BankCardUrl]
|
|
||||||
}
|
|
||||||
|
|
||||||
public func getBankCardInfo(account: Account, cardNumber: String) -> Signal<BankCardInfo?, NoError> {
|
|
||||||
return currentWebDocumentsHostDatacenterId(postbox: account.postbox, isTestingEnvironment: false)
|
return currentWebDocumentsHostDatacenterId(postbox: account.postbox, isTestingEnvironment: false)
|
||||||
|> mapToSignal { datacenterId in
|
|> mapToSignal { datacenterId in
|
||||||
let signal: Signal<Api.payments.BankCardData, MTRpcError>
|
let signal: Signal<Api.payments.BankCardData, MTRpcError>
|
||||||
@ -38,6 +28,16 @@ public func getBankCardInfo(account: Account, cardNumber: String) -> Signal<Bank
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct BankCardUrl {
|
||||||
|
public let title: String
|
||||||
|
public let url: String
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct BankCardInfo {
|
||||||
|
public let title: String
|
||||||
|
public let urls: [BankCardUrl]
|
||||||
|
}
|
||||||
|
|
||||||
extension BankCardUrl {
|
extension BankCardUrl {
|
||||||
init(apiBankCardOpenUrl: Api.BankCardOpenUrl) {
|
init(apiBankCardOpenUrl: Api.BankCardOpenUrl) {
|
||||||
switch apiBankCardOpenUrl {
|
switch apiBankCardOpenUrl {
|
@ -0,0 +1,15 @@
|
|||||||
|
import SwiftSignalKit
|
||||||
|
|
||||||
|
public extension TelegramEngine {
|
||||||
|
final class Payments {
|
||||||
|
private let account: Account
|
||||||
|
|
||||||
|
init(account: Account) {
|
||||||
|
self.account = account
|
||||||
|
}
|
||||||
|
|
||||||
|
public func getBankCardInfo(cardNumber: String) -> Signal<BankCardInfo?, NoError> {
|
||||||
|
return _internal_getBankCardInfo(account: self.account, cardNumber: cardNumber)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,7 @@ public enum AddressNameDomain {
|
|||||||
case theme(TelegramTheme)
|
case theme(TelegramTheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func checkAddressNameFormat(_ value: String, canEmpty: Bool = false) -> AddressNameFormatError? {
|
func _internal_checkAddressNameFormat(_ value: String, canEmpty: Bool = false) -> AddressNameFormatError? {
|
||||||
var index = 0
|
var index = 0
|
||||||
let length = value.count
|
let length = value.count
|
||||||
for char in value {
|
for char in value {
|
||||||
@ -52,7 +52,7 @@ public func checkAddressNameFormat(_ value: String, canEmpty: Bool = false) -> A
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public func addressNameAvailability(account: Account, domain: AddressNameDomain, name: String) -> Signal<AddressNameAvailability, NoError> {
|
func _internal_addressNameAvailability(account: Account, domain: AddressNameDomain, name: String) -> Signal<AddressNameAvailability, NoError> {
|
||||||
return account.postbox.transaction { transaction -> Signal<AddressNameAvailability, NoError> in
|
return account.postbox.transaction { transaction -> Signal<AddressNameAvailability, NoError> in
|
||||||
switch domain {
|
switch domain {
|
||||||
case .account:
|
case .account:
|
||||||
@ -120,7 +120,7 @@ public enum UpdateAddressNameError {
|
|||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateAddressName(account: Account, domain: AddressNameDomain, name: String?) -> Signal<Void, UpdateAddressNameError> {
|
func _internal_updateAddressName(account: Account, domain: AddressNameDomain, name: String?) -> Signal<Void, UpdateAddressNameError> {
|
||||||
return account.postbox.transaction { transaction -> Signal<Void, UpdateAddressNameError> in
|
return account.postbox.transaction { transaction -> Signal<Void, UpdateAddressNameError> in
|
||||||
switch domain {
|
switch domain {
|
||||||
case .account:
|
case .account:
|
||||||
@ -134,7 +134,7 @@ public func updateAddressName(account: Account, domain: AddressNameDomain, name:
|
|||||||
updatePeers(transaction: transaction, peers: [user], update: { _, updated in
|
updatePeers(transaction: transaction, peers: [user], update: { _, updated in
|
||||||
return updated
|
return updated
|
||||||
})
|
})
|
||||||
} |> mapError { _ -> UpdateAddressNameError in return .generic }
|
} |> mapError { _ -> UpdateAddressNameError in }
|
||||||
}
|
}
|
||||||
case let .peer(peerId):
|
case let .peer(peerId):
|
||||||
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
|
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
|
||||||
@ -155,7 +155,7 @@ public func updateAddressName(account: Account, domain: AddressNameDomain, name:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} |> mapError { _ -> UpdateAddressNameError in return .generic }
|
} |> mapError { _ -> UpdateAddressNameError in }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
@ -170,10 +170,10 @@ public func updateAddressName(account: Account, domain: AddressNameDomain, name:
|
|||||||
return Void()
|
return Void()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} |> mapError { _ -> UpdateAddressNameError in return .generic } |> switchToLatest
|
} |> mapError { _ -> UpdateAddressNameError in } |> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
public func checkPublicChannelCreationAvailability(account: Account, location: Bool = false) -> Signal<Bool, NoError> {
|
func _internal_checkPublicChannelCreationAvailability(account: Account, location: Bool = false) -> Signal<Bool, NoError> {
|
||||||
var flags: Int32 = (1 << 1)
|
var flags: Int32 = (1 << 1)
|
||||||
if location {
|
if location {
|
||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
@ -194,7 +194,7 @@ public enum AdminedPublicChannelsScope {
|
|||||||
case forVoiceChat
|
case forVoiceChat
|
||||||
}
|
}
|
||||||
|
|
||||||
public func adminedPublicChannels(account: Account, scope: AdminedPublicChannelsScope = .all) -> Signal<[Peer], NoError> {
|
func _internal_adminedPublicChannels(account: Account, scope: AdminedPublicChannelsScope = .all) -> Signal<[Peer], NoError> {
|
||||||
var flags: Int32 = 0
|
var flags: Int32 = 0
|
||||||
switch scope {
|
switch scope {
|
||||||
case .all:
|
case .all:
|
||||||
@ -238,7 +238,7 @@ public enum ChannelAddressNameAssignmentAvailability {
|
|||||||
case addressNameLimitReached
|
case addressNameLimitReached
|
||||||
}
|
}
|
||||||
|
|
||||||
public func channelAddressNameAssignmentAvailability(account: Account, peerId: PeerId?) -> Signal<ChannelAddressNameAssignmentAvailability, NoError> {
|
func _internal_channelAddressNameAssignmentAvailability(account: Account, peerId: PeerId?) -> Signal<ChannelAddressNameAssignmentAvailability, NoError> {
|
||||||
return account.postbox.transaction { transaction -> Signal<ChannelAddressNameAssignmentAvailability, NoError> in
|
return account.postbox.transaction { transaction -> Signal<ChannelAddressNameAssignmentAvailability, NoError> in
|
||||||
var inputChannel: Api.InputChannel?
|
var inputChannel: Api.InputChannel?
|
||||||
if let peerId = peerId {
|
if let peerId = peerId {
|
@ -3,7 +3,7 @@ import SwiftSignalKit
|
|||||||
import Postbox
|
import Postbox
|
||||||
import TelegramApi
|
import TelegramApi
|
||||||
|
|
||||||
public func findChannelById(postbox: Postbox, network: Network, channelId: Int32) -> Signal<Peer?, NoError> {
|
func _internal_findChannelById(postbox: Postbox, network: Network, channelId: Int32) -> Signal<Peer?, NoError> {
|
||||||
return network.request(Api.functions.channels.getChannels(id: [.inputChannel(channelId: channelId, accessHash: 0)]))
|
return network.request(Api.functions.channels.getChannels(id: [.inputChannel(channelId: channelId, accessHash: 0)]))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.messages.Chats?, NoError> in
|
|> `catch` { _ -> Signal<Api.messages.Chats?, NoError> in
|
@ -5,7 +5,7 @@ import MtProtoKit
|
|||||||
|
|
||||||
import SyncCore
|
import SyncCore
|
||||||
|
|
||||||
public func supportPeerId(account:Account) -> Signal<PeerId?, NoError> {
|
func _internal_supportPeerId(account: Account) -> Signal<PeerId?, NoError> {
|
||||||
return account.network.request(Api.functions.help.getSupport())
|
return account.network.request(Api.functions.help.getSupport())
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ in
|
|> `catch` { _ in
|
@ -0,0 +1,61 @@
|
|||||||
|
import SwiftSignalKit
|
||||||
|
import Postbox
|
||||||
|
|
||||||
|
public enum AddressNameValidationStatus: Equatable {
|
||||||
|
case checking
|
||||||
|
case invalidFormat(AddressNameFormatError)
|
||||||
|
case availability(AddressNameAvailability)
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension TelegramEngine {
|
||||||
|
final class PeerNames {
|
||||||
|
private let account: Account
|
||||||
|
|
||||||
|
init(account: Account) {
|
||||||
|
self.account = account
|
||||||
|
}
|
||||||
|
|
||||||
|
public func addressNameAvailability(domain: AddressNameDomain, name: String) -> Signal<AddressNameAvailability, NoError> {
|
||||||
|
return _internal_addressNameAvailability(account: self.account, domain: domain, name: name)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateAddressName(domain: AddressNameDomain, name: String?) -> Signal<Void, UpdateAddressNameError> {
|
||||||
|
return _internal_updateAddressName(account: self.account, domain: domain, name: name)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func checkPublicChannelCreationAvailability(location: Bool = false) -> Signal<Bool, NoError> {
|
||||||
|
return _internal_checkPublicChannelCreationAvailability(account: self.account, location: location)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func adminedPublicChannels(scope: AdminedPublicChannelsScope = .all) -> Signal<[Peer], NoError> {
|
||||||
|
return _internal_adminedPublicChannels(account: self.account, scope: scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func channelAddressNameAssignmentAvailability(peerId: PeerId?) -> Signal<ChannelAddressNameAssignmentAvailability, NoError> {
|
||||||
|
return _internal_channelAddressNameAssignmentAvailability(account: self.account, peerId: peerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func validateAddressNameInteractive(domain: AddressNameDomain, name: String) -> Signal<AddressNameValidationStatus, NoError> {
|
||||||
|
if let error = _internal_checkAddressNameFormat(name) {
|
||||||
|
return .single(.invalidFormat(error))
|
||||||
|
} else {
|
||||||
|
return .single(.checking)
|
||||||
|
|> then(
|
||||||
|
self.addressNameAvailability(domain: domain, name: name)
|
||||||
|
|> delay(0.3, queue: Queue.concurrentDefaultQueue())
|
||||||
|
|> map { result -> AddressNameValidationStatus in
|
||||||
|
.availability(result)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func findChannelById(channelId: Int32) -> Signal<Peer?, NoError> {
|
||||||
|
return _internal_findChannelById(postbox: self.account.postbox, network: self.account.network, channelId: channelId)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func supportPeerId() -> Signal<PeerId?, NoError> {
|
||||||
|
return _internal_supportPeerId(account: self.account)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,4 +15,12 @@ public final class TelegramEngine {
|
|||||||
public lazy var peersNearby: PeersNearby = {
|
public lazy var peersNearby: PeersNearby = {
|
||||||
return PeersNearby(account: self.account)
|
return PeersNearby(account: self.account)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
public lazy var payments: Payments = {
|
||||||
|
return Payments(account: self.account)
|
||||||
|
}()
|
||||||
|
|
||||||
|
public lazy var peerNames: PeerNames = {
|
||||||
|
return PeerNames(account: self.account)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public struct DateTime {
|
|
||||||
public let seconds: Int32 // 0 ... 59
|
|
||||||
public let minutes: Int32 // 0 ... 59
|
|
||||||
public let hours: Int32 // 0 ... 23
|
|
||||||
public let dayOfMonth: Int32 // 1 ... 31
|
|
||||||
public let month: Int32 // 0 ... 11
|
|
||||||
public let year: Int32 // since 1900
|
|
||||||
public let dayOfWeek: Int32 // 0 ... 6
|
|
||||||
public let dayOfYear: Int32 // 0 ... 365
|
|
||||||
}
|
|
||||||
|
|
||||||
private let daysSinceJan1st: [[UInt32]] =
|
|
||||||
[
|
|
||||||
[0,31,59,90,120,151,181,212,243,273,304,334,365], // 365 days, non-leap
|
|
||||||
[0,31,60,91,121,152,182,213,244,274,305,335,366] // 366 days, leap
|
|
||||||
]
|
|
||||||
|
|
||||||
public func secondsSinceEpochToDateTime(_ secondsSinceEpoch: Int64) -> DateTime {
|
|
||||||
var sec: UInt64
|
|
||||||
let quadricentennials: UInt32
|
|
||||||
var centennials: UInt32
|
|
||||||
var quadrennials: UInt32
|
|
||||||
var annuals: UInt32
|
|
||||||
let year: UInt32
|
|
||||||
let leap: UInt32
|
|
||||||
let yday: UInt32
|
|
||||||
let hour: UInt32
|
|
||||||
let min: UInt32
|
|
||||||
var month: UInt32
|
|
||||||
var mday: UInt32
|
|
||||||
let wday: UInt32
|
|
||||||
|
|
||||||
/*
|
|
||||||
400 years:
|
|
||||||
|
|
||||||
1st hundred, starting immediately after a leap year that's a multiple of 400:
|
|
||||||
n n n l \
|
|
||||||
n n n l } 24 times
|
|
||||||
... /
|
|
||||||
n n n l /
|
|
||||||
n n n n
|
|
||||||
|
|
||||||
2nd hundred:
|
|
||||||
n n n l \
|
|
||||||
n n n l } 24 times
|
|
||||||
... /
|
|
||||||
n n n l /
|
|
||||||
n n n n
|
|
||||||
|
|
||||||
3rd hundred:
|
|
||||||
n n n l \
|
|
||||||
n n n l } 24 times
|
|
||||||
... /
|
|
||||||
n n n l /
|
|
||||||
n n n n
|
|
||||||
|
|
||||||
4th hundred:
|
|
||||||
n n n l \
|
|
||||||
n n n l } 24 times
|
|
||||||
... /
|
|
||||||
n n n l /
|
|
||||||
n n n L <- 97'th leap year every 400 years
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Re-bias from 1970 to 1601:
|
|
||||||
// 1970 - 1601 = 369 = 3*100 + 17*4 + 1 years (incl. 89 leap days) =
|
|
||||||
// (3*100*(365+24/100) + 17*4*(365+1/4) + 1*365)*24*3600 seconds
|
|
||||||
sec = UInt64(secondsSinceEpoch) + (11644473600 as UInt64)
|
|
||||||
|
|
||||||
wday = (uint)((sec / 86400 + 1) % 7); // day of week
|
|
||||||
|
|
||||||
// Remove multiples of 400 years (incl. 97 leap days)
|
|
||||||
quadricentennials = UInt32((UInt64(sec) / (12622780800 as UInt64))) // 400*365.2425*24*3600
|
|
||||||
sec %= 12622780800 as UInt64
|
|
||||||
|
|
||||||
// Remove multiples of 100 years (incl. 24 leap days), can't be more than 3
|
|
||||||
// (because multiples of 4*100=400 years (incl. leap days) have been removed)
|
|
||||||
centennials = UInt32(UInt64(sec) / (3155673600 as UInt64)) // 100*(365+24/100)*24*3600
|
|
||||||
if centennials > 3 {
|
|
||||||
centennials = 3
|
|
||||||
}
|
|
||||||
sec -= UInt64(centennials) * (3155673600 as UInt64)
|
|
||||||
|
|
||||||
// Remove multiples of 4 years (incl. 1 leap day), can't be more than 24
|
|
||||||
// (because multiples of 25*4=100 years (incl. leap days) have been removed)
|
|
||||||
quadrennials = UInt32((UInt64(sec) / (126230400 as UInt64))) // 4*(365+1/4)*24*3600
|
|
||||||
if quadrennials > 24 {
|
|
||||||
quadrennials = 24
|
|
||||||
}
|
|
||||||
sec -= UInt64(quadrennials) * (126230400 as UInt64)
|
|
||||||
|
|
||||||
// Remove multiples of years (incl. 0 leap days), can't be more than 3
|
|
||||||
// (because multiples of 4 years (incl. leap days) have been removed)
|
|
||||||
annuals = UInt32(sec / (31536000 as UInt64)) // 365*24*3600
|
|
||||||
if annuals > 3 {
|
|
||||||
annuals = 3
|
|
||||||
}
|
|
||||||
sec -= UInt64(annuals) * (31536000 as UInt64)
|
|
||||||
|
|
||||||
// Calculate the year and find out if it's leap
|
|
||||||
year = 1601 + quadricentennials * 400 + centennials * 100 + quadrennials * 4 + annuals;
|
|
||||||
leap = (!(year % UInt32(4) != 0) && ((year % UInt32(100) != 0) || !(year % UInt32(400) != 0))) ? 1 : 0
|
|
||||||
|
|
||||||
// Calculate the day of the year and the time
|
|
||||||
yday = UInt32(sec / (86400 as UInt64))
|
|
||||||
sec %= 86400;
|
|
||||||
hour = UInt32(sec / 3600);
|
|
||||||
sec %= 3600;
|
|
||||||
min = UInt32(sec / 60);
|
|
||||||
sec %= 60;
|
|
||||||
|
|
||||||
mday = 1
|
|
||||||
month = 1
|
|
||||||
while month < 13 {
|
|
||||||
if (yday < daysSinceJan1st[Int(leap)][Int(month)]) {
|
|
||||||
mday += yday - daysSinceJan1st[Int(leap)][Int(month - 1)]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
month += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return DateTime(seconds: Int32(sec), minutes: Int32(min), hours: Int32(hour), dayOfMonth: Int32(mday), month: Int32(month - 1), year: Int32(year - 1900), dayOfWeek: Int32(wday), dayOfYear: Int32(yday))
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import Postbox
|
|
||||||
import SwiftSignalKit
|
|
||||||
|
|
||||||
public enum AddressNameValidationStatus: Equatable {
|
|
||||||
case checking
|
|
||||||
case invalidFormat(AddressNameFormatError)
|
|
||||||
case availability(AddressNameAvailability)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func validateAddressNameInteractive(account: Account, domain: AddressNameDomain, name: String) -> Signal<AddressNameValidationStatus, NoError> {
|
|
||||||
if let error = checkAddressNameFormat(name) {
|
|
||||||
return .single(.invalidFormat(error))
|
|
||||||
} else {
|
|
||||||
return .single(.checking)
|
|
||||||
|> then(
|
|
||||||
addressNameAvailability(account: account, domain: domain, name: name)
|
|
||||||
|> delay(0.3, queue: Queue.concurrentDefaultQueue())
|
|
||||||
|> map { result -> AddressNameValidationStatus in
|
|
||||||
.availability(result)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
module TelegramCore.TelegramCorePrivate {
|
|
||||||
export *
|
|
||||||
}
|
|
@ -1754,7 +1754,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var signal = getBankCardInfo(account: strongSelf.context.account, cardNumber: number)
|
var signal = strongSelf.context.engine.payments.getBankCardInfo(cardNumber: number)
|
||||||
let disposable: MetaDisposable
|
let disposable: MetaDisposable
|
||||||
if let current = strongSelf.bankCardDisposable {
|
if let current = strongSelf.bankCardDisposable {
|
||||||
disposable = current
|
disposable = current
|
||||||
|
@ -5336,7 +5336,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
self.controller?.push(watchSettingsController(context: self.context))
|
self.controller?.push(watchSettingsController(context: self.context))
|
||||||
case .support:
|
case .support:
|
||||||
let supportPeer = Promise<PeerId?>()
|
let supportPeer = Promise<PeerId?>()
|
||||||
supportPeer.set(supportPeerId(account: context.account))
|
supportPeer.set(context.engine.peerNames.supportPeerId())
|
||||||
|
|
||||||
self.controller?.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.Settings_FAQ_Intro, actions: [
|
self.controller?.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.Settings_FAQ_Intro, actions: [
|
||||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_FAQ_Button, action: { [weak self] in
|
TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_FAQ_Button, action: { [weak self] in
|
||||||
|
@ -374,7 +374,7 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig
|
|||||||
if let peer = peer {
|
if let peer = peer {
|
||||||
foundPeer = .single(peer)
|
foundPeer = .single(peer)
|
||||||
} else {
|
} else {
|
||||||
foundPeer = findChannelById(postbox: account.postbox, network: account.network, channelId: messageId.peerId.id)
|
foundPeer = TelegramEngine(account: account).peerNames.findChannelById(channelId: messageId.peerId.id)
|
||||||
}
|
}
|
||||||
return foundPeer
|
return foundPeer
|
||||||
|> mapToSignal { foundPeer -> Signal<ResolvedUrl?, NoError> in
|
|> mapToSignal { foundPeer -> Signal<ResolvedUrl?, NoError> in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user