Focus CW field immediately when CW enabled, move focus to main text view when return key pressed

Closes #226
This commit is contained in:
Shadowfacts 2022-11-12 14:16:05 -05:00
parent de0198946e
commit bf3f735062
3 changed files with 41 additions and 8 deletions

View File

@ -13,15 +13,19 @@ struct ComposeEmojiTextField: UIViewRepresentable {
@EnvironmentObject private var uiState: ComposeUIState @EnvironmentObject private var uiState: ComposeUIState
@Binding private var text: String @Binding var text: String
private let placeholder: String let placeholder: String
private var didChange: ((String) -> Void)? let becomeFirstResponder: Binding<Bool>?
private var didEndEditing: (() -> Void)? let focusNextView: Binding<Bool>?
private var didChange: ((String) -> Void)? = nil
private var didEndEditing: (() -> Void)? = nil
private var backgroundColor: UIColor? = nil private var backgroundColor: UIColor? = nil
init(text: Binding<String>, placeholder: String) { init(text: Binding<String>, placeholder: String, becomeFirstResponder: Binding<Bool>? = nil, focusNextView: Binding<Bool>? = nil) {
self._text = text self._text = text
self.placeholder = placeholder self.placeholder = placeholder
self.becomeFirstResponder = becomeFirstResponder
self.focusNextView = focusNextView
self.didChange = nil self.didChange = nil
self.didEndEditing = nil self.didEndEditing = nil
} }
@ -52,6 +56,7 @@ struct ComposeEmojiTextField: UIViewRepresentable {
view.delegate = context.coordinator view.delegate = context.coordinator
view.addTarget(context.coordinator, action: #selector(Coordinator.didChange(_:)), for: .editingChanged) view.addTarget(context.coordinator, action: #selector(Coordinator.didChange(_:)), for: .editingChanged)
view.addTarget(context.coordinator, action: #selector(Coordinator.returnKeyPressed), for: .primaryActionTriggered)
// otherwise when the text gets too wide it starts expanding the ComposeView // otherwise when the text gets too wide it starts expanding the ComposeView
view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
@ -71,6 +76,14 @@ struct ComposeEmojiTextField: UIViewRepresentable {
} }
context.coordinator.didChange = didChange context.coordinator.didChange = didChange
context.coordinator.didEndEditing = didEndEditing context.coordinator.didEndEditing = didEndEditing
context.coordinator.focusNextView = focusNextView
if becomeFirstResponder?.wrappedValue == true {
DispatchQueue.main.async {
uiView.becomeFirstResponder()
becomeFirstResponder?.wrappedValue = false
}
}
} }
func makeCoordinator() -> Coordinator { func makeCoordinator() -> Coordinator {
@ -84,6 +97,7 @@ struct ComposeEmojiTextField: UIViewRepresentable {
unowned var uiState: ComposeUIState! unowned var uiState: ComposeUIState!
var didChange: ((String) -> Void)? var didChange: ((String) -> Void)?
var didEndEditing: (() -> Void)? var didEndEditing: (() -> Void)?
var focusNextView: Binding<Bool>?
var skipSettingTextOnNextUpdate = false var skipSettingTextOnNextUpdate = false
@ -96,6 +110,10 @@ struct ComposeEmojiTextField: UIViewRepresentable {
didChange?(text.wrappedValue) didChange?(text.wrappedValue)
} }
@objc func returnKeyPressed() {
focusNextView?.wrappedValue = true
}
func textFieldDidBeginEditing(_ textField: UITextField) { func textFieldDidBeginEditing(_ textField: UITextField) {
uiState.currentInput = self uiState.currentInput = self
updateAutocompleteState(textField: textField) updateAutocompleteState(textField: textField)

View File

@ -47,6 +47,8 @@ struct ComposeView: View {
@EnvironmentObject var uiState: ComposeUIState @EnvironmentObject var uiState: ComposeUIState
@State private var globalFrameOutsideList: CGRect = .zero @State private var globalFrameOutsideList: CGRect = .zero
@State private var contentWarningBecomeFirstResponder = false
@State private var mainComposeTextViewBecomeFirstResponder = false
@OptionalStateObject private var poster: PostService? @OptionalStateObject private var poster: PostService?
@State private var isShowingPostErrorAlert = false @State private var isShowingPostErrorAlert = false
@ -145,12 +147,20 @@ struct ComposeView: View {
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
if draft.contentWarningEnabled { if draft.contentWarningEnabled {
ComposeEmojiTextField(text: $draft.contentWarning, placeholder: "Write your warning here") ComposeEmojiTextField(
text: $draft.contentWarning,
placeholder: "Write your warning here",
becomeFirstResponder: $contentWarningBecomeFirstResponder,
focusNextView: $mainComposeTextViewBecomeFirstResponder
)
.listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8)) .listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
} }
MainComposeTextView(draft: draft) MainComposeTextView(
draft: draft,
becomeFirstResponder: $mainComposeTextViewBecomeFirstResponder
)
.listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8)) .listRowInsets(EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8))
.listRowSeparator(.hidden) .listRowSeparator(.hidden)
@ -170,6 +180,11 @@ struct ComposeView: View {
.listStyle(.plain) .listStyle(.plain)
.disabled(isPosting) .disabled(isPosting)
.padding(.bottom, uiState.autocompleteState != nil ? 46 : 0) .padding(.bottom, uiState.autocompleteState != nil ? 46 : 0)
.onChange(of: draft.contentWarningEnabled) { newValue in
if newValue {
contentWarningBecomeFirstResponder = true
}
}
} }
private var header: some View { private var header: some View {

View File

@ -35,7 +35,7 @@ struct MainComposeTextView: View {
let minHeight: CGFloat = 150 let minHeight: CGFloat = 150
@State private var height: CGFloat? @State private var height: CGFloat?
@State private var becomeFirstResponder: Bool = false @Binding var becomeFirstResponder: Bool
@State private var hasFirstAppeared = false @State private var hasFirstAppeared = false
@ScaledMetric private var fontSize = 20 @ScaledMetric private var fontSize = 20