-
-
Notifications
You must be signed in to change notification settings - Fork 421
fix: limit feedback message length #8973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
86b175e
8874b9d
bfe48f5
74e8f39
d555640
3f955b2
ec14363
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,9 @@ protocol SentryUserFeedbackFormViewModelDelegate: NSObjectProtocol { | |
|
|
||
| @objcMembers | ||
| @_spi(Private) public class SentryUserFeedbackFormViewModel: NSObject { | ||
| // The backend uses Python code-point length, which matches Swift Unicode scalars. | ||
| static let maxMessageLength = 4_096 | ||
|
|
||
| let config: SentryUserFeedbackConfiguration | ||
| unowned let controller: SentryUserFeedbackFormController | ||
| weak var delegate: SentryUserFeedbackFormViewModelDelegate? | ||
|
|
@@ -126,6 +129,17 @@ protocol SentryUserFeedbackFormViewModelDelegate: NSObjectProtocol { | |
| textView.accessibilityIdentifier = "io.sentry.feedback.form.message" | ||
| return textView | ||
| }() | ||
|
|
||
| lazy var messageCharacterCountLabel = { | ||
| let label = UILabel(frame: .zero) | ||
| label.font = config.theme.scaledFont(style: .caption1) | ||
| label.adjustsFontForContentSizeCategory = true | ||
| label.textAlignment = .right | ||
| label.accessibilityIdentifier = "io.sentry.feedback.form.message-character-count" | ||
| label.accessibilityTraits.insert(.updatesFrequently) | ||
| updateMessageCharacterCount(label: label) | ||
| return label | ||
| }() | ||
|
|
||
| lazy var screenshotImageView = { | ||
| let iv = UIImageView() | ||
|
|
@@ -227,6 +241,7 @@ protocol SentryUserFeedbackFormViewModelDelegate: NSObjectProtocol { | |
|
|
||
| let messageAndScreenshotStack = UIStackView(arrangedSubviews: [ | ||
| self.messageTextView, | ||
| self.messageCharacterCountLabel, | ||
| self.addScreenshotButton, | ||
| self.removeScreenshotStack | ||
| ]) | ||
|
|
@@ -399,6 +414,17 @@ extension SentryUserFeedbackFormViewModel { | |
| case .failure(let error): submitButton.accessibilityHint = error.errorDescription | ||
| } | ||
| } | ||
|
|
||
| func updateMessageCharacterCount() { | ||
| updateMessageCharacterCount(label: messageCharacterCountLabel) | ||
| } | ||
|
|
||
| private func updateMessageCharacterCount(label: UILabel) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sg, please let me know if anything needs to be changed. ty |
||
| let count = messageTextView.text?.unicodeScalars.count ?? 0 | ||
| label.text = "\(count) / \(Self.maxMessageLength)" | ||
| label.accessibilityLabel = "\(count) of \(Self.maxMessageLength) characters used" | ||
| label.textColor = count > Self.maxMessageLength ? config.theme.errorColor : config.theme.foreground | ||
| } | ||
|
|
||
| func themeElements() { | ||
| [fullNameTextField, emailTextField].forEach { | ||
|
|
@@ -499,7 +525,9 @@ extension SentryUserFeedbackFormViewModel { | |
| } | ||
|
|
||
| // include the message they'll submit | ||
| var messageLength = 0 | ||
| if let message = messageTextView.textOrNil { | ||
| messageLength = message.unicodeScalars.count | ||
| hint.append("with message: \(message)") | ||
| } else { | ||
| missing.append(config.formConfig.messageLabel.lowercased()) | ||
|
llirik0 marked this conversation as resolved.
|
||
|
|
@@ -510,17 +538,24 @@ extension SentryUserFeedbackFormViewModel { | |
| let result = SentryUserFeedbackFormValidation.failure(InputError.validationError(missingFields: missing, localizedError: localizedError)) | ||
| return result | ||
| } | ||
|
|
||
| guard messageLength <= Self.maxMessageLength else { | ||
| return .failure(.messageTooLong(maximumLength: Self.maxMessageLength)) | ||
| } | ||
|
|
||
| return SentryUserFeedbackFormValidation.success(hint.joined(separator: " ").appending(".")) | ||
| } | ||
|
|
||
| enum InputError: LocalizedError { | ||
| case validationError(missingFields: [String], localizedError: String) | ||
| case messageTooLong(maximumLength: Int) | ||
|
|
||
| var description: String { | ||
| switch self { | ||
| case .validationError(_, let localizedError): | ||
| return localizedError | ||
| case .messageTooLong(let maximumLength): | ||
| return "The description must not exceed \(maximumLength) characters." | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.