From 6f5cd84019cd7fe8238965199dae9ddcd36a3c24 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 4 Nov 2025 14:43:17 +0400 Subject: [PATCH] Various improvements --- .../Sources/AccountContext.swift | 2 + ...rizationSequenceEmailEntryController.swift | 46 +++++-- .../Sources/ChatListController.swift | 30 +++++ .../LoginEmailSetupController.swift | 5 +- .../PrivacyAndSecurityController.swift | 10 +- .../Sources/PresentationGroupCall.swift | 2 +- .../Sources/State/AccountTaskManager.swift | 4 +- .../State/ManagedProxyInfoUpdates.swift | 114 +++++++++--------- .../TelegramCore/Sources/Suggestions.swift | 3 + .../Notices/TelegramEngineNotices.swift | 11 +- .../CameraScreen/Sources/CameraScreen.swift | 19 +-- .../Sources/CameraVideoSource.swift | 6 +- .../StoryItemSetContainerComponent.swift | 9 +- .../TelegramUI/Sources/ChatController.swift | 24 ++-- .../Sources/ComposeController.swift | 32 +++-- .../TelegramUI/Sources/OpenResolvedUrl.swift | 2 +- .../Sources/SharedAccountContext.swift | 4 + 17 files changed, 201 insertions(+), 122 deletions(-) diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index fc291ed6c0..77601c708a 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -1467,6 +1467,8 @@ public protocol SharedAccountContext: AnyObject { func makeNewContactScreen(context: AccountContext, peer: EnginePeer?, phoneNumber: String?, shareViaException: Bool, completion: @escaping (EnginePeer?, DeviceContactStableId?, DeviceContactExtendedData?) -> Void) -> ViewController + func makeLoginEmailSetupController(context: AccountContext, blocking: Bool, emailPattern: String?, canAutoDismissIfNeeded: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController + func navigateToCurrentCall() var hasOngoingCall: ValuePromise { get } var immediateHasOngoingCall: Bool { get } diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequenceEmailEntryController.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequenceEmailEntryController.swift index 2eb6744023..017a307466 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequenceEmailEntryController.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequenceEmailEntryController.swift @@ -2,8 +2,10 @@ import Foundation import UIKit import Display import AsyncDisplayKit +import SwiftSignalKit import TelegramPresentationData import ProgressNavigationButtonNode +import AccountContext public final class AuthorizationSequenceEmailEntryController: ViewController { public enum Mode { @@ -39,7 +41,10 @@ public final class AuthorizationSequenceEmailEntryController: ViewController { public var authorization: Any? public var authorizationDelegate: Any? - public init(presentationData: PresentationData, mode: Mode, blocking: Bool = false, back: @escaping () -> Void) { + private var inBackground = false + private var inBackgroundDisposable: Disposable? + + public init(context: AccountContext? = nil, presentationData: PresentationData, mode: Mode, blocking: Bool = false, back: @escaping () -> Void) { self.presentationData = presentationData self.mode = mode self.blocking = blocking @@ -58,12 +63,43 @@ public final class AuthorizationSequenceEmailEntryController: ViewController { self.navigationBar?.backPressed = { back() } + + if self.blocking { + self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView()) + } + + if let context { + self.inBackgroundDisposable = (context.sharedContext.applicationBindings.applicationInForeground + |> deliverOnMainQueue).start(next: { [weak self] value in + guard let self else { + return + } + let previousValue = self.inBackground + self.inBackground = value + + if !value && previousValue { + let _ = (context.engine.notices.getServerProvidedSuggestions(reload: true) + |> deliverOnMainQueue).start(next: { [weak self] currentValues in + guard let self else { + return + } + if !currentValues.contains(.setupLoginEmail) && !currentValues.contains(.setupLoginEmailBlocking) { + self.dismiss() + } + }) + } + }) + } } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + deinit { + self.inBackgroundDisposable?.dispose() + } + override public func loadDisplayNode() { self.displayNode = AuthorizationSequenceEmailEntryControllerNode(strings: self.presentationData.strings, theme: self.presentationData.theme, mode: self.mode) self.displayNodeDidLoad() @@ -91,11 +127,7 @@ public final class AuthorizationSequenceEmailEntryController: ViewController { guard let layout = self.validLayout, layout.size.width < 360.0 else { return } - - if self.blocking { - self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView()) - } - + if self.inProgress { let item = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: self.presentationData.theme.rootController.navigationBar.accentTextColor)) self.navigationItem.rightBarButtonItem = item @@ -118,7 +150,7 @@ public final class AuthorizationSequenceEmailEntryController: ViewController { } } - override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, transition: transition) let hadLayout = self.validLayout != nil diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index fc64fc8a76..4ad49c626a 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -136,6 +136,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController private let suggestAutoarchiveDisposable = MetaDisposable() private let dismissAutoarchiveDisposable = MetaDisposable() private var didSuggestAutoarchive = false + private var didSuggestLoginEmailSetup = false private var presentationData: PresentationData private let presentationDataValue = Promise() @@ -2551,6 +2552,35 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController guard let strongSelf = self else { return } + + let context = strongSelf.context + if values.contains(.setupLoginEmail) || values.contains(.setupLoginEmailBlocking) { + if strongSelf.didSuggestLoginEmailSetup { + return + } + + strongSelf.didSuggestLoginEmailSetup = true + + let _ = (context.engine.notices.getServerProvidedSuggestions(reload: true) + |> deliverOnMainQueue).start(next: { [weak self] currentValues in + guard let strongSelf = self, currentValues.contains(.setupLoginEmail) || currentValues.contains(.setupLoginEmailBlocking) else { + return + } + if let navigationController = strongSelf.navigationController as? NavigationController { + let blocking = currentValues.contains(.setupLoginEmailBlocking) + let controller = strongSelf.context.sharedContext.makeLoginEmailSetupController(context: strongSelf.context, blocking: blocking, emailPattern: nil, canAutoDismissIfNeeded: true, navigationController: navigationController, completion: { + let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: blocking ? ServerProvidedSuggestion.setupLoginEmailBlocking.id : ServerProvidedSuggestion.setupLoginEmail.id).startStandalone() + }, dismiss: { + if !blocking { + let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupLoginEmail.id).startStandalone() + } + }) + navigationController.pushViewController(controller) + } + }) + return + } + if strongSelf.didSuggestAutoarchive { return } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/LoginEmailSetupController.swift b/submodules/SettingsUI/Sources/Privacy and Security/LoginEmailSetupController.swift index 2befa317e3..4665aade46 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/LoginEmailSetupController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/LoginEmailSetupController.swift @@ -32,7 +32,7 @@ final class LoginEmailSetupDelegate: NSObject, ASAuthorizationControllerDelegate } } -public func loginEmailSetupController(context: AccountContext, blocking: Bool, emailPattern: String?, navigationController: NavigationController?, completion: @escaping () -> Void) -> ViewController { +public func loginEmailSetupController(context: AccountContext, blocking: Bool, emailPattern: String?, canAutoDismissIfNeeded: Bool = false, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } var dismissEmailControllerImpl: (() -> Void)? var presentControllerImpl: ((ViewController) -> Void)? @@ -65,7 +65,7 @@ public func loginEmailSetupController(context: AccountContext, blocking: Bool, e } } - let emailController = AuthorizationSequenceEmailEntryController(presentationData: presentationData, mode: emailPattern != nil ? .change : .setup, blocking: blocking, back: { + let emailController = AuthorizationSequenceEmailEntryController(context: canAutoDismissIfNeeded ? context : nil, presentationData: presentationData, mode: emailPattern != nil ? .change : .setup, blocking: blocking, back: { dismissEmailControllerImpl?() }) emailController.proceedWithEmail = { [weak emailController] email in @@ -78,6 +78,7 @@ public func loginEmailSetupController(context: AccountContext, blocking: Bool, e let codeController = AuthorizationSequenceCodeEntryController(presentationData: presentationData, back: { dismissCodeControllerImpl?() + dismiss() }) presentControllerImpl = { [weak codeController] c in diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 39bbd07164..11fbbb0e8c 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -682,8 +682,12 @@ private func privacyAndSecurityControllerEntries( showLoginEmail = true } if showLoginEmail { + var hasLoginEmail = false + if let loginEmail { + hasLoginEmail = !loginEmail.contains(" ") + } entries.append(.loginEmail(presentationData.theme, presentationData.strings.PrivacySettings_LoginEmail, loginEmail)) - entries.append(.loginEmailInfo(presentationData.theme, loginEmail == nil ? presentationData.strings.PrivacySettings_LoginEmailSetupInfo : presentationData.strings.PrivacySettings_LoginEmailInfo)) + entries.append(.loginEmailInfo(presentationData.theme, !hasLoginEmail ? presentationData.strings.PrivacySettings_LoginEmailSetupInfo : presentationData.strings.PrivacySettings_LoginEmailInfo)) } entries.append(.privacyHeader(presentationData.theme, presentationData.strings.PrivacySettings_PrivacyTitle)) @@ -1329,7 +1333,7 @@ public func privacyAndSecurityController( }, openDataSettings: { pushControllerImpl?(dataPrivacyController(context: context), true) }, openEmailSettings: { emailPattern in - if let emailPattern = emailPattern { + if let emailPattern, !emailPattern.contains(" ") { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let controller = textAlertController( context: context, title: emailPattern, text: presentationData.strings.PrivacySettings_LoginEmailAlertText, actions: [ @@ -1542,7 +1546,7 @@ public func privacyAndSecurityController( setupEmailImpl = { emailPattern in let controller = loginEmailSetupController(context: context, blocking: false, emailPattern: emailPattern, navigationController: getNavigationControllerImpl?(), completion: { updatedTwoStepAuthData?() - }) + }, dismiss: {}) pushControllerImpl?(controller, true) } diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index ac0ec27085..5560940956 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -3367,7 +3367,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { public func disableVideo() { self.hasVideo = false - self.useFrontCamera = true; + self.useFrontCamera = true if let _ = self.videoCapturer { self.videoCapturer = nil self.isVideoMutedDisposable.set(nil) diff --git a/submodules/TelegramCore/Sources/State/AccountTaskManager.swift b/submodules/TelegramCore/Sources/State/AccountTaskManager.swift index 027f6e3338..d470168d7f 100644 --- a/submodules/TelegramCore/Sources/State/AccountTaskManager.swift +++ b/submodules/TelegramCore/Sources/State/AccountTaskManager.swift @@ -19,6 +19,7 @@ final class AccountTaskManager { private var stateDisposable: Disposable? private let tasksDisposable = MetaDisposable() private let configurationDisposable = MetaDisposable() + private let promoDisposable = MetaDisposable() private let managedTopReactionsDisposable = MetaDisposable() @@ -133,7 +134,6 @@ final class AccountTaskManager { tasks.add(managedAutodownloadSettingsUpdates(accountManager: self.accountManager, network: self.stateManager.network).start()) tasks.add(managedTermsOfServiceUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start()) tasks.add(managedAppUpdateInfo(network: self.stateManager.network, stateManager: self.stateManager).start()) - tasks.add(managedPromoInfoUpdates(accountPeerId: self.accountPeerId, postbox: self.stateManager.postbox, network: self.stateManager.network, viewTracker: self.viewTracker).start()) tasks.add(managedLocalizationUpdatesOperations(accountManager: self.accountManager, postbox: self.stateManager.postbox, network: self.stateManager.network).start()) tasks.add(managedPendingPeerNotificationSettings(postbox: self.stateManager.postbox, network: self.stateManager.network).start()) tasks.add(managedSynchronizeAppLogEventsOperations(postbox: self.stateManager.postbox, network: self.stateManager.network).start()) @@ -155,10 +155,12 @@ final class AccountTaskManager { self.tasksDisposable.dispose() self.configurationDisposable.dispose() self.managedTopReactionsDisposable.dispose() + self.promoDisposable.dispose() } func reloadAppConfiguration() { self.configurationDisposable.set(managedAppConfigurationUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start()) + self.promoDisposable.set(managedPromoInfoUpdates(accountPeerId: self.accountPeerId, postbox: self.stateManager.postbox, network: self.stateManager.network, viewTracker: self.viewTracker).start()) } } diff --git a/submodules/TelegramCore/Sources/State/ManagedProxyInfoUpdates.swift b/submodules/TelegramCore/Sources/State/ManagedProxyInfoUpdates.swift index 1384758737..088ee5d044 100644 --- a/submodules/TelegramCore/Sources/State/ManagedProxyInfoUpdates.swift +++ b/submodules/TelegramCore/Sources/State/ManagedProxyInfoUpdates.swift @@ -186,6 +186,63 @@ extension ServerSuggestionInfo.Item { } } +func _internal_fetchPromoInfo(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network) -> Signal { + return network.request(Api.functions.help.getPromoData()) + |> `catch` { _ -> Signal in + return .single(.promoDataEmpty(expires: 10 * 60)) + } + |> mapToSignal { data -> Signal in + return postbox.transaction { transaction -> Void in + switch data { + case .promoDataEmpty: + transaction.replaceAdditionalChatListItems([]) + + let suggestionInfo = ServerSuggestionInfo( + legacyItems: [], + items: [], + dismissedIds: [] + ) + + transaction.updatePreferencesEntry(key: PreferencesKeys.serverSuggestionInfo(), { _ in + return PreferencesEntry(suggestionInfo) + }) + case let .promoData(flags, expires, peer, psaType, psaMessage, pendingSuggestions, dismissedSuggestions, customPendingSuggestion, chats, users): + let _ = expires + + let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users) + updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers) + + var kind: PromoChatListItem.Kind? + if let psaType { + kind = .psa(type: psaType, message: psaMessage) + } else if ((flags & 1) << 0) != 0 { + kind = .proxy + } + + var additionalChatListItems: [AdditionalChatListItem] = [] + if let kind, let peer, let parsedPeer = transaction.getPeer(peer.peerId) { + additionalChatListItems.append(PromoChatListItem(peerId: parsedPeer.id, kind: kind)) + } + transaction.replaceAdditionalChatListItems(additionalChatListItems) + + var customItems: [ServerSuggestionInfo.Item] = [] + if let customPendingSuggestion { + customItems.append(ServerSuggestionInfo.Item(customPendingSuggestion)) + } + let suggestionInfo = ServerSuggestionInfo( + legacyItems: pendingSuggestions, + items: customItems, + dismissedIds: dismissedSuggestions + ) + + transaction.updatePreferencesEntry(key: PreferencesKeys.serverSuggestionInfo(), { _ in + return PreferencesEntry(suggestionInfo) + }) + } + } + } +} + func managedPromoInfoUpdates(accountPeerId: PeerId, postbox: Postbox, network: Network, viewTracker: AccountViewTracker) -> Signal { return Signal { subscriber in let queue = Queue() @@ -193,62 +250,7 @@ func managedPromoInfoUpdates(accountPeerId: PeerId, postbox: Postbox, network: N |> distinctUntilChanged |> deliverOn(queue) |> mapToSignal { _ -> Signal in - let appliedOnce: Signal = network.request(Api.functions.help.getPromoData()) - |> `catch` { _ -> Signal in - return .single(.promoDataEmpty(expires: 10 * 60)) - } - |> mapToSignal { data -> Signal in - return postbox.transaction { transaction -> Void in - switch data { - case .promoDataEmpty: - transaction.replaceAdditionalChatListItems([]) - - let suggestionInfo = ServerSuggestionInfo( - legacyItems: [], - items: [], - dismissedIds: [] - ) - - transaction.updatePreferencesEntry(key: PreferencesKeys.serverSuggestionInfo(), { _ in - return PreferencesEntry(suggestionInfo) - }) - case let .promoData(flags, expires, peer, psaType, psaMessage, pendingSuggestions, dismissedSuggestions, customPendingSuggestion, chats, users): - let _ = expires - - let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users) - updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers) - - var kind: PromoChatListItem.Kind? - if let psaType { - kind = .psa(type: psaType, message: psaMessage) - } else if ((flags & 1) << 0) != 0 { - kind = .proxy - } - - var additionalChatListItems: [AdditionalChatListItem] = [] - if let kind, let peer, let parsedPeer = transaction.getPeer(peer.peerId) { - additionalChatListItems.append(PromoChatListItem(peerId: parsedPeer.id, kind: kind)) - } - transaction.replaceAdditionalChatListItems(additionalChatListItems) - - var customItems: [ServerSuggestionInfo.Item] = [] - if let customPendingSuggestion { - customItems.append(ServerSuggestionInfo.Item(customPendingSuggestion)) - } - let suggestionInfo = ServerSuggestionInfo( - legacyItems: pendingSuggestions, - items: customItems, - dismissedIds: dismissedSuggestions - ) - - transaction.updatePreferencesEntry(key: PreferencesKeys.serverSuggestionInfo(), { _ in - return PreferencesEntry(suggestionInfo) - }) - } - } - } - - return (appliedOnce + return (_internal_fetchPromoInfo(accountPeerId: accountPeerId, postbox: postbox, network: network) |> then( Signal.complete() |> delay(10.0 * 60.0, queue: Queue.concurrentDefaultQueue())) diff --git a/submodules/TelegramCore/Sources/Suggestions.swift b/submodules/TelegramCore/Sources/Suggestions.swift index e9f2866608..041af82f71 100644 --- a/submodules/TelegramCore/Sources/Suggestions.swift +++ b/submodules/TelegramCore/Sources/Suggestions.swift @@ -167,6 +167,9 @@ func _internal_dismissServerProvidedSuggestion(account: Account, suggestion: Str } else { dismissedSuggestions[account.id] = Set([suggestion]) } + if suggestion == ServerProvidedSuggestion.setupLoginEmailBlocking.id { + return .complete() + } return account.network.request(Api.functions.help.dismissSuggestion(peer: .inputPeerEmpty, suggestion: suggestion)) |> `catch` { _ -> Signal in return .single(.boolFalse) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift b/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift index e99676a0a6..95496f238f 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift @@ -21,8 +21,15 @@ public extension TelegramEngine { |> ignoreValues } - public func getServerProvidedSuggestions() -> Signal<[ServerProvidedSuggestion], NoError> { - return _internal_getServerProvidedSuggestions(account: self.account) + public func getServerProvidedSuggestions(reload: Bool = false) -> Signal<[ServerProvidedSuggestion], NoError> { + if reload { + return _internal_fetchPromoInfo(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network) + |> mapToSignal { + return _internal_getServerProvidedSuggestions(account: self.account) + } + } else { + return _internal_getServerProvidedSuggestions(account: self.account) + } } public func getServerDismissedSuggestions() -> Signal<[String], NoError> { diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index d20bcfa3ba..d635a2c004 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -315,7 +315,6 @@ private final class CameraScreenComponent: CombinedComponent { private weak var liveStreamCall: PresentationGroupCall? private var liveStreamVideoCapturer: OngoingCallVideoCapturer? private var liveStreamVideoDisposable: Disposable? - private var liveStreamAudioDisposable: Disposable? var cameraState: CameraState? var swipeHint: CaptureControlsComponent.SwipeHint = .none @@ -370,7 +369,6 @@ private final class CameraScreenComponent: CombinedComponent { self.lastGalleryAssetsDisposable?.dispose() self.resultDisposable.dispose() self.liveStreamVideoDisposable?.dispose() - self.liveStreamAudioDisposable?.dispose() } func setupRecentAssetSubscription() { @@ -1148,12 +1146,14 @@ private final class CameraScreenComponent: CombinedComponent { controller.present(alertController, in: .window(.root)) } - func setupStreamCamera(call: PresentationGroupCall) { + func setupLiveStreamCamera(call: PresentationGroupCall) { guard self.liveStreamVideoCapturer == nil, let call = call as? PresentationGroupCallImpl, let controller = self.getController() else { return } self.liveStreamCall = call + call.setIsMuted(action: .unmuted) + let liveStreamMediaSource = controller.node.liveStreamMediaSource let videoCapturer = OngoingCallVideoCapturer(keepLandscape: false, isCustom: true) self.liveStreamVideoCapturer = videoCapturer @@ -1166,15 +1166,6 @@ private final class CameraScreenComponent: CombinedComponent { videoCapturer.injectSampleBuffer(sampleBuffer, rotation: .up, completion: {}) } } - self.liveStreamAudioDisposable = liveStreamMediaSource.addOnAudioUpdated { [weak self, weak liveStreamMediaSource] in - guard let self, let liveStreamMediaSource, let call = self.liveStreamCall as? PresentationGroupCallImpl else { - return - } - if let audioData = liveStreamMediaSource.currentAudioOutput { - call.addExternalAudioData(data: audioData) - } - } - Queue.mainQueue().after(1.0) { call.requestVideo(capturer: videoCapturer, useFrontCamera: false) } @@ -1500,7 +1491,7 @@ private final class CameraScreenComponent: CombinedComponent { metrics: environment.metrics, deviceMetrics: environment.deviceMetrics, didSetupMediaStream: { [weak state] call in - state?.setupStreamCamera(call: call) + state?.setupLiveStreamCamera(call: call) } ), availableSize: availableSize, @@ -1540,7 +1531,7 @@ private final class CameraScreenComponent: CombinedComponent { ) } - if component.cameraState.isStreaming { + if component.cameraState.mode == .live && component.cameraState.isStreaming { let endStreamButton = endStreamButton.update( component: GlassBarButtonComponent( size: CGSize(width: 56.0, height: 40.0), diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraVideoSource.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraVideoSource.swift index 71327b888c..2778dd2ae2 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraVideoSource.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraVideoSource.swift @@ -101,8 +101,8 @@ final class LiveStreamMediaSource { private var onAudioUpdatedListeners = Bag<() -> Void>() public init() { - let width: Int32 = 1080 - let height: Int32 = 1920 + let width: Int32 = 720 + let height: Int32 = 1280 let dimensions = CGSize(width: CGFloat(width), height: CGFloat(height)) @@ -165,7 +165,7 @@ final class LiveStreamMediaSource { qualityPreset: nil ), dimensions: CGSize(width: 1080.0, height: 1920.0), - outputDimensions: CGSize(width: 1080.0, height: 1920.0), + outputDimensions: CGSize(width: 720.0, height: 1280.0), textScale: 1.0, videoDuration: nil, additionalVideoDuration: nil diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index c1ce048571..947b280323 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -5588,14 +5588,7 @@ public final class StoryItemSetContainerComponent: Component { guard let component = self.component else { return } - - #if DEBUG - if "".isEmpty { - self.performDeleteAction() - return - } - #endif - + self.isEditingStory = true self.updateIsProgressPaused() self.state?.updated(transition: .easeInOut(duration: 0.2)) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index ad4508bd99..3bdffbc9e2 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -8780,18 +8780,20 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } func addPeerContact() { - if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramUser, let peerStatusSettings = self.presentationInterfaceState.contactStatus?.peerStatusSettings, let contactData = DeviceContactExtendedData(peer: EnginePeer(peer)) { - self.present(context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: self.context), environment: ShareControllerAppEnvironment(sharedContext: self.context.sharedContext), subject: .create(peer: peer, contactData: contactData, isSharing: true, shareViaException: peerStatusSettings.contains(.addExceptionWhenAddingContact), completion: { [weak self] peer, stableId, contactData in - guard let strongSelf = self else { - return - } - if let peer = peer as? TelegramUser { - if let phone = peer.phone, !phone.isEmpty { + if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramUser, let peerStatusSettings = self.presentationInterfaceState.contactStatus?.peerStatusSettings { + let controller = self.context.sharedContext.makeNewContactScreen( + context: self.context, + peer: EnginePeer(peer), + phoneNumber: nil, + shareViaException: peerStatusSettings.contains(.addExceptionWhenAddingContact), + completion: { [weak self] peer, _, _ in + guard let self, let peer else { + return } - - self?.present(OverlayStatusController(theme: strongSelf.presentationData.theme, type: .genericSuccess(strongSelf.presentationData.strings.AddContact_StatusSuccess(EnginePeer(peer).compactDisplayTitle).string, true)), in: .window(.root)) + self.present(OverlayStatusController(theme: self.presentationData.theme, type: .genericSuccess(self.presentationData.strings.AddContact_StatusSuccess(peer.compactDisplayTitle).string, true)), in: .window(.root)) } - }), completed: nil, cancelled: nil), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + ) + self.push(controller) } } @@ -9777,7 +9779,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } ) strongSelf.chatDisplayNode.dismissInput() - strongSelf.present(controller, in: .window(.root)) + strongSelf.push(controller) }) } diff --git a/submodules/TelegramUI/Sources/ComposeController.swift b/submodules/TelegramUI/Sources/ComposeController.swift index 1738e15ebf..f4881a504b 100644 --- a/submodules/TelegramUI/Sources/ComposeController.swift +++ b/submodules/TelegramUI/Sources/ComposeController.swift @@ -199,29 +199,35 @@ public class ComposeControllerImpl: ViewController, ComposeController { } switch status { - case .allowed: - let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: "", lastName: "", phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!!$_", value: "+")]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "") - (strongSelf.navigationController as? NavigationController)?.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in + case .allowed: + let controller = strongSelf.context.sharedContext.makeNewContactScreen( + context: strongSelf.context, + peer: nil, + phoneNumber: nil, + shareViaException: false, + completion: { [weak self] peer, stableId, contactData in guard let strongSelf = self else { return } if let peer = peer { DispatchQueue.main.async { if let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer))) } } - } else { + } else if let stableId, let contactData { (strongSelf.navigationController as? NavigationController)?.replaceAllButRootController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil), animated: true) } - }), completed: nil, cancelled: nil)) - case .notDetermined: - DeviceAccess.authorizeAccess(to: .contacts) - default: - let presentationData = strongSelf.presentationData - strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.AccessDenied_Title, text: presentationData.strings.Contacts_AccessDeniedError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: { - self?.context.sharedContext.applicationBindings.openSettings() - })]), in: .window(.root)) + } + ) + (strongSelf.navigationController as? NavigationController)?.pushViewController(controller) + case .notDetermined: + DeviceAccess.authorizeAccess(to: .contacts) + default: + let presentationData = strongSelf.presentationData + strongSelf.present(textAlertController(context: strongSelf.context, title: presentationData.strings.AccessDenied_Title, text: presentationData.strings.Contacts_AccessDeniedError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: { + self?.context.sharedContext.applicationBindings.openSettings() + })]), in: .window(.root)) } }) } diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index f4ce285373..5c02a3b2bf 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -829,7 +829,7 @@ func openResolvedUrlImpl( }) case .loginEmail: if let navigationController { - let controller = loginEmailSetupController(context: context, blocking: true, emailPattern: nil, navigationController: navigationController, completion: {}) + let controller = loginEmailSetupController(context: context, blocking: false, emailPattern: nil, navigationController: navigationController, completion: {}, dismiss: {}) navigationController.pushViewController(controller) } } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 12fd16d4fe..16db8a5437 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -4038,6 +4038,10 @@ public final class SharedAccountContextImpl: SharedAccountContext { public func makeNewContactScreen(context: AccountContext, peer: EnginePeer?, phoneNumber: String?, shareViaException: Bool, completion: @escaping (EnginePeer?, DeviceContactStableId?, DeviceContactExtendedData?) -> Void) -> ViewController { return NewContactScreen(context: context, initialData: NewContactScreen.initialData(peer: peer, phoneNumber: phoneNumber, shareViaException: shareViaException), completion: completion) } + + public func makeLoginEmailSetupController(context: AccountContext, blocking: Bool, emailPattern: String?, canAutoDismissIfNeeded: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController { + return loginEmailSetupController(context: context, blocking: blocking, emailPattern: emailPattern, canAutoDismissIfNeeded: canAutoDismissIfNeeded, navigationController: navigationController, completion: completion, dismiss: dismiss) + } } private func peerInfoControllerImpl(context: AccountContext, updatedPresentationData: (PresentationData, Signal)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, requestsContext: PeerInvitationImportersContext? = nil) -> ViewController? {