Skip to content

Commit

Permalink
Add toggle to make action visible in CarPlay (#2529)
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="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. -->
  • Loading branch information
bgoncal committed Jan 18, 2024
1 parent d8b1396 commit 34765e8
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 7 deletions.
4 changes: 3 additions & 1 deletion Sources/App/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ Home Assistant is free and open source home automation software with a focus on
"settings_details.actions.scenes.select_all" = "Select All";
"settings_details.actions.scenes.title" = "Scene Actions";
"settings_details.actions.title" = "Actions";
"settings_details.actions.carPlay.available.title" = "Show in CarPlay";
"settings_details.actions.watch.available.title" = "Show in Watch";
"settings_details.general.app_icon.enum.beta" = "Beta";
"settings_details.general.app_icon.enum.black" = "Black";
"settings_details.general.app_icon.enum.blue" = "Blue";
Expand Down Expand Up @@ -814,4 +816,4 @@ Home Assistant is free and open source home automation software with a focus on
"widgets.open_page.description" = "Open a frontend page in Home Assistant.";
"widgets.open_page.not_configured" = "No Pages Available";
"widgets.open_page.title" = "Open Page";
"yes_label" = "Yes";
"yes_label" = "Yes";
32 changes: 29 additions & 3 deletions Sources/App/Settings/ActionConfigurator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,28 @@ class ActionConfigurator: HAFormViewController, TypedRowControllerType {
}
}

if !Current.isCatalyst {
firstSection <<< SwitchRow {
$0.title = L10n.SettingsDetails.Actions.CarPlay.Available.title
$0.value = action.showInCarPlay
$0.disabled = .init(booleanLiteral: !action.canConfigure(\Action.showInCarPlay))
}.onChange { row in
if let value = row.value {
self.action.showInCarPlay = value
}
}

firstSection <<< SwitchRow("showInWatch") {
$0.title = L10n.SettingsDetails.Actions.Watch.Available.title
$0.value = action.showInWatch
$0.disabled = .init(booleanLiteral: !action.canConfigure(\Action.showInWatch))
}.onChange { row in
if let value = row.value {
self.action.showInWatch = value
}
}
}

// After text if uneditable
firstSection <<< VoiceShortcutRow {
$0.buttonStyle = .automaticOutline
Expand Down Expand Up @@ -239,11 +261,15 @@ class ActionConfigurator: HAFormViewController, TypedRowControllerType {
form.append(visuals)
}

form +++ ViewRow<ActionPreview>("preview").cellSetup { cell, _ in
form +++ ViewRow<ActionPreview>("preview") { [weak self] row in
row.hidden = Condition.function(["showInWatch"], { _ in
!(self?.action.showInWatch ?? true)
})
}.cellSetup { [weak self] cell, _ in
cell.backgroundColor = UIColor.clear
cell.preservesSuperviewLayoutMargins = false
self.updatePreviews()
cell.view = self.preview
self?.updatePreviews()
cell.view = self?.preview
}

form +++ YamlSection(
Expand Down
2 changes: 1 addition & 1 deletion Sources/Extensions/Watch/InterfaceController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class InterfaceController: WKInterfaceController {

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

let actions = realm.objects(Action.self).sorted(byKeyPath: "Position")
let actions = realm.objects(Action.self).sorted(byKeyPath: "Position").filter("showInWatch == true")
self.actions = actions

notificationToken = actions.observe { (changes: RealmCollectionChange) in
Expand Down
18 changes: 18 additions & 0 deletions Sources/Shared/API/Models/Action.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
@objc public dynamic var Scene: RLMScene?
@objc public dynamic var isServerControlled: Bool = false
@objc public dynamic var serverIdentifier: String = ""
@objc public dynamic var showInCarPlay: Bool = true
@objc public dynamic var showInWatch: Bool = true

static func primaryKey(sourceIdentifier: String, serverIdentifier: String) -> String {
#warning("multiserver - primary key duplication")
Expand Down Expand Up @@ -68,6 +70,10 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
return Scene == nil
case \Action.serverIdentifier:
return Scene == nil
case \Action.showInCarPlay:
return Scene == nil
case \Action.showInWatch:
return Scene == nil
default:
return true
}
Expand All @@ -86,6 +92,8 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
self.CreatedAt = try map.value("CreatedAt", using: DateTransform())
self.isServerControlled = try map.value("isServerControlled")
self.serverIdentifier = try map.value("serverIdentifier")
self.showInCarPlay = try map.value("showInCarPlay")
self.showInWatch = try map.value("showInWatch")
super.init()
}

Expand All @@ -101,6 +109,8 @@ public final class Action: Object, ImmutableMappable, UpdatableModel {
CreatedAt >>> (map["CreatedAt"], DateTransform())
isServerControlled >>> map["isServerControlled"]
serverIdentifier >>> map["serverIdentifier"]
showInCarPlay >>> map["showInCarPlay"]
showInWatch >>> map["showInWatch"]
}

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

if let showInCarPlay = object.showInCarPlay {
self.showInCarPlay = showInCarPlay
}

if let showInWatch = object.showInWatch {
self.showInWatch = showInWatch
}

return true
}

Expand Down
4 changes: 4 additions & 0 deletions Sources/Shared/API/Responses/MobileAppConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public struct MobileAppConfigAction: ImmutableMappable, UpdatableModelSource {
var labelColor: String?
var iconIcon: String?
var iconColor: String?
var showInCarPlay: Bool?
var showInWatch: Bool?

public init(map: Map) throws {
self.name = try map.value("name")
Expand All @@ -16,6 +18,8 @@ public struct MobileAppConfigAction: ImmutableMappable, UpdatableModelSource {
self.labelColor = try? map.value("label.color")
self.iconIcon = try? map.value("icon.icon")
self.iconColor = try? map.value("icon.color")
self.showInCarPlay = try? map.value("show_in_carplay")
self.showInWatch = try? map.value("show_in_watch")
}

public var primaryKey: String { name }
Expand Down
10 changes: 9 additions & 1 deletion Sources/Shared/Common/Extensions/Realm+Initialization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ public extension Realm {
// 19 - 2021-11-27 v2021.12 (zone property renames)
// 20…25 - 2022-08-13 v2022.x undoing realm automatic migration
// 26 - 2022-08-13 v2022.x bumping mdi version
let schemaVersion: UInt64 = 26
// 27 - 2024-01-18 v2024.x adding CarPlay toggle to Actions
let schemaVersion: UInt64 = 27

let config = Realm.Configuration(
fileURL: storeURL,
Expand Down Expand Up @@ -183,6 +184,13 @@ public extension Realm {
}
}

if oldVersion < 27 {
migration.enumerateObjects(ofType: Action.className()) { _, newObject in
newObject?["showInCarPlay"] = true
newObject?["showInWatch"] = true
}
}

do {
// always do an MDI migration, since micro-managing whether it needs to be done is annoying
migration.enumerateObjects(ofType: Action.className()) { _, newObject in
Expand Down
12 changes: 12 additions & 0 deletions Sources/Shared/Resources/Swiftgen/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,12 @@ public enum L10n {
/// Synced Actions
public static var header: String { return L10n.tr("Localizable", "settings_details.actions.actions_synced.header") }
}
public enum CarPlay {
public enum Available {
/// Show in CarPlay
public static var title: String { return L10n.tr("Localizable", "settings_details.actions.carPlay.available.title") }
}
}
public enum Learn {
public enum Button {
/// Introduction to iOS Actions
Expand All @@ -1380,6 +1386,12 @@ public enum L10n {
/// Scene Actions
public static var title: String { return L10n.tr("Localizable", "settings_details.actions.scenes.title") }
}
public enum Watch {
public enum Available {
/// Show in Watch
public static var title: String { return L10n.tr("Localizable", "settings_details.actions.watch.available.title") }
}
}
}
public enum General {
/// General
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ final class CarPlayActionsViewModel {
func update() {
let actions = Current.realm().objects(Action.self)
.sorted(byKeyPath: "Position")
.filter("Scene == nil")
.filter("Scene == nil AND showInCarPlay == true")

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

0 comments on commit 34765e8

Please sign in to comment.