mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
bbb543f836
commit
34bd339d8c
@ -1473,7 +1473,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
return ASEditableTextNodeTargetForAction(target: nil)
|
||||
}
|
||||
}
|
||||
} else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) || action == #selector(self.formatAttributesStrikethrough(_:)) || action == #selector(self.formatAttributesUnderline(_:)) || action == #selector(self.formatAttributesSpoiler(_:)) {
|
||||
} else if action == #selector(self.formatAttributesBold(_:)) || action == #selector(self.formatAttributesItalic(_:)) || action == #selector(self.formatAttributesMonospace(_:)) || action == #selector(self.formatAttributesLink(_:)) || action == #selector(self.formatAttributesStrikethrough(_:)) || action == #selector(self.formatAttributesUnderline(_:)) || action == #selector(self.formatAttributesSpoiler(_:)) || action == #selector(self.formatAttributesQuote(_:)) {
|
||||
if case .format = self.inputMenu.state {
|
||||
return ASEditableTextNodeTargetForAction(target: self)
|
||||
} else {
|
||||
@ -1646,6 +1646,14 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
self.updateSpoilersRevealed(animated: animated)
|
||||
}
|
||||
|
||||
@objc func formatAttributesQuote(_ sender: Any) {
|
||||
self.inputMenu.back()
|
||||
|
||||
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
|
||||
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.quote), inputMode)
|
||||
}
|
||||
}
|
||||
|
||||
public func chatInputTextNode(shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
guard let editableTextNode = self.textInputNode else {
|
||||
return true
|
||||
@ -1728,6 +1736,10 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
return true
|
||||
}
|
||||
|
||||
public func chatInputTextNodeTargetForAction(action: Selector) -> ChatInputTextNode.TargetForAction? {
|
||||
return nil
|
||||
}
|
||||
|
||||
@objc public func editableTextNodeShouldPaste(_ editableTextNode: ASEditableTextNode) -> Bool {
|
||||
return self.chatInputTextNodeShouldPaste()
|
||||
}
|
||||
|
@ -554,6 +554,13 @@ public class CreatePollTextInputItemNode: ListViewItemNode, ASEditableTextNodeDe
|
||||
}
|
||||
}
|
||||
|
||||
@objc func formatAttributesQuote(_ sender: Any) {
|
||||
self.inputMenu.back()
|
||||
if let item = self.item {
|
||||
chatTextInputAddFormattingAttribute(item: item, textNode: self.textNode, theme: item.presentationData.theme, attribute: ChatTextInputAttributes.quote)
|
||||
}
|
||||
}
|
||||
|
||||
public func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
if let item = self.item {
|
||||
if text.count > 1, let processPaste = item.processPaste {
|
||||
|
@ -947,7 +947,11 @@ public final class TextNodeLayout: NSObject {
|
||||
rects.append((lineFrame, CGRect(origin: CGPoint(x: lineFrame.minX + min(leftOffset, rightOffset) + self.insets.left, y: lineFrame.minY + self.insets.top), size: CGSize(width: width, height: lineFrame.size.height))))
|
||||
}
|
||||
}
|
||||
if !rects.isEmpty, let startEdge = startEdge, let endEdge = endEdge {
|
||||
if !rects.isEmpty, var startEdge = startEdge, var endEdge = endEdge {
|
||||
startEdge.x += self.insets.left
|
||||
startEdge.y += self.insets.top
|
||||
endEdge.x += self.insets.left
|
||||
endEdge.y += self.insets.top
|
||||
return (rects.map { $1 }, startEdge, endEdge)
|
||||
}
|
||||
return nil
|
||||
|
@ -17,6 +17,7 @@
|
||||
@property (nonatomic, copy) bool (^ _Nullable shouldCopy)();
|
||||
@property (nonatomic, copy) bool (^ _Nullable shouldPaste)();
|
||||
@property (nonatomic, copy) bool (^ _Nullable shouldRespondToAction)(SEL _Nullable);
|
||||
@property (nonatomic, copy) ChatInputTextViewImplTargetForAction * _Nullable (^ _Nullable targetForAction)(SEL _Nullable);
|
||||
@property (nonatomic, copy) bool (^ _Nullable shouldReturn)();
|
||||
@property (nonatomic, copy) void (^ _Nullable backspaceWhileEmpty)();
|
||||
@property (nonatomic, copy) void (^ _Nullable dropAutocorrectioniOS16)();
|
||||
|
@ -68,6 +68,13 @@
|
||||
|
||||
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
||||
{
|
||||
if (_targetForAction) {
|
||||
ChatInputTextViewImplTargetForAction *result = _targetForAction(action);
|
||||
if (result) {
|
||||
return result.target != nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (_shouldRespondToAction) {
|
||||
if (!_shouldRespondToAction(action)) {
|
||||
return false;
|
||||
@ -102,6 +109,13 @@
|
||||
}
|
||||
|
||||
- (id)targetForAction:(SEL)action withSender:(id)__unused sender {
|
||||
if (_targetForAction) {
|
||||
ChatInputTextViewImplTargetForAction *result = _targetForAction(action);
|
||||
if (result) {
|
||||
return result.target;
|
||||
}
|
||||
}
|
||||
|
||||
return [super targetForAction:action withSender:sender];
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,18 @@ public protocol ChatInputTextNodeDelegate: AnyObject {
|
||||
func chatInputTextNodeShouldPaste() -> Bool
|
||||
|
||||
func chatInputTextNodeShouldRespondToAction(action: Selector) -> Bool
|
||||
func chatInputTextNodeTargetForAction(action: Selector) -> ChatInputTextNode.TargetForAction?
|
||||
}
|
||||
|
||||
open class ChatInputTextNode: ASDisplayNode, UITextViewDelegate {
|
||||
public final class TargetForAction {
|
||||
public let target: Any?
|
||||
|
||||
public init(target: Any?) {
|
||||
self.target = target
|
||||
}
|
||||
}
|
||||
|
||||
public weak var delegate: ChatInputTextNodeDelegate? {
|
||||
didSet {
|
||||
self.textView.customDelegate = self.delegate
|
||||
@ -124,6 +133,18 @@ open class ChatInputTextNode: ASDisplayNode, UITextViewDelegate {
|
||||
return true
|
||||
}
|
||||
}
|
||||
self.textView.targetForAction = { [weak self] action in
|
||||
guard let self, let action else {
|
||||
return nil
|
||||
}
|
||||
if let delegate = self.delegate {
|
||||
return delegate.chatInputTextNodeTargetForAction(action: action).flatMap { value in
|
||||
return ChatInputTextViewImplTargetForAction(target: value.target)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func resetInitialPrimaryLanguage() {
|
||||
|
@ -267,6 +267,31 @@ public class ShareRootControllerImpl {
|
||||
let accountManager = AccountManager<TelegramAccountManagerTypes>(basePath: rootPath + "/accounts-metadata", isTemporary: true, isReadOnly: false, useCaches: false, removeDatabaseOnError: false)
|
||||
initializeAccountManagement()
|
||||
|
||||
do {
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
var loggingSettings = LoggingSettings.defaultSettings
|
||||
if self.initializationData.appBuildType == .internal {
|
||||
loggingSettings = LoggingSettings(logToFile: true, logToConsole: false, redactSensitiveData: true)
|
||||
}
|
||||
let _ = (accountManager.transaction { transaction -> LoggingSettings? in
|
||||
if let value = transaction.getSharedData(SharedDataKeys.loggingSettings)?.get(LoggingSettings.self) {
|
||||
return value
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}).start(next: { value in
|
||||
if let value {
|
||||
loggingSettings = value
|
||||
}
|
||||
semaphore.signal()
|
||||
})
|
||||
semaphore.wait()
|
||||
|
||||
Logger.shared.logToFile = loggingSettings.logToFile
|
||||
Logger.shared.logToConsole = loggingSettings.logToConsole
|
||||
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
|
||||
}
|
||||
|
||||
var initialPresentationDataAndSettings: InitialPresentationDataAndSettings?
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
let systemUserInterfaceStyle: WindowUserInterfaceStyle
|
||||
@ -306,7 +331,6 @@ public class ShareRootControllerImpl {
|
||||
|> mapToSignal { sharedContext, loggingSettings -> Signal<(SharedAccountContextImpl, Account, [AccountWithInfo]), ShareAuthorizationError> in
|
||||
Logger.shared.logToFile = loggingSettings.logToFile
|
||||
Logger.shared.logToConsole = loggingSettings.logToConsole
|
||||
|
||||
Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData
|
||||
|
||||
return combineLatest(sharedContext.activeAccountsWithInfo, accountManager.transaction { transaction -> (Set<AccountRecordId>, PeerId?) in
|
||||
|
@ -772,10 +772,12 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
self.textInputViewInternalInsets = UIEdgeInsets(top: 1.0, left: 13.0, bottom: 1.0, right: 13.0)
|
||||
|
||||
var hasSpoilers = true
|
||||
var hasQuotes = true
|
||||
if presentationInterfaceState.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat {
|
||||
hasSpoilers = false
|
||||
hasQuotes = false
|
||||
}
|
||||
self.inputMenu = TextInputMenu(hasSpoilers: hasSpoilers)
|
||||
self.inputMenu = TextInputMenu(hasSpoilers: hasSpoilers, hasQuotes: hasQuotes)
|
||||
|
||||
self.clippingNode = ASDisplayNode()
|
||||
self.clippingNode.clipsToBounds = true
|
||||
@ -3954,18 +3956,17 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
||||
}
|
||||
|
||||
public func chatInputTextNodeShouldRespondToAction(action: Selector) -> Bool {
|
||||
guard let textInputNode = self.textInputNode else {
|
||||
return true
|
||||
}
|
||||
let _ = textInputNode
|
||||
|
||||
/*if textInputNode.attributedText == nil || textInputNode.attributedText!.length == 0 || textInputNode.selectedRange.length == 0 {
|
||||
print("action: \(action)")
|
||||
}*/
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public func chatInputTextNodeTargetForAction(action: Selector) -> ChatInputTextNode.TargetForAction? {
|
||||
if let target = self.editableTextNodeTarget(forAction: action) {
|
||||
return ChatInputTextNode.TargetForAction(target: target.target)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func chatInputTextNodeShouldPaste() -> Bool {
|
||||
let pasteboard = UIPasteboard.general
|
||||
|
||||
|
@ -16,8 +16,10 @@ public final class TextInputMenu {
|
||||
private var stringStrikethrough: String = "Strikethrough"
|
||||
private var stringUnderline: String = "Underline"
|
||||
private var stringSpoiler: String = "Spoiler"
|
||||
private var stringQuote: String = "Quote"
|
||||
|
||||
private let hasSpoilers: Bool
|
||||
private let hasQuotes: Bool
|
||||
|
||||
public private(set) var state: State = .inactive {
|
||||
didSet {
|
||||
@ -39,6 +41,9 @@ public final class TextInputMenu {
|
||||
if self.hasSpoilers {
|
||||
menuItems.insert(UIMenuItem(title: self.stringSpoiler, action: Selector(("formatAttributesSpoiler:"))), at: 0)
|
||||
}
|
||||
if self.hasQuotes {
|
||||
menuItems.insert(UIMenuItem(title: self.stringQuote, action: Selector(("formatAttributesQuote:"))), at: 0)
|
||||
}
|
||||
UIMenuController.shared.menuItems = menuItems
|
||||
}
|
||||
|
||||
@ -48,8 +53,9 @@ public final class TextInputMenu {
|
||||
|
||||
private var observer: NSObjectProtocol?
|
||||
|
||||
public init(hasSpoilers: Bool = false) {
|
||||
public init(hasSpoilers: Bool = false, hasQuotes: Bool = false) {
|
||||
self.hasSpoilers = hasSpoilers
|
||||
self.hasQuotes = hasQuotes
|
||||
self.observer = NotificationCenter.default.addObserver(forName: UIMenuController.didHideMenuNotification, object: nil, queue: nil, using: { [weak self] _ in
|
||||
self?.back()
|
||||
})
|
||||
@ -69,6 +75,7 @@ public final class TextInputMenu {
|
||||
self.stringStrikethrough = strings.TextFormat_Strikethrough
|
||||
self.stringUnderline = strings.TextFormat_Underline
|
||||
self.stringSpoiler = strings.TextFormat_Spoiler
|
||||
self.stringQuote = strings.TextFormat_Quote
|
||||
}
|
||||
|
||||
public func activate() {
|
||||
|
@ -589,7 +589,7 @@ public final class TextSelectionNode: ASDisplayNode {
|
||||
highlightOverlay.innerRadius = 2.0
|
||||
highlightOverlay.outerRadius = 2.0
|
||||
highlightOverlay.inset = 1.0
|
||||
highlightOverlay.useModernPathCalculation = true
|
||||
highlightOverlay.useModernPathCalculation = false
|
||||
|
||||
self.highlightOverlay = highlightOverlay
|
||||
self.highlightAreaNode.addSubnode(highlightOverlay)
|
||||
@ -597,8 +597,8 @@ public final class TextSelectionNode: ASDisplayNode {
|
||||
highlightOverlay.frame = self.bounds
|
||||
highlightOverlay.updateRects(rects)
|
||||
if let image = self.leftKnob.image {
|
||||
self.leftKnob.frame = CGRect(origin: CGPoint(x: floor(startEdge.x - image.size.width / 2.0), y: startEdge.y + 1.0 - 12.0), size: CGSize(width: image.size.width, height: self.theme.knobDiameter + startEdge.height + 2.0))
|
||||
self.rightKnob.frame = CGRect(origin: CGPoint(x: floor(endEdge.x + 1.0 - image.size.width / 2.0), y: endEdge.y + endEdge.height + 3.0 - (endEdge.height + 2.0)), size: CGSize(width: image.size.width, height: self.theme.knobDiameter + endEdge.height + 2.0))
|
||||
self.leftKnob.frame = CGRect(origin: CGPoint(x: floor(startEdge.x - image.size.width / 2.0), y: startEdge.y - self.theme.knobDiameter), size: CGSize(width: image.size.width, height: self.theme.knobDiameter + startEdge.height))
|
||||
self.rightKnob.frame = CGRect(origin: CGPoint(x: floor(endEdge.x - image.size.width / 2.0), y: endEdge.y), size: CGSize(width: image.size.width, height: self.theme.knobDiameter + endEdge.height))
|
||||
}
|
||||
if self.leftKnob.alpha.isZero {
|
||||
highlightOverlay.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
|
||||
|
Loading…
x
Reference in New Issue
Block a user