Swiftgram/submodules/TelegramUI/Sources/ChatControllerKeyShortcuts.swift
2024-01-10 00:45:01 +04:00

283 lines
16 KiB
Swift

import Foundation
import TelegramPresentationData
import AccountContext
import Postbox
import ChatInterfaceState
import TelegramCore
import SwiftSignalKit
import TextFormat
import UndoUI
import PresentationDataUtils
import UIKit
import Display
import ChatPresentationInterfaceState
import ChatControllerInteraction
extension ChatControllerImpl {
var keyShortcutsInternal: [KeyShortcut] {
if !self.traceVisibility() || !isTopmostChatController(self) {
return []
}
let strings = self.presentationData.strings
var inputShortcuts: [KeyShortcut]
if self.chatDisplayNode.isInputViewFocused {
inputShortcuts = [
KeyShortcut(title: strings.KeyCommand_SendMessage, input: "\r", action: {}),
KeyShortcut(input: "B", modifiers: [.command], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.bold, value: nil), inputMode)
}
}
}),
KeyShortcut(input: "I", modifiers: [.command], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.italic, value: nil), inputMode)
}
}
}),
KeyShortcut(input: "M", modifiers: [.shift, .command], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.monospace, value: nil), inputMode)
}
}
}),
KeyShortcut(input: "U", modifiers: [.command], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.underline, value: nil), inputMode)
}
}
}),
KeyShortcut(input: "X", modifiers: [.command, .shift], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.strikethrough, value: nil), inputMode)
}
}
}),
KeyShortcut(input: "P", modifiers: [.command, .shift], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.spoiler, value: nil), inputMode)
}
}
}),
KeyShortcut(input: "K", modifiers: [.command], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.openLinkEditing()
}
}),
KeyShortcut(input: "N", modifiers: [.shift, .command], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputClearFormattingAttributes(current), inputMode)
}
}
})
]
} else if UIResponder.currentFirst() == nil {
inputShortcuts = [
KeyShortcut(title: strings.KeyCommand_FocusOnInputField, input: "\r", action: { [weak self] in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
return state.updatedInterfaceState { interfaceState in
return interfaceState.withUpdatedEffectiveInputState(interfaceState.effectiveInputState)
}.updatedInputMode({ _ in .text })
})
}
}),
KeyShortcut(input: "/", modifiers: [], action: { [weak self] in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
if state.interfaceState.effectiveInputState.inputText.length == 0 {
return state.updatedInterfaceState { interfaceState in
let effectiveInputState = ChatTextInputState(inputText: NSAttributedString(string: "/"))
return interfaceState.withUpdatedEffectiveInputState(effectiveInputState)
}.updatedInputMode({ _ in .text })
} else {
return state
}
})
}
}),
KeyShortcut(input: "2", modifiers: [.shift], action: { [weak self] in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
if state.interfaceState.effectiveInputState.inputText.length == 0 {
return state.updatedInterfaceState { interfaceState in
let effectiveInputState = ChatTextInputState(inputText: NSAttributedString(string: "@"))
return interfaceState.withUpdatedEffectiveInputState(effectiveInputState)
}.updatedInputMode({ _ in .text })
} else {
return state
}
})
}
}),
KeyShortcut(input: "3", modifiers: [.shift], action: { [weak self] in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
if state.interfaceState.effectiveInputState.inputText.length == 0 {
return state.updatedInterfaceState { interfaceState in
let effectiveInputState = ChatTextInputState(inputText: NSAttributedString(string: "#"))
return interfaceState.withUpdatedEffectiveInputState(effectiveInputState)
}.updatedInputMode({ _ in .text })
} else {
return state
}
})
}
})
]
} else {
inputShortcuts = []
}
inputShortcuts.append(
KeyShortcut(
input: "W",
modifiers: [.command],
action: { [weak self] in
self?.dismiss(animated: true, completion: nil)
}
)
)
if canReplyInChat(self.presentationInterfaceState, accountPeerId: self.context.account.peerId) {
inputShortcuts.append(
KeyShortcut(
input: UIKeyCommand.inputUpArrow,
modifiers: [.alternate, .command],
action: { [weak self] in
guard let strongSelf = self else {
return
}
if let replyMessageSubject = strongSelf.presentationInterfaceState.interfaceState.replyMessageSubject {
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(before: replyMessageSubject.messageId) {
strongSelf.updateChatPresentationInterfaceState(interactive: true, { state in
var updatedState = state.updatedInterfaceState({ state in
return state.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(
messageId: message.id,
quote: nil
))
})
if updatedState.inputMode == .none {
updatedState = updatedState.updatedInputMode({ _ in .text })
}
return updatedState
})
strongSelf.navigateToMessage(messageLocation: .id(message.id, NavigateToMessageParams(timestamp: nil, quote: nil)), animated: true)
}
} else {
strongSelf.scrollToEndOfHistory()
Queue.mainQueue().after(0.1, {
let lastMessage = strongSelf.chatDisplayNode.historyNode.latestMessageInCurrentHistoryView()
strongSelf.updateChatPresentationInterfaceState(interactive: true, { state in
var updatedState = state.updatedInterfaceState({ state in
return state.withUpdatedReplyMessageSubject((lastMessage?.id).flatMap { id in
return ChatInterfaceState.ReplyMessageSubject(
messageId: id,
quote: nil
)
})
})
if updatedState.inputMode == .none {
updatedState = updatedState.updatedInputMode({ _ in .text })
}
return updatedState
})
if let lastMessage = lastMessage {
strongSelf.navigateToMessage(messageLocation: .id(lastMessage.id, NavigateToMessageParams(timestamp: nil, quote: nil)), animated: true)
}
})
}
}
)
)
inputShortcuts.append(
KeyShortcut(
input: UIKeyCommand.inputDownArrow,
modifiers: [.alternate, .command],
action: { [weak self] in
guard let strongSelf = self else {
return
}
if let replyMessageSubject = strongSelf.presentationInterfaceState.interfaceState.replyMessageSubject {
let lastMessage = strongSelf.chatDisplayNode.historyNode.latestMessageInCurrentHistoryView()
var updatedReplyMessageSubject: ChatInterfaceState.ReplyMessageSubject?
if replyMessageSubject.messageId == lastMessage?.id {
updatedReplyMessageSubject = nil
} else if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(after: replyMessageSubject.messageId) {
updatedReplyMessageSubject = ChatInterfaceState.ReplyMessageSubject(messageId: message.id, quote: nil)
}
strongSelf.updateChatPresentationInterfaceState(interactive: true, { state in
var updatedState = state.updatedInterfaceState({ state in
return state.withUpdatedReplyMessageSubject(updatedReplyMessageSubject)
})
if updatedState.inputMode == .none {
updatedState = updatedState.updatedInputMode({ _ in .text })
} else if updatedReplyMessageSubject == nil {
updatedState = updatedState.updatedInputMode({ _ in .none })
}
return updatedState
})
if let updatedReplyMessageSubject {
strongSelf.navigateToMessage(messageLocation: .id(updatedReplyMessageSubject.messageId, NavigateToMessageParams(timestamp: nil, quote: nil)), animated: true)
}
}
}
)
)
}
var canEdit = false
if self.presentationInterfaceState.interfaceState.effectiveInputState.inputText.length == 0 && self.presentationInterfaceState.interfaceState.editMessage == nil {
canEdit = true
}
if canEdit, let message = self.chatDisplayNode.historyNode.firstMessageForEditInCurrentHistoryView() {
inputShortcuts.append(KeyShortcut(input: UIKeyCommand.inputUpArrow, action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.setupEditMessage(message.id, { _ in })
}
}))
}
let otherShortcuts: [KeyShortcut] = [
KeyShortcut(title: strings.KeyCommand_ChatInfo, input: "I", modifiers: [.command, .control], action: { [weak self] in
if let strongSelf = self {
strongSelf.interfaceInteraction?.openPeerInfo()
}
}),
KeyShortcut(input: "/", modifiers: [.command], action: { [weak self] in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
return state.updatedInterfaceState { interfaceState in
return interfaceState.withUpdatedEffectiveInputState(interfaceState.effectiveInputState)
}.updatedInputMode({ _ in ChatInputMode.media(mode: .other, expanded: nil, focused: false) })
})
}
}),
KeyShortcut(title: strings.KeyCommand_SearchInChat, input: "F", modifiers: [.command], action: { [weak self] in
if let strongSelf = self {
strongSelf.beginMessageSearch("")
}
})
]
return inputShortcuts + otherShortcuts
}
}