Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ struct LockScreenStatsWidget<T: LockScreenStatsWidgetConfig>: Widget {
.configurationDisplayName(config.displayName)
.description(config.description)
.supportedFamilies(config.supportFamilies)
.iOS17ContentMarginsDisabled() /// Temporarily disable additional iOS17 margins for widgets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super nitpick, /// is a documentation comment, as opposed to the standard //. With /// Xcode and other tools will render the comment as documentation reading tags and markdown. However, the comment needs to be on a type or method declaration. We don't need to "document" method calls. I just wanted to point it out but I don't expect this to be addressed. 👍 😄

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ struct LockScreenMultiStatView: View {
Spacer()
}
}
.removableWidgetBackground()
.accessibilityElement(children: .combine)
} else {
Text("Not implemented for widget family \(family.debugDescription)")
.removableWidgetBackground()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious about the Swift UI architecture, which is not my strong suit. Would it have been possible to group the conditional logic, e.g. in an *Stack, to only write the removableWidgetBackground() transformation once?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I think it would be possible 👍

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ struct LockScreenSingleStatView: View {
Spacer()
}
}
.removableWidgetBackground()
.accessibilityElement(children: .combine)
} else {
Text("Not implemented for widget family \(family.debugDescription)")
.removableWidgetBackground()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ struct LockScreenUnconfiguredView: View {
.minimumScaleFactor(0.8)
.multilineTextAlignment(.center)
}
.removableWidgetBackground()
} else {
Text("Not implemented for widget family \(family.debugDescription)")
.removableWidgetBackground()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import SwiftUI

/// A card with a title and a string value that is shown on LockScreen without background
struct LockScreenFlexibleCard: View {
let title: LocalizedString
let description: LocalizedString
let lineLimit: Int

init(title: LocalizedString, description: LocalizedString, lineLimit: Int = 1) {
self.title = title
self.description = description
self.lineLimit = lineLimit
}

var body: some View {
VStack(alignment: .leading) {
HStack(alignment: .firstTextBaseline, spacing: 4) {
Image("icon-jetpack")
.resizable()
.frame(width: 14, height: 14)
Text(description)
.font(Appearance.textFont)
.fontWeight(Appearance.textFontWeight)
.foregroundColor(Appearance.textColor)
.lineLimit(lineLimit)
}
Text(title)
.font(Appearance.titleFont)
.foregroundColor(Appearance.titleColor)
}
}
}

// MARK: - Appearance
extension LockScreenFlexibleCard {
private enum Appearance {
static let textFont = Font.headline
static let textFontWeight = Font.Weight.semibold
static let textColor = Color(.label)

static let titleFont = Font.subheadline
static let titleColor = Color(.secondaryLabel)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import SwiftUI

/// A card with a title and a value stacked vertically shown on LockScreen without background
struct LockScreenVerticalCard: View {
let title: LocalizedString
let value: Int

private var accessibilityLabel: Text {
// The colon makes VoiceOver pause between elements
Text(title) + Text(": ") + Text(value.abbreviatedString())
}

var body: some View {
VStack(alignment: .leading) {
StatsValueView(value: value,
font: Appearance.extraLargeTextFont,
fontWeight: .heavy,
foregroundColor: Appearance.textColor,
lineLimit: nil)
.accessibility(label: accessibilityLabel)
Text(title)
.font(Appearance.titleFont)
.fontWeight(Appearance.titleFontWeight)
.foregroundColor(Appearance.titleColor)
.accessibility(hidden: true)
}
}
}

// MARK: - Appearance
extension LockScreenVerticalCard {
private enum Appearance {
static let titleFont = Font.headline
static let titleFontWeight = Font.Weight.semibold
static let titleColor = Color(UIColor.label)
static let extraLargeTextFont = Font.system(size: 48, weight: .bold)
static let textColor = Color(UIColor.label)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ struct StatsValueView: View {
.fontWeight(fontWeight)
.foregroundColor(foregroundColor)
.lineLimit(lineLimit)
.minimumScaleFactor(0.5)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 0.5?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.5 is an arbitrary value, could be smaller or a bit larget as well.

Previously created rectangular widgets can now appear without a background on iPadOS Horizontal Lock Screen. Since they appear without a background, I increased font sizes to have less space and resemble the look of other widgets without a background.

However, when numbers become large, I want font to Value font to shrink, to be fully displayed.

Without minimumScaleFactor:
image

With minimumScaleFactor:
image

}
}
40 changes: 28 additions & 12 deletions WordPress/JetpackStatsWidgets/Views/Cards/VerticalCard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ struct VerticalCard: View {
let value: Int
let largeText: Bool

@Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground: Bool

private var titleFont: Font {
largeText ? Appearance.largeTextFont : Appearance.textFont
}
Expand All @@ -17,18 +19,31 @@ struct VerticalCard: View {

var body: some View {
VStack(alignment: .leading) {
Text(title)
.font(Appearance.titleFont)
.fontWeight(Appearance.titleFontWeight)
.foregroundColor(Appearance.titleColor)
.accessibility(hidden: true)
StatsValueView(value: value,
font: titleFont,
fontWeight: .regular,
foregroundColor: Appearance.textColor,
lineLimit: nil)
.accessibility(label: accessibilityLabel)

if showsWidgetContainerBackground {
Text(title)
.font(Appearance.titleFont)
.fontWeight(Appearance.titleFontWeight)
.foregroundColor(Appearance.titleColor)
.accessibility(hidden: true)
StatsValueView(value: value,
font: titleFont,
fontWeight: .regular,
foregroundColor: Appearance.textColor,
lineLimit: nil)
.accessibility(label: accessibilityLabel)
} else {
StatsValueView(value: value,
font: Appearance.extraLargeTextFont,
fontWeight: .heavy,
foregroundColor: Appearance.textColor,
lineLimit: nil)
.accessibility(label: accessibilityLabel)
Text(title)
.font(Appearance.titleFont)
.fontWeight(Appearance.titleFontWeight)
.foregroundColor(Appearance.titleColor)
.accessibility(hidden: true)
}
}
}
}
Expand All @@ -43,6 +58,7 @@ extension VerticalCard {
static let titleColor = Color(UIColor.primary)

static let largeTextFont = Font.largeTitle
static let extraLargeTextFont = Font.system(size: 48, weight: .bold)
static let textFont = Font.title
static let textColor = Color(.label)
}
Expand Down
24 changes: 24 additions & 0 deletions WordPress/JetpackStatsWidgets/Views/Helpers/iOS17WidgetAPIs.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import SwiftUI
import WidgetKit

extension View {
func removableWidgetBackground(_ backgroundView: some View = EmptyView()) -> some View {
if #available(iOSApplicationExtension 17.0, *) {
return containerBackground(for: .widget) {
backgroundView
}
} else {
return background(backgroundView)
}
}
}

extension WidgetConfiguration {
func iOS17ContentMarginsDisabled() -> some WidgetConfiguration {
if #available(iOSApplicationExtension 17.0, *) {
return contentMarginsDisabled()
} else {
return self
}
}
}
1 change: 1 addition & 0 deletions WordPress/JetpackStatsWidgets/Views/ListStatsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct ListStatsView: View {
}
}
}
.removableWidgetBackground()
}
}

Expand Down
1 change: 1 addition & 0 deletions WordPress/JetpackStatsWidgets/Views/MultiStatsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
Spacer()
}
}
.removableWidgetBackground()
}

/// Constructs a two-card column for the medium size Today widget
Expand Down
52 changes: 46 additions & 6 deletions WordPress/JetpackStatsWidgets/Views/SingleStatView.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,59 @@
import SwiftUI
import WidgetKit

struct SingleStatView: View {
let title: String
let description: String
let valueTitle: String
let value: Int

let viewData: GroupedViewData
@Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground: Bool

init(viewData: GroupedViewData) {
self.title = viewData.widgetTitle
self.description = viewData.siteName
self.valueTitle = viewData.upperLeftTitle
self.value = viewData.upperLeftValue
}
Comment on lines +12 to +17

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider delegating to self.init(title:...?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good observation. I'll use self.init..


init(title: String, description: String, valueTitle: String, value: Int) {
self.title = title
self.description = description
self.valueTitle = valueTitle
self.value = value
}


var body: some View {
HStack {
VStack(alignment: .leading) {
FlexibleCard(axis: .vertical, title: viewData.widgetTitle, value: .description(viewData.siteName), lineLimit: 2)

Spacer()
VerticalCard(title: viewData.upperLeftTitle, value: viewData.upperLeftValue, largeText: true)
if showsWidgetContainerBackground {
VStack(alignment: .leading) {
FlexibleCard(axis: .vertical, title: title, value: .description(description), lineLimit: 2)
Spacer()
VerticalCard(title: valueTitle, value: value, largeText: true)
}
.padding()
} else {
VStack(alignment: .leading) {
Spacer()
LockScreenFlexibleCard(title: title, description: description, lineLimit: 2)
Spacer().frame(height: 4)
LockScreenVerticalCard(title: valueTitle, value: value)
Spacer()
}
}
Spacer()
}
.removableWidgetBackground()
}
}

@available(iOS 16.0, *)
struct SingleStatView_Previews: PreviewProvider {
static var previews: some View {
SingleStatView(title: "Today", description: "My WordPress Site", valueTitle: "Views", value: 124909)
.previewContext(
WidgetPreviewContext(family: .systemSmall)
)
}
}
1 change: 0 additions & 1 deletion WordPress/JetpackStatsWidgets/Views/StatsWidgetsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ struct StatsWidgetsView: View {
case .systemSmall:
SingleStatView(viewData: viewData)
.widgetURL(viewData.statsURL?.appendingSource(.homeScreenWidget))
.padding()

case .systemMedium:
MultiStatsView(viewData: viewData)
Expand Down
4 changes: 3 additions & 1 deletion WordPress/JetpackStatsWidgets/Views/UnconfiguredView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import SwiftUI
struct UnconfiguredView: View {

var timelineEntry: StatsWidgetEntry
@Environment(\.showsWidgetContainerBackground) var showsWidgetContainerBackground: Bool

var body: some View {
Text(unconfiguredMessage)
.font(.footnote)
.foregroundColor(Color(.secondaryLabel))
.foregroundColor(showsWidgetContainerBackground ? Color(.secondaryLabel) : Color(.label))
.multilineTextAlignment(.center)
.padding()
.removableWidgetBackground()
}

var unconfiguredMessage: LocalizedString {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ struct HomeWidgetAllTime: Widget {
.configurationDisplayName(LocalizableStrings.allTimeWidgetTitle)
.description(LocalizableStrings.allTimePreviewDescription)
.supportedFamilies([.systemSmall, .systemMedium])
.iOS17ContentMarginsDisabled() /// Temporarily disable additional iOS17 margins for widgets
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ struct HomeWidgetThisWeek: Widget {
.configurationDisplayName(LocalizableStrings.thisWeekWidgetTitle)
.description(LocalizableStrings.thisWeekPreviewDescription)
.supportedFamilies([.systemMedium, .systemLarge])
.iOS17ContentMarginsDisabled() /// Temporarily disable additional iOS17 margins for widgets
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ struct HomeWidgetToday: Widget {
.configurationDisplayName(LocalizableStrings.todayWidgetTitle)
.description(LocalizableStrings.todayPreviewDescription)
.supportedFamilies([.systemSmall, .systemMedium])
.iOS17ContentMarginsDisabled() /// Temporarily disable additional iOS17 margins for widgets for StandBy
}
}
Loading