From 2d45fbbd91c9d31ab25a885b3a5e9344b77e2a68 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 5 Feb 2023 11:37:44 -0500 Subject: [PATCH] Apply Mastodon poll limits in Compose view --- .../Compose/ComposeEmojiTextField.swift | 14 ++++++++++++- Tusker/Screens/Compose/ComposePollView.swift | 21 +++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Tusker/Screens/Compose/ComposeEmojiTextField.swift b/Tusker/Screens/Compose/ComposeEmojiTextField.swift index add3b4d1..cfaceb8d 100644 --- a/Tusker/Screens/Compose/ComposeEmojiTextField.swift +++ b/Tusker/Screens/Compose/ComposeEmojiTextField.swift @@ -15,15 +15,17 @@ struct ComposeEmojiTextField: UIViewRepresentable { @Binding var text: String let placeholder: String + let maxLength: Int? let becomeFirstResponder: Binding? let focusNextView: Binding? private var didChange: ((String) -> Void)? = nil private var didEndEditing: (() -> Void)? = nil private var backgroundColor: UIColor? = nil - init(text: Binding, placeholder: String, becomeFirstResponder: Binding? = nil, focusNextView: Binding? = nil) { + init(text: Binding, placeholder: String, maxLength: Int? = nil, becomeFirstResponder: Binding? = nil, focusNextView: Binding? = nil) { self._text = text self.placeholder = placeholder + self.maxLength = maxLength self.becomeFirstResponder = becomeFirstResponder self.focusNextView = focusNextView self.didChange = nil @@ -74,6 +76,7 @@ struct ComposeEmojiTextField: UIViewRepresentable { } else { uiView.text = text } + context.coordinator.maxLength = maxLength context.coordinator.didChange = didChange context.coordinator.didEndEditing = didEndEditing context.coordinator.focusNextView = focusNextView @@ -95,6 +98,7 @@ struct ComposeEmojiTextField: UIViewRepresentable { var text: Binding! // break retained cycle through ComposeUIState.currentInput unowned var uiState: ComposeUIState! + var maxLength: Int? var didChange: ((String) -> Void)? var didEndEditing: (() -> Void)? var focusNextView: Binding? @@ -114,6 +118,14 @@ struct ComposeEmojiTextField: UIViewRepresentable { focusNextView?.wrappedValue = true } + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + if let maxLength { + return ((textField.text ?? "") as NSString).replacingCharacters(in: range, with: string).count <= maxLength + } else { + return true + } + } + func textFieldDidBeginEditing(_ textField: UITextField) { uiState.currentInput = self updateAutocompleteState(textField: textField) diff --git a/Tusker/Screens/Compose/ComposePollView.swift b/Tusker/Screens/Compose/ComposePollView.swift index ebc4526f..5fd6dfb7 100644 --- a/Tusker/Screens/Compose/ComposePollView.swift +++ b/Tusker/Screens/Compose/ComposePollView.swift @@ -20,6 +20,7 @@ struct ComposePollView: View { @ObservedObject var draft: Draft @ObservedObject var poll: Draft.Poll + @EnvironmentObject var mastodonController: MastodonController @Environment(\.colorScheme) var colorScheme: ColorScheme @State private var duration: Duration @@ -30,6 +31,14 @@ struct ComposePollView: View { self._duration = State(initialValue: .fromTimeInterval(poll.duration) ?? .oneDay) } + + private var canAddOption: Bool { + if let pollConfig = mastodonController.instance?.pollsConfiguration { + return poll.options.count < pollConfig.maxOptions + } else { + return true + } + } var body: some View { VStack { @@ -67,9 +76,15 @@ struct ComposePollView: View { .frame(height: 44 * CGFloat(poll.options.count)) Button(action: self.addOption) { - Label("Add Option", systemImage: "plus") + Label { + Text("Add Option") + } icon: { + Image(systemName: "plus") + .foregroundColor(.accentColor) + } } .buttonStyle(.borderless) + .disabled(!canAddOption) HStack { MenuPicker(selection: $poll.multiple, options: [ @@ -155,6 +170,8 @@ struct ComposePollOption: View { @ObservedObject var option: Draft.Poll.Option let optionIndex: Int + @EnvironmentObject private var mastodonController: MastodonController + var body: some View { HStack(spacing: 4) { Checkbox(radiusFraction: poll.multiple ? 0.1 : 0.5, borderWidth: 2) @@ -173,7 +190,7 @@ struct ComposePollOption: View { } private var textField: some View { - var field = ComposeEmojiTextField(text: $option.text, placeholder: "Option \(optionIndex + 1)") + var field = ComposeEmojiTextField(text: $option.text, placeholder: "Option \(optionIndex + 1)", maxLength: mastodonController.instance?.pollsConfiguration?.maxCharactersPerOption) return field.backgroundColor(.systemBackground) }