Skip to content
Open
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
2 changes: 2 additions & 0 deletions Configuration/Entitlements/Extension-catalyst.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
</array>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.developer.usernotifications.communication</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)$(BUNDLE_ID_PREFIX).HomeAssistant$(BUNDLE_ID_SUFFIX)</string>
Expand Down
2 changes: 2 additions & 0 deletions Configuration/Entitlements/Extension-ios.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<array>
<string>group.$(BUNDLE_ID_PREFIX).homeassistant$(BUNDLE_ID_SUFFIX)</string>
</array>
<key>com.apple.developer.usernotifications.communication</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)$(BUNDLE_ID_PREFIX).HomeAssistant$(BUNDLE_ID_SUFFIX)</string>
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source 'https://rubygems.org'
gem 'cocoapods'
gem 'cocoapods-acknowledgements'
gem 'fastlane', '2.222.0'
gem 'abbrev'
gem 'rubocop', require: false

plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
Expand Down
4 changes: 3 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ GEM
base64
nkf
rexml
abbrev (0.1.2)
activesupport (7.1.3)
base64
bigdecimal
Expand Down Expand Up @@ -326,6 +327,7 @@ PLATFORMS
x86_64-darwin-23

DEPENDENCIES
abbrev
cocoapods
cocoapods-acknowledgements
fastlane (= 2.222.0)
Expand All @@ -335,4 +337,4 @@ DEPENDENCIES
rubocop

BUNDLED WITH
2.2.2
2.7.2
117 changes: 78 additions & 39 deletions HomeAssistant.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ final class CarPlayAssistSession: NSObject {
private let prompt: String?

private lazy var template: CPVoiceControlTemplate = {
#if compiler(>=6.3)
let recordButton = CPButton(
image: makeActionButtonImage(icon: .microphoneIcon, color: .haPrimary)
) { [weak self] _ in
Expand All @@ -73,6 +74,7 @@ final class CarPlayAssistSession: NSObject {
let actionButtons: [CPButton] = promptToSend == nil
? [recordButton, helpButton]
: [recordButton, replayPromptButton, helpButton]
#endif

let idleState = CPVoiceControlState(
identifier: VoiceControlStateID.idle.rawValue,
Expand All @@ -83,7 +85,9 @@ final class CarPlayAssistSession: NSObject {
),
repeats: false
)
#if compiler(>=6.3)
idleState.actionButtons = actionButtons
#endif

let recordingState = CPVoiceControlState(
identifier: VoiceControlStateID.recording.rawValue,
Expand Down Expand Up @@ -112,7 +116,9 @@ final class CarPlayAssistSession: NSObject {
image: MaterialDesignIcons.alertCircleIcon.carPlayIcon(color: .systemRed, context: .assistStateIndicator),
repeats: false
)
#if compiler(>=6.3)
errorState.actionButtons = actionButtons
#endif

return CPVoiceControlTemplate(
voiceControlStates: [recordingState, processingState, respondingState, idleState, errorState]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"aps": {
"alert": {
"title": "Dishwasher",
"body": "Cycle complete."
},
"sound": "default",
"category": "notification",
"mutable-content": 1
},
"notification_icon": "mdi:dishwasher",
"color": "#4CAF50",
"webhook_id": "REPLACE_WITH_YOUR_WEBHOOK_ID"
}
22 changes: 16 additions & 6 deletions Sources/Extensions/NotificationService/NotificationService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,35 @@ final class NotificationService: UNNotificationServiceExtension {
) {
Current.Log.info("didReceive \(request), user info \(request.content.userInfo)")

guard let server = Current.servers.server(for: request.content), let api = Current.api(for: server) else {
contentHandler(request.content)
guard let server = Current.servers.server(for: request.content),
let api = Current.api(for: server) else {
if let sender = NotificationSenderParser.parse(from: request.content) {
Current.notificationCommunicationDecorator
.decorate(content: request.content, sender: sender, api: nil)
.done { contentHandler($0) }
} else {
contentHandler(request.content)
}
return
}

firstly {
Current.notificationAttachmentManager.content(from: request.content, api: api)
}.recover { error in
}.recover { error -> Guarantee<UNNotificationContent> in
Current.Log.error("failed to get content, giving default: \(error)")
return .value(request.content)
}.then { content -> Guarantee<UNNotificationContent> in
guard let sender = NotificationSenderParser.parse(from: content) else {
return .value(content)
}
return Current.notificationCommunicationDecorator
.decorate(content: content, sender: sender, api: api)
}.done {
contentHandler($0)
}
}

override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content,
// otherwise the original push payload will be used.
Current.Log.warning("serviceExtensionTimeWillExpire")
}
}
11 changes: 11 additions & 0 deletions Sources/Extensions/NotificationService/Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,19 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSUserActivityTypes</key>
<array>
<string>INSendMessageIntent</string>
</array>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ public struct LegacyNotificationParserImpl: LegacyNotificationParser {
addAttachment(key: "image", contentType: "jpeg")
addAttachment(key: "audio", contentType: "waveformaudio")

for key in ["icon_url", "notification_icon", "notification_icon_color", "color"] {
if let value = data[key] {
payload[key] = value
}
}
if payload["icon_url"] != nil || payload["notification_icon"] != nil {
needsMutableContent = true
}

payload["url"] = data["url"]
payload["shortcut"] = data["shortcut"]
payload["presentation_options"] = data["presentation_options"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"input": {
"message": "test",
"title": "Phone",
"data": {
"notification_icon": "mdi:cellphone",
"notification_icon_color": "#FFFFFF",
"color": "#03A9F4"
},
"registration_info": {
"app_id": "io.robbie.HomeAssistant.dev",
"os_version": "10.15",
"app_version": "2021.5"
}
},
"rate_limit": true,
"headers": {
"apns-push-type": "alert"
},
"payload": {
"aps": {
"alert": {
"body": "test",
"title": "Phone"
},
"mutable-content": true,
"sound": "default"
},
"color": "#03A9F4",
"notification_icon": "mdi:cellphone",
"notification_icon_color": "#FFFFFF"
}
}
2 changes: 2 additions & 0 deletions Sources/Shared/Environment/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ public class AppEnvironment {
public var updater = Updater()
public var serverAlerter = ServerAlerter()
public var notificationAttachmentManager: NotificationAttachmentManager = NotificationAttachmentManagerImpl()
public var notificationCommunicationDecorator: NotificationCommunicationDecorator =
NotificationCommunicationDecoratorImpl()

/// Dispatchque local notifications (From the App to the App, not from Home Assistant)
public var notificationDispatcher: LocalNotificationDispatcherProtocol = LocalNotificationDispatcher()
Expand Down
6 changes: 6 additions & 0 deletions Sources/Shared/Notifications/LocalPush/LocalPushManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ public class LocalPushManager {
}.recover { error in
Current.Log.error("failed to get content, giving default: \(error)")
return .value(baseContent)
}.then { content -> Guarantee<UNNotificationContent> in
if let sender = NotificationSenderParser.parse(from: content) {
return Current.notificationCommunicationDecorator.decorate(content: content, sender: sender, api: api)
} else {
return .value(content)
}
}.then { [add] content -> Promise<Void> in
add(UNNotificationRequest(identifier: event.identifier, content: content, trigger: nil))
}.then { [subscription] () -> Promise<Void> in
Expand Down
Loading