mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Merge branch 'master' of github.com:peter-iakovlev/TelegramUI
# Conflicts: # TelegramUI.xcodeproj/project.pbxproj # TelegramUI/ChatController.swift # TelegramUI/UserInfoController.swift
This commit is contained in:
@@ -212,68 +212,76 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
self.ready.set(.never())
|
||||
|
||||
self.scrollToTop = { [weak self] in
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded {
|
||||
strongSelf.chatDisplayNode.scrollToTop()
|
||||
guard let strongSelf = self, strongSelf.isNodeLoaded else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.scrollToTop()
|
||||
}
|
||||
|
||||
self.attemptNavigation = { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if let _ = strongSelf.presentationInterfaceState.inputTextPanelState.mediaRecordingState {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Conversation_DiscardVoiceMessageDescription, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
if let strongSelf = self {
|
||||
strongSelf.stopMediaRecorder()
|
||||
}
|
||||
action()
|
||||
})]), in: .window(.root))
|
||||
|
||||
return false
|
||||
}
|
||||
guard let strongSelf = self else {
|
||||
return true
|
||||
}
|
||||
if let _ = strongSelf.presentationInterfaceState.inputTextPanelState.mediaRecordingState {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Conversation_DiscardVoiceMessageDescription, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
self?.stopMediaRecorder()
|
||||
action()
|
||||
})]), in: .window(.root))
|
||||
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
let controllerInteraction = ChatControllerInteraction(openMessage: { [weak self] message in
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) {
|
||||
strongSelf.commitPurposefulAction()
|
||||
|
||||
for media in message.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
switch action.action {
|
||||
case .pinnedMessageUpdated:
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId))
|
||||
break
|
||||
}
|
||||
guard let strongSelf = self, strongSelf.isNodeLoaded, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) else {
|
||||
return false
|
||||
}
|
||||
strongSelf.commitPurposefulAction()
|
||||
|
||||
var openMessageByAction: Bool = false
|
||||
|
||||
for media in message.media {
|
||||
if let action = media as? TelegramMediaAction {
|
||||
switch action.action {
|
||||
case .pinnedMessageUpdated:
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId))
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
case let .photoUpdated(image):
|
||||
openMessageByAction = image != nil
|
||||
default:
|
||||
break
|
||||
}
|
||||
if !openMessageByAction {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return openChatMessage(account: account, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: strongSelf.navigationController as? NavigationController, dismissInput: {
|
||||
self?.chatDisplayNode.dismissInput()
|
||||
}, present: { c, a in
|
||||
self?.present(c, in: .window(.root), with: a)
|
||||
}, transitionNode: { messageId, media in
|
||||
var selectedNode: (ASDisplayNode, () -> UIView?)?
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
||||
selectedNode = result
|
||||
}
|
||||
}
|
||||
|
||||
return openChatMessage(account: account, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: strongSelf.navigationController as? NavigationController, dismissInput: {
|
||||
self?.chatDisplayNode.dismissInput()
|
||||
}, present: { c, a in
|
||||
self?.present(c, in: .window(.root), with: a)
|
||||
}, transitionNode: { messageId, media in
|
||||
var selectedNode: (ASDisplayNode, () -> UIView?)?
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
||||
selectedNode = result
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedNode
|
||||
}, addToTransitionSurface: { view in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.view.superview?.insertSubview(view, aboveSubview: strongSelf.chatDisplayNode.historyNode.view)
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.historyNode.view.superview?.insertSubview(view, aboveSubview: strongSelf.chatDisplayNode.historyNode.view)
|
||||
}, openUrl: { url in
|
||||
self?.openUrl(url, concealed: false)
|
||||
}, openPeer: { peer, navigation in
|
||||
@@ -302,85 +310,102 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
}))
|
||||
}
|
||||
})
|
||||
}, openPeer: { [weak self] id, navigation, fromMessage in
|
||||
if let strongSelf = self {
|
||||
strongSelf.openPeer(peerId: id, navigation: navigation, fromMessage: fromMessage)
|
||||
}
|
||||
self?.openPeer(peerId: id, navigation: navigation, fromMessage: fromMessage)
|
||||
}, openPeerMention: { [weak self] name in
|
||||
if let strongSelf = self {
|
||||
strongSelf.openPeerMention(name)
|
||||
}
|
||||
self?.openPeerMention(name)
|
||||
}, openMessageContextMenu: { [weak self] message, node, frame in
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded {
|
||||
if let messages = strongSelf.chatDisplayNode.historyNode.messageGroupInCurrentHistoryView(message.id) {
|
||||
var updatedMessages = messages
|
||||
for i in 0 ..< updatedMessages.count {
|
||||
if updatedMessages[i].id == message.id {
|
||||
let message = updatedMessages.remove(at: i)
|
||||
updatedMessages.insert(message, at: 0)
|
||||
guard let strongSelf = self, strongSelf.isNodeLoaded else {
|
||||
return
|
||||
}
|
||||
if let messages = strongSelf.chatDisplayNode.historyNode.messageGroupInCurrentHistoryView(message.id) {
|
||||
var updatedMessages = messages
|
||||
for i in 0 ..< updatedMessages.count {
|
||||
if updatedMessages[i].id == message.id {
|
||||
let message = updatedMessages.remove(at: i)
|
||||
updatedMessages.insert(message, at: 0)
|
||||
break
|
||||
}
|
||||
}
|
||||
let _ = contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: strongSelf.presentationInterfaceState, account: strongSelf.account, messages: updatedMessages, interfaceInteraction: strongSelf.interfaceInteraction, debugStreamSingleVideo: { id in
|
||||
self?.debugStreamSingleVideo(id)
|
||||
}).start(next: { actions in
|
||||
guard let strongSelf = self, !actions.isEmpty else {
|
||||
return
|
||||
}
|
||||
var contextMenuController: ContextMenuController?
|
||||
var contextActions: [ContextMenuAction] = []
|
||||
var sheetActions: [ChatMessageContextMenuSheetAction] = []
|
||||
for action in actions {
|
||||
switch action {
|
||||
case let .context(contextAction):
|
||||
contextActions.append(contextAction)
|
||||
case let .sheet(sheetAction):
|
||||
sheetActions.append(sheetAction)
|
||||
}
|
||||
}
|
||||
|
||||
if !contextActions.isEmpty {
|
||||
contextMenuController = ContextMenuController(actions: contextActions, catchTapsOutside: true)
|
||||
}
|
||||
|
||||
contextMenuController?.dismissed = {
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.displayMessageActionSheet(stableId: nil, sheetActions: nil, displayContextMenuController: nil)
|
||||
}
|
||||
}
|
||||
|
||||
var hasActions = false
|
||||
for media in updatedMessages[0].media {
|
||||
if media is TelegramMediaAction {
|
||||
hasActions = true
|
||||
break
|
||||
}
|
||||
}
|
||||
let _ = contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: strongSelf.presentationInterfaceState, account: strongSelf.account, messages: updatedMessages, interfaceInteraction: strongSelf.interfaceInteraction, debugStreamSingleVideo: { id in
|
||||
self?.debugStreamSingleVideo(id)
|
||||
}).start(next: { actions in
|
||||
if let strongSelf = self, !actions.isEmpty {
|
||||
var contextMenuController: ContextMenuController?
|
||||
var contextActions: [ContextMenuAction] = []
|
||||
var sheetActions: [ChatMessageContextMenuSheetAction] = []
|
||||
for action in actions {
|
||||
switch action {
|
||||
case let .context(contextAction):
|
||||
contextActions.append(contextAction)
|
||||
case let .sheet(sheetAction):
|
||||
sheetActions.append(sheetAction)
|
||||
if hasActions {
|
||||
if let contextMenuController = contextMenuController {
|
||||
strongSelf.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: {
|
||||
guard let strongSelf = self else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if !contextActions.isEmpty {
|
||||
contextMenuController = ContextMenuController(actions: contextActions, catchTapsOutside: true)
|
||||
}
|
||||
|
||||
contextMenuController?.dismissed = {
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.displayMessageActionSheet(stableId: nil, sheetActions: nil, displayContextMenuController: nil)
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.chatDisplayNode.displayMessageActionSheet(stableId: updatedMessages[0].stableId, sheetActions: sheetActions, displayContextMenuController: contextMenuController.flatMap { ($0, node, frame) })
|
||||
return (node, frame, strongSelf.displayNode, strongSelf.displayNode.bounds)
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
strongSelf.chatDisplayNode.displayMessageActionSheet(stableId: updatedMessages[0].stableId, sheetActions: sheetActions, displayContextMenuController: contextMenuController.flatMap { ($0, node, frame) })
|
||||
}
|
||||
})
|
||||
}
|
||||
}, navigateToMessage: { [weak self] fromId, id in
|
||||
self?.navigateToMessage(from: fromId, to: .id(id))
|
||||
}, clickThroughMessage: { [weak self] in
|
||||
self?.chatDisplayNode.dismissInput()
|
||||
}, toggleMessagesSelection: { [weak self] ids, value in
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withToggledSelectedMessages(ids, value: value) } })
|
||||
guard let strongSelf = self, strongSelf.isNodeLoaded else {
|
||||
return
|
||||
}
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withToggledSelectedMessages(ids, value: value) } })
|
||||
}, sendMessage: { [weak self] text in
|
||||
if let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) {
|
||||
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) }
|
||||
})
|
||||
}
|
||||
})
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text, enabledTypes: .all)
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
strongSelf.sendMessages([.message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil)])
|
||||
guard let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) }
|
||||
})
|
||||
}
|
||||
})
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text, enabledTypes: .all)
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
strongSelf.sendMessages([.message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil)])
|
||||
}, sendSticker: { [weak self] fileReference in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
||||
@@ -849,17 +874,14 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
}
|
||||
return false
|
||||
}, navigateToFirstDateMessage: { [weak self] timestamp in
|
||||
guard let `self` = self else {return}
|
||||
switch self.chatLocation {
|
||||
case let .peer(peerId):
|
||||
self.messageIndexDisposable.set((searchMessageIdByTimestamp(account: self.account, peerId: peerId, timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT())) |> deliverOnMainQueue).start(next: { [weak self] messageId in
|
||||
guard let `self` = self else {return}
|
||||
if let messageId = messageId {
|
||||
self.navigateToMessage(from: nil, to: .id(messageId), scrollPosition: .bottom(0))
|
||||
}
|
||||
}))
|
||||
default:
|
||||
break
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
switch strongSelf.chatLocation {
|
||||
case let .peer(peerId):
|
||||
strongSelf.navigateToMessage(from: nil, to: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT()))), scrollPosition: .bottom(0.0), rememberInStack: false, animated: true, completion: nil)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}, requestMessageUpdate: { [weak self] id in
|
||||
if let strongSelf = self {
|
||||
@@ -1098,7 +1120,8 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
}
|
||||
})
|
||||
|
||||
self.videoRecorderDisposable = (self.videoRecorder.get() |> deliverOnMainQueue).start(next: { [weak self] videoRecorder in
|
||||
self.videoRecorderDisposable = (self.videoRecorder.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] videoRecorder in
|
||||
if let strongSelf = self {
|
||||
if strongSelf.videoRecorderValue !== videoRecorder {
|
||||
let previousVideoRecorderValue = strongSelf.videoRecorderValue
|
||||
@@ -1660,13 +1683,17 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
})
|
||||
}
|
||||
|
||||
self.chatDisplayNode.updateTypingActivity = { [weak self] in
|
||||
self.chatDisplayNode.updateTypingActivity = { [weak self] value in
|
||||
if let strongSelf = self, strongSelf.presentationInterfaceState.interfaceState.editMessage == nil {
|
||||
strongSelf.typingActivityPromise.set(Signal<Bool, NoError>.single(true)
|
||||
|> then(
|
||||
Signal<Bool, NoError>.single(false)
|
||||
|> delay(4.0, queue: Queue.mainQueue())
|
||||
))
|
||||
if value {
|
||||
strongSelf.typingActivityPromise.set(Signal<Bool, NoError>.single(true)
|
||||
|> then(
|
||||
Signal<Bool, NoError>.single(false)
|
||||
|> delay(4.0, queue: Queue.mainQueue())
|
||||
))
|
||||
} else {
|
||||
strongSelf.typingActivityPromise.set(.single(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1798,12 +1825,25 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
}, deleteMessages: { [weak self] messages in
|
||||
if let strongSelf = self, !messages.isEmpty {
|
||||
let messageIds = Set(messages.map { $0.id })
|
||||
strongSelf.messageContextDisposable.set((chatAvailableMessageActions(postbox: strongSelf.account.postbox, accountPeerId: strongSelf.account.peerId, messageIds: messageIds) |> deliverOnMainQueue).start(next: { actions in
|
||||
strongSelf.messageContextDisposable.set((chatAvailableMessageActions(postbox: strongSelf.account.postbox, accountPeerId: strongSelf.account.peerId, messageIds: messageIds)
|
||||
|> deliverOnMainQueue).start(next: { actions in
|
||||
if let strongSelf = self, !actions.options.isEmpty {
|
||||
if let banAuthor = actions.banAuthor {
|
||||
strongSelf.presentBanMessageOptions(author: banAuthor, messageIds: messageIds, options: actions.options)
|
||||
} else {
|
||||
strongSelf.presentDeleteMessageOptions(messageIds: messageIds, options: actions.options)
|
||||
var isAction = false
|
||||
if messages.count == 1 {
|
||||
for media in messages[0].media {
|
||||
if media is TelegramMediaAction {
|
||||
isAction = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if isAction && (actions.options == .deleteGlobally || actions.options == .deleteLocally) {
|
||||
let _ = deleteMessagesInteractively(postbox: strongSelf.account.postbox, messageIds: Array(messageIds), type: actions.options == .deleteLocally ? .forLocalPeer : .forEveryone).start()
|
||||
} else {
|
||||
strongSelf.presentDeleteMessageOptions(messageIds: messageIds, options: actions.options)
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -2081,7 +2121,8 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
} else {
|
||||
hasOngoingCall = .single(false)
|
||||
}
|
||||
let _ = (hasOngoingCall |> deliverOnMainQueue).start(next: { hasOngoingCall in
|
||||
let _ = (hasOngoingCall
|
||||
|> deliverOnMainQueue).start(next: { hasOngoingCall in
|
||||
if let strongSelf = self {
|
||||
if hasOngoingCall {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.Call_CallInProgressTitle, text: strongSelf.presentationData.strings.Call_RecordingDisabledMessage, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
@@ -3130,6 +3171,9 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
|
||||
let legacyController = LegacyController(presentation: .custom, theme: strongSelf.presentationData.theme, initialLayout: strongSelf.validLayout)
|
||||
legacyController.statusBar.statusBarStyle = .Ignore
|
||||
legacyController.controllerLoaded = { [weak legacyController] in
|
||||
legacyController?.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
}
|
||||
|
||||
let emptyController = LegacyEmptyController(context: legacyController.context)!
|
||||
let navigationController = makeLegacyNavigationController(rootController: emptyController)
|
||||
@@ -3262,37 +3306,39 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
let entry = transaction.getPreferencesEntry(key: ApplicationSpecificPreferencesKeys.generatedMediaStoreSettings) as? GeneratedMediaStoreSettings
|
||||
return entry ?? GeneratedMediaStoreSettings.defaultSettings
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] settings in
|
||||
|> deliverOnMainQueue).start(next: { [weak self] settings in
|
||||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
let _ = legacyAssetPicker(applicationContext: strongSelf.account.telegramApplicationContext, presentationData: strongSelf.presentationData, editingMedia: editingMedia, fileMode: fileMode, peer: peer, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true).start(next: { generator in
|
||||
if let strongSelf = self {
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
let _ = legacyAssetPicker(applicationContext: strongSelf.account.telegramApplicationContext, presentationData: strongSelf.presentationData, editingMedia: editingMedia, fileMode: fileMode, peer: peer, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true).start(next: { generator in
|
||||
if let strongSelf = self {
|
||||
let legacyController = LegacyController(presentation: .modal(animateIn: true), theme: strongSelf.presentationData.theme, initialLayout: strongSelf.validLayout)
|
||||
legacyController.statusBar.statusBarStyle = strongSelf.presentationData.theme.rootController.statusBar.style.style
|
||||
let controller = generator(legacyController.context)
|
||||
legacyController.bind(controller: controller)
|
||||
legacyController.deferScreenEdgeGestures = [.top]
|
||||
|
||||
configureLegacyAssetPicker(controller, account: strongSelf.account, peer: peer)
|
||||
controller.descriptionGenerator = legacyAssetPickerItemGenerator()
|
||||
controller.completionBlock = { [weak legacyController] signals in
|
||||
if let legacyController = legacyController {
|
||||
legacyController.dismiss()
|
||||
completion(signals!)
|
||||
}
|
||||
}
|
||||
controller.dismissalBlock = { [weak legacyController] in
|
||||
if let legacyController = legacyController {
|
||||
legacyController.dismiss()
|
||||
}
|
||||
}
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
strongSelf.present(legacyController, in: .window(.root))
|
||||
}
|
||||
})
|
||||
let legacyController = LegacyController(presentation: .modal(animateIn: true), theme: strongSelf.presentationData.theme, initialLayout: strongSelf.validLayout)
|
||||
legacyController.statusBar.statusBarStyle = strongSelf.presentationData.theme.rootController.statusBar.style.style
|
||||
legacyController.controllerLoaded = { [weak legacyController] in
|
||||
legacyController?.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
}
|
||||
let controller = generator(legacyController.context)
|
||||
legacyController.bind(controller: controller)
|
||||
legacyController.deferScreenEdgeGestures = [.top]
|
||||
|
||||
configureLegacyAssetPicker(controller, account: strongSelf.account, peer: peer)
|
||||
controller.descriptionGenerator = legacyAssetPickerItemGenerator()
|
||||
controller.completionBlock = { [weak legacyController] signals in
|
||||
if let legacyController = legacyController {
|
||||
legacyController.dismiss()
|
||||
completion(signals!)
|
||||
}
|
||||
}
|
||||
controller.dismissalBlock = { [weak legacyController] in
|
||||
if let legacyController = legacyController {
|
||||
legacyController.dismiss()
|
||||
}
|
||||
}
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
strongSelf.present(legacyController, in: .window(.root))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private func presentMapPicker(editingMessage: Bool) {
|
||||
@@ -3845,23 +3891,27 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
}
|
||||
let historyView = chatHistoryViewForLocation(.InitialSearch(location: searchLocation, count: 50), account: self.account, chatLocation: self.chatLocation, fixedCombinedReadStates: nil, tagMask: nil, additionalData: [])
|
||||
let signal = historyView
|
||||
|> mapToSignal { historyView -> Signal<MessageIndex?, NoError> in
|
||||
switch historyView {
|
||||
case .Loading:
|
||||
return .complete()
|
||||
case let .HistoryView(view, _, _, _, _):
|
||||
for entry in view.entries {
|
||||
if case let .MessageEntry(message, _, _, _) = entry {
|
||||
if message.id == messageLocation.messageId {
|
||||
return .single(MessageIndex(message))
|
||||
}
|
||||
|> mapToSignal { historyView -> Signal<MessageIndex?, NoError> in
|
||||
switch historyView {
|
||||
case .Loading:
|
||||
return .complete()
|
||||
case let .HistoryView(view, _, _, _, _):
|
||||
for entry in view.entries {
|
||||
if case let .MessageEntry(message, _, _, _) = entry {
|
||||
if message.id == messageLocation.messageId {
|
||||
return .single(MessageIndex(message))
|
||||
}
|
||||
}
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
if case let .index(index) = searchLocation {
|
||||
return .single(index)
|
||||
}
|
||||
return .single(nil)
|
||||
}
|
||||
|> take(1)
|
||||
self.messageIndexDisposable.set((signal |> deliverOnMainQueue).start(next: { [weak self] index in
|
||||
}
|
||||
|> take(1)
|
||||
self.messageIndexDisposable.set((signal
|
||||
|> deliverOnMainQueue).start(next: { [weak self] index in
|
||||
if let strongSelf = self, let index = index {
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated, scrollPosition: scrollPosition)
|
||||
completion?()
|
||||
@@ -4297,7 +4347,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
parsedUrlValue = parsed
|
||||
}
|
||||
|
||||
if concealed, let parsedUrlValue = parsedUrlValue, (parsedUrlValue.scheme == "http" || parsedUrlValue.scheme == "https") {
|
||||
if concealed, let parsedUrlValue = parsedUrlValue, (parsedUrlValue.scheme == "http" || parsedUrlValue.scheme == "https"), !isConcealedUrlWhitelisted(parsedUrlValue) {
|
||||
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: self.presentationData.theme), title: nil, text: self.presentationData.strings.Generic_OpenHiddenLinkAlert(url).0, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_No, action: {}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Yes, action: {
|
||||
openImpl()
|
||||
})]), in: .window(.root))
|
||||
@@ -4690,7 +4740,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
return UIDropProposal(operation: .cancel)
|
||||
}
|
||||
|
||||
let dropLocation = session.location(in: self.chatDisplayNode.view)
|
||||
//let dropLocation = session.location(in: self.chatDisplayNode.view)
|
||||
self.chatDisplayNode.updateDropInteraction(isActive: true)
|
||||
|
||||
let operation: UIDropOperation
|
||||
@@ -4700,12 +4750,15 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
|
||||
@available(iOSApplicationExtension 11.0, *)
|
||||
public func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
|
||||
session.loadObjects(ofClass: UIImage.self) { imageItems in
|
||||
session.loadObjects(ofClass: UIImage.self) { [weak self] imageItems in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let images = imageItems as! [UIImage]
|
||||
|
||||
self.chatDisplayNode.updateDropInteraction(isActive: false)
|
||||
strongSelf.chatDisplayNode.updateDropInteraction(isActive: false)
|
||||
|
||||
self.chatDisplayNode.displayPasteMenu(images)
|
||||
strongSelf.chatDisplayNode.displayPasteMenu(images)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user