Skip to content

Commit

Permalink
Simplify widgets and small UI tweaks (#2863)
Browse files Browse the repository at this point in the history
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->

## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
<img width="977" alt="Screenshot 2024-07-23 at 12 05 34"
src="https://github.com/user-attachments/assets/99094b2f-66da-4e6d-8c02-361e165b13cd">

## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#

## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
  • Loading branch information
bgoncal authored Jul 23, 2024
1 parent 2ef0087 commit 86e7c7b
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<RemoteRunnable
runnableDebuggingMode = "1"
BundleIdentifier = "com.apple.widgetkit.simulator"
RemotePath = "/System/Library/CoreServices/WidgetKit Simulator.app/Contents/MacOS/WidgetKit Simulator">
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.springboard">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1171506824DFCDE60065E874"
Expand All @@ -99,7 +98,7 @@
<EnvironmentVariables>
<EnvironmentVariable
key = "_XCWidgetKind"
value = "WidgetOpenPage"
value = "WidgetActions"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
Expand Down
22 changes: 11 additions & 11 deletions Sources/App/Resources/Base.lproj/Intents.intentdefinition
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
<key>INIntentDefinitionNamespace</key>
<string>sI7YSe</string>
<key>INIntentDefinitionSystemVersion</key>
<string>23D60</string>
<string>23F79</string>
<key>INIntentDefinitionToolsBuildVersion</key>
<string>15E204a</string>
<string>15F31d</string>
<key>INIntentDefinitionToolsVersion</key>
<string>15.3</string>
<string>15.4</string>
<key>INIntents</key>
<array>
<dict>
Expand Down Expand Up @@ -1419,25 +1419,25 @@
<array>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>1</integer>
<integer>2</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>Small</string>
</dict>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>8</integer>
<integer>4</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>Medium</string>
</dict>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>16</integer>
<integer>10</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>Large</string>
</dict>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>32</integer>
<integer>20</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>ExtraLarge</string>
</dict>
Expand Down Expand Up @@ -1730,25 +1730,25 @@
<array>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>1</integer>
<integer>2</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>Small</string>
</dict>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>8</integer>
<integer>4</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>Medium</string>
</dict>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>16</integer>
<integer>10</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>Large</string>
</dict>
<dict>
<key>INIntentParameterArraySizeSize</key>
<integer>32</integer>
<integer>20</integer>
<key>INIntentParameterArraySizeSizeClass</key>
<string>ExtraLarge</string>
</dict>
Expand Down
21 changes: 10 additions & 11 deletions Sources/App/Settings/ActionConfigurator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,18 @@ class ActionConfigurator: HAFormViewController, TypedRowControllerType {
}
}
}

if action.canConfigure(\Action.BackgroundColor) {
visuals <<< InlineColorPickerRow("background_color") {
$0.title = L10n.ActionsConfigurator.Rows.BackgroundColor.title
if action.canConfigure(\Action.IconColor) {
visuals <<< InlineColorPickerRow("icon_color") {
$0.title = L10n.ActionsConfigurator.Rows.IconColor.title
$0.isCircular = true
$0.showsPaletteNames = true
$0.value = UIColor(hex: self.action.BackgroundColor)
$0.value = UIColor(hex: self.action.IconColor)
}.onChange { picker in
Current.Log.verbose("icon color: \(picker.value!.hexString(false))")

}.onChange { row in
if let value = row.value {
self.action.BackgroundColor = value.hexString()
self.updatePreviews()
}
self.action.IconColor = picker.value!.hexString()

self.updatePreviews()
}
}

Expand Down Expand Up @@ -350,7 +349,7 @@ struct WidgetPreviewView: View {
subtitle: nil,
interactionType: .widgetURL(URL(string: "https://google.com")!),
icon: MaterialDesignIcons(named: action.IconName),
backgroundColor: Color(uiColor: .init(hex: action.BackgroundColor))
iconColor: Color(uiColor: .init(hex: action.IconColor))
),
sizeStyle: .condensed
)
Expand Down
2 changes: 1 addition & 1 deletion Sources/Extensions/AppIntents/WidgetActionsAppIntent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct WidgetActionsAppIntent: AppIntent, WidgetConfigurationIntent, CustomInten
@Parameter(
title: .init("widgets.actions.parameters.action", defaultValue: "Action"),
size: [
.systemSmall: 1,
.systemSmall: 2,
.systemMedium: 4,
.systemLarge: 10,
.systemExtraLarge: 20,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ struct WatchActionButtonView<ViewModel>: View where ViewModel: WatchHomeViewMode
VStack {
Image(uiImage: MaterialDesignIcons(named: action.iconName).image(
ofSize: .init(width: 24, height: 24),
color: .init(hex: action.backgroundColor)
color: .init(hex: action.iconColor)
))
.foregroundColor(Color(uiColor: .init(hex: action.backgroundColor)))
.foregroundColor(Color(uiColor: .init(hex: action.iconColor)))
.padding(Spaces.one)
}
.background(Color(uiColor: .init(hex: action.backgroundColor)).opacity(0.3))
.background(Color(uiColor: .init(hex: action.iconColor)).opacity(0.3))
.clipShape(Circle())
case .loading:
ProgressView()
Expand Down
8 changes: 2 additions & 6 deletions Sources/Extensions/Widgets/Actions/WidgetActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ struct WidgetActions: Widget {
subtitle: nil,
interactionType: .appIntent(.action(id: action.ID, name: action.Name)),
icon: MaterialDesignIcons(serversideValueNamed: action.IconName),
textColor: .init(hex: action.TextColor),
iconColor: .init(hex: action.IconColor),
backgroundColor: .init(hex: action.BackgroundColor)
iconColor: .init(hex: action.IconColor)
)
}
)
Expand Down Expand Up @@ -54,9 +52,7 @@ struct LegacyWidgetActions: Widget {
subtitle: nil,
interactionType: .widgetURL(action.widgetLinkURL),
icon: MaterialDesignIcons(serversideValueNamed: action.IconName),
textColor: .init(hex: action.TextColor),
iconColor: .init(hex: action.IconColor),
backgroundColor: .init(hex: action.BackgroundColor)
iconColor: .init(hex: action.IconColor)
)
}
)
Expand Down
35 changes: 12 additions & 23 deletions Sources/Extensions/Widgets/Common/WidgetBasicContainerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,16 @@ struct WidgetBasicContainerView: View {

var body: some View {
Group {
switch contents.count {
case 0: emptyViewGenerator()
case 1: singleView(for: contents.first!)
default: multiView(for: contents)
if contents.isEmpty {
emptyViewGenerator()
} else {
content(for: contents)
}
}
// Whenever Apple allow apps to use material backgrounds we should update this
.widgetBackground(Color.asset(Asset.Colors.primaryBackground))
}

@ViewBuilder
private func singleView(for model: WidgetBasicViewModel) -> some View {
if case let .widgetURL(url) = model.interactionType {
WidgetBasicView(model: model, sizeStyle: .single)
.widgetURL(url.withWidgetAuthenticity())
} else {
if #available(iOS 17.0, *), let intent = intent(for: model) {
Button(intent: intent) {
WidgetBasicView(model: model, sizeStyle: .single)
}
.buttonStyle(.plain)
}
}
}

@available(iOS 17.0, *)
private func intent(for model: WidgetBasicViewModel) -> (any AppIntent)? {
switch model.interactionType {
Expand All @@ -57,12 +42,16 @@ struct WidgetBasicContainerView: View {
}

@ViewBuilder
func multiView(for models: [WidgetBasicViewModel]) -> some View {
func content(for models: [WidgetBasicViewModel]) -> some View {
let actionCount = models.count
let columnCount = Self.columnCount(family: family, modelCount: actionCount)
let rows = Array(columnify(count: columnCount, models: models))

let sizeStyle: WidgetBasicSizeStyle = {
if models.count == 1 {
return .single
}

let compactBp = Self.compactSizeBreakpoint(for: family)

let condensed = compactBp < actionCount
Expand Down Expand Up @@ -97,7 +86,7 @@ struct WidgetBasicContainerView: View {
}
}
}
.padding(Spaces.one)
.padding(models.count == 1 ? 0 : Spaces.one)
}

private func columnify(count: Int, models: [WidgetBasicViewModel]) -> AnyIterator<[WidgetBasicViewModel]> {
Expand Down Expand Up @@ -136,7 +125,7 @@ struct WidgetBasicContainerView: View {
}
}

/// more than this number: show compact (icon left, text right) version
/// More than this number: show compact (icon left, text right) version
static func compactSizeBreakpoint(for family: WidgetFamily) -> Int {
switch family {
#if !targetEnvironment(macCatalyst) // no ventura SDK yet
Expand All @@ -145,7 +134,7 @@ struct WidgetBasicContainerView: View {
.accessoryRectangular:
return 1
#endif
case .systemSmall: return 1
case .systemSmall: return 2
case .systemMedium: return 4
case .systemLarge: return 10
case .systemExtraLarge: return 20
Expand Down
16 changes: 15 additions & 1 deletion Sources/Extensions/Widgets/Common/WidgetBasicSizeStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ enum WidgetBasicSizeStyle {
let size: CGFloat

switch self {
case .single, .expanded:
case .single:
size = 32
case .expanded:
size = 28
case .regular:
size = 20
case .condensed:
Expand All @@ -40,4 +42,16 @@ enum WidgetBasicSizeStyle {

return .custom(MaterialDesignIcons.familyName, size: size)
}

/// Icon circle background size
var iconCircleSize: CGSize {
switch self {
case .single:
return .init(width: 48, height: 48)
case .expanded:
return .init(width: 42, height: 42)
case .regular, .condensed:
return .init(width: 38, height: 38)
}
}
}
12 changes: 5 additions & 7 deletions Sources/Extensions/Widgets/Common/WidgetBasicView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ struct WidgetBasicView: View {
.multilineTextAlignment(.leading)
.foregroundStyle(Color(uiColor: .label))
.lineLimit(2)
.minimumScaleFactor(0.5)
}

@ViewBuilder
Expand All @@ -54,28 +53,27 @@ struct WidgetBasicView: View {
VStack {
Text(verbatim: model.icon.unicode)
.font(sizeStyle.iconFont)
.minimumScaleFactor(0.2)
.foregroundColor(model.backgroundColor)
.foregroundColor(model.iconColor)
.fixedSize(horizontal: false, vertical: false)
.padding(Spaces.one)
}
.background(model.backgroundColor.opacity(0.3))
.frame(width: sizeStyle.iconCircleSize.width, height: sizeStyle.iconCircleSize.height)
.background(model.iconColor.opacity(0.3))
.clipShape(Circle())
}

private var tileView: some View {
VStack(alignment: .leading) {
switch sizeStyle {
case .regular, .condensed:
HStack(alignment: .center, spacing: Spaces.two) {
HStack(alignment: .center, spacing: Spaces.oneAndHalf) {
icon
VStack(alignment: .leading, spacing: Spaces.half) {
text
subtext
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding([.leading, .trailing], Spaces.two)
.padding([.leading, .trailing], Spaces.oneAndHalf)
case .single, .expanded:
VStack(alignment: .leading, spacing: 0) {
icon
Expand Down
11 changes: 1 addition & 10 deletions Sources/Extensions/Widgets/Common/WidgetBasicViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,14 @@ struct WidgetBasicViewModel: Identifiable, Hashable, Encodable {
subtitle: String?,
interactionType: InteractionType,
icon: MaterialDesignIcons,
showsChevron: Bool = false,
textColor: Color = Color.black,
iconColor: Color = Color.black,
backgroundColor: Color = Color.white
iconColor: Color = Color.black
) {
self.id = id
self.title = title
self.subtitle = subtitle
self.interactionType = interactionType
self.textColor = textColor
self.icon = icon
self.showsChevron = showsChevron
self.iconColor = iconColor
self.backgroundColor = backgroundColor
}

var id: String
Expand All @@ -32,10 +26,7 @@ struct WidgetBasicViewModel: Identifiable, Hashable, Encodable {
var interactionType: InteractionType

var icon: MaterialDesignIcons
var showsChevron: Bool

var backgroundColor: Color
var textColor: Color
var iconColor: Color

enum InteractionType: Hashable, Encodable {
Expand Down
5 changes: 1 addition & 4 deletions Sources/Extensions/Widgets/OpenPage/WidgetOpenPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ struct WidgetOpenPage: Widget {
subtitle: showSubtitle ? Current.servers.server(for: panel)?.info.name : nil,
interactionType: .widgetURL(panel.widgetURL),
icon: panel.materialDesignIcon,
showsChevron: true,
textColor: .white,
iconColor: .white,
backgroundColor: Color(Constants.darkerTintColor)
iconColor: Color(Constants.darkerTintColor)
)
}
}()
Expand Down
1 change: 1 addition & 0 deletions Sources/Shared/DesignSystem/Constants/Spaces.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Foundation
public enum Spaces {
public static var half: CGFloat = 4
public static var one: CGFloat = 8
public static var oneAndHalf: CGFloat = 12
public static var two: CGFloat = 16
public static var three: CGFloat = 24
public static var four: CGFloat = 32
Expand Down

0 comments on commit 86e7c7b

Please sign in to comment.