From f24bd668433481c37f0990a47aa3f73e230ed066 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Thu, 14 Nov 2024 14:08:19 -0900 Subject: [PATCH] more docs, theming --- Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 12 ++-- ...SentryUserFeedbackThemeConfiguration.swift | 60 +++++++++++++------ .../UserFeedback/SentryUserFeedbackForm.swift | 49 +++++++-------- 3 files changed, 72 insertions(+), 49 deletions(-) diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index 923d96c17f..df2b19014e 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -204,8 +204,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { uiForm.messagePlaceholder = "Describe the nature of the jank. Its essence, if you will." } config.configureTheme = { theme in - let fontSize: CGFloat = 25 - let fontFamily: String if Locale.current.languageCode == "ar" { // arabic; ar_EG fontFamily = "Damascus" @@ -218,15 +216,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } else { fontFamily = "ChalkboardSE-Regular" } - theme.font = UIFont(name: fontFamily, size: fontSize) ?? UIFont.systemFont(ofSize: fontSize) + theme.fontFamily = fontFamily theme.outlineStyle = .init(outlineColor: .purple) theme.foreground = .purple - theme.background = .purple.withAlphaComponent(0.1) + theme.background = .init(red: 0.95, green: 0.9, blue: 0.95, alpha: 1) + theme.submitBackground = .orange + theme.submitForeground = .purple + theme.buttonBackground = .purple + theme.buttonForeground = .white } config.onSubmitSuccess = { info in let name = info["name"] ?? "$shakespearean_insult_name" let alert = UIAlertController(title: "Thanks?", message: "We have enough jank of our own, we really didn't need yours too, \(name).", preferredStyle: .alert) - alert.addAction(.init(title: "Derp", style: .default)) + alert.addAction(.init(title: "Deal with it 🕶️", style: .default)) self.window?.rootViewController?.present(alert, animated: true) } config.onSubmitError = { error in diff --git a/Sources/Swift/Integrations/UserFeedback/Configuration/SentryUserFeedbackThemeConfiguration.swift b/Sources/Swift/Integrations/UserFeedback/Configuration/SentryUserFeedbackThemeConfiguration.swift index e06181a46b..5607ed0118 100644 --- a/Sources/Swift/Integrations/UserFeedback/Configuration/SentryUserFeedbackThemeConfiguration.swift +++ b/Sources/Swift/Integrations/UserFeedback/Configuration/SentryUserFeedbackThemeConfiguration.swift @@ -9,29 +9,47 @@ import UIKit @available(iOS 13.0, *) @objcMembers public class SentryUserFeedbackThemeConfiguration: NSObject { - lazy var defaultFont = UIFont.preferredFont(forTextStyle: .callout) - - lazy var defaultTitleFont = UIFont.preferredFont(forTextStyle: .title1) + /** + * The font family to use for form text elements. + * - note: Defaults to the system default, if this property is `nil`. + */ + public lazy var fontFamily: String? = nil - lazy var defaultHeadingFont = UIFont.preferredFont(forTextStyle: .headline) + /** + * Font for form input elements. + * - note: Defaults to `UIFont.TextStyle.callout`. + */ + lazy var font = scaledFont(style: .callout) /** - * The default font to use. - * - note: Defaults to the current system default. + * Font for main header title of the feedback form. + * - note: Defaults to `UIFont.TextStyle.title1`. */ - public lazy var font = defaultFont + lazy var headerFont = scaledFont(style: .title1) - public lazy var titleFont = defaultTitleFont + /** + * Font for titles of text fields and buttons in the form. + * - note: Defaults to `UIFont.TextStyle.headline`. + */ + lazy var titleFont = scaledFont(style: .headline) - public lazy var headingFont = defaultHeadingFont + /** + * Return a scaled font for the given style, using the configured font family. + */ + func scaledFont(style: UIFont.TextStyle) -> UIFont { + guard let fontFamily = fontFamily, let font = UIFont(name: fontFamily, size: UIFont.systemFontSize) else { + return UIFont.preferredFont(forTextStyle: style) + } + return UIFontMetrics(forTextStyle: style).scaledFont(for: font) + } + /** + * Helps respond to dynamic font size changes when the app is in the background, and then comes back to the foreground. + */ func updateDefaultFonts() { - defaultFont = UIFont.preferredFont(forTextStyle: .callout) - defaultTitleFont = UIFont.preferredFont(forTextStyle: .title1) - defaultHeadingFont = UIFont.preferredFont(forTextStyle: .headline) - font = defaultFont - titleFont = defaultTitleFont - headingFont = defaultHeadingFont + font = scaledFont(style: .callout) + headerFont = scaledFont(style: .title1) + titleFont = scaledFont(style: .headline) } /** @@ -108,13 +126,19 @@ public class SentryUserFeedbackThemeConfiguration: NSObject { } } - // We need to keep a reference to a default instance of this for comparison purposes later. We don't use the default to give UITextFields a default style, instead, we use `UITextField.BorderStyle.roundedRect` if `SentryUserFeedbackThemeConfiguration.outlineStyle == defaultOutlineStyle`. + /** + * - note: We need to keep a reference to a default instance of this for comparison purposes later. We don't use the default to give UITextFields a default style, instead, we use `UITextField.BorderStyle.roundedRect` if `SentryUserFeedbackThemeConfiguration.outlineStyle == defaultOutlineStyle`. + */ let defaultOutlineStyle = OutlineStyle() - // Options for styling the outline of input elements and buttons in the feedback form. + /** + * Options for styling the outline of input elements and buttons in the feedback form. + */ public lazy var outlineStyle: OutlineStyle = defaultOutlineStyle - // The background color to use for text inputs in the feedback form. + /** + * Background color to use for text inputs in the feedback form. + */ public var inputBackground: UIColor = UIColor.secondarySystemBackground } diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift index 5569dbdbea..a2c1f10c5f 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackForm.swift @@ -16,33 +16,16 @@ class SentryUserFeedbackForm: UIViewController { weak var delegate: (any SentryUserFeedbackFormDelegate)? override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - if config.theme.font == config.theme.defaultFont { - config.theme.updateDefaultFonts() - config.recalculateScaleFactors() - } - + config.theme.updateDefaultFonts() + config.recalculateScaleFactors() updateLayout() } - let formElementHeight: CGFloat = 40 - let logoWidth: CGFloat = 47 - lazy var messageTextViewHeightConstraint = messageTextView.heightAnchor.constraint(equalToConstant: config.theme.font.lineHeight * 5) - lazy var logoViewWidthConstraint = sentryLogoView.widthAnchor.constraint(equalToConstant: logoWidth * config.scaleFactor) - lazy var messagePlaceholderLeadingConstraint = messageTextViewPlaceholder.leadingAnchor.constraint(equalTo: messageTextView.leadingAnchor, constant: messageTextView.textContainerInset.left + 5) - lazy var messagePlaceholderTopConstraint = messageTextViewPlaceholder.topAnchor.constraint(equalTo: messageTextView.topAnchor, constant: messageTextView.textContainerInset.top) - lazy var fullNameTextFieldHeightConstraint = fullNameTextField.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) - lazy var emailTextFieldHeightConstraint = emailTextField.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) - lazy var addScreenshotButtonHeightConstraint = addScreenshotButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) - lazy var removeScreenshotButtonHeightConstraint = removeScreenshotButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) - lazy var submitButtonHeightConstraint = submitButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) - lazy var cancelButtonHeightConstraint = cancelButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) - init(config: SentryUserFeedbackConfiguration, delegate: any SentryUserFeedbackFormDelegate) { self.config = config self.delegate = delegate super.init(nibName: nil, bundle: nil) - view.backgroundColor = .systemBackground - + view.backgroundColor = config.theme.background NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: config.margin), @@ -90,12 +73,12 @@ class SentryUserFeedbackForm: UIViewController { } [fullNameLabel, emailLabel, messageLabel].forEach { - $0.font = config.theme.headingFont + $0.font = config.theme.titleFont $0.adjustsFontForContentSizeCategory = true } [submitButton, addScreenshotButton, removeScreenshotButton, cancelButton].forEach { - $0.titleLabel?.font = config.theme.headingFont + $0.titleLabel?.font = config.theme.titleFont $0.titleLabel?.adjustsFontForContentSizeCategory = true } @@ -134,7 +117,20 @@ class SentryUserFeedbackForm: UIViewController { delegate?.cancelled() } - // MARK: UI + // MARK: Layout + + let formElementHeight: CGFloat = 40 + let logoWidth: CGFloat = 47 + lazy var messageTextViewHeightConstraint = messageTextView.heightAnchor.constraint(equalToConstant: config.theme.font.lineHeight * 5) + lazy var logoViewWidthConstraint = sentryLogoView.widthAnchor.constraint(equalToConstant: logoWidth * config.scaleFactor) + lazy var messagePlaceholderLeadingConstraint = messageTextViewPlaceholder.leadingAnchor.constraint(equalTo: messageTextView.leadingAnchor, constant: messageTextView.textContainerInset.left + 5) + lazy var messagePlaceholderTopConstraint = messageTextViewPlaceholder.topAnchor.constraint(equalTo: messageTextView.topAnchor, constant: messageTextView.textContainerInset.top) + lazy var fullNameTextFieldHeightConstraint = fullNameTextField.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) + lazy var emailTextFieldHeightConstraint = emailTextField.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) + lazy var addScreenshotButtonHeightConstraint = addScreenshotButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) + lazy var removeScreenshotButtonHeightConstraint = removeScreenshotButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) + lazy var submitButtonHeightConstraint = submitButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) + lazy var cancelButtonHeightConstraint = cancelButton.heightAnchor.constraint(equalToConstant: formElementHeight * config.scaleFactor) func updateLayout() { let verticalPadding: CGFloat = 8 @@ -150,14 +146,14 @@ class SentryUserFeedbackForm: UIViewController { removeScreenshotButtonHeightConstraint.constant = formElementHeight * config.scaleFactor submitButtonHeightConstraint.constant = formElementHeight * config.scaleFactor cancelButtonHeightConstraint.constant = formElementHeight * config.scaleFactor - - } + // MARK: UI Elements + lazy var formTitleLabel = { let label = UILabel(frame: .zero) label.text = config.formConfig.formTitle - label.font = config.theme.titleFont + label.font = config.theme.headerFont label.setContentCompressionResistancePriority(.required, for: .horizontal) label.adjustsFontForContentSizeCategory = true return label @@ -321,6 +317,7 @@ class SentryUserFeedbackForm: UIViewController { }() } +// MARK: UITextViewDelegate @available(iOS 13.0, *) extension SentryUserFeedbackForm: UITextViewDelegate { func textViewDidChange(_ textView: UITextView) {