mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2025-01-08 23:35:25 +00:00
Composer: Rework TextView for faster / smoother editing
This commit is contained in:
parent
3b5f2e823a
commit
0496727b6f
6 changed files with 21 additions and 193 deletions
|
@ -40,7 +40,6 @@ public struct StatusEditorView: View {
|
|||
viewModel.textView = textView
|
||||
})
|
||||
.placeholder(String(localized: "status.editor.text.placeholder"))
|
||||
.font(Font.scaledBodyUIFont)
|
||||
.setKeyboardType(preferences.isSocialKeyboardEnabled ? .twitter : .default)
|
||||
.padding(.horizontal, .layoutPadding)
|
||||
StatusEditorMediaView(viewModel: viewModel)
|
||||
|
|
|
@ -45,6 +45,7 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
|
|||
didSet {
|
||||
processText()
|
||||
checkEmbed()
|
||||
textView?.attributedText = statusText
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,8 +281,9 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
|
|||
private func processText() {
|
||||
guard markedTextRange == nil else { return }
|
||||
statusText.addAttributes([.foregroundColor: UIColor(Color.label),
|
||||
.backgroundColor: .clear,
|
||||
.underlineColor: .clear],
|
||||
.font: Font.scaledBodyUIFont,
|
||||
.backgroundColor: UIColor.clear,
|
||||
.underlineColor: UIColor.clear],
|
||||
range: NSMakeRange(0, statusText.string.utf16.count))
|
||||
let hashtagPattern = "(#+[a-zA-Z0-9(_)]{1,})"
|
||||
let mentionPattern = "(@+[a-zA-Z0-9(_).-]{1,})"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import SwiftUI
|
||||
import DesignSystem
|
||||
|
||||
extension TextView.Representable {
|
||||
final class Coordinator: NSObject, UITextViewDelegate {
|
||||
|
@ -10,7 +11,7 @@ extension TextView.Representable {
|
|||
private var calculatedHeight: Binding<CGFloat>
|
||||
|
||||
var didBecomeFirstResponder = false
|
||||
|
||||
|
||||
var getTextView: ((UITextView) -> Void)?
|
||||
|
||||
init(text: Binding<NSMutableAttributedString>,
|
||||
|
@ -29,8 +30,20 @@ extension TextView.Representable {
|
|||
self.getTextView = getTextView
|
||||
|
||||
super.init()
|
||||
|
||||
textView.delegate = self
|
||||
|
||||
textView.font = Font.scaledBodyUIFont
|
||||
textView.adjustsFontForContentSizeCategory = true
|
||||
textView.autocapitalizationType = .sentences
|
||||
textView.autocorrectionType = .yes
|
||||
textView.isEditable = true
|
||||
textView.isSelectable = true
|
||||
textView.dataDetectorTypes = []
|
||||
textView.allowsEditingTextAttributes = false
|
||||
textView.returnKeyType = .default
|
||||
textView.allowsEditingTextAttributes = true
|
||||
|
||||
self.getTextView?(textView)
|
||||
}
|
||||
|
||||
|
@ -58,38 +71,7 @@ extension TextView.Representable {
|
|||
extension TextView.Representable.Coordinator {
|
||||
|
||||
func update(representable: TextView.Representable) {
|
||||
textView.attributedText = representable.text
|
||||
textView.font = representable.font
|
||||
textView.adjustsFontForContentSizeCategory = true
|
||||
textView.autocapitalizationType = representable.autocapitalization
|
||||
textView.autocorrectionType = representable.autocorrection
|
||||
textView.isEditable = representable.isEditable
|
||||
textView.isSelectable = representable.isSelectable
|
||||
textView.dataDetectorTypes = representable.autoDetectionTypes
|
||||
textView.allowsEditingTextAttributes = representable.allowsRichText
|
||||
textView.keyboardType = representable.keyboard
|
||||
|
||||
switch representable.multilineTextAlignment {
|
||||
case .leading:
|
||||
textView.textAlignment = textView.traitCollection.layoutDirection ~= .leftToRight ? .left : .right
|
||||
case .trailing:
|
||||
textView.textAlignment = textView.traitCollection.layoutDirection ~= .leftToRight ? .right : .left
|
||||
case .center:
|
||||
textView.textAlignment = .center
|
||||
}
|
||||
|
||||
if let value = representable.enablesReturnKeyAutomatically {
|
||||
textView.enablesReturnKeyAutomatically = value
|
||||
} else {
|
||||
textView.enablesReturnKeyAutomatically = false
|
||||
}
|
||||
|
||||
if let returnKeyType = representable.returnKeyType {
|
||||
textView.returnKeyType = returnKeyType
|
||||
} else {
|
||||
textView.returnKeyType = .default
|
||||
}
|
||||
|
||||
recalculateHeight()
|
||||
textView.setNeedsDisplay()
|
||||
}
|
||||
|
|
|
@ -2,14 +2,6 @@ import SwiftUI
|
|||
|
||||
public extension TextView {
|
||||
|
||||
/// Specifies whether or not this view allows rich text
|
||||
/// - Parameter enabled: If `true`, rich text editing controls will be enabled for the user
|
||||
func allowsRichText(_ enabled: Bool) -> TextView {
|
||||
var view = self
|
||||
view.allowRichText = enabled
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specify a placeholder text
|
||||
/// - Parameter placeholder: The placeholder text
|
||||
func placeholder(_ placeholder: String) -> TextView {
|
||||
|
@ -38,116 +30,10 @@ public extension TextView {
|
|||
return view
|
||||
}
|
||||
|
||||
/// Enables auto detection for the specified types
|
||||
/// - Parameter types: The types to detect
|
||||
func autoDetectDataTypes(_ types: UIDataDetectorTypes) -> TextView {
|
||||
var view = self
|
||||
view.autoDetectionTypes = types
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specify the foreground color for the text
|
||||
/// - Parameter color: The foreground color
|
||||
func foregroundColor(_ color: UIColor) -> TextView {
|
||||
var view = self
|
||||
view.foregroundColor = color
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies the capitalization style to apply to the text
|
||||
/// - Parameter style: The capitalization style
|
||||
func autocapitalization(_ style: UITextAutocapitalizationType) -> TextView {
|
||||
var view = self
|
||||
view.autocapitalization = style
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies the alignment of multi-line text
|
||||
/// - Parameter alignment: The text alignment
|
||||
func multilineTextAlignment(_ alignment: TextAlignment) -> TextView {
|
||||
var view = self
|
||||
view.multilineTextAlignment = alignment
|
||||
return view
|
||||
}
|
||||
|
||||
func setKeyboardType(_ keyboardType: UIKeyboardType) -> TextView {
|
||||
var view = self
|
||||
view.keyboard = keyboardType
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies the font to apply to the text
|
||||
/// - Parameter font: The font to apply
|
||||
func font(_ font: UIFont) -> TextView {
|
||||
var view = self
|
||||
view.font = font
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies if the field should clear its content when editing begins
|
||||
/// - Parameter value: If true, the field will be cleared when it receives focus
|
||||
func clearOnInsertion(_ value: Bool) -> TextView {
|
||||
var view = self
|
||||
view.clearsOnInsertion = value
|
||||
return view
|
||||
}
|
||||
|
||||
/// Disables auto-correct
|
||||
/// - Parameter disable: If true, autocorrection will be disabled
|
||||
func disableAutocorrection(_ disable: Bool?) -> TextView {
|
||||
var view = self
|
||||
if let disable = disable {
|
||||
view.autocorrection = disable ? .no : .yes
|
||||
} else {
|
||||
view.autocorrection = .default
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies whether the text can be edited
|
||||
/// - Parameter isEditable: If true, the text can be edited via the user's keyboard
|
||||
func isEditable(_ isEditable: Bool) -> TextView {
|
||||
var view = self
|
||||
view.isEditable = isEditable
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies whether the text can be selected
|
||||
/// - Parameter isSelectable: If true, the text can be selected
|
||||
func isSelectable(_ isSelectable: Bool) -> TextView {
|
||||
var view = self
|
||||
view.isSelectable = isSelectable
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies the type of return key to be shown during editing, for the device keyboard
|
||||
/// - Parameter style: The return key style
|
||||
func returnKey(_ style: UIReturnKeyType?) -> TextView {
|
||||
var view = self
|
||||
view.returnKeyType = style
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies whether the return key should auto enable/disable based on the current text
|
||||
/// - Parameter value: If true, when the text is empty the return key will be disabled
|
||||
func automaticallyEnablesReturn(_ value: Bool?) -> TextView {
|
||||
var view = self
|
||||
view.enablesReturnKeyAutomatically = value
|
||||
return view
|
||||
}
|
||||
|
||||
/// Specifies the truncation mode for this field
|
||||
/// - Parameter mode: The truncation mode
|
||||
func truncationMode(_ mode: Text.TruncationMode) -> TextView {
|
||||
var view = self
|
||||
switch mode {
|
||||
case .head: view.truncationMode = .byTruncatingHead
|
||||
case .tail: view.truncationMode = .byTruncatingTail
|
||||
case .middle: view.truncationMode = .byTruncatingMiddle
|
||||
@unknown default:
|
||||
fatalError("Unknown text truncation mode")
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,21 +6,7 @@ extension TextView {
|
|||
@Binding var text: NSMutableAttributedString
|
||||
@Binding var calculatedHeight: CGFloat
|
||||
|
||||
let foregroundColor: UIColor
|
||||
let autocapitalization: UITextAutocapitalizationType
|
||||
var multilineTextAlignment: TextAlignment
|
||||
let font: UIFont
|
||||
let returnKeyType: UIReturnKeyType?
|
||||
let clearsOnInsertion: Bool
|
||||
let autocorrection: UITextAutocorrectionType
|
||||
let truncationMode: NSLineBreakMode
|
||||
let isEditable: Bool
|
||||
let keyboard: UIKeyboardType
|
||||
let isSelectable: Bool
|
||||
let enablesReturnKeyAutomatically: Bool?
|
||||
var autoDetectionTypes: UIDataDetectorTypes = []
|
||||
var allowsRichText: Bool
|
||||
|
||||
var getTextView: ((UITextView) -> Void)?
|
||||
|
||||
func makeUIView(context: Context) -> UIKitTextView {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import SwiftUI
|
||||
import DesignSystem
|
||||
|
||||
/// A SwiftUI TextView implementation that supports both scrolling and auto-sizing layouts
|
||||
public struct TextView: View {
|
||||
|
@ -13,20 +14,7 @@ public struct TextView: View {
|
|||
private var getTextView: ((UITextView) -> Void)?
|
||||
|
||||
var placeholderView: AnyView?
|
||||
var foregroundColor: UIColor = .label
|
||||
var autocapitalization: UITextAutocapitalizationType = .sentences
|
||||
var multilineTextAlignment: TextAlignment = .leading
|
||||
var font: UIFont = .preferredFont(forTextStyle: .body)
|
||||
var returnKeyType: UIReturnKeyType?
|
||||
var clearsOnInsertion: Bool = false
|
||||
var autocorrection: UITextAutocorrectionType = .default
|
||||
var truncationMode: NSLineBreakMode = .byTruncatingTail
|
||||
var keyboard: UIKeyboardType = .default
|
||||
var isEditable: Bool = true
|
||||
var isSelectable: Bool = true
|
||||
var enablesReturnKeyAutomatically: Bool?
|
||||
var autoDetectionTypes: UIDataDetectorTypes = []
|
||||
var allowRichText: Bool
|
||||
|
||||
/// Makes a new TextView that supports `NSAttributedString`
|
||||
/// - Parameters:
|
||||
|
@ -41,28 +29,13 @@ public struct TextView: View {
|
|||
)
|
||||
|
||||
self.getTextView = getTextView
|
||||
|
||||
allowRichText = true
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
Representable(
|
||||
text: $text,
|
||||
calculatedHeight: $calculatedHeight,
|
||||
foregroundColor: foregroundColor,
|
||||
autocapitalization: autocapitalization,
|
||||
multilineTextAlignment: multilineTextAlignment,
|
||||
font: font,
|
||||
returnKeyType: returnKeyType,
|
||||
clearsOnInsertion: clearsOnInsertion,
|
||||
autocorrection: autocorrection,
|
||||
truncationMode: truncationMode,
|
||||
isEditable: isEditable,
|
||||
keyboard: keyboard,
|
||||
isSelectable: isSelectable,
|
||||
enablesReturnKeyAutomatically: enablesReturnKeyAutomatically,
|
||||
autoDetectionTypes: autoDetectionTypes,
|
||||
allowsRichText: allowRichText,
|
||||
getTextView: getTextView
|
||||
)
|
||||
.frame(
|
||||
|
@ -72,8 +45,8 @@ public struct TextView: View {
|
|||
.background(
|
||||
placeholderView?
|
||||
.foregroundColor(Color(.placeholderText))
|
||||
.multilineTextAlignment(multilineTextAlignment)
|
||||
.font(Font(font))
|
||||
.multilineTextAlignment(.leading)
|
||||
.font(.scaledBody)
|
||||
.padding(.horizontal, 0)
|
||||
.padding(.vertical, 0)
|
||||
.opacity(isEmpty ? 1 : 0),
|
||||
|
|
Loading…
Reference in a new issue