Refactoring [skip ci]

This commit is contained in:
Ali 2021-07-05 00:48:11 +04:00
parent 58217226c0
commit 4893e41de2
56 changed files with 783 additions and 840 deletions

View File

@ -944,7 +944,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
self.listNode.supernode?.insertSubnode(self.inProgressDimNode, aboveSubnode: self.listNode)
self.passwordTipDisposable = (twoStepVerificationConfiguration(account: self.context.account)
self.passwordTipDisposable = (self.context.engine.auth.twoStepVerificationConfiguration()
|> deliverOnMainQueue).start(next: { [weak self] value in
guard let strongSelf = self else {
return
@ -1069,7 +1069,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
if let savedCredentialsToken = savedCredentialsToken {
credentials = .saved(id: id, tempPassword: savedCredentialsToken.token)
} else {
let _ = (cachedTwoStepPasswordToken(postbox: self.context.account.postbox)
let _ = (self.context.engine.auth.cachedTwoStepPasswordToken()
|> deliverOnMainQueue).start(next: { [weak self] token in
if let strongSelf = self {
let timestamp = strongSelf.context.account.network.getApproximateRemoteTimestamp()
@ -1340,7 +1340,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
}),
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Yes, action: {
if let strongSelf = self {
let _ = cacheTwoStepPasswordToken(postbox: strongSelf.context.account.postbox, token: token).start()
let _ = strongSelf.context.engine.auth.cacheTwoStepPasswordToken(token: token).start()
strongSelf.pay(savedCredentialsToken: token)
}
})

View File

@ -285,7 +285,7 @@ private final class BotCheckoutPasswordAlertContentNode: AlertContentNode {
}
self.isVerifying = true
self.disposable.set((requestTemporaryTwoStepPasswordToken(account: self.context.account, password: text, period: self.period, requiresBiometrics: self.requiresBiometrics) |> deliverOnMainQueue).start(next: { [weak self] token in
self.disposable.set((self.context.engine.auth.requestTemporaryTwoStepPasswordToken(password: text, period: self.period, requiresBiometrics: self.requiresBiometrics) |> deliverOnMainQueue).start(next: { [weak self] token in
if let strongSelf = self {
strongSelf.completion(token)
}

View File

@ -68,16 +68,16 @@ private final class ImportManager {
private let account: Account
private let archivePath: String?
private let entries: [(SSZipEntry, String, ChatHistoryImport.MediaType)]
private let entries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)]
private var session: ChatHistoryImport.Session?
private var session: TelegramEngine.HistoryImport.Session?
private let disposable = MetaDisposable()
private let totalBytes: Int
private let totalMediaBytes: Int
private let mainFileSize: Int
private var pendingEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType)]
private var pendingEntries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)]
private var entryProgress: [String: (Int, Int)] = [:]
private var activeEntries: [String: Disposable] = [:]
@ -91,7 +91,7 @@ private final class ImportManager {
return self.statePromise.get()
}
init(account: Account, peerId: PeerId, mainFile: TempBoxFile, archivePath: String?, entries: [(SSZipEntry, String, ChatHistoryImport.MediaType)]) {
init(account: Account, peerId: PeerId, mainFile: TempBoxFile, archivePath: String?, entries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)]) {
self.account = account
self.archivePath = archivePath
self.entries = entries
@ -114,7 +114,7 @@ private final class ImportManager {
Logger.shared.log("ChatImportScreen", " \(entry.1)")
}
self.disposable.set((ChatHistoryImport.initSession(account: self.account, peerId: peerId, file: mainFile, mediaCount: Int32(entries.count))
self.disposable.set((TelegramEngine(account: self.account).historyImport.initSession(peerId: peerId, file: mainFile, mediaCount: Int32(entries.count))
|> mapError { error -> ImportError in
switch error {
case .chatAdminRequired:
@ -180,7 +180,7 @@ private final class ImportManager {
self.failWithError(.generic)
return
}
self.disposable.set((ChatHistoryImport.startImport(account: self.account, session: session)
self.disposable.set((TelegramEngine(account: self.account).historyImport.startImport(session: session)
|> deliverOnMainQueue).start(error: { [weak self] _ in
guard let strongSelf = self else {
return
@ -258,7 +258,7 @@ private final class ImportManager {
if !pathExtension.isEmpty, let value = TGMimeTypeMap.mimeType(forExtension: pathExtension) {
mimeType = value
}
return ChatHistoryImport.uploadMedia(account: account, session: session, file: tempFile, disposeFileAfterDone: true, fileName: entry.0.path, mimeType: mimeType, type: entry.2)
return TelegramEngine(account: account).historyImport.uploadMedia(session: session, file: tempFile, disposeFileAfterDone: true, fileName: entry.0.path, mimeType: mimeType, type: entry.2)
|> mapError { error -> ImportError in
switch error {
case .chatAdminRequired:
@ -732,7 +732,7 @@ public final class ChatImportActivityScreen: ViewController {
private let mainEntry: TempBoxFile
private let totalBytes: Int
private let totalMediaBytes: Int
private let otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType)]
private let otherEntries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)]
private var importManager: ImportManager?
private var progressEstimator: ProgressEstimator?
@ -749,14 +749,14 @@ public final class ChatImportActivityScreen: ViewController {
}
}
public init(context: AccountContext, cancel: @escaping () -> Void, peerId: PeerId, archivePath: String?, mainEntry: TempBoxFile, otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType)]) {
public init(context: AccountContext, cancel: @escaping () -> Void, peerId: PeerId, archivePath: String?, mainEntry: TempBoxFile, otherEntries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)]) {
self.context = context
self.cancel = cancel
self.peerId = peerId
self.archivePath = archivePath
self.mainEntry = mainEntry
self.otherEntries = otherEntries.map { entry -> (SSZipEntry, String, ChatHistoryImport.MediaType) in
self.otherEntries = otherEntries.map { entry -> (SSZipEntry, String, TelegramEngine.HistoryImport.MediaType) in
return (entry.0, entry.1, entry.2)
}

View File

@ -2448,7 +2448,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
guard let strongSelf = self else {
return
}
let _ = requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.peerId, isBlocked: true).start()
let _ = strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.peerId, isBlocked: true).start()
})
}
}))

View File

@ -885,7 +885,7 @@ public class GalleryController: ViewController, StandalonePresentableController
self.screenCaptureEventsDisposable = (screenCaptureEvents()
|> deliverOnMainQueue).start(next: { [weak self] _ in
if let strongSelf = self, strongSelf.traceVisibility() {
let _ = addSecretChatMessageScreenshot(account: strongSelf.context.account, peerId: id.peerId).start()
let _ = strongSelf.context.engine.messages.addSecretChatMessageScreenshot(peerId: id.peerId).start()
}
})
}

View File

@ -351,7 +351,7 @@ public final class SecretMediaPreviewController: ViewController {
if strongSelf.messageId.peerId.namespace == Namespaces.Peer.CloudUser {
let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start()
} else if strongSelf.messageId.peerId.namespace == Namespaces.Peer.SecretChat {
let _ = addSecretChatMessageScreenshot(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId).start()
let _ = strongSelf.context.engine.messages.addSecretChatMessageScreenshot(peerId: strongSelf.messageId.peerId).start()
}
}
})

View File

@ -147,7 +147,7 @@ final class GameControllerNode: ViewControllerTracingNode {
if eventName == "share_score" {
self.present(ShareController(context: self.context, subject: .fromExternal({ [weak self] peerIds, text, account in
if let strongSelf = self {
let signals = peerIds.map { forwardGameWithScore(account: account, messageId: strongSelf.message.id, to: $0) }
let signals = peerIds.map { TelegramEngine(account: account).messages.forwardGameWithScore(messageId: strongSelf.message.id, to: $0) }
return .single(.preparing)
|> then(
combineLatest(signals)

View File

@ -122,7 +122,7 @@ public final class SecureIdAuthController: ViewController, StandalonePresentable
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationInfoIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.infoPressed))
self.challengeDisposable.set((twoStepAuthData(context.account.network)
self.challengeDisposable.set((context.engine.auth.twoStepAuthData()
|> deliverOnMainQueue).start(next: { [weak self] data in
if let strongSelf = self {
let storedPassword = context.getStoredSecureIdPassword()
@ -512,7 +512,7 @@ public final class SecureIdAuthController: ViewController, StandalonePresentable
guard let strongSelf = self else {
return
}
strongSelf.recoveryDisposable.set((requestTwoStepVerificationPasswordRecoveryCode(network: strongSelf.context.account.network)
strongSelf.recoveryDisposable.set((strongSelf.context.engine.auth.requestTwoStepVerificationPasswordRecoveryCode()
|> deliverOnMainQueue).start(next: { emailPattern in
guard let strongSelf = self else {
return

View File

@ -140,7 +140,7 @@ public func resetPasswordController(context: AccountContext, emailPattern: Strin
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.TwoStepAuth_RecoveryUnavailableResetTitle, text: presentationData.strings.TwoStepAuth_RecoveryEmailResetText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.TwoStepAuth_RecoveryUnavailableResetAction, action: {
let _ = (requestTwoStepPasswordReset(network: context.account.network)
let _ = (context.engine.auth.requestTwoStepPasswordReset()
|> deliverOnMainQueue).start(next: { result in
switch result {
case .done, .waitingForReset:
@ -179,7 +179,7 @@ public func resetPasswordController(context: AccountContext, emailPattern: Strin
state.checking = true
return state
}
saveDisposable.set((recoverTwoStepVerificationPassword(network: context.account.network, code: state.code)
saveDisposable.set((context.engine.auth.recoverTwoStepVerificationPassword(code: state.code)
|> deliverOnMainQueue).start(error: { error in
updateState { state in
var state = state

View File

@ -11,8 +11,7 @@ import ProgressNavigationButtonNode
import AccountContext
public class SetupTwoStepVerificationController: ViewController {
private let network: Network
private let sharedContext: SharedAccountContext
private let context: AccountContext
private let initialState: SetupTwoStepVerificationInitialState
private let stateUpdated: (SetupTwoStepVerificationStateUpdate, Bool, SetupTwoStepVerificationController) -> Void
@ -33,19 +32,14 @@ public class SetupTwoStepVerificationController: ViewController {
private var presentationData: PresentationData
private var presentationDataDisposable: Disposable?
convenience public init(context: AccountContext, initialState: SetupTwoStepVerificationInitialState, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate, Bool, SetupTwoStepVerificationController) -> Void) {
self.init(sharedContext: context.sharedContext, network: context.account.network, initialState: initialState, stateUpdated: stateUpdated)
}
public init(sharedContext: SharedAccountContext, network: Network, initialState: SetupTwoStepVerificationInitialState, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate, Bool, SetupTwoStepVerificationController) -> Void) {
self.sharedContext = sharedContext
self.network = network
public init(context: AccountContext, initialState: SetupTwoStepVerificationInitialState, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate, Bool, SetupTwoStepVerificationController) -> Void) {
self.context = context
self.initialState = initialState
self.stateUpdated = stateUpdated
self.presentationData = self.sharedContext.currentPresentationData.with { $0 }
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(buttonColor: self.presentationData.theme.rootController.navigationBar.accentTextColor, disabledButtonColor: self.presentationData.theme.rootController.navigationBar.disabledButtonColor, primaryTextColor: self.presentationData.theme.rootController.navigationBar.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear), strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
@ -53,7 +47,7 @@ public class SetupTwoStepVerificationController: ViewController {
self.navigationItem.setLeftBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)), animated: false)
self.presentationDataDisposable = (self.sharedContext.presentationData
self.presentationDataDisposable = (self.context.sharedContext.presentationData
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
if let strongSelf = self {
let previousTheme = strongSelf.presentationData.theme
@ -103,7 +97,7 @@ public class SetupTwoStepVerificationController: ViewController {
}
override public func loadDisplayNode() {
self.displayNode = SetupTwoStepVerificationControllerNode(sharedContext: self.sharedContext, network: self.network, updateBackAction: { [weak self] action in
self.displayNode = SetupTwoStepVerificationControllerNode(context: self.context, updateBackAction: { [weak self] action in
guard let strongSelf = self else {
return
}

View File

@ -141,8 +141,7 @@ public enum SetupTwoStepVerificationStateUpdate {
}
final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
private let sharedContext: SharedAccountContext
private let network: Network
private let context: AccountContext
private var presentationData: PresentationData
private let updateBackAction: (Bool) -> Void
private let updateNextAction: (SetupTwoStepVerificationNextAction) -> Void
@ -155,15 +154,14 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
private var contentNode: SetupTwoStepVerificationContentNode?
private let actionDisposable = MetaDisposable()
init(sharedContext: SharedAccountContext, network: Network, updateBackAction: @escaping (Bool) -> Void, updateNextAction: @escaping (SetupTwoStepVerificationNextAction) -> Void, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate, Bool) -> Void, present: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void, initialState: SetupTwoStepVerificationInitialState) {
self.sharedContext = sharedContext
self.network = network
init(context: AccountContext, updateBackAction: @escaping (Bool) -> Void, updateNextAction: @escaping (SetupTwoStepVerificationNextAction) -> Void, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate, Bool) -> Void, present: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void, initialState: SetupTwoStepVerificationInitialState) {
self.context = context
self.updateBackAction = updateBackAction
self.updateNextAction = updateNextAction
self.stateUpdated = stateUpdated
self.present = present
self.dismiss = dismiss
self.presentationData = self.sharedContext.currentPresentationData.with { $0 }
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
self.innerState = SetupTwoStepVerificationControllerInnerState(layout: nil, data: SetupTwoStepVerificationControllerDataState(activity: false, state: SetupTwoStepVerificationState(initialState: initialState)))
self.activityIndicator = ActivityIndicator(type: .custom(self.presentationData.theme.list.itemAccentColor, 22.0, 2.0, false))
@ -173,7 +171,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
self.processStateUpdated()
if self.innerState.data.state == nil {
self.actionDisposable.set((twoStepAuthData(self.network)
self.actionDisposable.set((self.context.engine.auth.twoStepAuthData()
|> deliverOnMainQueue).start(next: { [weak self] data in
guard let strongSelf = self else {
return
@ -342,7 +340,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
state.data.activity = true
return state
}, transition: .animated(duration: 0.5, curve: .spring))
strongSelf.actionDisposable.set((updateTwoStepVerificationPassword(network: strongSelf.network, currentPassword: nil, updatedPassword: .none)
strongSelf.actionDisposable.set((strongSelf.context.engine.auth.updateTwoStepVerificationPassword(currentPassword: nil, updatedPassword: .none)
|> deliverOnMainQueue).start(next: { _ in
guard let strongSelf = self else {
return
@ -358,7 +356,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
guard let strongSelf = self else {
return
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.present(textAlertController(sharedContext: strongSelf.context.sharedContext, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.updateState({ state in
var state = state
state.data.activity = false
@ -395,7 +393,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
state.data.activity = true
return state
}, transition: .animated(duration: 0.5, curve: .spring))
strongSelf.actionDisposable.set((resendTwoStepRecoveryEmail(network: strongSelf.network)
strongSelf.actionDisposable.set((strongSelf.context.engine.auth.resendTwoStepRecoveryEmail()
|> deliverOnMainQueue).start(error: { error in
guard let strongSelf = self else {
return
@ -407,7 +405,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
case .generic:
text = strongSelf.presentationData.strings.Login_UnknownError
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.present(textAlertController(sharedContext: strongSelf.context.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.updateState({ state in
var state = state
state.data.activity = false
@ -528,7 +526,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
if password == confirmation {
state.data.state = .enterHint(mode: mode, password: password, hint: "")
} else {
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: strongSelf.presentationData.strings.TwoStepAuth_SetupPasswordConfirmFailed, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.present(textAlertController(sharedContext: strongSelf.context.sharedContext, title: nil, text: strongSelf.presentationData.strings.TwoStepAuth_SetupPasswordConfirmFailed, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
}
case let .enterHint(mode, password, hint):
switch mode {
@ -536,7 +534,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
state.data.state = .enterEmail(state: .create(password: password, hint: hint), email: "")
case let .update(current, hasRecoveryEmail, hasSecureValues):
state.data.activity = true
strongSelf.actionDisposable.set((updateTwoStepVerificationPassword(network: strongSelf.network, currentPassword: current, updatedPassword: .password(password: password, hint: hint, email: nil))
strongSelf.actionDisposable.set((strongSelf.context.engine.auth.updateTwoStepVerificationPassword(currentPassword: current, updatedPassword: .password(password: password, hint: hint, email: nil))
|> deliverOnMainQueue).start(next: { result in
guard let strongSelf = self else {
return
@ -560,7 +558,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
guard let strongSelf = self else {
return
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.present(textAlertController(sharedContext: strongSelf.context.sharedContext, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.updateState({ state in
var state = state
state.data.activity = false
@ -572,7 +570,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
state.data.activity = true
switch enterState {
case let .create(password, hint):
strongSelf.actionDisposable.set((updateTwoStepVerificationPassword(network: strongSelf.network, currentPassword: nil, updatedPassword: .password(password: password, hint: hint, email: email))
strongSelf.actionDisposable.set((strongSelf.context.engine.auth.updateTwoStepVerificationPassword(currentPassword: nil, updatedPassword: .password(password: password, hint: hint, email: email))
|> deliverOnMainQueue).start(next: { result in
guard let strongSelf = self else {
return
@ -604,7 +602,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
case .generic:
text = strongSelf.presentationData.strings.Login_UnknownError
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.present(textAlertController(sharedContext: strongSelf.context.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.updateState({ state in
var state = state
state.data.activity = false
@ -620,7 +618,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
state.data.activity = true
return state
}, transition: .animated(duration: 0.5, curve: .spring))
strongSelf.actionDisposable.set((updateTwoStepVerificationEmail(network: strongSelf.network, currentPassword: password, updatedEmail: email)
strongSelf.actionDisposable.set((strongSelf.context.engine.auth.updateTwoStepVerificationEmail(currentPassword: password, updatedEmail: email)
|> deliverOnMainQueue).start(next: { result in
guard let strongSelf = self else {
return
@ -646,7 +644,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
guard let strongSelf = self else {
return
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.present(textAlertController(sharedContext: strongSelf.context.sharedContext, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.updateState({ state in
var state = state
state.data.activity = false
@ -656,7 +654,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
}
case let .confirmEmail(confirmState, _, _, code):
state.data.activity = true
strongSelf.actionDisposable.set((confirmTwoStepRecoveryEmail(network: strongSelf.network, code: code)
strongSelf.actionDisposable.set((strongSelf.context.engine.auth.confirmTwoStepRecoveryEmail(code: code)
|> deliverOnMainQueue).start(error: { error in
guard let strongSelf = self else {
return
@ -675,7 +673,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
case .generic:
text = strongSelf.presentationData.strings.Login_UnknownError
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.present(textAlertController(sharedContext: strongSelf.context.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
strongSelf.updateState({ state in
var state = state
@ -700,7 +698,7 @@ final class SetupTwoStepVerificationControllerNode: ViewControllerTracingNode {
}, transition: .animated(duration: 0.5, curve: .spring))
}
if case let .enterEmail(enterEmailState, enterEmailEmail)? = self.innerState.data.state, case .create = enterEmailState, enterEmailEmail.isEmpty {
self.present(textAlertController(sharedContext: self.sharedContext, title: nil, text: self.presentationData.strings.TwoStepAuth_EmailSkipAlert, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .destructiveAction, title: self.presentationData.strings.TwoStepAuth_EmailSkip, action: {
self.present(textAlertController(sharedContext: self.context.sharedContext, title: nil, text: self.presentationData.strings.TwoStepAuth_EmailSkipAlert, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .destructiveAction, title: self.presentationData.strings.TwoStepAuth_EmailSkip, action: {
continueImpl()
})]), nil)
} else {

View File

@ -35,14 +35,14 @@ public enum TwoFactorDataInputMode {
public final class TwoFactorDataInputScreen: ViewController {
private let sharedContext: SharedAccountContext
private let network: Network
private let engine: SomeTelegramEngine
private var presentationData: PresentationData
private let mode: TwoFactorDataInputMode
private let stateUpdated: (SetupTwoStepVerificationStateUpdate) -> Void
public init(sharedContext: SharedAccountContext, network: Network, mode: TwoFactorDataInputMode, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate) -> Void) {
public init(sharedContext: SharedAccountContext, engine: SomeTelegramEngine, mode: TwoFactorDataInputMode, stateUpdated: @escaping (SetupTwoStepVerificationStateUpdate) -> Void) {
self.sharedContext = sharedContext
self.network = network
self.engine = engine
self.mode = mode
self.stateUpdated = stateUpdated
@ -101,7 +101,7 @@ public final class TwoFactorDataInputScreen: ViewController {
}
return true
}
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .passwordHint(recovery: nil, password: values[0]), stateUpdated: strongSelf.stateUpdated))
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .passwordHint(recovery: nil, password: values[0]), stateUpdated: strongSelf.stateUpdated))
navigationController.setViewControllers(controllers, animated: true)
case let .passwordRecovery(recovery):
let values = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText
@ -129,7 +129,7 @@ public final class TwoFactorDataInputScreen: ViewController {
}
return true
}
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .passwordHint(recovery: recovery, password: values[0]), stateUpdated: strongSelf.stateUpdated))
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .passwordHint(recovery: recovery, password: values[0]), stateUpdated: strongSelf.stateUpdated))
navigationController.setViewControllers(controllers, animated: true)
case let .emailAddress(password, hint):
guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else {
@ -138,7 +138,7 @@ public final class TwoFactorDataInputScreen: ViewController {
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
strongSelf.present(statusController, in: .window(.root))
let _ = (updateTwoStepVerificationPassword(network: strongSelf.network, currentPassword: "", updatedPassword: .password(password: password, hint: hint, email: text))
let _ = (strongSelf.engine.auth.updateTwoStepVerificationPassword(currentPassword: "", updatedPassword: .password(password: password, hint: hint, email: text))
|> deliverOnMainQueue).start(next: { [weak statusController] result in
statusController?.dismiss()
@ -163,7 +163,7 @@ public final class TwoFactorDataInputScreen: ViewController {
}
return true
}
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .emailConfirmation(passwordAndHint: (password, hint), emailPattern: text, codeLength: pendingEmail.codeLength.flatMap(Int.init)), stateUpdated: strongSelf.stateUpdated))
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .emailConfirmation(passwordAndHint: (password, hint), emailPattern: text, codeLength: pendingEmail.codeLength.flatMap(Int.init)), stateUpdated: strongSelf.stateUpdated))
navigationController.setViewControllers(controllers, animated: true)
} else {
guard let navigationController = strongSelf.navigationController as? NavigationController else {
@ -178,7 +178,7 @@ public final class TwoFactorDataInputScreen: ViewController {
}
return true
}
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .done))
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .done))
navigationController.setViewControllers(controllers, animated: true)
}
}
@ -205,120 +205,130 @@ public final class TwoFactorDataInputScreen: ViewController {
}
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
strongSelf.present(statusController, in: .window(.root))
let _ = (updateTwoStepVerificationEmail(network: strongSelf.network, currentPassword: password, updatedEmail: text)
|> deliverOnMainQueue).start(next: { [weak statusController] result in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
switch result {
case .none:
break
case let .password(_, pendingEmail):
if let pendingEmail = pendingEmail {
guard let navigationController = strongSelf.navigationController as? NavigationController else {
return
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is TwoFactorAuthSplashScreen {
return false
}
if controller is TwoFactorDataInputScreen {
return false
}
return true
}
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .emailConfirmation(passwordAndHint: (password, ""), emailPattern: text, codeLength: pendingEmail.codeLength.flatMap(Int.init)), stateUpdated: strongSelf.stateUpdated))
navigationController.setViewControllers(controllers, animated: true)
} else {
guard let navigationController = strongSelf.navigationController as? NavigationController else {
return
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is TwoFactorAuthSplashScreen {
return false
}
if controller is TwoFactorDataInputScreen {
return false
}
return true
}
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .done))
navigationController.setViewControllers(controllers, animated: true)
switch strongSelf.engine {
case let .authorized(engine):
let _ = (engine.auth.updateTwoStepVerificationEmail(currentPassword: password, updatedEmail: text)
|> deliverOnMainQueue).start(next: { [weak statusController] result in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
}
}, error: { [weak statusController] error in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
let presentationData = strongSelf.presentationData
let alertText: String
switch error {
case .generic:
alertText = presentationData.strings.Login_UnknownError
case .invalidEmail:
alertText = presentationData.strings.TwoStepAuth_EmailInvalid
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: alertText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
})
switch result {
case .none:
break
case let .password(_, pendingEmail):
if let pendingEmail = pendingEmail {
guard let navigationController = strongSelf.navigationController as? NavigationController else {
return
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is TwoFactorAuthSplashScreen {
return false
}
if controller is TwoFactorDataInputScreen {
return false
}
return true
}
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .emailConfirmation(passwordAndHint: (password, ""), emailPattern: text, codeLength: pendingEmail.codeLength.flatMap(Int.init)), stateUpdated: strongSelf.stateUpdated))
navigationController.setViewControllers(controllers, animated: true)
} else {
guard let navigationController = strongSelf.navigationController as? NavigationController else {
return
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is TwoFactorAuthSplashScreen {
return false
}
if controller is TwoFactorDataInputScreen {
return false
}
return true
}
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .done))
navigationController.setViewControllers(controllers, animated: true)
}
}
}, error: { [weak statusController] error in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
let presentationData = strongSelf.presentationData
let alertText: String
switch error {
case .generic:
alertText = presentationData.strings.Login_UnknownError
case .invalidEmail:
alertText = presentationData.strings.TwoStepAuth_EmailInvalid
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: alertText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
})
case .unauthorized:
break
}
case .emailConfirmation:
guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else {
return
}
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
strongSelf.present(statusController, in: .window(.root))
let _ = (confirmTwoStepRecoveryEmail(network: strongSelf.network, code: text)
|> deliverOnMainQueue).start(error: { [weak statusController] error in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
let presentationData = strongSelf.presentationData
let text: String
switch error {
case .invalidEmail:
text = presentationData.strings.TwoStepAuth_EmailInvalid
case .invalidCode:
text = presentationData.strings.Login_InvalidCodeError
case .expired:
text = presentationData.strings.TwoStepAuth_EmailCodeExpired
case .flood:
text = presentationData.strings.TwoStepAuth_FloodError
case .generic:
text = presentationData.strings.Login_UnknownError
}
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, completed: { [weak statusController] in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
guard let navigationController = strongSelf.navigationController as? NavigationController else {
return
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is TwoFactorAuthSplashScreen {
return false
switch strongSelf.engine {
case let .authorized(engine):
let _ = (engine.auth.confirmTwoStepRecoveryEmail(code: text)
|> deliverOnMainQueue).start(error: { [weak statusController] error in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
if controller is TwoFactorDataInputScreen {
return false
let presentationData = strongSelf.presentationData
let text: String
switch error {
case .invalidEmail:
text = presentationData.strings.TwoStepAuth_EmailInvalid
case .invalidCode:
text = presentationData.strings.Login_InvalidCodeError
case .expired:
text = presentationData.strings.TwoStepAuth_EmailCodeExpired
case .flood:
text = presentationData.strings.TwoStepAuth_FloodError
case .generic:
text = presentationData.strings.Login_UnknownError
}
return true
}
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .done))
navigationController.setViewControllers(controllers, animated: true)
})
strongSelf.present(textAlertController(sharedContext: strongSelf.sharedContext, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, completed: { [weak statusController] in
statusController?.dismiss()
guard let strongSelf = self else {
return
}
guard let navigationController = strongSelf.navigationController as? NavigationController else {
return
}
var controllers = navigationController.viewControllers.filter { controller in
if controller is TwoFactorAuthSplashScreen {
return false
}
if controller is TwoFactorDataInputScreen {
return false
}
return true
}
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .done))
navigationController.setViewControllers(controllers, animated: true)
})
case .unauthorized:
break
}
case let .passwordHint(recovery, password):
guard let value = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !value.isEmpty else {
return
@ -327,7 +337,7 @@ public final class TwoFactorDataInputScreen: ViewController {
if let recovery = recovery {
strongSelf.performRecovery(recovery: recovery, password: password, hint: value)
} else {
strongSelf.push(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .emailAddress(password: password, hint: value), stateUpdated: strongSelf.stateUpdated))
strongSelf.push(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .emailAddress(password: password, hint: value), stateUpdated: strongSelf.stateUpdated))
}
}
}, skipAction: { [weak self] in
@ -344,7 +354,7 @@ public final class TwoFactorDataInputScreen: ViewController {
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
strongSelf.present(statusController, in: .window(.root))
let _ = (updateTwoStepVerificationPassword(network: strongSelf.network, currentPassword: "", updatedPassword: .password(password: password, hint: hint, email: nil))
let _ = (strongSelf.engine.auth.updateTwoStepVerificationPassword(currentPassword: "", updatedPassword: .password(password: password, hint: hint, email: nil))
|> deliverOnMainQueue).start(next: { [weak statusController] result in
statusController?.dismiss()
@ -368,7 +378,7 @@ public final class TwoFactorDataInputScreen: ViewController {
}
return true
}
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .done))
controllers.append(TwoFactorAuthSplashScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .done))
navigationController.setViewControllers(controllers, animated: true)
}
}, error: { [weak statusController] error in
@ -395,7 +405,7 @@ public final class TwoFactorDataInputScreen: ViewController {
if let recovery = recovery {
strongSelf.performRecovery(recovery: recovery, password: password, hint: "")
} else {
strongSelf.push(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .emailAddress(password: password, hint: ""), stateUpdated: strongSelf.stateUpdated))
strongSelf.push(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .emailAddress(password: password, hint: ""), stateUpdated: strongSelf.stateUpdated))
}
case let .passwordRecovery(recovery):
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.TwoFactorSetup_PasswordRecovery_SkipAlertTitle, text: strongSelf.presentationData.strings.TwoFactorSetup_PasswordRecovery_SkipAlertText, actions: [
@ -429,7 +439,7 @@ public final class TwoFactorDataInputScreen: ViewController {
}
return true
}
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .emailAddress(password: password, hint: hint), stateUpdated: strongSelf.stateUpdated))
controllers.append(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .emailAddress(password: password, hint: hint), stateUpdated: strongSelf.stateUpdated))
navigationController.setViewControllers(controllers, animated: true)
} else {
}
@ -443,8 +453,8 @@ public final class TwoFactorDataInputScreen: ViewController {
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
strongSelf.present(statusController, in: .window(.root))
let _ = (resendTwoStepRecoveryEmail(network: strongSelf.network)
let _ = (strongSelf.engine.auth.resendTwoStepRecoveryEmail()
|> deliverOnMainQueue).start(error: { [weak statusController] error in
statusController?.dismiss()
@ -475,10 +485,13 @@ public final class TwoFactorDataInputScreen: ViewController {
}
private func performRecovery(recovery: TwoFactorDataInputMode.Recovery, password: String, hint: String) {
guard case let .unauthorized(engine) = self.engine else {
return
}
let statusController = OverlayStatusController(theme: self.presentationData.theme, type: .loading(cancelled: nil))
self.present(statusController, in: .window(.root))
let _ = (performPasswordRecovery(accountManager: self.sharedContext.accountManager, account: recovery.account, code: recovery.code, syncContacts: recovery.syncContacts, updatedPassword: password.isEmpty ? .none : .password(password: password, hint: hint, email: nil))
let _ = (engine.auth.performPasswordRecovery(accountManager: self.sharedContext.accountManager, code: recovery.code, syncContacts: recovery.syncContacts, updatedPassword: password.isEmpty ? .none : .password(password: password, hint: hint, email: nil))
|> deliverOnMainQueue).start(error: { [weak self, weak statusController] error in
statusController?.dismiss()

View File

@ -19,13 +19,13 @@ public enum TwoFactorAuthSplashMode {
public final class TwoFactorAuthSplashScreen: ViewController {
private let sharedContext: SharedAccountContext
private let network: Network
private let engine: SomeTelegramEngine
private var presentationData: PresentationData
private var mode: TwoFactorAuthSplashMode
public init(sharedContext: SharedAccountContext, network: Network, mode: TwoFactorAuthSplashMode) {
public init(sharedContext: SharedAccountContext, engine: SomeTelegramEngine, mode: TwoFactorAuthSplashMode) {
self.sharedContext = sharedContext
self.network = network
self.engine = engine
self.mode = mode
self.presentationData = self.sharedContext.currentPresentationData.with { $0 }
@ -57,7 +57,7 @@ public final class TwoFactorAuthSplashScreen: ViewController {
}
switch strongSelf.mode {
case .intro:
strongSelf.push(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.network, mode: .password, stateUpdated: { _ in
strongSelf.push(TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: strongSelf.engine, mode: .password, stateUpdated: { _ in
}))
case .done:
guard let navigationController = strongSelf.navigationController as? NavigationController else {

View File

@ -779,7 +779,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
}
let state = stateValue.with { $0 }
if let modifiedSlowmodeTimeout = state.modifiedSlowmodeTimeout {
updateDefaultRightsDisposable.set(updateChannelSlowModeInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: view.peerId, timeout: modifiedSlowmodeTimeout == 0 ? nil : value).start())
updateDefaultRightsDisposable.set(context.engine.peers.updateChannelSlowModeInteractively(peerId: view.peerId, timeout: modifiedSlowmodeTimeout == 0 ? nil : value).start())
}
} else if let _ = view.peers[view.peerId] as? TelegramGroup, let _ = view.cachedData as? CachedGroupData {
updateState { state in
@ -815,7 +815,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
}
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, UpdateChannelSlowModeError> in
return updateChannelSlowModeInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: upgradedPeerId, timeout: modifiedSlowmodeTimeout == 0 ? nil : value)
return context.engine.peers.updateChannelSlowModeInteractively(peerId: upgradedPeerId, timeout: modifiedSlowmodeTimeout == 0 ? nil : value)
|> mapToSignal { _ -> Signal<PeerId?, UpdateChannelSlowModeError> in
return .complete()
}

View File

@ -1,244 +0,0 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
import SyncCore
import TelegramPresentationData
import TelegramUIPreferences
import ItemListUI
import PresentationDataUtils
import AccountContext
import ItemListPeerItem
import ContextUI
private final class GroupsInCommonControllerArguments {
let context: AccountContext
let openPeer: (PeerId) -> Void
let contextAction: (Peer, ASDisplayNode, ContextGesture?) -> Void
init(context: AccountContext, openPeer: @escaping (PeerId) -> Void, contextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void) {
self.context = context
self.openPeer = openPeer
self.contextAction = contextAction
}
}
private enum GroupsInCommonSection: Int32 {
case peers
}
private enum GroupsInCommonEntryStableId: Hashable {
case peer(PeerId)
}
private enum GroupsInCommonEntry: ItemListNodeEntry {
case peerItem(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, Peer)
var section: ItemListSectionId {
switch self {
case .peerItem:
return GroupsInCommonSection.peers.rawValue
}
}
var stableId: GroupsInCommonEntryStableId {
switch self {
case let .peerItem(_, _, _, _, _, peer):
return .peer(peer.id)
}
}
static func ==(lhs: GroupsInCommonEntry, rhs: GroupsInCommonEntry) -> Bool {
switch lhs {
case let .peerItem(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameOrder, lhsPeer):
if case let .peerItem(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameOrder, rhsPeer) = rhs {
if lhsIndex != rhsIndex {
return false
}
if lhsTheme !== rhsTheme {
return false
}
if lhsStrings !== rhsStrings {
return false
}
if lhsDateTimeFormat != rhsDateTimeFormat {
return false
}
if !lhsPeer.isEqual(rhsPeer) {
return false
}
if lhsNameOrder != rhsNameOrder {
return false
}
return true
} else {
return false
}
}
}
static func <(lhs: GroupsInCommonEntry, rhs: GroupsInCommonEntry) -> Bool {
switch lhs {
case let .peerItem(index, _, _, _, _, _):
switch rhs {
case let .peerItem(rhsIndex, _, _, _, _, _):
return index < rhsIndex
}
}
}
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! GroupsInCommonControllerArguments
switch self {
case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
arguments.openPeer(peer.id)
}, setPeerIdWithRevealedOptions: { _, _ in
}, removePeer: { _ in
}, contextAction: { node, gesture in
arguments.contextAction(peer, node, gesture)
})
}
}
}
private struct GroupsInCommonControllerState: Equatable {
static func ==(lhs: GroupsInCommonControllerState, rhs: GroupsInCommonControllerState) -> Bool {
return true
}
}
private func groupsInCommonControllerEntries(presentationData: PresentationData, state: GroupsInCommonControllerState, peers: [Peer]?) -> [GroupsInCommonEntry] {
var entries: [GroupsInCommonEntry] = []
if let peers = peers {
var index: Int32 = 0
for peer in peers {
entries.append(.peerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peer))
index += 1
}
}
return entries
}
public func groupsInCommonController(context: AccountContext, peerId: PeerId) -> ViewController {
let statePromise = ValuePromise(GroupsInCommonControllerState(), ignoreRepeated: true)
let stateValue = Atomic(value: GroupsInCommonControllerState())
let updateState: ((GroupsInCommonControllerState) -> GroupsInCommonControllerState) -> Void = { f in
statePromise.set(stateValue.modify { f($0) })
}
let actionsDisposable = DisposableSet()
let peersPromise = Promise<[Peer]?>(nil)
var pushControllerImpl: ((ViewController) -> Void)?
var getNavigationControllerImpl: (() -> NavigationController?)?
var contextActionImpl: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?
let arguments = GroupsInCommonControllerArguments(context: context, openPeer: { memberId in
guard let navigationController = getNavigationControllerImpl?() else {
return
}
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(memberId), animated: true))
}, contextAction: { peer, node, gesture in
contextActionImpl?(peer, node, gesture)
})
let peersSignal: Signal<[Peer]?, NoError> = .single(nil) |> then(groupsInCommon(account: context.account, peerId: peerId) |> mapToSignal { peerIds -> Signal<[Peer], NoError> in
return context.account.postbox.transaction { transaction -> [Peer] in
var result: [Peer] = []
for id in peerIds {
if let peer = transaction.getPeer(id.id) {
result.append(peer)
}
}
return result
}
}
|> map(Optional.init))
peersPromise.set(peersSignal)
var previousPeers: [Peer]?
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get(), peersPromise.get())
|> deliverOnMainQueue
|> map { presentationData, state, peers -> (ItemListControllerState, (ItemListNodeState, Any)) in
var emptyStateItem: ItemListControllerEmptyStateItem?
if peers == nil {
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
}
let previous = previousPeers
previousPeers = peers
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.UserInfo_GroupsInCommon), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupsInCommonControllerEntries(presentationData: presentationData, state: state, peers: peers), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: previous != nil && peers != nil && previous!.count >= peers!.count)
return (controllerState, (listState, arguments))
} |> afterDisposed {
actionsDisposable.dispose()
}
let controller = ItemListController(context: context, state: signal)
pushControllerImpl = { [weak controller] c in
if let controller = controller {
(controller.navigationController as? NavigationController)?.pushViewController(c)
}
}
getNavigationControllerImpl = { [weak controller] in
return controller?.navigationController as? NavigationController
}
contextActionImpl = { [weak controller] peer, node, gesture in
guard let controller = controller else {
return
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
chatController.canReadHistory.set(false)
let items: [ContextMenuItem] = [
.action(ContextMenuActionItem(text: presentationData.strings.Conversation_LinkDialogOpen, icon: { _ in nil }, action: { _, f in
f(.dismissWithoutContent)
arguments.openPeer(peer.id)
}))
]
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture)
controller.presentInGlobalOverlay(contextController)
}
return controller
}
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
let controller: ViewController
weak var sourceNode: ASDisplayNode?
let navigationController: NavigationController? = nil
let passthroughTouches: Bool = true
init(controller: ViewController, sourceNode: ASDisplayNode?) {
self.controller = controller
self.sourceNode = sourceNode
}
func transitionInfo() -> ContextControllerTakeControllerInfo? {
let sourceNode = self.sourceNode
return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in
if let sourceNode = sourceNode {
return (sourceNode, sourceNode.bounds)
} else {
return nil
}
})
}
func animatedIn() {
}
}

View File

@ -107,19 +107,19 @@ public func presentPeerReportOptions(context: AccountContext, parent: ViewContro
} else {
switch subject {
case let .peer(peerId):
let _ = (reportPeer(account: context.account, peerId: peerId, reason: reportReason, message: "")
let _ = (context.engine.peers.reportPeer(peerId: peerId, reason: reportReason, message: "")
|> deliverOnMainQueue).start(completed: {
displaySuccess()
completion(nil, false)
})
case let .messages(messageIds):
let _ = (reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason, message: "")
let _ = (context.engine.peers.reportPeerMessages(messageIds: messageIds, reason: reportReason, message: "")
|> deliverOnMainQueue).start(completed: {
displaySuccess()
completion(nil, false)
})
case let .profilePhoto(peerId, photoId):
let _ = (reportPeerPhoto(account: context.account, peerId: peerId, reason: reportReason, message: "")
let _ = (context.engine.peers.reportPeerPhoto(peerId: peerId, reason: reportReason, message: "")
|> deliverOnMainQueue).start(completed: {
displaySuccess()
completion(nil, false)
@ -233,19 +233,19 @@ public func peerReportOptionsController(context: AccountContext, subject: PeerRe
} else {
switch subject {
case let .peer(peerId):
let _ = (reportPeer(account: context.account, peerId: peerId, reason: reportReason, message: message)
let _ = (context.engine.peers.reportPeer(peerId: peerId, reason: reportReason, message: message)
|> deliverOnMainQueue).start(completed: {
displaySuccess()
completion(nil, true)
})
case let .messages(messageIds):
let _ = (reportPeerMessages(account: context.account, messageIds: messageIds, reason: reportReason, message: message)
let _ = (context.engine.peers.reportPeerMessages(messageIds: messageIds, reason: reportReason, message: message)
|> deliverOnMainQueue).start(completed: {
displaySuccess()
completion(nil, true)
})
case let .profilePhoto(peerId, photoId):
let _ = (reportPeerPhoto(account: context.account, peerId: peerId, reason: reportReason, message: message)
let _ = (context.engine.peers.reportPeerPhoto(peerId: peerId, reason: reportReason, message: message)
|> deliverOnMainQueue).start(completed: {
displaySuccess()
completion(nil, true)

View File

@ -274,7 +274,7 @@ func createPasswordController(context: AccountContext, createPasswordContext: Cr
state.saving = true
return state
}
saveDisposable.set((updateTwoStepVerificationPassword(network: context.account.network, currentPassword: currentPassword, updatedPassword: .password(password: state.passwordText, hint: state.hintText, email: email))
saveDisposable.set((context.engine.auth.updateTwoStepVerificationPassword(currentPassword: currentPassword, updatedPassword: .password(password: state.passwordText, hint: state.hintText, email: email))
|> deliverOnMainQueue).start(next: { update in
switch update {
case .none:
@ -356,7 +356,7 @@ func createPasswordController(context: AccountContext, createPasswordContext: Cr
return state
}
saveDisposable.set((updateTwoStepVerificationPassword(network: context.account.network, currentPassword: currentPassword, updatedPassword: .none)
saveDisposable.set((context.engine.auth.updateTwoStepVerificationPassword(currentPassword: currentPassword, updatedPassword: .none)
|> deliverOnMainQueue).start(next: { _ in
updateState { state in
var state = state

View File

@ -542,7 +542,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
}
let updateHasTwoStepAuth: () -> Void = {
let signal = twoStepVerificationConfiguration(account: context.account)
let signal = context.engine.auth.twoStepVerificationConfiguration()
|> map { value -> TwoStepVerificationAccessConfiguration? in
return TwoStepVerificationAccessConfiguration(configuration: value, password: nil)
}
@ -735,7 +735,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
case let .notSet(pendingEmail):
//intro = pendingEmail == nil
if pendingEmail == nil {
let controller = TwoFactorAuthSplashScreen(sharedContext: context.sharedContext, network: context.account.network, mode: .intro)
let controller = TwoFactorAuthSplashScreen(sharedContext: context.sharedContext, engine: .authorized(context.engine), mode: .intro)
pushControllerImpl?(controller, true)
return
} else {

View File

@ -332,7 +332,7 @@ func twoStepVerificationPasswordEntryController(context: AccountContext, mode: T
if case let .change(current) = mode {
currentPassword = current
}
updatePasswordDisposable.set((updateTwoStepVerificationPassword(network: context.account.network, currentPassword: currentPassword, updatedPassword: .password(password: password, hint: hint, email: email)) |> deliverOnMainQueue).start(next: { update in
updatePasswordDisposable.set((context.engine.auth.updateTwoStepVerificationPassword(currentPassword: currentPassword, updatedPassword: .password(password: password, hint: hint, email: email)) |> deliverOnMainQueue).start(next: { update in
updateState {
$0.withUpdatedUpdating(false)
}
@ -357,7 +357,7 @@ func twoStepVerificationPasswordEntryController(context: AccountContext, mode: T
presentControllerImpl?(textAlertController(context: context, title: nil, text: alertText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}))
case let .setupEmail(password):
updatePasswordDisposable.set((updateTwoStepVerificationEmail(network: context.account.network, currentPassword: password, updatedEmail: email) |> deliverOnMainQueue).start(next: { update in
updatePasswordDisposable.set((context.engine.auth.updateTwoStepVerificationEmail(currentPassword: password, updatedEmail: email) |> deliverOnMainQueue).start(next: { update in
updateState {
$0.withUpdatedUpdating(false)
}

View File

@ -168,7 +168,7 @@ func twoStepVerificationResetController(context: AccountContext, emailPattern: S
}
}
if let code = code {
resetPasswordDisposable.set((recoverTwoStepVerificationPassword(network: context.account.network, code: code) |> deliverOnMainQueue).start(error: { error in
resetPasswordDisposable.set((context.engine.auth.recoverTwoStepVerificationPassword(code: code) |> deliverOnMainQueue).start(error: { error in
updateState {
return $0.withUpdatedChecking(false)
}
@ -204,7 +204,7 @@ func twoStepVerificationResetController(context: AccountContext, emailPattern: S
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.TwoStepAuth_RecoveryUnavailableResetTitle, text: presentationData.strings.TwoStepAuth_RecoveryEmailResetText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.TwoStepAuth_RecoveryUnavailableResetAction, action: {
let _ = (requestTwoStepPasswordReset(network: context.account.network)
let _ = (context.engine.auth.requestTwoStepPasswordReset()
|> deliverOnMainQueue).start(next: { result in
switch result {
case .done, .waitingForReset:

View File

@ -316,7 +316,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
} else {
dataPromise.set(.single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: nil))
|> then(remoteDataPromise.get()))
remoteDataPromise.set(twoStepVerificationConfiguration(account: context.account)
remoteDataPromise.set(context.engine.auth.twoStepVerificationConfiguration()
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil)) })
}
case let .manage(password, email, pendingEmail, hasSecureValues):
@ -355,7 +355,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
return state
}
if let code = code {
setupDisposable.set((confirmTwoStepRecoveryEmail(network: context.account.network, code: code)
setupDisposable.set((context.engine.auth.confirmTwoStepRecoveryEmail(code: code)
|> deliverOnMainQueue).start(error: { error in
updateState { state in
var state = state
@ -404,7 +404,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
dataPromise.set(.single(TwoStepVerificationUnlockSettingsControllerData.manage(password: password, emailSet: true, pendingEmail: nil, hasSecureValues: false)))
} else {
dataPromise.set(.single(.access(configuration: nil))
|> then(twoStepVerificationConfiguration(account: context.account) |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: pendingEmail.password)) }))
|> then(context.engine.auth.twoStepVerificationConfiguration() |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: pendingEmail.password)) }))
}
case let .manage(manage):
dataPromise.set(.single(TwoStepVerificationUnlockSettingsControllerData.manage(password: manage.password, emailSet: true, pendingEmail: nil, hasSecureValues: manage.hasSecureValues)))
@ -441,9 +441,9 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
}
if let password = password, !password.isEmpty, !wasChecking {
checkDisposable.set((requestTwoStepVerifiationSettings(network: context.account.network, password: password)
checkDisposable.set((context.engine.auth.requestTwoStepVerifiationSettings(password: password)
|> mapToSignal { settings -> Signal<(TwoStepVerificationSettings, TwoStepVerificationPendingEmail?), AuthorizationPasswordVerificationError> in
return twoStepVerificationConfiguration(account: context.account)
return context.engine.auth.twoStepVerificationConfiguration()
|> mapError { _ -> AuthorizationPasswordVerificationError in
}
|> map { configuration in
@ -500,7 +500,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
state.checking = true
return state
}
setupResultDisposable.set((requestTwoStepVerificationPasswordRecoveryCode(network: context.account.network)
setupResultDisposable.set((context.engine.auth.requestTwoStepVerificationPasswordRecoveryCode()
|> deliverOnMainQueue).start(next: { emailPattern in
updateState { state in
var state = state
@ -514,7 +514,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
})
completionImpl = { [weak controller] result in
if !result {
dataPromise.set(twoStepVerificationConfiguration(account: context.account)
dataPromise.set(context.engine.auth.twoStepVerificationConfiguration()
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil))
})
controller?.view.endEditing(true)
@ -541,11 +541,11 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
if let pendingResetTimestamp = pendingResetTimestamp {
let remainingSeconds = pendingResetTimestamp - Int32(Date().timeIntervalSince1970)
if remainingSeconds <= 0 {
let _ = (requestTwoStepPasswordReset(network: context.account.network)
let _ = (context.engine.auth.requestTwoStepPasswordReset()
|> deliverOnMainQueue).start(next: { result in
switch result {
case .done, .waitingForReset:
dataPromise.set(twoStepVerificationConfiguration(account: context.account)
dataPromise.set(context.engine.auth.twoStepVerificationConfiguration()
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil))
})
case .declined:
@ -557,11 +557,11 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
}
} else {
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.TwoStepAuth_RecoveryUnavailableResetTitle, text: presentationData.strings.TwoStepAuth_RecoveryUnavailableResetText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.TwoStepAuth_RecoveryUnavailableResetAction, action: {
let _ = (requestTwoStepPasswordReset(network: context.account.network)
let _ = (context.engine.auth.requestTwoStepPasswordReset()
|> deliverOnMainQueue).start(next: { result in
switch result {
case .done, .waitingForReset:
dataPromise.set(twoStepVerificationConfiguration(account: context.account)
dataPromise.set(context.engine.auth.twoStepVerificationConfiguration()
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil))
})
case .declined:
@ -603,7 +603,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.TwoStepAuth_EnabledSuccess, false)), nil)
} else {
dataPromise.set(.single(.access(configuration: nil))
|> then(twoStepVerificationConfiguration(account: context.account) |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
|> then(context.engine.auth.twoStepVerificationConfiguration() |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
}
}
if shouldDismiss {
@ -635,7 +635,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.TwoStepAuth_PasswordChangeSuccess, false)), nil)
} else {
dataPromise.set(.single(.access(configuration: nil))
|> then(twoStepVerificationConfiguration(account: context.account) |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
|> then(context.engine.auth.twoStepVerificationConfiguration() |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
}
}
if shouldDismiss {
@ -677,7 +677,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
case let .manage(password, _, _, _):
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.TwoStepAuth_DisableSuccess, false)), nil)
return updateTwoStepVerificationPassword(network: context.account.network, currentPassword: password, updatedPassword: .none)
return context.engine.auth.updateTwoStepVerificationPassword(currentPassword: password, updatedPassword: .none)
|> mapToSignal { _ -> Signal<Void, UpdateTwoStepVerificationPasswordError> in
return .complete()
}
@ -730,7 +730,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(emailSet ? presentationData.strings.TwoStepAuth_EmailChangeSuccess : presentationData.strings.TwoStepAuth_EmailAddSuccess, false)), nil)
} else {
dataPromise.set(.single(.access(configuration: nil))
|> then(twoStepVerificationConfiguration(account: context.account) |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
|> then(context.engine.auth.twoStepVerificationConfiguration() |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
}
}
if shouldDismiss {
@ -746,7 +746,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
state.checking = true
return state
}
setupDisposable.set((updateTwoStepVerificationPassword(network: context.account.network, currentPassword: nil, updatedPassword: .none)
setupDisposable.set((context.engine.auth.updateTwoStepVerificationPassword(currentPassword: nil, updatedPassword: .none)
|> deliverOnMainQueue).start(next: { _ in
updateState { state in
var state = state
@ -817,7 +817,7 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
dataPromise.set(.single(data))
} else {
dataPromise.set(.single(.access(configuration: nil))
|> then(twoStepVerificationConfiguration(account: context.account) |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
|> then(context.engine.auth.twoStepVerificationConfiguration() |> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: password)) }))
}
}
if shouldDismiss {
@ -830,22 +830,22 @@ func twoStepVerificationUnlockSettingsController(context: AccountContext, mode:
}, declinePasswordReset: {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.TwoStepAuth_CancelResetTitle, text: presentationData.strings.TwoStepAuth_CancelResetText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Yes, action: {
let _ = (declineTwoStepPasswordReset(network: context.account.network)
let _ = (context.engine.auth.declineTwoStepPasswordReset()
|> deliverOnMainQueue).start(completed: {
dataPromise.set(twoStepVerificationConfiguration(account: context.account)
dataPromise.set(context.engine.auth.twoStepVerificationConfiguration()
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil))
})
})
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_No, action: {
})]), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, resetPassword: {
let _ = (requestTwoStepPasswordReset(network: context.account.network)
let _ = (context.engine.auth.requestTwoStepPasswordReset()
|> deliverOnMainQueue).start(next: { result in
switch result {
case .done:
dismissImpl?()
case .waitingForReset:
dataPromise.set(twoStepVerificationConfiguration(account: context.account)
dataPromise.set(context.engine.auth.twoStepVerificationConfiguration()
|> map { TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: $0, password: nil))
})
case .declined:

View File

@ -314,7 +314,7 @@ public func callFeedbackController(sharedContext: SharedAccountContext, account:
}
comment.append(hashtags)
let _ = rateCallAndSendLogs(account: account, callId: callId, starsCount: rating, comment: comment, userInitiated: userInitiated, includeLogs: state.includeLogs).start()
let _ = rateCallAndSendLogs(engine: TelegramEngine(account: account), callId: callId, starsCount: rating, comment: comment, userInitiated: userInitiated, includeLogs: state.includeLogs).start()
dismissImpl?()
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .starSuccess(presentationData.strings.CallFeedback_Success)))

View File

@ -240,24 +240,24 @@ private final class CallRatingAlertContentNode: AlertContentNode {
}
}
func rateCallAndSendLogs(account: Account, callId: CallId, starsCount: Int, comment: String, userInitiated: Bool, includeLogs: Bool) -> Signal<Void, NoError> {
func rateCallAndSendLogs(engine: TelegramEngine, callId: CallId, starsCount: Int, comment: String, userInitiated: Bool, includeLogs: Bool) -> Signal<Void, NoError> {
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt32Value(4244000))
let rate = rateCall(account: account, callId: callId, starsCount: Int32(starsCount), comment: comment, userInitiated: userInitiated)
let rate = engine.calls.rateCall(callId: callId, starsCount: Int32(starsCount), comment: comment, userInitiated: userInitiated)
if includeLogs {
let id = Int64.random(in: Int64.min ... Int64.max)
let name = "\(callId.id)_\(callId.accessHash).log.json"
let path = callLogsPath(account: account) + "/" + name
let path = callLogsPath(account: engine.account) + "/" + name
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)])
let message = EnqueueMessage.message(text: comment, attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
return rate
|> then(enqueueMessages(account: account, peerId: peerId, messages: [message])
|> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [message])
|> mapToSignal({ _ -> Signal<Void, NoError> in
return .single(Void())
}))
} else if !comment.isEmpty {
return rate
|> then(enqueueMessages(account: account, peerId: peerId, messages: [.message(text: comment, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)])
|> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [.message(text: comment, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)])
|> mapToSignal({ _ -> Signal<Void, NoError> in
return .single(Void())
}))
@ -284,7 +284,7 @@ public func callRatingController(sharedContext: SharedAccountContext, account: A
if rating < 4 {
push(callFeedbackController(sharedContext: sharedContext, account: account, callId: callId, rating: rating, userInitiated: userInitiated, isVideo: isVideo))
} else {
let _ = rateCallAndSendLogs(account: account, callId: callId, starsCount: rating, comment: "", userInitiated: userInitiated, includeLogs: false).start()
let _ = rateCallAndSendLogs(engine: TelegramEngine(account: account), callId: callId, starsCount: rating, comment: "", userInitiated: userInitiated, includeLogs: false).start()
}
})

View File

@ -373,7 +373,7 @@ public struct TwoStepAuthData {
public let pendingResetTimestamp: Int32?
}
public func twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MTRpcError> {
func _internal_twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MTRpcError> {
return network.request(Api.functions.account.getPassword())
|> map { config -> TwoStepAuthData in
switch config {
@ -664,7 +664,7 @@ func securePasswordKDF(password: String, derivation: TwoStepSecurePasswordDeriva
}
func verifyPassword(_ account: UnauthorizedAccount, password: String) -> Signal<Api.auth.Authorization, MTRpcError> {
return twoStepAuthData(account.network)
return _internal_twoStepAuthData(account.network)
|> mapToSignal { authData -> Signal<Api.auth.Authorization, MTRpcError> in
guard let currentPasswordDerivation = authData.currentPasswordDerivation, let srpSessionData = authData.srpSessionData else {
return .fail(MTRpcError(errorCode: 400, errorDescription: "INTERNAL_NO_PASSWORD"))

View File

@ -389,8 +389,8 @@ public func checkPasswordRecoveryCode(network: Network, code: String) -> Signal<
}
}
public func performPasswordRecovery(accountManager: AccountManager, account: UnauthorizedAccount, code: String, syncContacts: Bool, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<Void, PasswordRecoveryError> {
return twoStepAuthData(account.network)
func _internal_performPasswordRecovery(accountManager: AccountManager, account: UnauthorizedAccount, code: String, syncContacts: Bool, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<Void, PasswordRecoveryError> {
return _internal_twoStepAuthData(account.network)
|> mapError { _ -> PasswordRecoveryError in
return .generic
}

View File

@ -95,7 +95,7 @@ public func updateChannelOwnership(account: Account, accountStateManager: Accoun
let updatedParticipant = ChannelParticipant.creator(id: user.id, adminInfo: nil, rank: currentParticipant?.rank)
let updatedPreviousCreator = ChannelParticipant.member(id: accountUser.id, invitedAt: Int32(Date().timeIntervalSince1970), adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(rights: flags), promotedBy: accountUser.id, canBeEditedByAccountPeer: false), banInfo: nil, rank: currentCreator?.rank)
let checkPassword = twoStepAuthData(account.network)
let checkPassword = _internal_twoStepAuthData(account.network)
|> mapError { error -> ChannelOwnershipTransferError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded

View File

@ -1,244 +0,0 @@
import Foundation
import SwiftSignalKit
import Postbox
import SyncCore
import TelegramApi
public enum ChatHistoryImport {
public struct Session {
fileprivate var peerId: PeerId
fileprivate var inputPeer: Api.InputPeer
fileprivate var id: Int64
}
public enum InitImportError {
case generic
case chatAdminRequired
case invalidChatType
case userBlocked
case limitExceeded
}
public enum ParsedInfo {
case privateChat(title: String?)
case group(title: String?)
case unknown(title: String?)
}
public enum GetInfoError {
case generic
case parseError
}
public static func getInfo(account: Account, header: String) -> Signal<ParsedInfo, GetInfoError> {
return account.network.request(Api.functions.messages.checkHistoryImport(importHead: header))
|> mapError { _ -> GetInfoError in
return .generic
}
|> mapToSignal { result -> Signal<ParsedInfo, GetInfoError> in
switch result {
case let .historyImportParsed(flags, title):
if (flags & (1 << 0)) != 0 {
return .single(.privateChat(title: title))
} else if (flags & (1 << 1)) != 0 {
return .single(.group(title: title))
} else {
return .single(.unknown(title: title))
}
}
}
}
public static func initSession(account: Account, peerId: PeerId, file: TempBoxFile, mediaCount: Int32) -> Signal<Session, InitImportError> {
return multipartUpload(network: account.network, postbox: account.postbox, source: .tempFile(file), encrypt: false, tag: nil, hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: true, useLargerParts: true, increaseParallelParts: true, useMultiplexedRequests: false, useCompression: true)
|> mapError { _ -> InitImportError in
return .generic
}
|> mapToSignal { result -> Signal<Session, InitImportError> in
switch result {
case let .inputFile(inputFile):
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
}
|> castError(InitImportError.self)
|> mapToSignal { inputPeer -> Signal<Session, InitImportError> in
guard let inputPeer = inputPeer else {
return .fail(.generic)
}
return account.network.request(Api.functions.messages.initHistoryImport(peer: inputPeer, file: inputFile, mediaCount: mediaCount), automaticFloodWait: false)
|> mapError { error -> InitImportError in
if error.errorDescription == "CHAT_ADMIN_REQUIRED" {
return .chatAdminRequired
} else if error.errorDescription == "IMPORT_PEER_TYPE_INVALID" {
return .invalidChatType
} else if error.errorDescription == "USER_IS_BLOCKED" {
return .userBlocked
} else if error.errorDescription == "FLOOD_WAIT" {
return .limitExceeded
} else {
return .generic
}
}
|> map { result -> Session in
switch result {
case let .historyImport(id):
return Session(peerId: peerId, inputPeer: inputPeer, id: id)
}
}
}
case .progress:
return .complete()
case .inputSecretFile:
return .fail(.generic)
}
}
}
public enum MediaType {
case photo
case file
case video
case sticker
case voice
}
public enum UploadMediaError {
case generic
case chatAdminRequired
}
public static func uploadMedia(account: Account, session: Session, file: TempBoxFile, disposeFileAfterDone: Bool, fileName: String, mimeType: String, type: MediaType) -> Signal<Float, UploadMediaError> {
var forceNoBigParts = true
guard let size = fileSize(file.path), size != 0 else {
return .single(1.0)
}
if size >= 30 * 1024 * 1024 {
forceNoBigParts = false
}
return multipartUpload(network: account.network, postbox: account.postbox, source: .tempFile(file), encrypt: false, tag: nil, hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: forceNoBigParts, useLargerParts: true, useMultiplexedRequests: true)
|> mapError { _ -> UploadMediaError in
return .generic
}
|> mapToSignal { result -> Signal<Float, UploadMediaError> in
let inputMedia: Api.InputMedia
switch result {
case let .inputFile(inputFile):
switch type {
case .photo:
inputMedia = .inputMediaUploadedPhoto(flags: 0, file: inputFile, stickers: nil, ttlSeconds: nil)
case .file, .video, .sticker, .voice:
var attributes: [Api.DocumentAttribute] = []
attributes.append(.documentAttributeFilename(fileName: fileName))
var resolvedMimeType = mimeType
switch type {
case .video:
resolvedMimeType = "video/mp4"
case .sticker:
resolvedMimeType = "image/webp"
case .voice:
resolvedMimeType = "audio/ogg"
default:
break
}
inputMedia = .inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: resolvedMimeType, attributes: attributes, stickers: nil, ttlSeconds: nil)
}
case let .progress(value):
return .single(value)
case .inputSecretFile:
return .fail(.generic)
}
return account.network.request(Api.functions.messages.uploadImportedMedia(peer: session.inputPeer, importId: session.id, fileName: fileName, media: inputMedia))
|> mapError { error -> UploadMediaError in
switch error.errorDescription {
case "CHAT_ADMIN_REQUIRED":
return .chatAdminRequired
default:
return .generic
}
}
|> mapToSignal { result -> Signal<Float, UploadMediaError> in
return .single(1.0)
}
|> afterDisposed {
if disposeFileAfterDone {
TempBox.shared.dispose(file)
}
}
}
}
public enum StartImportError {
case generic
}
public static func startImport(account: Account, session: Session) -> Signal<Never, StartImportError> {
return account.network.request(Api.functions.messages.startHistoryImport(peer: session.inputPeer, importId: session.id))
|> mapError { _ -> StartImportError in
return .generic
}
|> mapToSignal { result -> Signal<Never, StartImportError> in
if case .boolTrue = result {
return .complete()
} else {
return .fail(.generic)
}
}
}
public enum CheckPeerImportResult {
case allowed
case alert(String)
}
public enum CheckPeerImportError {
case generic
case chatAdminRequired
case invalidChatType
case userBlocked
case limitExceeded
case notMutualContact
}
public static func checkPeerImport(account: Account, peerId: PeerId) -> Signal<CheckPeerImportResult, CheckPeerImportError> {
return account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
|> castError(CheckPeerImportError.self)
|> mapToSignal { peer -> Signal<CheckPeerImportResult, CheckPeerImportError> in
guard let peer = peer else {
return .fail(.generic)
}
guard let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
return account.network.request(Api.functions.messages.checkHistoryImportPeer(peer: inputPeer))
|> mapError { error -> CheckPeerImportError in
if error.errorDescription == "CHAT_ADMIN_REQUIRED" {
return .chatAdminRequired
} else if error.errorDescription == "IMPORT_PEER_TYPE_INVALID" {
return .invalidChatType
} else if error.errorDescription == "USER_IS_BLOCKED" {
return .userBlocked
} else if error.errorDescription == "USER_NOT_MUTUAL_CONTACT" {
return .notMutualContact
} else if error.errorDescription == "FLOOD_WAIT" {
return .limitExceeded
} else {
return .generic
}
}
|> map { result -> CheckPeerImportResult in
switch result {
case let .checkedHistoryImportPeer(confirmText):
if confirmText.isEmpty {
return .allowed
} else {
return .alert(confirmText)
}
}
}
}
}
}

View File

@ -1,5 +0,0 @@
import Foundation
public final class GlobalTelegramCoreConfiguration {
public static var readMessages: Bool = true
}

View File

@ -4,7 +4,7 @@ import SwiftSignalKit
import SyncCore
public func setSecretChatMessageAutoremoveTimeoutInteractively(account: Account, peerId: PeerId, timeout: Int32?) -> Signal<Void, NoError> {
func _internal_setSecretChatMessageAutoremoveTimeoutInteractively(account: Account, peerId: PeerId, timeout: Int32?) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
if let peer = transaction.getPeer(peerId) as? TelegramSecretChat, let state = transaction.getPeerChatState(peerId) as? SecretChatState {
if state.messageAutoremoveTimeout != timeout {
@ -23,7 +23,7 @@ public func setSecretChatMessageAutoremoveTimeoutInteractively(account: Account,
}
}
public func addSecretChatMessageScreenshot(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
func _internal_addSecretChatMessageScreenshot(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
if let _ = transaction.getPeer(peerId) as? TelegramSecretChat, let state = transaction.getPeerChatState(peerId) as? SecretChatState {
switch state.embeddedState {

View File

@ -563,7 +563,7 @@ private final class CallSessionManagerContext {
|> timeout(5.0, queue: strongSelf.queue, alternate: .single(nil))
|> deliverOnMainQueue).start(next: { debugLog in
if let debugLog = debugLog {
let _ = saveCallDebugLog(network: network, callId: CallId(id: id, accessHash: accessHash), log: debugLog).start()
_internal_saveCallDebugLog(network: network, callId: CallId(id: id, accessHash: accessHash), log: debugLog).start()
}
})
}

View File

@ -206,10 +206,6 @@ private func validatePeerReadState(network: Network, postbox: Postbox, stateMana
}
private func pushPeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId, readState: PeerReadState) -> Signal<PeerReadState, PeerReadStateValidationError> {
if !GlobalTelegramCoreConfiguration.readMessages {
return .single(readState)
}
if peerId.namespace == Namespaces.Peer.SecretChat {
return inputSecretChat(postbox: postbox, peerId: peerId)
|> mapToSignal { inputPeer -> Signal<PeerReadState, PeerReadStateValidationError> in

View File

@ -12,7 +12,7 @@ public enum ConfirmTwoStepRecoveryEmailError {
case generic
}
public func confirmTwoStepRecoveryEmail(network: Network, code: String) -> Signal<Never, ConfirmTwoStepRecoveryEmailError> {
func _internal_confirmTwoStepRecoveryEmail(network: Network, code: String) -> Signal<Never, ConfirmTwoStepRecoveryEmailError> {
return network.request(Api.functions.account.confirmPasswordEmail(code: code), automaticFloodWait: false)
|> mapError { error -> ConfirmTwoStepRecoveryEmailError in
if error.errorDescription == "EMAIL_INVALID" {
@ -34,7 +34,7 @@ public enum ResendTwoStepRecoveryEmailError {
case generic
}
public func resendTwoStepRecoveryEmail(network: Network) -> Signal<Never, ResendTwoStepRecoveryEmailError> {
func _internal_resendTwoStepRecoveryEmail(network: Network) -> Signal<Never, ResendTwoStepRecoveryEmailError> {
return network.request(Api.functions.account.resendPasswordEmail(), automaticFloodWait: false)
|> mapError { error -> ResendTwoStepRecoveryEmailError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
@ -49,7 +49,7 @@ public enum CancelTwoStepRecoveryEmailError {
case generic
}
public func cancelTwoStepRecoveryEmail(network: Network) -> Signal<Never, CancelTwoStepRecoveryEmailError> {
func _internal_cancelTwoStepRecoveryEmail(network: Network) -> Signal<Never, CancelTwoStepRecoveryEmailError> {
return network.request(Api.functions.account.cancelPasswordEmail(), automaticFloodWait: false)
|> mapError { _ -> CancelTwoStepRecoveryEmailError in
return .generic

View File

@ -1,6 +1,8 @@
import SwiftSignalKit
import Postbox
import TelegramApi
import MtProtoKit
import SyncCore
public extension TelegramEngineUnauthorized {
final class Auth {
@ -13,6 +15,22 @@ public extension TelegramEngineUnauthorized {
public func exportAuthTransferToken(accountManager: AccountManager, otherAccountUserIds: [PeerId.Id], syncContacts: Bool) -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> {
return _internal_exportAuthTransferToken(accountManager: accountManager, account: self.account, otherAccountUserIds: otherAccountUserIds, syncContacts: syncContacts)
}
public func twoStepAuthData() -> Signal<TwoStepAuthData, MTRpcError> {
return _internal_twoStepAuthData(self.account.network)
}
public func updateTwoStepVerificationPassword(currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
return _internal_updateTwoStepVerificationPassword(network: self.account.network, currentPassword: currentPassword, updatedPassword: updatedPassword)
}
public func performPasswordRecovery(accountManager: AccountManager, code: String, syncContacts: Bool, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<Void, PasswordRecoveryError> {
return _internal_performPasswordRecovery(accountManager: accountManager, account: self.account, code: code, syncContacts: syncContacts, updatedPassword: updatedPassword)
}
public func resendTwoStepRecoveryEmail() -> Signal<Never, ResendTwoStepRecoveryEmailError> {
return _internal_resendTwoStepRecoveryEmail(network: self.account.network)
}
}
}
@ -21,19 +39,120 @@ public enum DeleteAccountError {
}
public extension TelegramEngine {
final class Auth {
private let account: Account
final class Auth {
private let account: Account
init(account: Account) {
self.account = account
}
init(account: Account) {
self.account = account
}
public func deleteAccount() -> Signal<Never, DeleteAccountError> {
return self.account.network.request(Api.functions.account.deleteAccount(reason: "GDPR"))
|> mapError { _ -> DeleteAccountError in
return .generic
}
|> ignoreValues
}
}
public func twoStepAuthData() -> Signal<TwoStepAuthData, MTRpcError> {
return _internal_twoStepAuthData(self.account.network)
}
public func updateTwoStepVerificationPassword(currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
return _internal_updateTwoStepVerificationPassword(network: self.account.network, currentPassword: currentPassword, updatedPassword: updatedPassword)
}
public func deleteAccount() -> Signal<Never, DeleteAccountError> {
return self.account.network.request(Api.functions.account.deleteAccount(reason: "GDPR"))
|> mapError { _ -> DeleteAccountError in
return .generic
}
|> ignoreValues
}
public func updateTwoStepVerificationEmail(currentPassword: String, updatedEmail: String) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
return _internal_updateTwoStepVerificationEmail(network: self.account.network, currentPassword: currentPassword, updatedEmail: updatedEmail)
}
public func confirmTwoStepRecoveryEmail(code: String) -> Signal<Never, ConfirmTwoStepRecoveryEmailError> {
return _internal_confirmTwoStepRecoveryEmail(network: self.account.network, code: code)
}
public func resendTwoStepRecoveryEmail() -> Signal<Never, ResendTwoStepRecoveryEmailError> {
return _internal_resendTwoStepRecoveryEmail(network: self.account.network)
}
public func cancelTwoStepRecoveryEmail() -> Signal<Never, CancelTwoStepRecoveryEmailError> {
return _internal_cancelTwoStepRecoveryEmail(network: self.account.network)
}
public func twoStepVerificationConfiguration() -> Signal<TwoStepVerificationConfiguration, NoError> {
return _internal_twoStepVerificationConfiguration(account: self.account)
}
public func requestTwoStepVerifiationSettings(password: String) -> Signal<TwoStepVerificationSettings, AuthorizationPasswordVerificationError> {
return _internal_requestTwoStepVerifiationSettings(network: self.account.network, password: password)
}
public func requestTwoStepVerificationPasswordRecoveryCode() -> Signal<String, RequestTwoStepVerificationPasswordRecoveryCodeError> {
return _internal_requestTwoStepVerificationPasswordRecoveryCode(network: self.account.network)
}
public func recoverTwoStepVerificationPassword(code: String) -> Signal<Void, RecoverTwoStepVerificationPasswordError> {
return _internal_recoverTwoStepVerificationPassword(network: self.account.network, code: code)
}
public func cachedTwoStepPasswordToken() -> Signal<TemporaryTwoStepPasswordToken?, NoError> {
return _internal_cachedTwoStepPasswordToken(postbox: self.account.postbox)
}
public func cacheTwoStepPasswordToken(token: TemporaryTwoStepPasswordToken?) -> Signal<Void, NoError> {
return _internal_cacheTwoStepPasswordToken(postbox: self.account.postbox, token: token)
}
public func requestTemporaryTwoStepPasswordToken(password: String, period: Int32, requiresBiometrics: Bool) -> Signal<TemporaryTwoStepPasswordToken, AuthorizationPasswordVerificationError> {
return _internal_requestTemporaryTwoStepPasswordToken(account: self.account, password: password, period: period, requiresBiometrics: requiresBiometrics)
}
public func requestTwoStepPasswordReset() -> Signal<RequestTwoStepPasswordResetResult, NoError> {
return _internal_requestTwoStepPasswordReset(network: self.account.network)
}
public func declineTwoStepPasswordReset() -> Signal<Never, NoError> {
return _internal_declineTwoStepPasswordReset(network: self.account.network)
}
}
}
public extension SomeTelegramEngine {
final class Auth {
private let engine: SomeTelegramEngine
init(engine: SomeTelegramEngine) {
self.engine = engine
}
public func twoStepAuthData() -> Signal<TwoStepAuthData, MTRpcError> {
switch self.engine {
case let .authorized(engine):
return engine.auth.twoStepAuthData()
case let .unauthorized(engine):
return engine.auth.twoStepAuthData()
}
}
public func updateTwoStepVerificationPassword(currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
switch self.engine {
case let .authorized(engine):
return engine.auth.updateTwoStepVerificationPassword(currentPassword: currentPassword, updatedPassword: updatedPassword)
case let .unauthorized(engine):
return engine.auth.updateTwoStepVerificationPassword(currentPassword: currentPassword, updatedPassword: updatedPassword)
}
}
public func resendTwoStepRecoveryEmail() -> Signal<Never, ResendTwoStepRecoveryEmailError> {
switch self.engine {
case let .authorized(engine):
return engine.auth.resendTwoStepRecoveryEmail()
case let .unauthorized(engine):
return engine.auth.resendTwoStepRecoveryEmail()
}
}
}
var auth: Auth {
return Auth(engine: self)
}
}

View File

@ -11,7 +11,7 @@ public enum TwoStepVerificationConfiguration {
case set(hint: String, hasRecoveryEmail: Bool, pendingEmail: TwoStepVerificationPendingEmail?, hasSecureValues: Bool, pendingResetTimestamp: Int32?)
}
public func twoStepVerificationConfiguration(account: Account) -> Signal<TwoStepVerificationConfiguration, NoError> {
func _internal_twoStepVerificationConfiguration(account: Account) -> Signal<TwoStepVerificationConfiguration, NoError> {
return account.network.request(Api.functions.account.getPassword())
|> retryRequest
|> map { result -> TwoStepVerificationConfiguration in
@ -37,8 +37,8 @@ public struct TwoStepVerificationSettings {
public let secureSecret: TwoStepVerificationSecureSecret?
}
public func requestTwoStepVerifiationSettings(network: Network, password: String) -> Signal<TwoStepVerificationSettings, AuthorizationPasswordVerificationError> {
return twoStepAuthData(network)
func _internal_requestTwoStepVerifiationSettings(network: Network, password: String) -> Signal<TwoStepVerificationSettings, AuthorizationPasswordVerificationError> {
return _internal_twoStepAuthData(network)
|> mapError { error -> AuthorizationPasswordVerificationError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
@ -111,14 +111,14 @@ public enum UpdatedTwoStepVerificationPassword {
case password(password: String, hint: String, email: String?)
}
public func updateTwoStepVerificationPassword(network: Network, currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
return twoStepAuthData(network)
func _internal_updateTwoStepVerificationPassword(network: Network, currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
return _internal_twoStepAuthData(network)
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
return .generic
}
|> mapToSignal { authData -> Signal<TwoStepVerificationSecureSecret?, UpdateTwoStepVerificationPasswordError> in
if let _ = authData.currentPasswordDerivation {
return requestTwoStepVerifiationSettings(network: network, password: currentPassword ?? "")
return _internal_requestTwoStepVerifiationSettings(network: network, password: currentPassword ?? "")
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
return .generic
}
@ -130,7 +130,7 @@ public func updateTwoStepVerificationPassword(network: Network, currentPassword:
}
}
|> mapToSignal { secureSecret -> Signal<(TwoStepAuthData, TwoStepVerificationSecureSecret?), UpdateTwoStepVerificationPasswordError> in
return twoStepAuthData(network)
return _internal_twoStepAuthData(network)
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
return .generic
}
@ -205,7 +205,7 @@ public func updateTwoStepVerificationPassword(network: Network, currentPassword:
codeLength = value
}
}
return twoStepAuthData(network)
return _internal_twoStepAuthData(network)
|> map { result -> UpdateTwoStepVerificationPasswordResult in
return .password(password: password, pendingEmail: result.unconfirmedEmailPattern.flatMap({ TwoStepVerificationPendingEmail(pattern: $0, codeLength: codeLength) }))
}
@ -233,7 +233,7 @@ enum UpdateTwoStepVerificationSecureSecretError {
}
func updateTwoStepVerificationSecureSecret(network: Network, password: String, secret: Data) -> Signal<UpdateTwoStepVerificationSecureSecretResult, UpdateTwoStepVerificationSecureSecretError> {
return twoStepAuthData(network)
return _internal_twoStepAuthData(network)
|> mapError { _ -> UpdateTwoStepVerificationSecureSecretError in
return .generic
}
@ -263,8 +263,8 @@ func updateTwoStepVerificationSecureSecret(network: Network, password: String, s
}
}
public func updateTwoStepVerificationEmail(network: Network, currentPassword: String, updatedEmail: String) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
return twoStepAuthData(network)
func _internal_updateTwoStepVerificationEmail(network: Network, currentPassword: String, updatedEmail: String) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
return _internal_twoStepAuthData(network)
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
return .generic
}
@ -286,7 +286,7 @@ public func updateTwoStepVerificationEmail(network: Network, currentPassword: St
}
|> `catch` { error -> Signal<UpdateTwoStepVerificationPasswordResult, MTRpcError> in
if error.errorDescription.hasPrefix("EMAIL_UNCONFIRMED") {
return twoStepAuthData(network)
return _internal_twoStepAuthData(network)
|> map { result -> UpdateTwoStepVerificationPasswordResult in
var codeLength: Int32?
if error.errorDescription.hasPrefix("EMAIL_UNCONFIRMED_") {
@ -314,7 +314,7 @@ public enum RequestTwoStepVerificationPasswordRecoveryCodeError {
case generic
}
public func requestTwoStepVerificationPasswordRecoveryCode(network: Network) -> Signal<String, RequestTwoStepVerificationPasswordRecoveryCodeError> {
func _internal_requestTwoStepVerificationPasswordRecoveryCode(network: Network) -> Signal<String, RequestTwoStepVerificationPasswordRecoveryCodeError> {
return network.request(Api.functions.auth.requestPasswordRecovery(), automaticFloodWait: false)
|> mapError { _ -> RequestTwoStepVerificationPasswordRecoveryCodeError in
return .generic
@ -334,8 +334,8 @@ public enum RecoverTwoStepVerificationPasswordError {
case invalidCode
}
public func recoverTwoStepVerificationPassword(network: Network, code: String) -> Signal<Void, RecoverTwoStepVerificationPasswordError> {
return twoStepAuthData(network)
func _internal_recoverTwoStepVerificationPassword(network: Network, code: String) -> Signal<Void, RecoverTwoStepVerificationPasswordError> {
return _internal_twoStepAuthData(network)
|> mapError { _ -> RecoverTwoStepVerificationPasswordError in
return .generic
}
@ -363,7 +363,7 @@ public func recoverTwoStepVerificationPassword(network: Network, code: String) -
}
}
public func cachedTwoStepPasswordToken(postbox: Postbox) -> Signal<TemporaryTwoStepPasswordToken?, NoError> {
func _internal_cachedTwoStepPasswordToken(postbox: Postbox) -> Signal<TemporaryTwoStepPasswordToken?, NoError> {
return postbox.transaction { transaction -> TemporaryTwoStepPasswordToken? in
let key = ValueBoxKey(length: 1)
key.setUInt8(0, value: 0)
@ -371,7 +371,7 @@ public func cachedTwoStepPasswordToken(postbox: Postbox) -> Signal<TemporaryTwoS
}
}
public func cacheTwoStepPasswordToken(postbox: Postbox, token: TemporaryTwoStepPasswordToken?) -> Signal<Void, NoError> {
func _internal_cacheTwoStepPasswordToken(postbox: Postbox, token: TemporaryTwoStepPasswordToken?) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Void in
let key = ValueBoxKey(length: 1)
key.setUInt8(0, value: 0)
@ -383,8 +383,8 @@ public func cacheTwoStepPasswordToken(postbox: Postbox, token: TemporaryTwoStepP
}
}
public func requestTemporaryTwoStepPasswordToken(account: Account, password: String, period: Int32, requiresBiometrics: Bool) -> Signal<TemporaryTwoStepPasswordToken, AuthorizationPasswordVerificationError> {
return twoStepAuthData(account.network)
func _internal_requestTemporaryTwoStepPasswordToken(account: Account, password: String, period: Int32, requiresBiometrics: Bool) -> Signal<TemporaryTwoStepPasswordToken, AuthorizationPasswordVerificationError> {
return _internal_twoStepAuthData(account.network)
|> mapToSignal { authData -> Signal<TemporaryTwoStepPasswordToken, MTRpcError> in
guard let currentPasswordDerivation = authData.currentPasswordDerivation, let srpSessionData = authData.srpSessionData else {
return .fail(MTRpcError(errorCode: 400, errorDescription: "NO_PASSWORD"))
@ -426,7 +426,7 @@ public enum RequestTwoStepPasswordResetResult {
case error(reason: ErrorReason)
}
public func requestTwoStepPasswordReset(network: Network) -> Signal<RequestTwoStepPasswordResetResult, NoError> {
func _internal_requestTwoStepPasswordReset(network: Network) -> Signal<RequestTwoStepPasswordResetResult, NoError> {
return network.request(Api.functions.account.resetPassword(), automaticFloodWait: false)
|> map { _ -> RequestTwoStepPasswordResetResult in
return .done
@ -456,7 +456,7 @@ public func requestTwoStepPasswordReset(network: Network) -> Signal<RequestTwoSt
}
}
public func declineTwoStepPasswordReset(network: Network) -> Signal<Never, NoError> {
func _internal_declineTwoStepPasswordReset(network: Network) -> Signal<Never, NoError> {
return network.request(Api.functions.account.declinePasswordReset())
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)

View File

@ -4,7 +4,7 @@ import MtProtoKit
import SwiftSignalKit
import TelegramApi
public func rateCall(account: Account, callId: CallId, starsCount: Int32, comment: String = "", userInitiated: Bool) -> Signal<Void, NoError> {
func _internal_rateCall(account: Account, callId: CallId, starsCount: Int32, comment: String = "", userInitiated: Bool) -> Signal<Void, NoError> {
var flags: Int32 = 0
if userInitiated {
flags |= (1 << 0)
@ -14,7 +14,7 @@ public func rateCall(account: Account, callId: CallId, starsCount: Int32, commen
|> map { _ in }
}
public func saveCallDebugLog(network: Network, callId: CallId, log: String) -> Signal<Void, NoError> {
func _internal_saveCallDebugLog(network: Network, callId: CallId, log: String) -> Signal<Void, NoError> {
if log.count > 1024 * 16 {
return .complete()
}

View File

@ -0,0 +1,19 @@
import SwiftSignalKit
public extension TelegramEngine {
final class Calls {
private let account: Account
init(account: Account) {
self.account = account
}
public func rateCall(callId: CallId, starsCount: Int32, comment: String = "", userInitiated: Bool) -> Signal<Void, NoError> {
return _internal_rateCall(account: self.account, callId: callId, starsCount: starsCount, comment: comment, userInitiated: userInitiated)
}
public func saveCallDebugLog(callId: CallId, log: String) -> Signal<Void, NoError> {
return _internal_saveCallDebugLog(network: self.account.network, callId: callId, log: log)
}
}
}

View File

@ -0,0 +1,255 @@
import Foundation
import SwiftSignalKit
import Postbox
import SyncCore
import TelegramApi
public extension TelegramEngine {
final class HistoryImport {
private let account: Account
init(account: Account) {
self.account = account
}
public struct Session {
fileprivate var peerId: PeerId
fileprivate var inputPeer: Api.InputPeer
fileprivate var id: Int64
}
public enum InitImportError {
case generic
case chatAdminRequired
case invalidChatType
case userBlocked
case limitExceeded
}
public enum ParsedInfo {
case privateChat(title: String?)
case group(title: String?)
case unknown(title: String?)
}
public enum GetInfoError {
case generic
case parseError
}
public func getInfo(header: String) -> Signal<ParsedInfo, GetInfoError> {
return self.account.network.request(Api.functions.messages.checkHistoryImport(importHead: header))
|> mapError { _ -> GetInfoError in
return .generic
}
|> mapToSignal { result -> Signal<ParsedInfo, GetInfoError> in
switch result {
case let .historyImportParsed(flags, title):
if (flags & (1 << 0)) != 0 {
return .single(.privateChat(title: title))
} else if (flags & (1 << 1)) != 0 {
return .single(.group(title: title))
} else {
return .single(.unknown(title: title))
}
}
}
}
public func initSession(peerId: PeerId, file: TempBoxFile, mediaCount: Int32) -> Signal<Session, InitImportError> {
let account = self.account
return multipartUpload(network: self.account.network, postbox: self.account.postbox, source: .tempFile(file), encrypt: false, tag: nil, hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: true, useLargerParts: true, increaseParallelParts: true, useMultiplexedRequests: false, useCompression: true)
|> mapError { _ -> InitImportError in
return .generic
}
|> mapToSignal { result -> Signal<Session, InitImportError> in
switch result {
case let .inputFile(inputFile):
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
}
|> castError(InitImportError.self)
|> mapToSignal { inputPeer -> Signal<Session, InitImportError> in
guard let inputPeer = inputPeer else {
return .fail(.generic)
}
return account.network.request(Api.functions.messages.initHistoryImport(peer: inputPeer, file: inputFile, mediaCount: mediaCount), automaticFloodWait: false)
|> mapError { error -> InitImportError in
if error.errorDescription == "CHAT_ADMIN_REQUIRED" {
return .chatAdminRequired
} else if error.errorDescription == "IMPORT_PEER_TYPE_INVALID" {
return .invalidChatType
} else if error.errorDescription == "USER_IS_BLOCKED" {
return .userBlocked
} else if error.errorDescription == "FLOOD_WAIT" {
return .limitExceeded
} else {
return .generic
}
}
|> map { result -> Session in
switch result {
case let .historyImport(id):
return Session(peerId: peerId, inputPeer: inputPeer, id: id)
}
}
}
case .progress:
return .complete()
case .inputSecretFile:
return .fail(.generic)
}
}
}
public enum MediaType {
case photo
case file
case video
case sticker
case voice
}
public enum UploadMediaError {
case generic
case chatAdminRequired
}
public func uploadMedia(session: Session, file: TempBoxFile, disposeFileAfterDone: Bool, fileName: String, mimeType: String, type: MediaType) -> Signal<Float, UploadMediaError> {
var forceNoBigParts = true
guard let size = fileSize(file.path), size != 0 else {
return .single(1.0)
}
if size >= 30 * 1024 * 1024 {
forceNoBigParts = false
}
let account = self.account
return multipartUpload(network: self.account.network, postbox: self.account.postbox, source: .tempFile(file), encrypt: false, tag: nil, hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: forceNoBigParts, useLargerParts: true, useMultiplexedRequests: true)
|> mapError { _ -> UploadMediaError in
return .generic
}
|> mapToSignal { result -> Signal<Float, UploadMediaError> in
let inputMedia: Api.InputMedia
switch result {
case let .inputFile(inputFile):
switch type {
case .photo:
inputMedia = .inputMediaUploadedPhoto(flags: 0, file: inputFile, stickers: nil, ttlSeconds: nil)
case .file, .video, .sticker, .voice:
var attributes: [Api.DocumentAttribute] = []
attributes.append(.documentAttributeFilename(fileName: fileName))
var resolvedMimeType = mimeType
switch type {
case .video:
resolvedMimeType = "video/mp4"
case .sticker:
resolvedMimeType = "image/webp"
case .voice:
resolvedMimeType = "audio/ogg"
default:
break
}
inputMedia = .inputMediaUploadedDocument(flags: 0, file: inputFile, thumb: nil, mimeType: resolvedMimeType, attributes: attributes, stickers: nil, ttlSeconds: nil)
}
case let .progress(value):
return .single(value)
case .inputSecretFile:
return .fail(.generic)
}
return account.network.request(Api.functions.messages.uploadImportedMedia(peer: session.inputPeer, importId: session.id, fileName: fileName, media: inputMedia))
|> mapError { error -> UploadMediaError in
switch error.errorDescription {
case "CHAT_ADMIN_REQUIRED":
return .chatAdminRequired
default:
return .generic
}
}
|> mapToSignal { result -> Signal<Float, UploadMediaError> in
return .single(1.0)
}
|> afterDisposed {
if disposeFileAfterDone {
TempBox.shared.dispose(file)
}
}
}
}
public enum StartImportError {
case generic
}
public func startImport(session: Session) -> Signal<Never, StartImportError> {
return self.account.network.request(Api.functions.messages.startHistoryImport(peer: session.inputPeer, importId: session.id))
|> mapError { _ -> StartImportError in
return .generic
}
|> mapToSignal { result -> Signal<Never, StartImportError> in
if case .boolTrue = result {
return .complete()
} else {
return .fail(.generic)
}
}
}
public enum CheckPeerImportResult {
case allowed
case alert(String)
}
public enum CheckPeerImportError {
case generic
case chatAdminRequired
case invalidChatType
case userBlocked
case limitExceeded
case notMutualContact
}
public func checkPeerImport(peerId: PeerId) -> Signal<CheckPeerImportResult, CheckPeerImportError> {
let account = self.account
return self.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
|> castError(CheckPeerImportError.self)
|> mapToSignal { peer -> Signal<CheckPeerImportResult, CheckPeerImportError> in
guard let peer = peer else {
return .fail(.generic)
}
guard let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
return account.network.request(Api.functions.messages.checkHistoryImportPeer(peer: inputPeer))
|> mapError { error -> CheckPeerImportError in
if error.errorDescription == "CHAT_ADMIN_REQUIRED" {
return .chatAdminRequired
} else if error.errorDescription == "IMPORT_PEER_TYPE_INVALID" {
return .invalidChatType
} else if error.errorDescription == "USER_IS_BLOCKED" {
return .userBlocked
} else if error.errorDescription == "USER_NOT_MUTUAL_CONTACT" {
return .notMutualContact
} else if error.errorDescription == "FLOOD_WAIT" {
return .limitExceeded
} else {
return .generic
}
}
|> map { result -> CheckPeerImportResult in
switch result {
case let .checkedHistoryImportPeer(confirmText):
if confirmText.isEmpty {
return .allowed
} else {
return .alert(confirmText)
}
}
}
}
}
}
}

View File

@ -3,7 +3,7 @@ import Postbox
import TelegramApi
import SwiftSignalKit
public func forwardGameWithScore(account: Account, messageId: MessageId, to peerId: PeerId) -> Signal<Void, NoError> {
func _internal_forwardGameWithScore(account: Account, messageId: MessageId, to peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let _ = transaction.getMessage(messageId), let fromPeer = transaction.getPeer(messageId.peerId), let fromInputPeer = apiInputPeer(fromPeer), let toPeer = transaction.getPeer(peerId), let toInputPeer = apiInputPeer(toPeer) {
return account.network.request(Api.functions.messages.forwardMessages(flags: 1 << 8, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, scheduleDate: nil))

View File

@ -92,7 +92,7 @@ func _internal_requestMessageActionCallback(account: Account, messageId: Message
if let password = password, !password.isEmpty {
flags |= Int32(1 << 2)
checkPassword = twoStepAuthData(account.network)
checkPassword = _internal_twoStepAuthData(account.network)
|> mapError { error -> MessageActionCallbackError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded

View File

@ -85,5 +85,14 @@ public extension TelegramEngine {
public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal<Void, NoError> {
return _internal_requestEditLiveLocation(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, messageId: messageId, stop: stop, coordinate: coordinate, heading: heading, proximityNotificationRadius: proximityNotificationRadius)
}
public func addSecretChatMessageScreenshot(peerId: PeerId) -> Signal<Never, NoError> {
return _internal_addSecretChatMessageScreenshot(account: self.account, peerId: peerId)
|> ignoreValues
}
public func forwardGameWithScore(messageId: MessageId, to peerId: PeerId) -> Signal<Void, NoError> {
return _internal_forwardGameWithScore(account: self.account, messageId: messageId, to: peerId)
}
}
}

View File

@ -154,36 +154,3 @@ public final class GroupsInCommonContext {
}
}
}
public func groupsInCommon(account: Account, peerId: PeerId) -> Signal<[Peer], NoError> {
return account.postbox.transaction { transaction -> Signal<[Peer], NoError> in
if let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) {
return account.network.request(Api.functions.messages.getCommonChats(userId: inputUser, maxId: 0, limit: 100))
|> retryRequest
|> mapToSignal { result -> Signal<[Peer], NoError> in
let chats: [Api.Chat]
switch result {
case let .chats(chats: apiChats):
chats = apiChats
case let .chatsSlice(count: _, chats: apiChats):
chats = apiChats
}
return account.postbox.transaction { transaction -> [Peer] in
var peers: [Peer] = []
for chat in chats {
if let peer = parseTelegramGroupOrChannel(chat: chat) {
peers.append(peer)
}
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer? in
return updated
})
return peers
}
}
} else {
return .single([])
}
} |> switchToLatest
}

View File

@ -6,7 +6,7 @@ import MtProtoKit
import SyncCore
public func reportPeer(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
func _internal_reportPeer(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId) {
if let peer = peer as? TelegramSecretChat {
@ -110,7 +110,7 @@ private extension ReportReason {
}
}
public func reportPeer(account: Account, peerId: PeerId, reason: ReportReason, message: String) -> Signal<Void, NoError> {
func _internal_reportPeer(account: Account, peerId: PeerId, reason: ReportReason, message: String) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
return account.network.request(Api.functions.account.reportPeer(peer: inputPeer, reason: reason.apiReason, message: message))
@ -126,7 +126,7 @@ public func reportPeer(account: Account, peerId: PeerId, reason: ReportReason, m
} |> switchToLatest
}
public func reportPeerPhoto(account: Account, peerId: PeerId, reason: ReportReason, message: String) -> Signal<Void, NoError> {
func _internal_reportPeerPhoto(account: Account, peerId: PeerId, reason: ReportReason, message: String) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
return account.network.request(Api.functions.account.reportProfilePhoto(peer: inputPeer, photoId: .inputPhotoEmpty, reason: reason.apiReason, message: message))
@ -142,7 +142,7 @@ public func reportPeerPhoto(account: Account, peerId: PeerId, reason: ReportReas
} |> switchToLatest
}
public func reportPeerMessages(account: Account, messageIds: [MessageId], reason: ReportReason, message: String) -> Signal<Void, NoError> {
func _internal_reportPeerMessages(account: Account, messageIds: [MessageId], reason: ReportReason, message: String) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
let groupedIds = messagesIdsGroupedByPeerId(messageIds)
let signals = groupedIds.values.compactMap { ids -> Signal<Void, NoError>? in
@ -165,7 +165,7 @@ public func reportPeerMessages(account: Account, messageIds: [MessageId], reason
} |> switchToLatest
}
public func dismissPeerStatusOptions(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
func _internal_dismissPeerStatusOptions(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedUserData {
@ -203,7 +203,7 @@ public func dismissPeerStatusOptions(account: Account, peerId: PeerId) -> Signal
} |> switchToLatest
}
public func reportRepliesMessage(account: Account, messageId: MessageId, deleteMessage: Bool, deleteHistory: Bool, reportSpam: Bool) -> Signal<Never, NoError> {
func _internal_reportRepliesMessage(account: Account, messageId: MessageId, deleteMessage: Bool, deleteHistory: Bool, reportSpam: Bool) -> Signal<Never, NoError> {
if messageId.namespace != Namespaces.Message.Cloud {
return .complete()
}

View File

@ -9,7 +9,7 @@ public enum UpdateChannelSlowModeError {
case tooManyChannels
}
public func updateChannelSlowModeInteractively(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, peerId: PeerId, timeout: Int32?) -> Signal<Void, UpdateChannelSlowModeError> {
func _internal_updateChannelSlowModeInteractively(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, peerId: PeerId, timeout: Int32?) -> Signal<Void, UpdateChannelSlowModeError> {
return postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}

View File

@ -92,7 +92,41 @@ public extension TelegramEngine {
}
public func setChatMessageAutoremoveTimeoutInteractively(peerId: PeerId, timeout: Int32?) -> Signal<Never, SetChatMessageAutoremoveTimeoutError> {
return _internal_setChatMessageAutoremoveTimeoutInteractively(account: self.account, peerId: peerId, timeout: timeout)
if peerId.namespace == Namespaces.Peer.SecretChat {
return _internal_setSecretChatMessageAutoremoveTimeoutInteractively(account: self.account, peerId: peerId, timeout: timeout)
|> ignoreValues
|> castError(SetChatMessageAutoremoveTimeoutError.self)
} else {
return _internal_setChatMessageAutoremoveTimeoutInteractively(account: self.account, peerId: peerId, timeout: timeout)
}
}
public func updateChannelSlowModeInteractively(peerId: PeerId, timeout: Int32?) -> Signal<Void, UpdateChannelSlowModeError> {
return _internal_updateChannelSlowModeInteractively(postbox: self.account.postbox, network: self.account.network, accountStateManager: self.account.stateManager, peerId: peerId, timeout: timeout)
}
public func reportPeer(peerId: PeerId) -> Signal<Void, NoError> {
return _internal_reportPeer(account: self.account, peerId: peerId)
}
public func reportPeer(peerId: PeerId, reason: ReportReason, message: String) -> Signal<Void, NoError> {
return _internal_reportPeer(account: self.account, peerId: peerId, reason: reason, message: message)
}
public func reportPeerPhoto(peerId: PeerId, reason: ReportReason, message: String) -> Signal<Void, NoError> {
return _internal_reportPeerPhoto(account: self.account, peerId: peerId, reason: reason, message: message)
}
public func reportPeerMessages(messageIds: [MessageId], reason: ReportReason, message: String) -> Signal<Void, NoError> {
return _internal_reportPeerMessages(account: account, messageIds: messageIds, reason: reason, message: message)
}
public func dismissPeerStatusOptions(peerId: PeerId) -> Signal<Void, NoError> {
return _internal_dismissPeerStatusOptions(account: self.account, peerId: peerId)
}
public func reportRepliesMessage(messageId: MessageId, deleteMessage: Bool, deleteHistory: Bool, reportSpam: Bool) -> Signal<Never, NoError> {
return _internal_reportRepliesMessage(account: self.account, messageId: messageId, deleteMessage: deleteMessage, deleteHistory: deleteHistory, reportSpam: reportSpam)
}
}
}

View File

@ -41,7 +41,7 @@ public func requestBlockedPeers(account: Account) -> Signal<[Peer], NoError> {
}
}
public func requestUpdatePeerIsBlocked(account: Account, peerId: PeerId, isBlocked: Bool) -> Signal<Void, NoError> {
func _internal_requestUpdatePeerIsBlocked(account: Account, peerId: PeerId, isBlocked: Bool) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
let signal: Signal<Api.Bool, MTRpcError>

View File

@ -3,7 +3,6 @@ import TelegramApi
import Postbox
import SwiftSignalKit
import MtProtoKit
import SyncCore
public struct BlockedPeersContextState: Equatable {

View File

@ -0,0 +1,16 @@
import SwiftSignalKit
import Postbox
public extension TelegramEngine {
final class Privacy {
private let account: Account
init(account: Account) {
self.account = account
}
public func requestUpdatePeerIsBlocked(peerId: PeerId, isBlocked: Bool) -> Signal<Void, NoError> {
return _internal_requestUpdatePeerIsBlocked(account: self.account, peerId: peerId, isBlocked: isBlocked)
}
}
}

View File

@ -154,7 +154,7 @@ public enum SecureIdAccessError {
}
func _internal_accessSecureId(network: Network, password: String) -> Signal<(context: SecureIdAccessContext, settings: TwoStepVerificationSettings), SecureIdAccessError> {
return requestTwoStepVerifiationSettings(network: network, password: password)
return _internal_requestTwoStepVerifiationSettings(network: network, password: password)
|> mapError { error -> SecureIdAccessError in
return .passwordError(error)
}

View File

@ -276,7 +276,7 @@ public func deleteSecureIdValues(network: Network, keys: Set<SecureIdValueKey>)
}
public func dropSecureId(network: Network, currentPassword: String) -> Signal<Void, AuthorizationPasswordVerificationError> {
return twoStepAuthData(network)
return _internal_twoStepAuthData(network)
|> mapError { _ -> AuthorizationPasswordVerificationError in
return .generic
}

View File

@ -47,6 +47,18 @@ public final class TelegramEngine {
public lazy var messages: Messages = {
return Messages(account: self.account)
}()
public lazy var privacy: Privacy = {
return Privacy(account: self.account)
}()
public lazy var calls: Calls = {
return Calls(account: self.account)
}()
public lazy var historyImport: HistoryImport = {
return HistoryImport(account: self.account)
}()
}
public final class TelegramEngineUnauthorized {
@ -64,3 +76,8 @@ public final class TelegramEngineUnauthorized {
return Localization(account: self.account)
}()
}
public enum SomeTelegramEngine {
case unauthorized(TelegramEngineUnauthorized)
case authorized(TelegramEngine)
}

View File

@ -597,7 +597,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
}
controller?.inProgress = false
let setupController = TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, network: strongSelf.account.network, mode: .passwordRecovery(TwoFactorDataInputMode.Recovery(code: code, syncContacts: syncContacts, account: strongSelf.account)), stateUpdated: { _ in
let setupController = TwoFactorDataInputScreen(sharedContext: strongSelf.sharedContext, engine: .unauthorized(TelegramEngineUnauthorized(account: strongSelf.account)), mode: .passwordRecovery(TwoFactorDataInputMode.Recovery(code: code, syncContacts: syncContacts, account: strongSelf.account)), stateUpdated: { _ in
guard let _ = self else {
return
}

View File

@ -5045,7 +5045,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
items.append(ActionSheetButtonItem(title: presentationData.strings.Report_Report, color: .accent, font: .bold, enabled: true, action: {
dismissAction()
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }, completion: { _ in
let _ = (reportPeerMessages(account: strongSelf.context.account, messageIds: Array(messageIds), reason: reportReason, message: message)
let _ = (strongSelf.context.engine.peers.reportPeerMessages(messageIds: Array(messageIds), reason: reportReason, message: message)
|> deliverOnMainQueue).start(completed: { [weak self] in
if let strongSelf = self, let path = getAppBundle().path(forResource: "PoliceCar", ofType: "tgs") {
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .emoji(path: path, text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return false }), in: .current)
@ -5110,12 +5110,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else {
return
}
let _ = requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: true).start()
let _ = strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: true).start()
let context = strongSelf.context
let _ = (context.account.postbox.transaction { transasction -> Void in
context.engine.messages.deleteAllMessagesWithForwardAuthor(transaction: transasction, peerId: message.id.peerId, forwardAuthorId: peer.id, namespace: Namespaces.Message.Cloud)
}).start()
let _ = reportRepliesMessage(account: strongSelf.context.account, messageId: message.id, deleteMessage: true, deleteHistory: true, reportSpam: reportSpam).start()
let _ = strongSelf.context.engine.peers.reportRepliesMessage(messageId: message.id, deleteMessage: true, deleteHistory: true, reportSpam: reportSpam).start()
})
] as [ActionSheetItem])
@ -5815,7 +5815,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let peer = peer as? TelegramSecretChat {
let controller = ChatSecretAutoremoveTimerActionSheetController(context: strongSelf.context, currentValue: peer.messageAutoremoveTimeout == nil ? 0 : peer.messageAutoremoveTimeout!, applyValue: { value in
if let strongSelf = self {
let _ = setSecretChatMessageAutoremoveTimeoutInteractively(account: strongSelf.context.account, peerId: peer.id, timeout: value == 0 ? nil : value).start()
let _ = strongSelf.context.engine.peers.setChatMessageAutoremoveTimeoutInteractively(peerId: peer.id, timeout: value == 0 ? nil : value).start()
}
})
strongSelf.present(controller, in: .window(.root))
@ -6511,7 +6511,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else {
return
}
strongSelf.reportIrrelvantGeoDisposable = (TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peerId, reason: .irrelevantLocation, message: "")
strongSelf.reportIrrelvantGeoDisposable = (strongSelf.context.engine.peers.reportPeer(peerId: peerId, reason: .irrelevantLocation, message: "")
|> deliverOnMainQueue).start(completed: { [weak self] in
if let strongSelf = self {
strongSelf.reportIrrelvantGeoNoticePromise.set(.single(true))
@ -7111,7 +7111,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if case let .peer(peerId) = self.chatLocation, peerId.namespace == Namespaces.Peer.SecretChat, self.screenCaptureManager == nil {
self.screenCaptureManager = ScreenCaptureDetectionManager(check: { [weak self] in
if let strongSelf = self, strongSelf.canReadHistoryValue, strongSelf.traceVisibility() {
let _ = addSecretChatMessageScreenshot(account: strongSelf.context.account, peerId: peerId).start()
let _ = strongSelf.context.engine.messages.addSecretChatMessageScreenshot(peerId: peerId).start()
return true
} else {
return false
@ -11312,7 +11312,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let user = self.presentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
restartBot = true
}
self.editMessageDisposable.set((requestUpdatePeerIsBlocked(account: self.context.account, peerId: peerId, isBlocked: false)
self.editMessageDisposable.set((self.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peerId, isBlocked: false)
|> afterDisposed({ [weak self] in
Queue.mainQueue().async {
unblockingPeer.set(false)
@ -11382,7 +11382,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else {
return
}
let _ = requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: true).start()
let _ = strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: true).start()
if let _ = chatPeer as? TelegramSecretChat {
let _ = (strongSelf.context.account.postbox.transaction { transaction in
terminateSecretChat(transaction: transaction, peerId: chatPeer.id, requestRemoteHistoryRemoval: true)
@ -11392,7 +11392,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let _ = removePeerChat(account: strongSelf.context.account, peerId: chatPeer.id, reportChatSpam: reportSpam).start()
strongSelf.effectiveNavigationController?.filterController(strongSelf, animated: true)
} else if reportSpam {
let _ = TelegramCore.reportPeer(account: strongSelf.context.account, peerId: peer.id, reason: .spam, message: "").start()
let _ = strongSelf.context.engine.peers.reportPeer(peerId: peer.id, reason: .spam, message: "").start()
}
})
] as [ActionSheetItem])
@ -11512,7 +11512,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} else {
dismissPeerId = peerId
}
self.editMessageDisposable.set((dismissPeerStatusOptions(account: self.context.account, peerId: dismissPeerId)
self.editMessageDisposable.set((self.context.engine.peers.dismissPeerStatusOptions(peerId: dismissPeerId)
|> afterDisposed({
Queue.mainQueue().async {
}
@ -11528,7 +11528,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let _ = removePeerChat(account: self.context.account, peerId: peerId, reportChatSpam: reportChatSpam).start()
self.effectiveNavigationController?.popToRoot(animated: true)
let _ = requestUpdatePeerIsBlocked(account: self.context.account, peerId: peerId, isBlocked: true).start()
let _ = self.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peerId, isBlocked: true).start()
}
private func startBot(_ payload: String?) {

View File

@ -2746,7 +2746,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
))
self.privacySettings.set(.single(nil) |> then(requestAccountPrivacySettings(account: context.account) |> map(Optional.init)))
self.archivedPacks.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks() |> map(Optional.init)))
self.hasPassport.set(.single(false) |> then(twoStepAuthData(context.account.network)
self.hasPassport.set(.single(false) |> then(context.engine.auth.twoStepAuthData()
|> map { value -> Bool in
return value.hasSecretValues
}
@ -4267,7 +4267,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
let presentationData = strongSelf.presentationData
if let peer = peer as? TelegramUser, let _ = peer.botInfo {
strongSelf.activeActionDisposable.set(requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: block).start())
strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: block).start())
if !block {
let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start()
if let navigationController = strongSelf.controller?.navigationController as? NavigationController {
@ -4292,12 +4292,12 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
return
}
strongSelf.activeActionDisposable.set(requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: true).start())
strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: true).start())
if deleteChat {
let _ = removePeerChat(account: strongSelf.context.account, peerId: strongSelf.peerId, reportChatSpam: reportSpam).start()
(strongSelf.controller?.navigationController as? NavigationController)?.popToRoot(animated: true)
} else if reportSpam {
let _ = reportPeer(account: strongSelf.context.account, peerId: strongSelf.peerId, reason: .spam, message: "").start()
let _ = strongSelf.context.engine.peers.reportPeer(peerId: strongSelf.peerId, reason: .spam, message: "").start()
}
deleteSendMessageIntents(peerId: strongSelf.peerId)
@ -4318,7 +4318,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
guard let strongSelf = self else {
return
}
strongSelf.activeActionDisposable.set(requestUpdatePeerIsBlocked(account: strongSelf.context.account, peerId: peer.id, isBlocked: block).start())
strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: block).start())
})]), in: .window(.root))
}
}

View File

@ -443,7 +443,7 @@ public class ShareRootControllerImpl {
let fileExtension = (fileName as NSString).pathExtension
var archivePathValue: String?
var otherEntries: [(SSZipEntry, String, ChatHistoryImport.MediaType)] = []
var otherEntries: [(SSZipEntry, String, TelegramEngine.HistoryImport.MediaType)] = []
var mainFile: TempBoxFile?
let appConfiguration = context.currentAppConfiguration.with({ $0 })
@ -528,7 +528,7 @@ public class ShareRootControllerImpl {
} else {
let entryFileName = (entryPath as NSString).lastPathComponent
if !entryFileName.isEmpty {
let mediaType: ChatHistoryImport.MediaType
let mediaType: TelegramEngine.HistoryImport.MediaType
let fullRange = NSRange(entryFileName.startIndex ..< entryFileName.endIndex, in: entryFileName)
if photoRegex.firstMatch(in: entryFileName, options: [], range: fullRange) != nil {
mediaType = .photo
@ -641,7 +641,7 @@ public class ShareRootControllerImpl {
navigationController.viewControllers = [TempController(context: context)]
strongSelf.mainWindow?.present(navigationController, on: .root)
let _ = (ChatHistoryImport.getInfo(account: context.account, header: mainFileHeader)
let _ = (context.engine.historyImport.getInfo(header: mainFileHeader)
|> deliverOnMainQueue).start(next: { parseInfo in
switch parseInfo {
case let .group(groupTitle):
@ -695,7 +695,7 @@ public class ShareRootControllerImpl {
strongSelf.mainWindow?.present(controller, on: .root)
} else {
controller.inProgress = true
let _ = (ChatHistoryImport.checkPeerImport(account: context.account, peerId: peer.id)
let _ = (context.engine.historyImport.checkPeerImport(peerId: peer.id)
|> deliverOnMainQueue).start(next: { result in
controller.inProgress = false
@ -846,7 +846,7 @@ public class ShareRootControllerImpl {
attemptSelectionImpl = { [weak controller] peer in
controller?.inProgress = true
let _ = (ChatHistoryImport.checkPeerImport(account: context.account, peerId: peer.id)
let _ = (context.engine.historyImport.checkPeerImport(peerId: peer.id)
|> deliverOnMainQueue).start(next: { result in
controller?.inProgress = false
@ -921,7 +921,7 @@ public class ShareRootControllerImpl {
attemptSelectionImpl = { [weak controller] peer in
controller?.inProgress = true
let _ = (ChatHistoryImport.checkPeerImport(account: context.account, peerId: peer.id)
let _ = (context.engine.historyImport.checkPeerImport(peerId: peer.id)
|> deliverOnMainQueue).start(next: { result in
controller?.inProgress = false

View File

@ -904,7 +904,7 @@ public final class OngoingCallContext {
if let callId = callId, !statsLogPath.isEmpty, let data = try? Data(contentsOf: URL(fileURLWithPath: statsLogPath)), let dataString = String(data: data, encoding: .utf8) {
debugLogValue.set(.single(dataString))
if sendDebugLogs {
let _ = saveCallDebugLog(network: self.account.network, callId: callId, log: dataString).start()
let _ = TelegramEngine(account: self.account).calls.saveCallDebugLog(callId: callId, log: dataString).start()
}
}
}

View File

@ -843,7 +843,7 @@ final class WatchPeerSettingsHandler: WatchRequestHandler {
if let args = subscription as? TGBridgePeerUpdateNotificationSettingsSubscription, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) {
signal = togglePeerMuted(account: context.account, peerId: peerId)
} else if let args = subscription as? TGBridgePeerUpdateBlockStatusSubscription, let peerId = makePeerIdFromBridgeIdentifier(args.peerId) {
signal = requestUpdatePeerIsBlocked(account: context.account, peerId: peerId, isBlocked: args.blocked)
signal = context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peerId, isBlocked: args.blocked)
}
if let signal = signal {