mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Refactor toolbar to be a part of MessageInputPanel
This commit is contained in:
parent
7194cdc6d2
commit
9e1acf72dd
@ -19,6 +19,7 @@ public struct ChatToolbarView: View {
|
|||||||
@Binding private var showNewLine: Bool
|
@Binding private var showNewLine: Bool
|
||||||
|
|
||||||
var onClearFormatting: () -> Void
|
var onClearFormatting: () -> Void
|
||||||
|
var preferredColorScheme: ColorScheme?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
onQuote: @escaping () -> Void,
|
onQuote: @escaping () -> Void,
|
||||||
@ -32,7 +33,8 @@ public struct ChatToolbarView: View {
|
|||||||
onCode: @escaping () -> Void,
|
onCode: @escaping () -> Void,
|
||||||
onNewLine: @escaping () -> Void,
|
onNewLine: @escaping () -> Void,
|
||||||
showNewLine: Binding<Bool>,
|
showNewLine: Binding<Bool>,
|
||||||
onClearFormatting: @escaping () -> Void
|
onClearFormatting: @escaping () -> Void,
|
||||||
|
preferredColorScheme: ColorScheme? = nil
|
||||||
) {
|
) {
|
||||||
self.onQuote = onQuote
|
self.onQuote = onQuote
|
||||||
self.onSpoiler = onSpoiler
|
self.onSpoiler = onSpoiler
|
||||||
@ -46,6 +48,7 @@ public struct ChatToolbarView: View {
|
|||||||
self.onNewLine = onNewLine
|
self.onNewLine = onNewLine
|
||||||
self._showNewLine = showNewLine
|
self._showNewLine = showNewLine
|
||||||
self.onClearFormatting = onClearFormatting
|
self.onClearFormatting = onClearFormatting
|
||||||
|
self.preferredColorScheme = preferredColorScheme // TODO(swiftgram): Does not work for buttons :(
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setShowNewLine(_ value: Bool) {
|
public func setShowNewLine(_ value: Bool) {
|
||||||
@ -59,36 +62,42 @@ public struct ChatToolbarView: View {
|
|||||||
Button(action: onNewLine) {
|
Button(action: onNewLine) {
|
||||||
Image(systemName: "return")
|
Image(systemName: "return")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
}
|
}
|
||||||
Button(action: onClearFormatting) {
|
Button(action: onClearFormatting) {
|
||||||
Image(systemName: "pencil.slash")
|
Image(systemName: "pencil.slash")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
Spacer()
|
Spacer()
|
||||||
// Quote Button
|
// Quote Button
|
||||||
Button(action: onQuote) {
|
Button(action: onQuote) {
|
||||||
Image(systemName: "text.quote")
|
Image(systemName: "text.quote")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
// Spoiler Button
|
// Spoiler Button
|
||||||
Button(action: onSpoiler) {
|
Button(action: onSpoiler) {
|
||||||
Image(systemName: "eye.slash")
|
Image(systemName: "eye.slash")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
// Bold Button
|
// Bold Button
|
||||||
Button(action: onBold) {
|
Button(action: onBold) {
|
||||||
Image(systemName: "bold")
|
Image(systemName: "bold")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
// Italic Button
|
// Italic Button
|
||||||
Button(action: onItalic) {
|
Button(action: onItalic) {
|
||||||
Image(systemName: "italic")
|
Image(systemName: "italic")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
// Monospace Button
|
// Monospace Button
|
||||||
Button(action: onMonospace) {
|
Button(action: onMonospace) {
|
||||||
@ -98,43 +107,52 @@ public struct ChatToolbarView: View {
|
|||||||
Text("M")
|
Text("M")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
// Link Button
|
// Link Button
|
||||||
Button(action: onLink) {
|
Button(action: onLink) {
|
||||||
Image(systemName: "link")
|
Image(systemName: "link")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
// Underline Button
|
// Underline Button
|
||||||
Button(action: onUnderline) {
|
Button(action: onUnderline) {
|
||||||
Image(systemName: "underline")
|
Image(systemName: "underline")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
|
|
||||||
// Strikethrough Button
|
// Strikethrough Button
|
||||||
Button(action: onStrikethrough) {
|
Button(action: onStrikethrough) {
|
||||||
Image(systemName: "strikethrough")
|
Image(systemName: "strikethrough")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
|
|
||||||
|
|
||||||
// Code Button
|
// Code Button
|
||||||
Button(action: onCode) {
|
Button(action: onCode) {
|
||||||
Image(systemName: "chevron.left.forwardslash.chevron.right")
|
Image(systemName: "chevron.left.forwardslash.chevron.right")
|
||||||
}
|
}
|
||||||
.buttonStyle(ToolbarButtonStyle())
|
.buttonStyle(ToolbarButtonStyle(preferredColorScheme: preferredColorScheme))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 8)
|
.padding(.horizontal, 8)
|
||||||
.padding(.vertical, 8)
|
.padding(.vertical, 8)
|
||||||
}
|
}
|
||||||
.background(Color(UIColor.clear))
|
.background(Color(UIColor.clear))
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 13.0, *)
|
@available(iOS 13.0, *)
|
||||||
struct ToolbarButtonStyle: ButtonStyle {
|
struct ToolbarButtonStyle: ButtonStyle {
|
||||||
|
|
||||||
|
var preferredColorScheme: ColorScheme? = nil
|
||||||
|
|
||||||
func makeBody(configuration: Configuration) -> some View {
|
func makeBody(configuration: Configuration) -> some View {
|
||||||
configuration.label
|
configuration.label
|
||||||
.font(.system(size: 17))
|
.font(.system(size: 17))
|
||||||
@ -143,5 +161,6 @@ struct ToolbarButtonStyle: ButtonStyle {
|
|||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
// TODO(swiftgram): Does not work for fast taps (like mine)
|
// TODO(swiftgram): Does not work for fast taps (like mine)
|
||||||
.opacity(configuration.isPressed ? 0.4 : 1.0)
|
.opacity(configuration.isPressed ? 0.4 : 1.0)
|
||||||
|
.preferredColorScheme(preferredColorScheme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
sgDeps = [
|
|
||||||
"//Swiftgram/SGSimpleSettings:SGSimpleSettings",
|
|
||||||
"//Swiftgram/SGInputToolbar:SGInputToolbar"
|
|
||||||
]
|
|
||||||
|
|
||||||
swift_library(
|
swift_library(
|
||||||
name = "LegacyMessageInputPanel",
|
name = "LegacyMessageInputPanel",
|
||||||
@ -14,7 +10,7 @@ swift_library(
|
|||||||
copts = [
|
copts = [
|
||||||
"-warnings-as-errors",
|
"-warnings-as-errors",
|
||||||
],
|
],
|
||||||
deps = sgDeps + [
|
deps = [
|
||||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||||
"//submodules/Display",
|
"//submodules/Display",
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
// MARK: Swiftgram
|
|
||||||
import SwiftUI
|
|
||||||
import SGInputToolbar
|
|
||||||
import SGSimpleSettings
|
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
@ -43,9 +38,6 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
|
|
||||||
private let hapticFeedback = HapticFeedback()
|
private let hapticFeedback = HapticFeedback()
|
||||||
|
|
||||||
// MARK: Swiftgram
|
|
||||||
private var toolbarNode: ASDisplayNode?
|
|
||||||
|
|
||||||
private var inputView: LegacyMessageInputPanelInputView?
|
private var inputView: LegacyMessageInputPanelInputView?
|
||||||
private var isEmojiKeyboardActive = false
|
private var isEmojiKeyboardActive = false
|
||||||
|
|
||||||
@ -84,9 +76,6 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
self.update(transition: transition.containedViewLayoutTransition)
|
self.update(transition: transition.containedViewLayoutTransition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Swiftgram
|
|
||||||
self.initToolbarIfNeeded()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateLayoutSize(_ size: CGSize, keyboardHeight: CGFloat, sideInset: CGFloat, animated: Bool) -> CGFloat {
|
public func updateLayoutSize(_ size: CGSize, keyboardHeight: CGFloat, sideInset: CGFloat, animated: Bool) -> CGFloat {
|
||||||
@ -215,7 +204,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.inputPanel.parentState = self.state
|
self.inputPanel.parentState = self.state
|
||||||
var inputPanelSize = self.inputPanel.update(
|
let inputPanelSize = self.inputPanel.update(
|
||||||
transition: ComponentTransition(transition),
|
transition: ComponentTransition(transition),
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
MessageInputPanelComponent(
|
MessageInputPanelComponent(
|
||||||
@ -306,12 +295,6 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: width, height: maxInputPanelHeight)
|
containerSize: CGSize(width: width, height: maxInputPanelHeight)
|
||||||
)
|
)
|
||||||
|
|
||||||
// MARK: Swiftgram
|
|
||||||
var toolbarOffset: CGFloat = 0.0
|
|
||||||
toolbarOffset = self.layoutToolbar(transition: transition, panelHeight: inputPanelSize.height - 8.0, width: width, leftInset: leftInset, rightInset: rightInset)
|
|
||||||
inputPanelSize.height += toolbarOffset
|
|
||||||
|
|
||||||
if let view = self.inputPanel.view {
|
if let view = self.inputPanel.view {
|
||||||
if view.superview == nil {
|
if view.superview == nil {
|
||||||
self.view.addSubview(view)
|
self.view.addSubview(view)
|
||||||
@ -556,9 +539,6 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
|
|
||||||
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
let result = super.hitTest(point, with: event)
|
let result = super.hitTest(point, with: event)
|
||||||
if let toolbarNode = self.toolbarNode, let toolbarResult = toolbarNode.hitTest(self.view.convert(point, to: toolbarNode.view), with: event) {
|
|
||||||
return toolbarResult
|
|
||||||
}
|
|
||||||
if let view = self.inputPanel.view, let panelResult = view.hitTest(self.view.convert(point, to: view), with: event) {
|
if let view = self.inputPanel.view, let panelResult = view.hitTest(self.view.convert(point, to: view), with: event) {
|
||||||
return panelResult
|
return panelResult
|
||||||
}
|
}
|
||||||
@ -583,90 +563,3 @@ private final class HeaderContextReferenceContentSource: ContextReferenceContent
|
|||||||
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds, actionsPosition: self.position)
|
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds, actionsPosition: self.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension LegacyMessageInputPanelNode {
|
|
||||||
func initToolbarIfNeeded() {
|
|
||||||
guard #available(iOS 13.0, *) else { return }
|
|
||||||
guard SGSimpleSettings.shared.inputToolbar else { return }
|
|
||||||
guard SGSimpleSettings.shared.b else { return }
|
|
||||||
guard self.toolbarNode == nil else { return }
|
|
||||||
let notificationName = Notification.Name("sgToolbarAction")
|
|
||||||
let toolbarView = ChatToolbarView(
|
|
||||||
onQuote: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "quote"])
|
|
||||||
},
|
|
||||||
onSpoiler: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "spoiler"])
|
|
||||||
},
|
|
||||||
onBold: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "bold"])
|
|
||||||
},
|
|
||||||
onItalic: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "italic"])
|
|
||||||
},
|
|
||||||
onMonospace: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "monospace"])
|
|
||||||
},
|
|
||||||
onLink: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "link"])
|
|
||||||
},
|
|
||||||
onStrikethrough: { [weak self]
|
|
||||||
in guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "strikethrough"])
|
|
||||||
},
|
|
||||||
onUnderline: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "underline"])
|
|
||||||
},
|
|
||||||
onCode: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "code"])
|
|
||||||
},
|
|
||||||
onNewLine: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "newline"])
|
|
||||||
},
|
|
||||||
// TODO(swiftgram): Binding
|
|
||||||
showNewLine: .constant(true), //.constant(self.sendWithReturnKey)
|
|
||||||
onClearFormatting: { [weak self] in
|
|
||||||
guard let _ = self else { return }
|
|
||||||
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "clearFormatting"])
|
|
||||||
}
|
|
||||||
)
|
|
||||||
let toolbarHostingController = UIHostingController(rootView: toolbarView)
|
|
||||||
toolbarHostingController.view.backgroundColor = .clear
|
|
||||||
let toolbarNode = ASDisplayNode { toolbarHostingController.view }
|
|
||||||
self.toolbarNode = toolbarNode
|
|
||||||
// assigning toolbarHostingController bugs responsivness and overrides layout
|
|
||||||
// self.toolbarHostingController = toolbarHostingController
|
|
||||||
|
|
||||||
// Disable "Swipe to go back" gesture when touching scrollview
|
|
||||||
self.view.interactiveTransitionGestureRecognizerTest = { [weak self] point in
|
|
||||||
if let self, let _ = self.toolbarNode?.view.hitTest(point, with: nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
self.addSubnode(toolbarNode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func layoutToolbar(transition: ContainedViewLayoutTransition, panelHeight: CGFloat, width: CGFloat, leftInset: CGFloat, rightInset: CGFloat) -> CGFloat {
|
|
||||||
// TODO(swiftgram): Do not show if locked formatting
|
|
||||||
var toolbarHeight: CGFloat = 0.0
|
|
||||||
var toolbarSpacing: CGFloat = 0.0
|
|
||||||
if let toolbarNode = self.toolbarNode {
|
|
||||||
toolbarHeight = 44.0
|
|
||||||
toolbarSpacing = 1.0
|
|
||||||
transition.updateFrame(node: toolbarNode, frame: CGRect(origin: CGPoint(x: leftInset, y: panelHeight + toolbarSpacing), size: CGSize(width: width - rightInset - leftInset, height: toolbarHeight)))
|
|
||||||
}
|
|
||||||
return toolbarHeight + toolbarSpacing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
sgDeps = [
|
||||||
|
"//Swiftgram/SGSimpleSettings:SGSimpleSettings",
|
||||||
|
"//Swiftgram/SGInputToolbar:SGInputToolbar"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
swift_library(
|
swift_library(
|
||||||
name = "MessageInputPanelComponent",
|
name = "MessageInputPanelComponent",
|
||||||
module_name = "MessageInputPanelComponent",
|
module_name = "MessageInputPanelComponent",
|
||||||
@ -9,7 +15,7 @@ swift_library(
|
|||||||
copts = [
|
copts = [
|
||||||
"-warnings-as-errors",
|
"-warnings-as-errors",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = sgDeps + [
|
||||||
"//submodules/Display",
|
"//submodules/Display",
|
||||||
"//submodules/ComponentFlow",
|
"//submodules/ComponentFlow",
|
||||||
"//submodules/AppBundle",
|
"//submodules/AppBundle",
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
// MARK: Swiftgram
|
||||||
|
import class SwiftUI.UIHostingController
|
||||||
|
import SGSimpleSettings
|
||||||
|
import SGInputToolbar
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import Display
|
import Display
|
||||||
@ -467,6 +472,9 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
private let counter = ComponentView<Empty>()
|
private let counter = ComponentView<Empty>()
|
||||||
private var header: ComponentView<Empty>?
|
private var header: ComponentView<Empty>?
|
||||||
|
|
||||||
|
// MARK: Swiftgram
|
||||||
|
private var toolbarView: UIView?
|
||||||
|
|
||||||
private var disabledPlaceholder: ComponentView<Empty>?
|
private var disabledPlaceholder: ComponentView<Empty>?
|
||||||
private var textClippingView = UIView()
|
private var textClippingView = UIView()
|
||||||
private let textField = ComponentView<Empty>()
|
private let textField = ComponentView<Empty>()
|
||||||
@ -563,6 +571,9 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
self.state?.updated()
|
self.state?.updated()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MARK: Swiftgram
|
||||||
|
self.initToolbarIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
@ -733,6 +744,11 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
return panelResult
|
return panelResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Swiftgram
|
||||||
|
if result == nil, let toolbarView = self.toolbarView, let toolbarResult = toolbarView.hitTest(self.convert(point, to: toolbarView), with: event) {
|
||||||
|
return toolbarResult
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2253,6 +2269,9 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Swiftgram
|
||||||
|
size = self.layoutToolbar(transition: transition, layoutFromTop: layoutFromTop, size: size, availableSize: availableSize, defaultInsets: defaultInsets, textFieldSize: textFieldSize, previousComponent: previousComponent)
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2306,3 +2325,110 @@ final class ViewForOverlayContent: UIView {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension MessageInputPanelComponent.View {
|
||||||
|
func initToolbarIfNeeded() {
|
||||||
|
guard #available(iOS 13.0, *) else { return }
|
||||||
|
guard SGSimpleSettings.shared.inputToolbar else { return }
|
||||||
|
guard SGSimpleSettings.shared.b else { return }
|
||||||
|
guard self.toolbarView == nil else { return }
|
||||||
|
let notificationName = Notification.Name("sgToolbarAction")
|
||||||
|
let toolbar = ChatToolbarView(
|
||||||
|
onQuote: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "quote"])
|
||||||
|
},
|
||||||
|
onSpoiler: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "spoiler"])
|
||||||
|
},
|
||||||
|
onBold: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "bold"])
|
||||||
|
},
|
||||||
|
onItalic: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "italic"])
|
||||||
|
},
|
||||||
|
onMonospace: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "monospace"])
|
||||||
|
},
|
||||||
|
onLink: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "link"])
|
||||||
|
},
|
||||||
|
onStrikethrough: { [weak self]
|
||||||
|
in guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "strikethrough"])
|
||||||
|
},
|
||||||
|
onUnderline: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "underline"])
|
||||||
|
},
|
||||||
|
onCode: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "code"])
|
||||||
|
},
|
||||||
|
onNewLine: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "newline"])
|
||||||
|
},
|
||||||
|
// TODO(swiftgram): Binding
|
||||||
|
showNewLine: .constant(true), //.constant(self.sendWithReturnKey)
|
||||||
|
onClearFormatting: { [weak self] in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
NotificationCenter.default.post(name: notificationName, object: nil, userInfo: ["action": "clearFormatting"])
|
||||||
|
},
|
||||||
|
preferredColorScheme: .dark
|
||||||
|
)
|
||||||
|
|
||||||
|
let toolbarHostingController = UIHostingController(rootView: toolbar)
|
||||||
|
toolbarHostingController.view.backgroundColor = .clear
|
||||||
|
let toolbarView = toolbarHostingController.view
|
||||||
|
self.toolbarView = toolbarView
|
||||||
|
// assigning toolbarHostingController bugs responsivness and overrides layout
|
||||||
|
// self.toolbarHostingController = toolbarHostingController
|
||||||
|
|
||||||
|
// Disable "Swipe to go back" gesture when touching scrollview
|
||||||
|
self.interactiveTransitionGestureRecognizerTest = { [weak self] point in
|
||||||
|
if let self, let _ = self.toolbarView?.hitTest(point, with: nil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if let toolbarView = self.toolbarView {
|
||||||
|
self.addSubview(toolbarView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func layoutToolbar(transition: ComponentTransition, layoutFromTop: Bool, size: CGSize, availableSize: CGSize, defaultInsets: UIEdgeInsets, textFieldSize: CGSize, previousComponent: MessageInputPanelComponent?) -> CGSize {
|
||||||
|
// TODO(swiftgram): Do not show if locked formatting
|
||||||
|
var transition = transition
|
||||||
|
if let previousComponent = previousComponent {
|
||||||
|
let previousLayoutFromTop = previousComponent.attachmentButtonMode == .captionDown
|
||||||
|
if previousLayoutFromTop != layoutFromTop {
|
||||||
|
// attachmentButtonMode changed
|
||||||
|
transition = .immediate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var size = size
|
||||||
|
if let toolbarView = self.toolbarView {
|
||||||
|
let toolbarHeight: CGFloat = 44.0
|
||||||
|
let toolbarSpacing: CGFloat = 1.0
|
||||||
|
let toolbarSize = CGSize(width: availableSize.width, height: toolbarHeight)
|
||||||
|
let hasFirstResponder = self.hasFirstResponder()
|
||||||
|
transition.setAlpha(view: toolbarView, alpha: hasFirstResponder ? 1.0 : 0.0)
|
||||||
|
if layoutFromTop {
|
||||||
|
transition.setFrame(view: toolbarView, frame: CGRect(origin: CGPoint(x: .zero, y: availableSize.height + toolbarSpacing), size: toolbarSize))
|
||||||
|
} else {
|
||||||
|
transition.setFrame(view: toolbarView, frame: CGRect(origin: CGPoint(x: .zero, y: textFieldSize.height + defaultInsets.top + toolbarSpacing), size: toolbarSize))
|
||||||
|
if hasFirstResponder {
|
||||||
|
size.height += toolbarHeight + toolbarSpacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user