diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 2aaaf98b80..1fe5648935 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -393,6 +393,9 @@ public protocol AppLockContext: class { func failedUnlockAttempt() } +public protocol RecentSessionsController: class { +} + public protocol SharedAccountContext: class { var basePath: String { get } var mainWindow: Window1? { get } @@ -456,6 +459,8 @@ public protocol SharedAccountContext: class { func openWallet(context: AccountContext, walletContext: OpenWalletContext, present: @escaping (ViewController) -> Void) func openImagePicker(context: AccountContext, completion: @escaping (UIImage) -> Void, present: @escaping (ViewController) -> Void) + func makeRecentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext) -> ViewController & RecentSessionsController + func navigateToCurrentCall() var hasOngoingCall: ValuePromise { get } var immediateHasOngoingCall: Bool { get } diff --git a/submodules/AuthTransferUI/BUCK b/submodules/AuthTransferUI/BUCK index 690bff6fc3..69bd9a6a32 100644 --- a/submodules/AuthTransferUI/BUCK +++ b/submodules/AuthTransferUI/BUCK @@ -25,6 +25,7 @@ static_library( "//submodules/AnimationUI:AnimationUI", "//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/DeviceAccess:DeviceAccess", + "//submodules/UndoUI:UndoUI", ], frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", diff --git a/submodules/AuthTransferUI/Sources/AuthTransferScanScreen.swift b/submodules/AuthTransferUI/Sources/AuthTransferScanScreen.swift index 3b3329304d..e3f6a7ce16 100644 --- a/submodules/AuthTransferUI/Sources/AuthTransferScanScreen.swift +++ b/submodules/AuthTransferUI/Sources/AuthTransferScanScreen.swift @@ -10,6 +10,7 @@ import CoreImage import AlertUI import TelegramPresentationData import TelegramCore +import UndoUI private func parseAuthTransferUrl(_ url: URL) -> Data? { var tokenString: String? @@ -72,7 +73,7 @@ private func generateFrameImage() -> UIImage? { public final class AuthTransferScanScreen: ViewController { private let context: AccountContext - private let activeSessionsContext: ActiveSessionsContext? + private let activeSessionsContext: ActiveSessionsContext private var presentationData: PresentationData private var codeDisposable: Disposable? @@ -83,7 +84,7 @@ public final class AuthTransferScanScreen: ViewController { return self.displayNode as! AuthTransferScanScreenNode } - public init(context: AccountContext, activeSessionsContext: ActiveSessionsContext?) { + public init(context: AccountContext, activeSessionsContext: ActiveSessionsContext) { self.context = context self.activeSessionsContext = activeSessionsContext @@ -99,7 +100,7 @@ public final class AuthTransferScanScreen: ViewController { self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) self.navigationBar?.intrinsicCanTransitionInline = false - self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Wallet_Navigation_Back, style: .plain, target: nil, action: nil) + self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) self.inForegroundDisposable = (context.sharedContext.applicationBindings.applicationInForeground |> deliverOnMainQueue).start(next: { [weak self] inForeground in @@ -108,6 +109,10 @@ public final class AuthTransferScanScreen: ViewController { } (strongSelf.displayNode as! AuthTransferScanScreenNode).updateInForeground(inForeground) }) + + #if DEBUG + self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Test", style: .plain, target: self, action: #selector(self.testPressed)) + #endif } required init(coder aDecoder: NSCoder) { @@ -120,8 +125,34 @@ public final class AuthTransferScanScreen: ViewController { self.approveDisposable.dispose() } - @objc private func backPressed() { - self.dismiss() + @objc private func testPressed() { + self.dismissWithSuccess(session: nil) + } + + private func dismissWithSuccess(session: RecentAccountSession?) { + if let navigationController = navigationController as? NavigationController { + let activeSessionsContext = self.activeSessionsContext + self.present(UndoOverlayController(presentationData: self.presentationData, content: .actionSucceeded(title: "Loggin Successful", text: "Telegram for macOS", cancel: "Terminate"), elevatedLayout: false, animateInAsReplacement: false, action: { value in + if !value, let session = session { + let _ = activeSessionsContext.remove(hash: session.hash).start() + } + }), in: .window(.root)) + + var viewControllers = navigationController.viewControllers + viewControllers = viewControllers.filter { controller in + if controller is RecentSessionsController { + return false + } + if controller === self { + return false + } + return true + } + viewControllers.append(self.context.sharedContext.makeRecentSessionsController(context: self.context, activeSessionsContext: activeSessionsContext)) + navigationController.setViewControllers(viewControllers, animated: true) + } else { + self.dismiss() + } } override public func loadDisplayNode() { @@ -145,36 +176,24 @@ public final class AuthTransferScanScreen: ViewController { return } if let url = URL(string: code), let parsedToken = parseAuthTransferUrl(url) { - let _ = (getAuthTransferTokenInfo(network: strongSelf.context.account.network, token: parsedToken) - |> deliverOnMainQueue).start(next: { tokenInfo in + strongSelf.approveDisposable.set((approveAuthTransferToken(account: strongSelf.context.account, token: parsedToken, activeSessionsContext: strongSelf.activeSessionsContext) + |> deliverOnMainQueue).start(next: { session in guard let strongSelf = self else { return } - strongSelf.approveDisposable.set((approveAuthTransferToken(account: strongSelf.context.account, token: parsedToken) - |> deliverOnMainQueue).start(error: { _ in - guard let strongSelf = self else { - return - } - strongSelf.controllerNode.codeWithError = code - strongSelf.controllerNode.updateFocusedRect(nil) - }, completed: { - guard let strongSelf = self else { - return - } - strongSelf.controllerNode.codeWithError = nil - let activeSessionsContext = strongSelf.activeSessionsContext - Queue.mainQueue().after(1.5, { - activeSessionsContext?.loadMore() - }) - strongSelf.dismiss() - })) + strongSelf.controllerNode.codeWithError = nil + let activeSessionsContext = strongSelf.activeSessionsContext + Queue.mainQueue().after(1.5, { + activeSessionsContext.loadMore() + }) + strongSelf.dismissWithSuccess(session: session) }, error: { _ in guard let strongSelf = self else { return } strongSelf.controllerNode.codeWithError = code strongSelf.controllerNode.updateFocusedRect(nil) - }) + })) } }) } diff --git a/submodules/Postbox/Sources/MediaBox.swift b/submodules/Postbox/Sources/MediaBox.swift index ec5059eb2f..45a01133f4 100644 --- a/submodules/Postbox/Sources/MediaBox.swift +++ b/submodules/Postbox/Sources/MediaBox.swift @@ -229,6 +229,9 @@ public final class MediaBox { } public func moveResourceData(from: MediaResourceId, to: MediaResourceId) { + if from.isEqual(to: to) { + return + } self.dataQueue.async { let pathsFrom = self.storePathsForId(from) let pathsTo = self.storePathsForId(to) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift index 8fd7f7bdb7..9a1d034d43 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsController.swift @@ -447,7 +447,10 @@ private func recentSessionsControllerEntries(presentationData: PresentationData, return entries } -public func recentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext, webSessionsContext: WebSessionsContext, websitesOnly: Bool) -> ViewController { +private final class RecentSessionsControllerImpl: ItemListController, RecentSessionsController { +} + +public func recentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext, webSessionsContext: WebSessionsContext, websitesOnly: Bool) -> ViewController & RecentSessionsController { let statePromise = ValuePromise(RecentSessionsControllerState(), ignoreRepeated: true) let stateValue = Atomic(value: RecentSessionsControllerState()) let updateState: ((RecentSessionsControllerState) -> RecentSessionsControllerState) -> Void = { f in @@ -685,7 +688,7 @@ public func recentSessionsController(context: AccountContext, activeSessionsCont actionsDisposable.dispose() } - let controller = ItemListController(context: context, state: signal) + let controller = RecentSessionsControllerImpl(context: context, state: signal) controller.titleControlValueChanged = { [weak mode] index in mode?.set(index == 0 ? .sessions : .websites) } diff --git a/submodules/TelegramApi/Sources/Api3.swift b/submodules/TelegramApi/Sources/Api3.swift index 7ce2e5280f..cbc6bc300a 100644 --- a/submodules/TelegramApi/Sources/Api3.swift +++ b/submodules/TelegramApi/Sources/Api3.swift @@ -4167,29 +4167,15 @@ public extension Api { }) } - public static func acceptLoginToken(token: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + public static func acceptLoginToken(token: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(1122447801) + buffer.appendInt32(-392909491) serializeBytes(token, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.acceptLoginToken", parameters: [("token", token)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + return (FunctionDescription(name: "auth.acceptLoginToken", parameters: [("token", token)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Authorization? in let reader = BufferReader(buffer) - var result: Api.Updates? + var result: Api.Authorization? if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } - - public static func checkLoginToken(token: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2102383792) - serializeBytes(token, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.checkLoginToken", parameters: [("token", token)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.LoginTokenInfo? in - let reader = BufferReader(buffer) - var result: Api.auth.LoginTokenInfo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.LoginTokenInfo + result = Api.parse(reader, signature: signature) as? Api.Authorization } return result }) diff --git a/submodules/TelegramCore/Sources/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/AccountIntermediateState.swift index d14c243bac..cc26d95bec 100644 --- a/submodules/TelegramCore/Sources/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/AccountIntermediateState.swift @@ -126,6 +126,8 @@ struct AccountMutableState { var externallyUpdatedPeerId = Set() + var authorizationListUpdated: Bool = false + init(initialState: AccountInitialState, initialPeers: [PeerId: Peer], initialReferencedMessageIds: Set, initialStoredMessages: Set, initialReadInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set]) { self.initialState = initialState self.state = initialState.state @@ -534,12 +536,13 @@ struct AccountFinalStateEvents { let updatedMaxMessageId: Int32? let updatedQts: Int32? let externallyUpdatedPeerId: Set + let authorizationListUpdated: Bool var isEmpty: Bool { - return self.addedIncomingMessageIds.isEmpty && self.wasScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty + return self.addedIncomingMessageIds.isEmpty && self.wasScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated } - init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set = Set()) { + init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set = Set(), authorizationListUpdated: Bool = false) { self.addedIncomingMessageIds = addedIncomingMessageIds self.wasScheduledMessageIds = wasScheduledMessageIds self.updatedTypingActivities = updatedTypingActivities @@ -552,6 +555,7 @@ struct AccountFinalStateEvents { self.updatedMaxMessageId = updatedMaxMessageId self.updatedQts = updatedQts self.externallyUpdatedPeerId = externallyUpdatedPeerId + self.authorizationListUpdated = authorizationListUpdated } init(state: AccountReplayedFinalState) { @@ -567,6 +571,7 @@ struct AccountFinalStateEvents { self.updatedMaxMessageId = state.state.state.updatedMaxMessageId self.updatedQts = state.state.state.updatedQts self.externallyUpdatedPeerId = state.state.state.externallyUpdatedPeerId + self.authorizationListUpdated = state.state.state.authorizationListUpdated } func union(with other: AccountFinalStateEvents) -> AccountFinalStateEvents { @@ -590,7 +595,8 @@ struct AccountFinalStateEvents { } let externallyUpdatedPeerId = self.externallyUpdatedPeerId.union(other.externallyUpdatedPeerId) + let authorizationListUpdated = self.authorizationListUpdated || other.authorizationListUpdated - return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId) + return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated) } } diff --git a/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift index 9ae4df884d..8be3970f31 100644 --- a/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift @@ -962,6 +962,10 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo attributes.append(AutoremoveTimeoutMessageAttribute(timeout: expirationTimer, countdownBeginTime: nil)) } + if type.hasPrefix("auth") { + updatedState.authorizationListUpdated = true + } + let message = StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: nil, groupingKey: nil, timestamp: date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: peerId, text: messageText, attributes: attributes, media: medias) updatedState.addMessages([message], location: .UpperHistoryBlock) } diff --git a/submodules/TelegramCore/Sources/AccountStateManager.swift b/submodules/TelegramCore/Sources/AccountStateManager.swift index b627f2c5cf..6b2d23ccc7 100644 --- a/submodules/TelegramCore/Sources/AccountStateManager.swift +++ b/submodules/TelegramCore/Sources/AccountStateManager.swift @@ -130,6 +130,11 @@ public final class AccountStateManager { return self.significantStateUpdateCompletedPipe.signal() } + private let authorizationListUpdatesPipe = ValuePipe() + var authorizationListUpdates: Signal { + return self.authorizationListUpdatesPipe.signal() + } + private var updatedWebpageContexts: [MediaId: UpdatedWebpageSubscriberContext] = [:] private var updatedPeersNearbyContext = UpdatedPeersNearbySubscriberContext() @@ -702,6 +707,10 @@ public final class AccountStateManager { if !events.externallyUpdatedPeerId.isEmpty { self.externallyUpdatedPeerIdsPipe.putNext(Array(events.externallyUpdatedPeerId)) } + + if events.authorizationListUpdated { + self.authorizationListUpdatesPipe.putNext(Void()) + } case let .pollCompletion(pollId, preMessageIds, preSubscribers): if self.operations.count > 1 { self.operations.removeFirst() diff --git a/submodules/TelegramCore/Sources/ActiveSessionsContext.swift b/submodules/TelegramCore/Sources/ActiveSessionsContext.swift index cfe51296a1..c060382a5a 100644 --- a/submodules/TelegramCore/Sources/ActiveSessionsContext.swift +++ b/submodules/TelegramCore/Sources/ActiveSessionsContext.swift @@ -8,7 +8,7 @@ public struct ActiveSessionsContextState: Equatable { public var sessions: [RecentAccountSession] } -public final class ActiveSessionsContext { +private final class ActiveSessionsContextImpl { private let account: Account private var _state: ActiveSessionsContextState { didSet { @@ -18,13 +18,14 @@ public final class ActiveSessionsContext { } } private let _statePromise = Promise() - public var state: Signal { + var state: Signal { return self._statePromise.get() } private let disposable = MetaDisposable() + private var authorizationListUpdatesDisposable: Disposable? - public init(account: Account) { + init(account: Account) { assert(Queue.mainQueue().isCurrent()) self.account = account @@ -32,14 +33,20 @@ public final class ActiveSessionsContext { self._statePromise.set(.single(self._state)) self.loadMore() + + self.authorizationListUpdatesDisposable = (account.stateManager.authorizationListUpdates + |> deliverOnMainQueue).start(next: { [weak self] _ in + self?.loadMore() + }) } deinit { assert(Queue.mainQueue().isCurrent()) self.disposable.dispose() + self.authorizationListUpdatesDisposable?.dispose() } - public func loadMore() { + func loadMore() { assert(Queue.mainQueue().isCurrent()) if self._state.isLoadingMore { @@ -59,7 +66,23 @@ public final class ActiveSessionsContext { })) } - public func remove(hash: Int64) -> Signal { + func addSession(_ session: RecentAccountSession) { + var mergedSessions = self._state.sessions + var found = false + for i in 0 ..< mergedSessions.count { + if mergedSessions[i].hash == session.hash { + found = true + break + } + } + if !found { + mergedSessions.insert(session, at: 0) + } + + self._state = ActiveSessionsContextState(isLoadingMore: self._state.isLoadingMore, sessions: mergedSessions) + } + + func remove(hash: Int64) -> Signal { assert(Queue.mainQueue().isCurrent()) return terminateAccountSession(account: self.account, hash: hash) @@ -82,7 +105,7 @@ public final class ActiveSessionsContext { } } - public func removeOther() -> Signal { + func removeOther() -> Signal { return terminateOtherAccountSessions(account: self.account) |> deliverOnMainQueue |> mapToSignal { [weak self] _ -> Signal in @@ -98,6 +121,68 @@ public final class ActiveSessionsContext { } } +public final class ActiveSessionsContext { + private let impl: QueueLocalObject + + public var state: Signal { + return Signal { subscriber in + let disposable = MetaDisposable() + self.impl.with { impl in + disposable.set(impl.state.start(next: { value in + subscriber.putNext(value) + })) + } + return disposable + } + } + + public init(account: Account) { + self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: { + return ActiveSessionsContextImpl(account: account) + }) + } + + public func loadMore() { + self.impl.with { impl in + impl.loadMore() + } + } + + func addSession(_ session: RecentAccountSession) { + self.impl.with { impl in + impl.addSession(session) + } + } + + public func remove(hash: Int64) -> Signal { + return Signal { subscriber in + let disposable = MetaDisposable() + self.impl.with { impl in + disposable.set(impl.remove(hash: hash).start(error: { error in + subscriber.putError(error) + }, completed: { + subscriber.putCompletion() + })) + } + return disposable + } + } + + public func removeOther() -> Signal { + return Signal { subscriber in + let disposable = MetaDisposable() + self.impl.with { impl in + disposable.set(impl.removeOther().start(error: { error in + subscriber.putError(error) + }, completed: { + subscriber.putCompletion() + })) + } + return disposable + } + } +} + public struct WebSessionsContextState: Equatable { public var isLoadingMore: Bool public var sessions: [WebAuthorization] diff --git a/submodules/TelegramCore/Sources/AuthTransfer.swift b/submodules/TelegramCore/Sources/AuthTransfer.swift index a691167d34..793079c53e 100644 --- a/submodules/TelegramCore/Sources/AuthTransfer.swift +++ b/submodules/TelegramCore/Sources/AuthTransfer.swift @@ -9,19 +9,6 @@ public struct AuthTransferExportedToken { public let validUntil: Int32 } -public struct AuthTransferTokenInfo { - public let datacenterId: Int32 - public let authKeyId: Int64 - public let deviceModel: String - public let platform: String - public let systemVersion: String - public let apiId: Int32 - public let appName: String - public let appVersion: String - public let ip: String - public let region: String -} - public enum ExportAuthTransferTokenError { case generic case limitExceeded @@ -152,16 +139,16 @@ public func exportAuthTransferToken(accountManager: AccountManager, account: Una } } -public enum GetAuthTransferTokenInfoError { +public enum ApproveAuthTransferTokenError { case generic case invalid case expired case alreadyAccepted } -public func getAuthTransferTokenInfo(network: Network, token: Data) -> Signal { - return network.request(Api.functions.auth.checkLoginToken(token: Buffer(data: token))) - |> mapError { error -> GetAuthTransferTokenInfoError in +public func approveAuthTransferToken(account: Account, token: Data, activeSessionsContext: ActiveSessionsContext) -> Signal { + return account.network.request(Api.functions.auth.acceptLoginToken(token: Buffer(data: token))) + |> mapError { error -> ApproveAuthTransferTokenError in switch error.errorDescription { case "AUTH_TOKEN_INVALID": return .invalid @@ -173,25 +160,9 @@ public func getAuthTransferTokenInfo(network: Network, token: Data) -> Signal map { result -> AuthTransferTokenInfo in - switch result { - case let .loginTokenInfo(dcId, authKeyId, deviceModel, platform, systemVersion, apiId, appName, appVersion, ip, region): - return AuthTransferTokenInfo(datacenterId: dcId, authKeyId: authKeyId, deviceModel: deviceModel, platform: platform, systemVersion: systemVersion, apiId: apiId, appName: appName, appVersion: appVersion, ip: ip, region: region) - } - } -} - -public enum ApproveAuthTransferTokenError { - case generic -} - -public func approveAuthTransferToken(account: Account, token: Data) -> Signal { - return account.network.request(Api.functions.auth.acceptLoginToken(token: Buffer(data: token))) - |> mapError { _ -> ApproveAuthTransferTokenError in - return .generic - } - |> mapToSignal { updates -> Signal in - account.stateManager.addUpdates(updates) - return .complete() + |> mapToSignal { authorization -> Signal in + let session = RecentAccountSession(apiAuthorization: authorization) + activeSessionsContext.addSession(session) + return .single(session) } } diff --git a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift index 97ce963eb4..0ac70353b0 100644 --- a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift +++ b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift @@ -1159,6 +1159,10 @@ public final class SharedAccountContextImpl: SharedAccountContext { present(legacyController) }) } + + public func makeRecentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext) -> ViewController & RecentSessionsController { + return recentSessionsController(context: context, activeSessionsContext: activeSessionsContext, webSessionsContext: WebSessionsContext(account: context.account), websitesOnly: false) + } } private let defaultChatControllerInteraction = ChatControllerInteraction.default diff --git a/submodules/UndoUI/Sources/UndoOverlayController.swift b/submodules/UndoUI/Sources/UndoOverlayController.swift index fdb12ffcaf..aec849f42b 100644 --- a/submodules/UndoUI/Sources/UndoOverlayController.swift +++ b/submodules/UndoUI/Sources/UndoOverlayController.swift @@ -11,6 +11,7 @@ public enum UndoOverlayContent { case succeed(text: String) case emoji(path: String, text: String) case swipeToReply(title: String, text: String) + case actionSucceeded(title: String, text: String, cancel: String) } public final class UndoOverlayController: ViewController { diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index f89c417530..d18a5ab7e2 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -56,6 +56,8 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.textNode.maximumNumberOfLines = 0 var displayUndo = true + var undoText = presentationData.strings.Undo_Undo + var undoTextColor = UIColor(rgb: 0x5ac8fa) if presentationData.theme.overallDarkAppearance { self.animationBackgroundColor = presentationData.theme.rootController.tabBar.backgroundColor @@ -122,6 +124,18 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.textNode.maximumNumberOfLines = 2 displayUndo = false self.originalRemainingSeconds = 5 + case let .actionSucceeded(title, text, cancel): + self.iconNode = nil + self.iconCheckNode = nil + self.animationNode = AnimationNode(animation: "anim_success", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) + self.animatedStickerNode = nil + + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white) + self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) + displayUndo = true + undoText = cancel + undoTextColor = UIColor(rgb: 0xff7b74) + self.originalRemainingSeconds = 3 case let .emoji(path, text): self.iconNode = nil self.iconCheckNode = nil @@ -155,7 +169,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.buttonTextNode = ImmediateTextNode() self.buttonTextNode.displaysAsynchronously = false - self.buttonTextNode.attributedText = NSAttributedString(string: presentationData.strings.Undo_Undo, font: Font.regular(17.0), textColor: UIColor(rgb: 0x5ac8fa)) + self.buttonTextNode.attributedText = NSAttributedString(string: undoText, font: Font.regular(17.0), textColor: undoTextColor) self.buttonNode = HighlightTrackingButtonNode() @@ -175,11 +189,11 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { super.init() switch content { - case .removedChat: - self.panelWrapperNode.addSubnode(self.timerTextNode) - self.panelWrapperNode.addSubnode(self.statusNode) - case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply: - break + case .removedChat: + self.panelWrapperNode.addSubnode(self.timerTextNode) + self.panelWrapperNode.addSubnode(self.statusNode) + case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded: + break } self.iconNode.flatMap(self.panelWrapperNode.addSubnode) self.iconCheckNode.flatMap(self.panelWrapperNode.addSubnode)