From af3283b86a3102a17a01a4f500bdd8468366d27d Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Wed, 14 Dec 2022 15:28:00 +0200 Subject: [PATCH 1/6] Expand Add Stats Card view section height when dynamic type increases --- .../Insights Management/InsightsManagementViewController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Insights/Insights Management/InsightsManagementViewController.swift b/WordPress/Classes/ViewRelated/Stats/Insights/Insights Management/InsightsManagementViewController.swift index 1a3929480ac6..bbf2e53aba6e 100644 --- a/WordPress/Classes/ViewRelated/Stats/Insights/Insights Management/InsightsManagementViewController.swift +++ b/WordPress/Classes/ViewRelated/Stats/Insights/Insights Management/InsightsManagementViewController.swift @@ -62,6 +62,7 @@ class InsightsManagementViewController: UITableViewController { reloadViewModel() WPStyleGuide.configureColors(view: view, tableView: tableView) WPStyleGuide.configureAutomaticHeightRows(for: tableView) + tableView.estimatedSectionHeaderHeight = 38 tableView.accessibilityIdentifier = TextContent.title if FeatureFlag.statsNewAppearance.enabled { @@ -83,7 +84,7 @@ class InsightsManagementViewController: UITableViewController { // MARK: TableView Data Source / Delegate Overrides override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 38 + return UITableView.automaticDimension } override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { From 869444b7341d4444d1cc439c442a9c4fa10b11e2 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Wed, 14 Dec 2022 18:00:36 +0200 Subject: [PATCH 2/6] Support dynamic type in chartView legends - Switch to vertical stack view when appropriate - Increase text size --- .../Stats/Charts/DonutChartView.swift | 27 +++++++++++++++++-- .../StatsFollowersChartViewModel.swift | 2 +- .../StatsReferrersChartViewModel.swift | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift b/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift index 599a18995d5d..b33ac8cb50e2 100644 --- a/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift +++ b/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift @@ -79,10 +79,12 @@ class DonutChartView: UIView { titleLabel = UILabel() titleLabel.textAlignment = .center titleLabel.font = .preferredFont(forTextStyle: .subheadline) + titleLabel.adjustsFontForContentSizeCategory = true totalCountLabel = UILabel() totalCountLabel.textAlignment = .center totalCountLabel.font = .preferredFont(forTextStyle: .title1).bold() + totalCountLabel.adjustsFontForContentSizeCategory = true titleStackView = UIStackView(arrangedSubviews: [titleLabel, totalCountLabel]) @@ -98,6 +100,7 @@ class DonutChartView: UIView { legendStackView.translatesAutoresizingMaskIntoConstraints = false legendStackView.spacing = Constants.legendStackViewSpacing legendStackView.distribution = .equalSpacing + legendStackView.alignment = .center addSubview(legendStackView) } @@ -252,6 +255,20 @@ class DonutChartView: UIView { } } + // MARK: - Dynamic Type + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { + legendStackView.axis = .vertical + legendStackView.alignment = .leading + } else { + legendStackView.axis = .horizontal + legendStackView.alignment = .center + } + } + // MARK: Helpers private func makeSegmentLayer(_ segment: Segment) -> CAShapeLayer { @@ -320,22 +337,28 @@ private class LegendView: UIView { } private func configureSubviews() { + let indicatorContainer = UIView() let indicator = UIView() indicator.backgroundColor = segment.color indicator.layer.cornerRadius = 6.0 + indicator.translatesAutoresizingMaskIntoConstraints = false + indicatorContainer.addSubview(indicator) let titleLabel = UILabel() titleLabel.font = .preferredFont(forTextStyle: .subheadline) + titleLabel.adjustsFontForContentSizeCategory = true titleLabel.text = segment.title - let stackView = UIStackView(arrangedSubviews: [indicator, titleLabel]) + let stackView = UIStackView(arrangedSubviews: [indicatorContainer, titleLabel]) stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.spacing = 8.0 + stackView.spacing = 16.0 addSubview(stackView) NSLayoutConstraint.activate([ indicator.widthAnchor.constraint(equalToConstant: 12.0), indicator.heightAnchor.constraint(equalToConstant: 12.0), + indicator.centerXAnchor.constraint(equalTo: indicatorContainer.centerXAnchor), + indicator.centerYAnchor.constraint(equalTo: indicatorContainer.centerYAnchor), stackView.leadingAnchor.constraint(equalTo: leadingAnchor), stackView.trailingAnchor.constraint(equalTo: trailingAnchor), diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsFollowersChartViewModel.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsFollowersChartViewModel.swift index 064fd1cf3c86..eb7d42acf9c8 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsFollowersChartViewModel.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsFollowersChartViewModel.swift @@ -15,7 +15,7 @@ struct StatsFollowersChartViewModel { let chartView = DonutChartView() chartView.configure(title: "", totalCount: CGFloat(totalCount()), segments: segments()) chartView.translatesAutoresizingMaskIntoConstraints = false - chartView.heightAnchor.constraint(equalToConstant: Constants.chartHeight).isActive = true + chartView.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.chartHeight).isActive = true return chartView } diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsReferrersChartViewModel.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsReferrersChartViewModel.swift index d17e798bfe40..2242c1d36641 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsReferrersChartViewModel.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsReferrersChartViewModel.swift @@ -53,7 +53,7 @@ struct StatsReferrersChartViewModel { let chartView = DonutChartView() chartView.configure(title: Constants.chartTitle, totalCount: CGFloat(referrers.totalReferrerViewsCount), segments: segments) chartView.translatesAutoresizingMaskIntoConstraints = false - chartView.heightAnchor.constraint(equalToConstant: Constants.chartHeight).isActive = true + chartView.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.chartHeight).isActive = true return chartView } From 0a7a0aee94e870f0efdc7c357944eaf125e15d25 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 19 Dec 2022 14:47:33 +0200 Subject: [PATCH 3/6] Set maximum font sizes for data switcher element in Stats There's a limited space in a header that displays date in a date switcher. Set the maximum font sizes to support limited amount of text increase for a dynamic type. --- .../SiteStatsTableHeaderView.swift | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/WordPress/Classes/ViewRelated/Stats/Shared Views/Date Chooser/SiteStatsTableHeaderView.swift b/WordPress/Classes/ViewRelated/Stats/Shared Views/Date Chooser/SiteStatsTableHeaderView.swift index 0b9571b2a792..23e22b01272d 100644 --- a/WordPress/Classes/ViewRelated/Stats/Shared Views/Date Chooser/SiteStatsTableHeaderView.swift +++ b/WordPress/Classes/ViewRelated/Stats/Shared Views/Date Chooser/SiteStatsTableHeaderView.swift @@ -144,8 +144,17 @@ private extension SiteStatsTableHeaderView { func applyStyles() { backgroundColor = .listForeground + Style.configureLabelAsCellRowTitle(dateLabel) + dateLabel.font = Metrics.dateLabelFont + dateLabel.adjustsFontForContentSizeCategory = true + dateLabel.minimumScaleFactor = Metrics.minimumScaleFactor + Style.configureLabelAsChildRowTitle(timezoneLabel) + timezoneLabel.font = Metrics.timezoneFont + timezoneLabel.adjustsFontForContentSizeCategory = true + timezoneLabel.minimumScaleFactor = Metrics.minimumScaleFactor + Style.configureViewAsSeparator(bottomSeparatorLine) // Required as the Style separator configure method clears all @@ -311,3 +320,25 @@ extension SiteStatsTableHeaderView: StatsBarChartViewDelegate { reloadView() } } + +private extension SiteStatsTableHeaderView { + enum Metrics { + static let dateLabelFontSize: CGFloat = 20 + static let maximumDateLabelFontSize: CGFloat = 32 + static let timezoneFontSize: CGFloat = 16 + static let maximumTimezoneFontSize: CGFloat = 20 + static let minimumScaleFactor: CGFloat = 0.8 + + static var dateLabelFont: UIFont { + let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .headline) + let font = UIFont(descriptor: fontDescriptor, size: dateLabelFontSize) + return UIFontMetrics.default.scaledFont(for: font, maximumPointSize: maximumDateLabelFontSize) + } + + static var timezoneFont: UIFont { + let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .callout) + let font = UIFont(descriptor: fontDescriptor, size: timezoneFontSize) + return UIFontMetrics.default.scaledFont(for: font, maximumPointSize: maximumTimezoneFontSize) + } + } +} From 5e6e64cb8aa14b06ed606bf63271a9940b56f52b Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 19 Dec 2022 16:01:08 +0200 Subject: [PATCH 4/6] Increase button title sizes automatically in Insights update prompt --- .../Collapsable Header/CollapsableHeaderViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPress/Classes/ViewRelated/Gutenberg/Collapsable Header/CollapsableHeaderViewController.swift b/WordPress/Classes/ViewRelated/Gutenberg/Collapsable Header/CollapsableHeaderViewController.swift index acdd91331363..6665dac9fee2 100644 --- a/WordPress/Classes/ViewRelated/Gutenberg/Collapsable Header/CollapsableHeaderViewController.swift +++ b/WordPress/Classes/ViewRelated/Gutenberg/Collapsable Header/CollapsableHeaderViewController.swift @@ -410,6 +410,7 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost { [defaultActionButton, secondaryActionButton].forEach { (button) in button?.titleLabel?.font = WPStyleGuide.fontForTextStyle(.body, fontWeight: .medium) button?.titleLabel?.adjustsFontSizeToFitWidth = true + button?.titleLabel?.adjustsFontForContentSizeCategory = true button?.layer.borderColor = seperator.cgColor button?.layer.borderWidth = 1 button?.layer.cornerRadius = 8 @@ -417,6 +418,7 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost { primaryActionButton.titleLabel?.font = WPStyleGuide.fontForTextStyle(.body, fontWeight: .medium) primaryActionButton.titleLabel?.adjustsFontSizeToFitWidth = true + primaryActionButton.titleLabel?.adjustsFontForContentSizeCategory = true primaryActionButton.backgroundColor = accentColor primaryActionButton.layer.cornerRadius = 8 } From dd0afa99b7bce03c571aa0b881c49994c3bd9138 Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 19 Dec 2022 16:04:44 +0200 Subject: [PATCH 5/6] Decrease maximum font size for charts in Views and Visitors --- .../ViewRelated/Stats/Extensions/WPStyleGuide+Stats.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Extensions/WPStyleGuide+Stats.swift b/WordPress/Classes/ViewRelated/Stats/Extensions/WPStyleGuide+Stats.swift index 654daf5ea19e..86da013b7b45 100644 --- a/WordPress/Classes/ViewRelated/Stats/Extensions/WPStyleGuide+Stats.swift +++ b/WordPress/Classes/ViewRelated/Stats/Extensions/WPStyleGuide+Stats.swift @@ -206,7 +206,7 @@ extension WPStyleGuide { // MARK: - Font Size - static let maximumChartAxisFontPointSize: CGFloat = 22 + static let maximumChartAxisFontPointSize: CGFloat = 18 // MARK: - Style Values From ab3c108708a5b9017f9bf6202c928f44cb9264ef Mon Sep 17 00:00:00 2001 From: Povilas Staskus Date: Mon, 19 Dec 2022 20:25:11 +0200 Subject: [PATCH 6/6] Improve chart view to support longer legend titles Using equalSpacing makes long titles go out of bounds. - Use fillEqually for each legend title to take same amount of space - Rebuild legend layout to support fillEqually distribution --- .../Stats/Charts/DonutChartView.swift | 56 ++++++++++++++----- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift b/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift index b33ac8cb50e2..645540569865 100644 --- a/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift +++ b/WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift @@ -99,7 +99,7 @@ class DonutChartView: UIView { legendStackView = UIStackView() legendStackView.translatesAutoresizingMaskIntoConstraints = false legendStackView.spacing = Constants.legendStackViewSpacing - legendStackView.distribution = .equalSpacing + legendStackView.distribution = .fillEqually legendStackView.alignment = .center addSubview(legendStackView) @@ -110,6 +110,7 @@ class DonutChartView: UIView { chartContainer.leadingAnchor.constraint(equalTo: leadingAnchor), chartContainer.trailingAnchor.constraint(equalTo: trailingAnchor), chartContainer.topAnchor.constraint(equalTo: topAnchor), + chartContainer.heightAnchor.constraint(equalToConstant: Constants.chartHeight), legendStackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), legendStackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), @@ -263,9 +264,11 @@ class DonutChartView: UIView { if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { legendStackView.axis = .vertical legendStackView.alignment = .leading + legendStackView.subviews.forEach { ($0 as? LegendView)?.isCentered = false } } else { legendStackView.axis = .horizontal legendStackView.alignment = .center + legendStackView.subviews.forEach { ($0 as? LegendView)?.isCentered = true } } } @@ -310,6 +313,7 @@ class DonutChartView: UIView { static let titleStackViewSpacing: CGFloat = 8.0 static let legendStackViewSpacing: CGFloat = 8.0 static let chartToLegendSpacing: CGFloat = 32.0 + static let chartHeight: CGFloat = 180.0 // We'll rotate the chart back by 90 degrees so it starts at the top rather than the right static let chartRotationDegrees: CGFloat = -90.0 @@ -324,6 +328,17 @@ class DonutChartView: UIView { private class LegendView: UIView { let segment: DonutChartView.Segment + var isCentered: Bool { + get { + return leadingConstraint?.isActive ?? false + } + + set { + leadingConstraint?.isActive = !newValue + } + } + private var leadingConstraint: NSLayoutConstraint? + init(segment: DonutChartView.Segment) { self.segment = segment @@ -337,33 +352,44 @@ private class LegendView: UIView { } private func configureSubviews() { - let indicatorContainer = UIView() + let containerView = UIView() + containerView.translatesAutoresizingMaskIntoConstraints = false + let indicator = UIView() indicator.backgroundColor = segment.color indicator.layer.cornerRadius = 6.0 indicator.translatesAutoresizingMaskIntoConstraints = false - indicatorContainer.addSubview(indicator) let titleLabel = UILabel() - titleLabel.font = .preferredFont(forTextStyle: .subheadline) + titleLabel.font = .preferredFont(forTextStyle: .footnote) titleLabel.adjustsFontForContentSizeCategory = true titleLabel.text = segment.title + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) - let stackView = UIStackView(arrangedSubviews: [indicatorContainer, titleLabel]) - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.spacing = 16.0 - addSubview(stackView) + containerView.addSubviews([titleLabel, indicator]) + addSubview(containerView) + + leadingConstraint = containerView.leadingAnchor.constraint(equalTo: leadingAnchor) + leadingConstraint?.priority = .required NSLayoutConstraint.activate([ indicator.widthAnchor.constraint(equalToConstant: 12.0), indicator.heightAnchor.constraint(equalToConstant: 12.0), - indicator.centerXAnchor.constraint(equalTo: indicatorContainer.centerXAnchor), - indicator.centerYAnchor.constraint(equalTo: indicatorContainer.centerYAnchor), - - stackView.leadingAnchor.constraint(equalTo: leadingAnchor), - stackView.trailingAnchor.constraint(equalTo: trailingAnchor), - stackView.topAnchor.constraint(equalTo: topAnchor), - stackView.bottomAnchor.constraint(equalTo: bottomAnchor) + indicator.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), + indicator.centerYAnchor.constraint(equalTo: containerView.centerYAnchor), + + titleLabel.leadingAnchor.constraint(equalTo: indicator.trailingAnchor, constant: 8), + titleLabel.centerYAnchor.constraint(equalTo: containerView.centerYAnchor), + titleLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), + titleLabel.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor), + titleLabel.bottomAnchor.constraint(lessThanOrEqualTo: containerView.bottomAnchor), + + containerView.topAnchor.constraint(equalTo: topAnchor), + containerView.bottomAnchor.constraint(equalTo: bottomAnchor), + containerView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor), + containerView.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor), + containerView.centerXAnchor.constraint(equalTo: centerXAnchor) ]) } }