Skip to content

Commit 34765e8

Browse files
authored
Add toggle to make action visible in CarPlay (#2529)
<!-- 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="584" alt="Screenshot 2024-01-18 at 02 24 31" src="https://github.com/home-assistant/iOS/assets/5808343/bc037f5d-d916-4715-aaf1-2b823014a99a"> ## 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. -->
1 parent d8b1396 commit 34765e8

File tree

8 files changed

+77
-7
lines changed

8 files changed

+77
-7
lines changed

Sources/App/Resources/en.lproj/Localizable.strings

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ Home Assistant is free and open source home automation software with a focus on
399399
"settings_details.actions.scenes.select_all" = "Select All";
400400
"settings_details.actions.scenes.title" = "Scene Actions";
401401
"settings_details.actions.title" = "Actions";
402+
"settings_details.actions.carPlay.available.title" = "Show in CarPlay";
403+
"settings_details.actions.watch.available.title" = "Show in Watch";
402404
"settings_details.general.app_icon.enum.beta" = "Beta";
403405
"settings_details.general.app_icon.enum.black" = "Black";
404406
"settings_details.general.app_icon.enum.blue" = "Blue";
@@ -814,4 +816,4 @@ Home Assistant is free and open source home automation software with a focus on
814816
"widgets.open_page.description" = "Open a frontend page in Home Assistant.";
815817
"widgets.open_page.not_configured" = "No Pages Available";
816818
"widgets.open_page.title" = "Open Page";
817-
"yes_label" = "Yes";
819+
"yes_label" = "Yes";

Sources/App/Settings/ActionConfigurator.swift

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,28 @@ class ActionConfigurator: HAFormViewController, TypedRowControllerType {
113113
}
114114
}
115115

116+
if !Current.isCatalyst {
117+
firstSection <<< SwitchRow {
118+
$0.title = L10n.SettingsDetails.Actions.CarPlay.Available.title
119+
$0.value = action.showInCarPlay
120+
$0.disabled = .init(booleanLiteral: !action.canConfigure(\Action.showInCarPlay))
121+
}.onChange { row in
122+
if let value = row.value {
123+
self.action.showInCarPlay = value
124+
}
125+
}
126+
127+
firstSection <<< SwitchRow("showInWatch") {
128+
$0.title = L10n.SettingsDetails.Actions.Watch.Available.title
129+
$0.value = action.showInWatch
130+
$0.disabled = .init(booleanLiteral: !action.canConfigure(\Action.showInWatch))
131+
}.onChange { row in
132+
if let value = row.value {
133+
self.action.showInWatch = value
134+
}
135+
}
136+
}
137+
116138
// After text if uneditable
117139
firstSection <<< VoiceShortcutRow {
118140
$0.buttonStyle = .automaticOutline
@@ -239,11 +261,15 @@ class ActionConfigurator: HAFormViewController, TypedRowControllerType {
239261
form.append(visuals)
240262
}
241263

242-
form +++ ViewRow<ActionPreview>("preview").cellSetup { cell, _ in
264+
form +++ ViewRow<ActionPreview>("preview") { [weak self] row in
265+
row.hidden = Condition.function(["showInWatch"], { _ in
266+
!(self?.action.showInWatch ?? true)
267+
})
268+
}.cellSetup { [weak self] cell, _ in
243269
cell.backgroundColor = UIColor.clear
244270
cell.preservesSuperviewLayoutMargins = false
245-
self.updatePreviews()
246-
cell.view = self.preview
271+
self?.updatePreviews()
272+
cell.view = self?.preview
247273
}
248274

249275
form +++ YamlSection(

Sources/Extensions/Watch/InterfaceController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class InterfaceController: WKInterfaceController {
3737

3838
noActionsLabel.setText(L10n.Watch.Labels.noAction)
3939

40-
let actions = realm.objects(Action.self).sorted(byKeyPath: "Position")
40+
let actions = realm.objects(Action.self).sorted(byKeyPath: "Position").filter("showInWatch == true")
4141
self.actions = actions
4242

4343
notificationToken = actions.observe { (changes: RealmCollectionChange) in

Sources/Shared/API/Models/Action.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
2222
@objc public dynamic var Scene: RLMScene?
2323
@objc public dynamic var isServerControlled: Bool = false
2424
@objc public dynamic var serverIdentifier: String = ""
25+
@objc public dynamic var showInCarPlay: Bool = true
26+
@objc public dynamic var showInWatch: Bool = true
2527

2628
static func primaryKey(sourceIdentifier: String, serverIdentifier: String) -> String {
2729
#warning("multiserver - primary key duplication")
@@ -68,6 +70,10 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
6870
return Scene == nil
6971
case \Action.serverIdentifier:
7072
return Scene == nil
73+
case \Action.showInCarPlay:
74+
return Scene == nil
75+
case \Action.showInWatch:
76+
return Scene == nil
7177
default:
7278
return true
7379
}
@@ -86,6 +92,8 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
8692
self.CreatedAt = try map.value("CreatedAt", using: DateTransform())
8793
self.isServerControlled = try map.value("isServerControlled")
8894
self.serverIdentifier = try map.value("serverIdentifier")
95+
self.showInCarPlay = try map.value("showInCarPlay")
96+
self.showInWatch = try map.value("showInWatch")
8997
super.init()
9098
}
9199

@@ -101,6 +109,8 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
101109
CreatedAt >>> (map["CreatedAt"], DateTransform())
102110
isServerControlled >>> map["isServerControlled"]
103111
serverIdentifier >>> map["serverIdentifier"]
112+
showInCarPlay >>> map["showInCarPlay"]
113+
showInWatch >>> map["showInWatch"]
104114
}
105115

106116
static func didUpdate(objects: [Action], server: Server, realm: Realm) {
@@ -153,6 +163,14 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
153163
TextColor = textColor
154164
}
155165

166+
if let showInCarPlay = object.showInCarPlay {
167+
self.showInCarPlay = showInCarPlay
168+
}
169+
170+
if let showInWatch = object.showInWatch {
171+
self.showInWatch = showInWatch
172+
}
173+
156174
return true
157175
}
158176

Sources/Shared/API/Responses/MobileAppConfig.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ public struct MobileAppConfigAction: ImmutableMappable, UpdatableModelSource {
88
var labelColor: String?
99
var iconIcon: String?
1010
var iconColor: String?
11+
var showInCarPlay: Bool?
12+
var showInWatch: Bool?
1113

1214
public init(map: Map) throws {
1315
self.name = try map.value("name")
@@ -16,6 +18,8 @@ public struct MobileAppConfigAction: ImmutableMappable, UpdatableModelSource {
1618
self.labelColor = try? map.value("label.color")
1719
self.iconIcon = try? map.value("icon.icon")
1820
self.iconColor = try? map.value("icon.color")
21+
self.showInCarPlay = try? map.value("show_in_carplay")
22+
self.showInWatch = try? map.value("show_in_watch")
1923
}
2024

2125
public var primaryKey: String { name }

Sources/Shared/Common/Extensions/Realm+Initialization.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ public extension Realm {
8080
// 19 - 2021-11-27 v2021.12 (zone property renames)
8181
// 20…25 - 2022-08-13 v2022.x undoing realm automatic migration
8282
// 26 - 2022-08-13 v2022.x bumping mdi version
83-
let schemaVersion: UInt64 = 26
83+
// 27 - 2024-01-18 v2024.x adding CarPlay toggle to Actions
84+
let schemaVersion: UInt64 = 27
8485

8586
let config = Realm.Configuration(
8687
fileURL: storeURL,
@@ -183,6 +184,13 @@ public extension Realm {
183184
}
184185
}
185186

187+
if oldVersion < 27 {
188+
migration.enumerateObjects(ofType: Action.className()) { _, newObject in
189+
newObject?["showInCarPlay"] = true
190+
newObject?["showInWatch"] = true
191+
}
192+
}
193+
186194
do {
187195
// always do an MDI migration, since micro-managing whether it needs to be done is annoying
188196
migration.enumerateObjects(ofType: Action.className()) { _, newObject in

Sources/Shared/Resources/Swiftgen/Strings.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,12 @@ public enum L10n {
13621362
/// Synced Actions
13631363
public static var header: String { return L10n.tr("Localizable", "settings_details.actions.actions_synced.header") }
13641364
}
1365+
public enum CarPlay {
1366+
public enum Available {
1367+
/// Show in CarPlay
1368+
public static var title: String { return L10n.tr("Localizable", "settings_details.actions.carPlay.available.title") }
1369+
}
1370+
}
13651371
public enum Learn {
13661372
public enum Button {
13671373
/// Introduction to iOS Actions
@@ -1380,6 +1386,12 @@ public enum L10n {
13801386
/// Scene Actions
13811387
public static var title: String { return L10n.tr("Localizable", "settings_details.actions.scenes.title") }
13821388
}
1389+
public enum Watch {
1390+
public enum Available {
1391+
/// Show in Watch
1392+
public static var title: String { return L10n.tr("Localizable", "settings_details.actions.watch.available.title") }
1393+
}
1394+
}
13831395
}
13841396
public enum General {
13851397
/// General

Sources/Vehicle/Templates/Actions/CarPlayActionsViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ final class CarPlayActionsViewModel {
1010
func update() {
1111
let actions = Current.realm().objects(Action.self)
1212
.sorted(byKeyPath: "Position")
13-
.filter("Scene == nil")
13+
.filter("Scene == nil AND showInCarPlay == true")
1414

1515
actionsToken?.invalidate()
1616
actionsToken = actions.observe { [weak self] _ in

0 commit comments

Comments
 (0)