Modernize weak references

This commit is contained in:
Isaac 2025-02-28 14:40:28 +01:00
parent 3c38b4df89
commit 99d210e364

View File

@ -887,29 +887,33 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
let controllerInteraction = ChatControllerInteraction(openMessage: { [weak self] message, params in let controllerInteraction = ChatControllerInteraction(openMessage: { [weak self] message, params in
guard let strongSelf = self, strongSelf.isNodeLoaded, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) else { guard let self, self.isNodeLoaded, let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) else {
return false return false
} }
let mode = params.mode let mode = params.mode
let displayVoiceMessageDiscardAlert: () -> Bool = { let displayVoiceMessageDiscardAlert: () -> Bool = { [weak self] in
if strongSelf.presentVoiceMessageDiscardAlert(action: { [weak self] in guard let self else {
if let strongSelf = self { return true
Queue.mainQueue().after(0.1, {
let _ = strongSelf.controllerInteraction?.openMessage(message, params)
})
} }
if self.presentVoiceMessageDiscardAlert(action: { [weak self] in
Queue.mainQueue().after(0.1, {
guard let self else {
return
}
let _ = self.controllerInteraction?.openMessage(message, params)
})
}, performAction: false) { }, performAction: false) {
return false return false
} }
return true return true
} }
strongSelf.commitPurposefulAction() self.commitPurposefulAction()
strongSelf.dismissAllTooltips() self.dismissAllTooltips()
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() self.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
var openMessageByAction = false var openMessageByAction = false
var isLocation = false var isLocation = false
@ -923,9 +927,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if let file = media as? TelegramMediaFile { if let file = media as? TelegramMediaFile {
if file.isInstantVideo { if file.isInstantVideo {
if strongSelf.chatDisplayNode.isInputViewFocused { if self.chatDisplayNode.isInputViewFocused {
strongSelf.returnInputViewFocus = true self.returnInputViewFocus = true
strongSelf.chatDisplayNode.dismissInput() self.chatDisplayNode.dismissInput()
} }
} }
if file.isMusic || file.isVoice || file.isInstantVideo { if file.isMusic || file.isVoice || file.isInstantVideo {
@ -934,7 +938,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if (file.isVoice || file.isInstantVideo) && message.minAutoremoveOrClearTimeout == viewOnceTimeout { if (file.isVoice || file.isInstantVideo) && message.minAutoremoveOrClearTimeout == viewOnceTimeout {
strongSelf.openViewOnceMediaMessage(message) self.openViewOnceMediaMessage(message)
return false return false
} }
} else if file.isVideo { } else if file.isVideo {
@ -947,7 +951,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
switch extendedMedia { switch extendedMedia {
case .preview: case .preview:
if displayVoiceMessageDiscardAlert() { if displayVoiceMessageDiscardAlert() {
strongSelf.controllerInteraction?.openCheckoutOrReceipt(message.id, params) self.controllerInteraction?.openCheckoutOrReceipt(message.id, params)
return true return true
} else { } else {
return false return false
@ -959,7 +963,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
switch extendedMedia { switch extendedMedia {
case .preview: case .preview:
if displayVoiceMessageDiscardAlert() { if displayVoiceMessageDiscardAlert() {
strongSelf.controllerInteraction?.openCheckoutOrReceipt(message.id, nil) self.controllerInteraction?.openCheckoutOrReceipt(message.id, nil)
return true return true
} else { } else {
return false return false
@ -969,15 +973,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} else if media is TelegramMediaGiveaway || media is TelegramMediaGiveawayResults { } else if media is TelegramMediaGiveaway || media is TelegramMediaGiveawayResults {
let progress = params.progress let progress = params.progress
let presentationData = strongSelf.presentationData let presentationData = self.presentationData
var signal = strongSelf.context.engine.payments.premiumGiveawayInfo(peerId: message.id.peerId, messageId: message.id) var signal = self.context.engine.payments.premiumGiveawayInfo(peerId: message.id.peerId, messageId: message.id)
let disposable: MetaDisposable let disposable: MetaDisposable
if let current = strongSelf.giveawayStatusDisposable { if let current = self.giveawayStatusDisposable {
disposable = current disposable = current
} else { } else {
disposable = MetaDisposable() disposable = MetaDisposable()
strongSelf.giveawayStatusDisposable = disposable self.giveawayStatusDisposable = disposable
} }
let progressSignal = Signal<Never, NoError> { [weak self] subscriber in let progressSignal = Signal<Never, NoError> { [weak self] subscriber in
@ -1010,8 +1014,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
disposable.set((signal disposable.set((signal
|> deliverOnMainQueue).startStrict(next: { [weak self] info in |> deliverOnMainQueue).startStrict(next: { [weak self] info in
if let strongSelf = self, let info { if let self, let info {
strongSelf.displayGiveawayStatusInfo(messageId: message.id, giveawayInfo: info) self.displayGiveawayStatusInfo(messageId: message.id, giveawayInfo: info)
} }
})) }))
@ -1024,22 +1028,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
case .pinnedMessageUpdated, .gameScore, .setSameChatWallpaper, .giveawayResults, .customText: case .pinnedMessageUpdated, .gameScore, .setSameChatWallpaper, .giveawayResults, .customText:
for attribute in message.attributes { for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute { if let attribute = attribute as? ReplyMessageAttribute {
strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote.flatMap { quote in NavigateToMessageParams.Quote(string: quote.text, offset: quote.offset) } : nil))) self.navigateToMessage(from: message.id, to: .id(attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote.flatMap { quote in NavigateToMessageParams.Quote(string: quote.text, offset: quote.offset) } : nil)))
break break
} }
} }
case let .photoUpdated(image): case let .photoUpdated(image):
openMessageByAction = image != nil openMessageByAction = image != nil
case .groupPhoneCall, .inviteToGroupPhoneCall: case .groupPhoneCall, .inviteToGroupPhoneCall:
if let activeCall = strongSelf.presentationInterfaceState.activeGroupCallInfo?.activeCall { if let activeCall = self.presentationInterfaceState.activeGroupCallInfo?.activeCall {
strongSelf.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: EngineGroupCallDescription(id: activeCall.id, accessHash: activeCall.accessHash, title: activeCall.title, scheduleTimestamp: activeCall.scheduleTimestamp, subscribedToScheduled: activeCall.subscribedToScheduled, isStream: activeCall.isStream)) self.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: EngineGroupCallDescription(id: activeCall.id, accessHash: activeCall.accessHash, title: activeCall.title, scheduleTimestamp: activeCall.scheduleTimestamp, subscribedToScheduled: activeCall.subscribedToScheduled, isStream: activeCall.isStream))
} else { } else {
var canManageGroupCalls = false var canManageGroupCalls = false
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel { if let channel = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel {
if channel.flags.contains(.isCreator) || channel.hasPermission(.manageCalls) { if channel.flags.contains(.isCreator) || channel.hasPermission(.manageCalls) {
canManageGroupCalls = true canManageGroupCalls = true
} }
} else if let group = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramGroup { } else if let group = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramGroup {
if case .creator = group.role { if case .creator = group.role {
canManageGroupCalls = true canManageGroupCalls = true
} else if case let .admin(rights, _) = group.role { } else if case let .admin(rights, _) = group.role {
@ -1051,80 +1055,80 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if canManageGroupCalls { if canManageGroupCalls {
let text: String let text: String
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info { if let channel = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_CreateNewVoiceChatText text = self.presentationData.strings.LiveStream_CreateNewVoiceChatText
} else { } else {
text = strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatText text = self.presentationData.strings.VoiceChat_CreateNewVoiceChatText
} }
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatStartNow, action: { self.present(textAlertController(context: self.context, updatedPresentationData: self.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.VoiceChat_CreateNewVoiceChatStartNow, action: { [weak self] in
if let strongSelf = self { if let self {
var dismissStatus: (() -> Void)? var dismissStatus: (() -> Void)?
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: { let statusController = OverlayStatusController(theme: self.presentationData.theme, type: .loading(cancelled: {
dismissStatus?() dismissStatus?()
})) }))
dismissStatus = { [weak self, weak statusController] in dismissStatus = { [weak self, weak statusController] in
self?.createVoiceChatDisposable.set(nil) self?.createVoiceChatDisposable.set(nil)
statusController?.dismiss() statusController?.dismiss()
} }
strongSelf.present(statusController, in: .window(.root)) self.present(statusController, in: .window(.root))
strongSelf.createVoiceChatDisposable.set((strongSelf.context.engine.calls.createGroupCall(peerId: message.id.peerId, title: nil, scheduleDate: nil, isExternalStream: false) self.createVoiceChatDisposable.set((self.context.engine.calls.createGroupCall(peerId: message.id.peerId, title: nil, scheduleDate: nil, isExternalStream: false)
|> deliverOnMainQueue).startStrict(next: { [weak self] info in |> deliverOnMainQueue).startStrict(next: { [weak self] info in
guard let strongSelf = self else { guard let self else {
return return
} }
strongSelf.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: EngineGroupCallDescription(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: info.subscribedToScheduled, isStream: info.isStream)) self.joinGroupCall(peerId: message.id.peerId, invite: nil, activeCall: EngineGroupCallDescription(id: info.id, accessHash: info.accessHash, title: info.title, scheduleTimestamp: info.scheduleTimestamp, subscribedToScheduled: info.subscribedToScheduled, isStream: info.isStream))
}, error: { [weak self] error in }, error: { [weak self] error in
dismissStatus?() dismissStatus?()
guard let strongSelf = self else { guard let self else {
return return
} }
let text: String let text: String
switch error { switch error {
case .generic, .scheduledTooLate: case .generic, .scheduledTooLate:
text = strongSelf.presentationData.strings.Login_UnknownError text = self.presentationData.strings.Login_UnknownError
case .anonymousNotAllowed: case .anonymousNotAllowed:
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info { if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info {
text = strongSelf.presentationData.strings.LiveStream_AnonymousDisabledAlertText text = self.presentationData.strings.LiveStream_AnonymousDisabledAlertText
} else { } else {
text = strongSelf.presentationData.strings.VoiceChat_AnonymousDisabledAlertText text = self.presentationData.strings.VoiceChat_AnonymousDisabledAlertText
} }
} }
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) self.present(textAlertController(context: self.context, updatedPresentationData: self.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, completed: { }, completed: {
dismissStatus?() dismissStatus?()
})) }))
} }
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatSchedule, action: { }), TextAlertAction(type: .genericAction, title: self.presentationData.strings.VoiceChat_CreateNewVoiceChatSchedule, action: { [weak self] in
if let strongSelf = self { if let self {
strongSelf.context.scheduleGroupCall(peerId: message.id.peerId, parentController: strongSelf) self.context.scheduleGroupCall(peerId: message.id.peerId, parentController: self)
} }
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root)) }), TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
} }
} }
return true return true
case .messageAutoremoveTimeoutUpdated: case .messageAutoremoveTimeoutUpdated:
var canSetupAutoremoveTimeout = false var canSetupAutoremoveTimeout = false
if let _ = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramSecretChat { if let _ = self.presentationInterfaceState.renderedPeer?.peer as? TelegramSecretChat {
canSetupAutoremoveTimeout = false canSetupAutoremoveTimeout = false
} else if let group = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramGroup { } else if let group = self.presentationInterfaceState.renderedPeer?.peer as? TelegramGroup {
if !group.hasBannedPermission(.banChangeInfo) { if !group.hasBannedPermission(.banChangeInfo) {
canSetupAutoremoveTimeout = true canSetupAutoremoveTimeout = true
} }
} else if let user = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramUser { } else if let user = self.presentationInterfaceState.renderedPeer?.peer as? TelegramUser {
if user.id != strongSelf.context.account.peerId && user.botInfo == nil { if user.id != self.context.account.peerId && user.botInfo == nil {
canSetupAutoremoveTimeout = true canSetupAutoremoveTimeout = true
} }
} else if let channel = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel { } else if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel {
if channel.hasPermission(.changeInfo) { if channel.hasPermission(.changeInfo) {
canSetupAutoremoveTimeout = true canSetupAutoremoveTimeout = true
} }
} }
if canSetupAutoremoveTimeout { if canSetupAutoremoveTimeout {
strongSelf.presentAutoremoveSetup() self.presentAutoremoveSetup()
} }
case let .paymentSent(currency, _, _, _, _): case let .paymentSent(currency, _, _, _, _):
if currency == "XTR" { if currency == "XTR" {
@ -1136,14 +1140,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.push(self.context.sharedContext.makeStarsReceiptScreen(context: self.context, receipt: receipt)) self.push(self.context.sharedContext.makeStarsReceiptScreen(context: self.context, receipt: receipt))
}) })
} else { } else {
strongSelf.present(BotReceiptController(context: strongSelf.context, messageId: message.id), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) self.present(BotReceiptController(context: self.context, messageId: message.id), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
} }
return true return true
case .setChatTheme: case .setChatTheme:
strongSelf.presentThemeSelection() self.presentThemeSelection()
return true return true
case let .setChatWallpaper(wallpaper, _): case let .setChatWallpaper(wallpaper, _):
guard let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else { guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
return true return true
} }
if let peer = peer as? TelegramChannel { if let peer = peer as? TelegramChannel {
@ -1158,11 +1162,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
return true return true
} }
guard message.effectivelyIncoming(strongSelf.context.account.peerId), let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else { guard message.effectivelyIncoming(self.context.account.peerId), let peer = self.presentationInterfaceState.renderedPeer?.peer else {
strongSelf.presentThemeSelection() self.presentThemeSelection()
return true return true
} }
strongSelf.chatDisplayNode.dismissInput() self.chatDisplayNode.dismissInput()
var options = WallpaperPresentationOptions() var options = WallpaperPresentationOptions()
var intensity: Int32? var intensity: Int32?
if let settings = wallpaper.settings { if let settings = wallpaper.settings {
@ -1176,7 +1180,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
intensity = settings.intensity intensity = settings.intensity
} }
} }
let wallpaperPreviewController = WallpaperGalleryController(context: strongSelf.context, source: .wallpaper(wallpaper, options, [], intensity, nil, nil), mode: .peer(EnginePeer(peer), true)) let wallpaperPreviewController = WallpaperGalleryController(context: self.context, source: .wallpaper(wallpaper, options, [], intensity, nil, nil), mode: .peer(EnginePeer(peer), true))
wallpaperPreviewController.apply = { [weak wallpaperPreviewController] entry, options, _, _, brightness, forBoth in wallpaperPreviewController.apply = { [weak wallpaperPreviewController] entry, options, _, _, brightness, forBoth in
var settings: WallpaperSettings? var settings: WallpaperSettings?
if case let .wallpaper(wallpaper, _) = entry { if case let .wallpaper(wallpaper, _) = entry {
@ -1189,69 +1193,69 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
settings = WallpaperSettings(blur: options.contains(.blur), motion: options.contains(.motion), colors: baseSettings?.colors ?? [], intensity: intensity, rotation: baseSettings?.rotation) settings = WallpaperSettings(blur: options.contains(.blur), motion: options.contains(.motion), colors: baseSettings?.colors ?? [], intensity: intensity, rotation: baseSettings?.rotation)
} }
let _ = (strongSelf.context.engine.themes.setExistingChatWallpaper(messageId: message.id, settings: settings, forBoth: forBoth) let _ = (self.context.engine.themes.setExistingChatWallpaper(messageId: message.id, settings: settings, forBoth: forBoth)
|> deliverOnMainQueue).startStandalone() |> deliverOnMainQueue).startStandalone()
Queue.mainQueue().after(0.1) { Queue.mainQueue().after(0.1) {
wallpaperPreviewController?.dismiss() wallpaperPreviewController?.dismiss()
} }
} }
strongSelf.push(wallpaperPreviewController) self.push(wallpaperPreviewController)
return true return true
case let .giftPremium(_, _, duration, _, _, _, _): case let .giftPremium(_, _, duration, _, _, _, _):
strongSelf.chatDisplayNode.dismissInput() self.chatDisplayNode.dismissInput()
let fromPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? strongSelf.context.account.peerId : message.id.peerId let fromPeerId: PeerId = message.author?.id == self.context.account.peerId ? self.context.account.peerId : message.id.peerId
let toPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? message.id.peerId : strongSelf.context.account.peerId let toPeerId: PeerId = message.author?.id == self.context.account.peerId ? message.id.peerId : self.context.account.peerId
let controller = PremiumIntroScreen(context: strongSelf.context, source: .gift(from: fromPeerId, to: toPeerId, duration: duration, giftCode: nil)) let controller = PremiumIntroScreen(context: self.context, source: .gift(from: fromPeerId, to: toPeerId, duration: duration, giftCode: nil))
strongSelf.push(controller) self.push(controller)
return true return true
case .starGift, .starGiftUnique: case .starGift, .starGiftUnique:
let controller = strongSelf.context.sharedContext.makeGiftViewScreen(context: strongSelf.context, message: EngineMessage(message), shareStory: { [weak self] uniqueGift in let controller = self.context.sharedContext.makeGiftViewScreen(context: self.context, message: EngineMessage(message), shareStory: { [weak self] uniqueGift in
if let self {
Queue.mainQueue().after(0.15) { Queue.mainQueue().after(0.15) {
if let self {
let controller = self.context.sharedContext.makeStorySharingScreen(context: self.context, subject: .gift(uniqueGift), parentController: self) let controller = self.context.sharedContext.makeStorySharingScreen(context: self.context, subject: .gift(uniqueGift), parentController: self)
self.push(controller) self.push(controller)
} }
} }
}) })
strongSelf.push(controller) self.push(controller)
return true return true
case .giftStars: case .giftStars:
let controller = strongSelf.context.sharedContext.makeStarsGiftScreen(context: strongSelf.context, message: EngineMessage(message)) let controller = self.context.sharedContext.makeStarsGiftScreen(context: self.context, message: EngineMessage(message))
strongSelf.push(controller) self.push(controller)
return true return true
case let .giftCode(slug, _, _, _, _, _, _, _, _, _, _): case let .giftCode(slug, _, _, _, _, _, _, _, _, _, _):
strongSelf.openResolved(result: .premiumGiftCode(slug: slug), sourceMessageId: message.id, progress: params.progress) self.openResolved(result: .premiumGiftCode(slug: slug), sourceMessageId: message.id, progress: params.progress)
return true return true
case .prizeStars: case .prizeStars:
let controller = strongSelf.context.sharedContext.makeStarsGiftScreen(context: strongSelf.context, message: EngineMessage(message)) let controller = self.context.sharedContext.makeStarsGiftScreen(context: self.context, message: EngineMessage(message))
strongSelf.push(controller) self.push(controller)
return true return true
case let .suggestedProfilePhoto(image): case let .suggestedProfilePhoto(image):
strongSelf.chatDisplayNode.dismissInput() self.chatDisplayNode.dismissInput()
if let image = image { if let image = image {
if message.effectivelyIncoming(strongSelf.context.account.peerId) { if message.effectivelyIncoming(self.context.account.peerId) {
if let emojiMarkup = image.emojiMarkup { if let emojiMarkup = image.emojiMarkup {
let controller = AvatarEditorScreen(context: strongSelf.context, inputData: AvatarEditorScreen.inputData(context: strongSelf.context, isGroup: false), peerType: .user, markup: emojiMarkup) let controller = AvatarEditorScreen(context: self.context, inputData: AvatarEditorScreen.inputData(context: self.context, isGroup: false), peerType: .user, markup: emojiMarkup)
controller.imageCompletion = { [weak self] image, commit in controller.imageCompletion = { [weak self] image, commit in
if let strongSelf = self { if let self {
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl { if let rootController = self.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
settingsController.updateProfilePhoto(image, mode: .accept, uploadStatus: nil) settingsController.updateProfilePhoto(image, mode: .accept, uploadStatus: nil)
commit() commit()
} }
} }
} }
controller.videoCompletion = { [weak self] image, url, values, markup, commit in controller.videoCompletion = { [weak self] image, url, values, markup, commit in
if let strongSelf = self { if let self {
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl { if let rootController = self.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
settingsController.updateProfileVideo(image, video: nil, values: nil, markup: markup, mode: .accept, uploadStatus: nil) settingsController.updateProfileVideo(image, video: nil, values: nil, markup: markup, mode: .accept, uploadStatus: nil)
commit() commit()
} }
} }
} }
strongSelf.push(controller) self.push(controller)
} else { } else {
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView { if let itemNode = itemNode as? ChatMessageItemView {
if let result = itemNode.transitionNode(id: message.id, media: image, adjustRect: false) { if let result = itemNode.transitionNode(id: message.id, media: image, adjustRect: false) {
selectedNode = result selectedNode = result
@ -1267,17 +1271,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
senderName = nil senderName = nil
} }
legacyAvatarEditor(context: strongSelf.context, media: .message(message: MessageReference(message), media: image), transitionView: transitionView, senderName: senderName, present: { [weak self] c, a in legacyAvatarEditor(context: self.context, media: .message(message: MessageReference(message), media: image), transitionView: transitionView, senderName: senderName, present: { [weak self] c, a in
self?.present(c, in: .window(.root), with: a) self?.present(c, in: .window(.root), with: a)
}, imageCompletion: { [weak self] image in }, imageCompletion: { [weak self] image in
if let strongSelf = self { if let self {
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl { if let rootController = self.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
settingsController.updateProfilePhoto(image, mode: .accept, uploadStatus: nil) settingsController.updateProfilePhoto(image, mode: .accept, uploadStatus: nil)
} }
} }
}, videoCompletion: { [weak self] image, url, adjustments in }, videoCompletion: { [weak self] image, url, adjustments in
if let strongSelf = self { if let self {
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl { if let rootController = self.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
settingsController.oldUpdateProfileVideo(image, asset: AVURLAsset(url: url), adjustments: adjustments, mode: .accept) settingsController.oldUpdateProfileVideo(image, asset: AVURLAsset(url: url), adjustments: adjustments, mode: .accept)
} }
} }
@ -1288,7 +1292,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
case .boostsApplied: case .boostsApplied:
strongSelf.controllerInteraction?.openGroupBoostInfo(nil, 0) self.controllerInteraction?.openGroupBoostInfo(nil, 0)
return true return true
default: default:
break break
@ -1299,29 +1303,33 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
let openChatLocation = strongSelf.chatLocation let openChatLocation = self.chatLocation
var chatFilterTag: MemoryBuffer? var chatFilterTag: MemoryBuffer?
if case let .customTag(value, _) = strongSelf.chatDisplayNode.historyNode.tag { if case let .customTag(value, _) = self.chatDisplayNode.historyNode.tag {
chatFilterTag = value chatFilterTag = value
} }
var standalone = false var standalone = false
if case .customChatContents = strongSelf.chatLocation { if case .customChatContents = self.chatLocation {
standalone = true standalone = true
} }
if let adAttribute = message.attributes.first(where: { $0 is AdMessageAttribute }) as? AdMessageAttribute { if let adAttribute = message.attributes.first(where: { $0 is AdMessageAttribute }) as? AdMessageAttribute {
if let file = message.media.first(where: { $0 is TelegramMediaFile}) as? TelegramMediaFile, file.isVideo && !file.isAnimated { if let file = message.media.first(where: { $0 is TelegramMediaFile}) as? TelegramMediaFile, file.isVideo && !file.isAnimated {
strongSelf.chatDisplayNode.historyNode.adMessagesContext?.markAction(opaqueId: adAttribute.opaqueId, media: true, fullscreen: false) self.chatDisplayNode.historyNode.adMessagesContext?.markAction(opaqueId: adAttribute.opaqueId, media: true, fullscreen: false)
} else { } else {
strongSelf.controllerInteraction?.activateAdAction(message.id, nil, true, false) self.controllerInteraction?.activateAdAction(message.id, nil, true, false)
return true return true
} }
} }
return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: openChatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: strongSelf.chatLocationContextHolder, message: message, mediaIndex: params.mediaIndex, standalone: standalone, reverseMessageGalleryOrder: false, mode: mode, navigationController: strongSelf.effectiveNavigationController, dismissInput: { let openChatMessageParams = OpenChatMessageParams(context: context, updatedPresentationData: self.updatedPresentationData, chatLocation: openChatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: self.chatLocationContextHolder, message: message, mediaIndex: params.mediaIndex, standalone: standalone, reverseMessageGalleryOrder: false, mode: mode, navigationController: self.effectiveNavigationController, dismissInput: { [weak self] in
self?.chatDisplayNode.dismissInput() self?.chatDisplayNode.dismissInput()
}, present: { c, a, i in }, present: { [weak self] c, a, i in
guard let self else {
return
}
if case .current = i { if case .current = i {
c.presentationArguments = a c.presentationArguments = a
c.statusBar.alphaUpdated = { [weak self] transition in c.statusBar.alphaUpdated = { [weak self] transition in
@ -1330,14 +1338,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
self.updateStatusBarPresentation(animated: transition.isAnimated) self.updateStatusBarPresentation(animated: transition.isAnimated)
} }
self?.galleryPresentationContext.present(c, on: PresentationSurfaceLevel(rawValue: 0), blockInteraction: true, completion: {}) self.galleryPresentationContext.present(c, on: PresentationSurfaceLevel(rawValue: 0), blockInteraction: true, completion: {})
} else { } else {
self?.present(c, in: .window(.root), with: a, blockInteraction: true) self.present(c, in: .window(.root), with: a, blockInteraction: true)
} }
}, transitionNode: { messageId, media, adjustRect in }, transitionNode: { [weak self] messageId, media, adjustRect in
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
if let strongSelf = self { if let self {
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView { if let itemNode = itemNode as? ChatMessageItemView {
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: adjustRect) { if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: adjustRect) {
selectedNode = result selectedNode = result
@ -1346,27 +1354,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
return selectedNode return selectedNode
}, addToTransitionSurface: { view in }, addToTransitionSurface: { [weak self] view in
guard let strongSelf = self else { guard let self else {
return return
} }
strongSelf.chatDisplayNode.historyNode.view.superview?.insertSubview(view, aboveSubview: strongSelf.chatDisplayNode.historyNode.view) self.chatDisplayNode.historyNode.view.superview?.insertSubview(view, aboveSubview: self.chatDisplayNode.historyNode.view)
}, openUrl: { url in }, openUrl: { [weak self] url in
self?.openUrl(url, concealed: false, skipConcealedAlert: isLocation, message: nil) self?.openUrl(url, concealed: false, skipConcealedAlert: isLocation, message: nil)
}, openPeer: { peer, navigation in }, openPeer: { [weak self] peer, navigation in
self?.openPeer(peer: EnginePeer(peer), navigation: navigation, fromMessage: nil) self?.openPeer(peer: EnginePeer(peer), navigation: navigation, fromMessage: nil)
}, callPeer: { peerId, isVideo in }, callPeer: { [weak self] peerId, isVideo in
self?.controllerInteraction?.callPeer(peerId, isVideo) self?.controllerInteraction?.callPeer(peerId, isVideo)
}, enqueueMessage: { message in }, enqueueMessage: { [weak self] message in
self?.sendMessages([message]) self?.sendMessages([message])
}, sendSticker: canSendMessagesToChat(strongSelf.presentationInterfaceState) ? { fileReference, sourceNode, sourceRect in }, sendSticker: canSendMessagesToChat(self.presentationInterfaceState) ? { [weak self] fileReference, sourceNode, sourceRect in
return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) ?? false return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) ?? false
} : nil, sendEmoji: canSendMessagesToChat(strongSelf.presentationInterfaceState) ? { text, attribute in } : nil, sendEmoji: canSendMessagesToChat(self.presentationInterfaceState) ? { [weak self] text, attribute in
self?.controllerInteraction?.sendEmoji(text, attribute, false) self?.controllerInteraction?.sendEmoji(text, attribute, false)
} : nil, setupTemporaryHiddenMedia: { signal, centralIndex, galleryMedia in } : nil, setupTemporaryHiddenMedia: { [weak self] signal, centralIndex, galleryMedia in
if let strongSelf = self { if let self {
strongSelf.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { entry in self.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { [weak self] entry in
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { if let self, let controllerInteraction = self.controllerInteraction {
var messageIdAndMedia: [MessageId: [Media]] = [:] var messageIdAndMedia: [MessageId: [Media]] = [:]
if let entry = entry as? InstantPageGalleryEntry, entry.index == centralIndex { if let entry = entry as? InstantPageGalleryEntry, entry.index == centralIndex {
@ -1375,7 +1383,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
controllerInteraction.hiddenMedia = messageIdAndMedia controllerInteraction.hiddenMedia = messageIdAndMedia
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView { if let itemNode = itemNode as? ChatMessageItemView {
itemNode.updateHiddenMedia() itemNode.updateHiddenMedia()
} }
@ -1383,10 +1391,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
})) }))
} }
}, chatAvatarHiddenMedia: { signal, media in }, chatAvatarHiddenMedia: { [weak self] signal, media in
if let strongSelf = self { if let self {
strongSelf.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { messageId in self.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { [weak self] messageId in
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { if let self, let controllerInteraction = self.controllerInteraction {
var messageIdAndMedia: [MessageId: [Media]] = [:] var messageIdAndMedia: [MessageId: [Media]] = [:]
if let messageId = messageId { if let messageId = messageId {
@ -1395,7 +1403,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
controllerInteraction.hiddenMedia = messageIdAndMedia controllerInteraction.hiddenMedia = messageIdAndMedia
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView { if let itemNode = itemNode as? ChatMessageItemView {
itemNode.updateHiddenMedia() itemNode.updateHiddenMedia()
} }
@ -1405,54 +1413,54 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
}, actionInteraction: GalleryControllerActionInteraction( }, actionInteraction: GalleryControllerActionInteraction(
openUrl: { [weak self] url, concealed in openUrl: { [weak self] url, concealed in
if let strongSelf = self { if let self {
strongSelf.openUrl(url, concealed: concealed, message: nil) self.openUrl(url, concealed: concealed, message: nil)
} }
}, openUrlIn: { [weak self] url in }, openUrlIn: { [weak self] url in
if let strongSelf = self { if let self {
strongSelf.openUrlIn(url) self.openUrlIn(url)
} }
}, openPeerMention: { [weak self] mention in }, openPeerMention: { [weak self] mention in
if let strongSelf = self { if let self {
strongSelf.controllerInteraction?.openPeerMention(mention, nil) self.controllerInteraction?.openPeerMention(mention, nil)
} }
}, openPeer: { [weak self] peer in }, openPeer: { [weak self] peer in
if let strongSelf = self { if let self {
strongSelf.controllerInteraction?.openPeer(peer, .default, nil, .default) self.controllerInteraction?.openPeer(peer, .default, nil, .default)
} }
}, openHashtag: { [weak self] peerName, hashtag in }, openHashtag: { [weak self] peerName, hashtag in
if let strongSelf = self { if let self {
strongSelf.controllerInteraction?.openHashtag(peerName, hashtag) self.controllerInteraction?.openHashtag(peerName, hashtag)
} }
}, openBotCommand: { [weak self] command in }, openBotCommand: { [weak self] command in
if let strongSelf = self { if let self {
strongSelf.controllerInteraction?.sendBotCommand(nil, command) self.controllerInteraction?.sendBotCommand(nil, command)
} }
}, openAd: { [weak self] messageId in }, openAd: { [weak self] messageId in
if let strongSelf = self { if let self {
strongSelf.controllerInteraction?.activateAdAction(messageId, nil, true, true) self.controllerInteraction?.activateAdAction(messageId, nil, true, true)
} }
}, addContact: { [weak self] phoneNumber in }, addContact: { [weak self] phoneNumber in
if let strongSelf = self { if let self {
strongSelf.controllerInteraction?.addContact(phoneNumber) self.controllerInteraction?.addContact(phoneNumber)
} }
}, storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in }, storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in
guard let strongSelf = self else { guard let self else {
return return
} }
var storedState: MediaPlaybackStoredState? var storedState: MediaPlaybackStoredState?
if let timestamp = timestamp { if let timestamp = timestamp {
storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate)) storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate))
} }
let _ = updateMediaPlaybackStoredStateInteractively(engine: strongSelf.context.engine, messageId: messageId, state: storedState).startStandalone() let _ = updateMediaPlaybackStoredStateInteractively(engine: self.context.engine, messageId: messageId, state: storedState).startStandalone()
}, editMedia: { [weak self] messageId, snapshots, transitionCompletion in }, editMedia: { [weak self] messageId, snapshots, transitionCompletion in
guard let strongSelf = self else { guard let self else {
return return
} }
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId)) let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|> deliverOnMainQueue).startStandalone(next: { [weak self] message in |> deliverOnMainQueue).startStandalone(next: { [weak self] message in
guard let strongSelf = self, let message = message else { guard let self, let message = message else {
return return
} }
@ -1472,17 +1480,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if let mediaReference = mediaReference, let peer = message.peers[message.id.peerId] { if let mediaReference = mediaReference, let peer = message.peers[message.id.peerId] {
legacyMediaEditor(context: strongSelf.context, peer: peer, threadTitle: strongSelf.threadInfo?.title, media: mediaReference, mode: .draw, initialCaption: NSAttributedString(), snapshots: snapshots, transitionCompletion: { legacyMediaEditor(context: self.context, peer: peer, threadTitle: self.threadInfo?.title, media: mediaReference, mode: .draw, initialCaption: NSAttributedString(), snapshots: snapshots, transitionCompletion: {
transitionCompletion() transitionCompletion()
}, getCaptionPanelView: { [weak self] in }, getCaptionPanelView: { [weak self] in
return self?.getCaptionPanelView(isFile: false) return self?.getCaptionPanelView(isFile: false)
}, sendMessagesWithSignals: { [weak self] signals, _, _, isCaptionAbove in }, sendMessagesWithSignals: { [weak self] signals, _, _, isCaptionAbove in
if let strongSelf = self { if let self {
var parameters: ChatSendMessageActionSheetController.SendParameters? var parameters: ChatSendMessageActionSheetController.SendParameters?
if isCaptionAbove { if isCaptionAbove {
parameters = ChatSendMessageActionSheetController.SendParameters(effect: nil, textIsAboveMedia: true) parameters = ChatSendMessageActionSheetController.SendParameters(effect: nil, textIsAboveMedia: true)
} }
strongSelf.enqueueMediaMessages(signals: signals, silentPosting: false, parameters: parameters) self.enqueueMediaMessages(signals: signals, silentPosting: false, parameters: parameters)
} }
}, present: { [weak self] c, a in }, present: { [weak self] c, a in
self?.present(c, in: .window(.root), with: a) self?.present(c, in: .window(.root), with: a)
@ -1493,18 +1501,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self?.canReadHistory.set(canReadHistory) self?.canReadHistory.set(canReadHistory)
}), }),
getSourceRect: { [weak self] in getSourceRect: { [weak self] in
guard let strongSelf = self else { guard let self else {
return nil return nil
} }
var rect: CGRect? var rect: CGRect?
strongSelf.chatDisplayNode.historyNode.forEachVisibleMessageItemNode({ itemNode in self.chatDisplayNode.historyNode.forEachVisibleMessageItemNode({ itemNode in
if itemNode.item?.message.id == message.id { if itemNode.item?.message.id == message.id {
rect = itemNode.view.convert(itemNode.contentFrame(), to: nil) rect = itemNode.view.convert(itemNode.contentFrame(), to: nil)
} }
}) })
return rect return rect
} }
)) )
self.controllerInteraction?.isOpeningMediaSignal = openChatMessageParams.blockInteraction.get()
return context.sharedContext.openChatMessage(openChatMessageParams)
}, openPeer: { [weak self] peer, navigation, fromMessage, source in }, openPeer: { [weak self] peer, navigation, fromMessage, source in
var expandAvatar = false var expandAvatar = false
if case let .groupParticipant(storyStats, avatarHeaderNode) = source { if case let .groupParticipant(storyStats, avatarHeaderNode) = source {