<!-- 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. -->
## 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. -->
https://github.com/user-attachments/assets/e79c6e4d-13ff-405a-9463-02e597ce4996
<!-- 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
Put together a technique to reuse previews to generate and assert
snapshots.
This either saves time writing snapshot tests or makes snapshot tests
more useful by using them as previews.
This is implemented in a couple of libraries already
([example](https://github.com/BarredEwe/Prefire)). Went with a simple
implementation here but a library can be adopted to leverage additional
features and support.
To hold the code for snapshotting, a new framework was introduced,
SharedTesting, to collect all the utilities built for testing. It must
only be imported in test targets.
The preview side of the code lives in the Shared framework.
Applying this new technique will come in a separate PR.
[Original PR](https://github.com/home-assistant/iOS/pull/3484)
---------
Co-authored-by: Bruno Pantaleão Gonçalves <5808343+bgoncal@users.noreply.github.com>
<!-- 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 -->
First iteration of the widget builder, user is able to choose what
entities to display, choose a display text for them, color customization
and "on tap" action.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
https://github.com/user-attachments/assets/5949322a-a8df-4b3d-aaab-d4ba3853cc84
## 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. -->
<!-- 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. -->

## 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. -->
<!-- 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 -->
This PR also adds a dependency: `SFSafeSymbols` to safely iterate over
SFSymbols. For ControlWidget we can't use MaterialDesign icons, unless
they are converted into custom SFSymbols and embedded in the App but
this would increase a lot the App size
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->

## 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. -->
<!-- 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. -->
## 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. -->
<!-- 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 -->
Pending:
- Allow color customisation
- Choose to receive or not notification confirmation
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## 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. -->
<!-- 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. -->
<!-- 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. -->
## 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. -->
## Summary
Add missing languages so Lokalise pipeline can succeed
## Screenshots
## Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- 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. -->
## 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. -->
Refs #1570 and home-assistant/core#50750. Fixes#1382.
## Summary
Adds a new app extension to do local push notifications on iOS 14 when connected to internal SSIDs.
## Screenshots
Adds a default-on setting to Internal URL:
| Light | Dark |
| -- | -- |
|  |  |
## Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#539
## Any other notes
- Updates the "you need always permission" warning in Internal URL editing to be vibrantly red, to really point out its importance.
- Sets the code signing for the app and the push target to 'manual' on device, hopefully for our internal team only. Special entitlements really do not play well with open source. Worth noting that it is not possible to test this feature without being on the HA team since it does not work in simulator (as far as I can tell) and running on-device requires entitlements.
- Moves commands into Shared in a slightly-easier registration mechanism, so we can share them in the local push extension.
Fixes#1591.
## Summary
Adds support for using video and audio notification attachments in the content extension, including audio playback for both.
## Screenshots
https://user-images.githubusercontent.com/74188/115503572-7c70e900-a22b-11eb-970b-b4e9c2225986.mov
## Any other notes
Dynamic actions require the 'DYNAMIC' category but our content extension causes attachments to not appear and we want every possible feature to work with just this category.
Depends on home-assistant/mobile-apps-fcm-push#47 which allows the actions to be included in the notification data, and also on-the-fly silently sets the category to `DYNAMIC` which this requires.
## Summary
Allows for specifying the actions for a notification on-the-fly without defining a category. This should allow us to make all of the category config and setup unnecessary, so I'll probably consider marking it as deprecated in this release.
## Screenshots
For a notification that looks like…
```yaml
service: notify.mobile_app_iphone
data:
title: title here
message: body here
data:
actions:
- action: "id1"
title: "id1 title"
# this mirrors the action definition in yaml now, it just _also_ supports what android
- identifier: "id2"
title: "id2 title"
```


## Link to pull request in Documentation repository
- Documentation: home-assistant/companion.home-assistant#496
## Any other notes
- Dynamic actions are visual - we provide custom UI on both iOS and watchOS for the additional actions, which does require we run the app on the given platform; for example, this doesn't yet work on macOS [I need to figure out how to make Catalyst notification content work, if it is] and if you uninstall the watch app these actions will not show up.
- Allows `map` and `camera`-esque notification content on any category. In other words, if you send a notification with `map` it'll still prefer the camera `entity_id` if present. This is largely to continue in the direction of making category deprecated; as long as the content extension launches, it'll figure out what to display.
All of the normal action configuration is allowed in these actions:
- action or identifier
- title
- authenticationRequired (default: false)
- behavior (default: default, aka not textinput)
- activationMode (default: background)
- destructive (default: false)
- textInputButtonTitle (default: nil)
- textInputPlaceholder (default: nil)
Some additional things occur to match existing Android functionality:
- `uri` (or `url`) being provided in the action makes it a 'foreground' action
- action/identifier of `REPLY` changes the behavior to textinput
- `mobile_app_notification_action` is now fired with data that looks like theirs:
```
Sending action: mobile_app_notification_action
payload: ["action": "REPLY", "reply_text": "Reply text"]
```
and
```
Sending action: mobile_app_notification_action
payload: ["action": "id1"]
```
## Summary
When the accuracy is fuzzed based on a region enter, we need to use that fuzzed location for the next fuzzer.
## Any other notes
To make it less easy to make this bug happen again (where the intermediary fuzz value is ignored), this moves them to be reducing the same variable in a row.
Also fixed the test case for this flow to explicitly have this double-up requirement.
## Summary
- Creates a Developer ID build, notarizes it, staples and then makes a .zip out of it.
- Re-exports the same Developer ID build for the Mac App Store and uploads it.
- Creates an iOS App Store build and uploads it.
- Uploads dSYMs and other debug information to Sentry during the build.
- Builds for every push to master. Does not automatically expose to beta users, at least not yet. But for internal TestFlight this should produce the latest and greatest as it goes.
## Any other notes
- Necessitates doing an automatic incrementing number for the build number, since it must be monotonically increasing for macOS builds. Uses the format `2021.{RUN_NUMBER}`.
- Moves to use manual code signing for Release builds. It was already this way before (we were just using the Xcode UI at submission time specify), but now it doesn't require fiddling.
- Changes Firebase config to be not in a scheme. When it's in a scheme, it's after the code sign phase, which can produce issues for Fastlane.
- Changes Firebase to not be an xcframework in CI, since they do not ship ARM Mac Catalyst slices yet.
- Removes some incorrect code sign statuses in the Mac Launcher app.
Adds code coverage reports to pull requests. Enabling code coverage gathering appears to be about a 25% increase in build time, unfortunately, so just enabling it for the App/Shared targets and doing it in a separate scheme so it doesn't impact local build times.
Fixes#1383. Refs #949.
## Summary
Allows the user to choose to launch the app on startup, which toggles on a login item which launches the app.
## Screenshots
<img width="350" alt="Screen Shot 2021-01-18 at 13 03 28" src="https://user-images.githubusercontent.com/74188/104962618-aa753180-598d-11eb-8711-f3b45ded80ba.png"><img width="350" alt="Screen Shot 2021-01-18 at 13 03 23" src="https://user-images.githubusercontent.com/74188/104962622-aba65e80-598d-11eb-8c76-e6ec61fe320a.png">
## Any other notes
- Effectively this setting turns on whether to launch this Launcher app on login, and then the Launcher app launches the app whenever it's started, before terminating itself.
- Routes through the Mac Bridge to call `SMLoginItemSetEnabled` which appears to have no public API counterpart to get the current status. Various places point to `SMJobIsEnabled` which doesn't appear in any headers.
- Thanks @rudyrichter for the pointer on how to get this working.
- Saves a few seconds of incremental build time, especially by using input/output file lists for swiftgen.
- Fixes changing e.g. Localizable.strings not immediately taking effect in any target other than the main app.
## Summary
- Refactors notification attachment into smaller units. Adds tests.
- Adds an image attachment with whatever the error reason is when an attachment fails to download.
- Adds a Shared framework scheme which can run just its tests. It's a bit faster than doing the whole app which has a lot of extensions and watchOS targets.
## Screenshots

## Any other notes
This does not (yet?) create the error images for the service timeout. Not sure how relevant that may end up. I haven't yet come across a case of this happening in logs and being confusing.
This allows for configuring more than 1 e.g. Modular Small at a time. This requires watchOS 7; for releases before watchOS 7 we do not allow a secondary template to be created. This could be improved by allowing swapping between one of the multiple for watchOS 6 and earlier, but I didn't implement this.
- Adds a "Display Name" to Complications. This is optional and falls back to the template type. This is primarily to differentiate complications; the underlying unique ID is just a UUID.
- Enable previews of complications, which is used when selecting them. This is a stripped-down version of the items in the template, usually just an icon provider or one of the text providers. This is largely easier now since we're now requesting templates for all complications, even those not actively visible.
This also changes the flow when setting up initially. Instead of a list of families to choose from at the start, the user must tap the 'Add' button and pick one from there.
Fixes#839.
- Combines all .entitlements into either: App-iOS, App-catalyst, WatchApp, Extension-iOS or Extension-catalyst.
- Cleans up and renames all the schemes to match target names
- Moves around several folders and deletes some old files.
- Converts Podfile to be hierarchical, rather than calling shared methods.
- Always runs MaterialDesignIcons script; aborts early if it's up-to-date.
- Updates all dependencies.
This is somewhat in prep of being able to make the project file generated, but also just organizes things into more concrete directory structures.
This pulls out _all_ of the build settings from the root level, and most from the target level, into xcconfigs.
The new directory structure looks like:
- Sources
- App
- (everything from HomeAssistant/)
- WatchApp
- Shared
- MacBridge
- Extensions
- Intents
- NotificationContent
- NotificationService
- Share
- Today
- Watch
- Widgets
- Tests
- App
- UI
- Shared
Somewhat intentionally, the file structure under these is not yet standardized/organized.
The project targets are now:
- App
- WatchApp
- Shared-iOS
- Shared-watchOS
- MacBridge
- Tests-App
- Tests-UI
- Tests-Shared
- Extension-Intents
- Extension-NotificationContent
- Extension-NotificationService
- Extension-Share
- Extension-Today
- Extension-Widget
- WatchExtension-Watch
This does not yet clean up resources vs. sources, nor does it handle some of the "it's in Sources/App but it's part of Shared" crossover directory issues.
- The previous deletion of the Frameworks directory was just for the folder, and not recursive, which didn't work.
- Moves MacBridge.bundle into Shared.framework's PlugIns so it is accessible in extensions, which now creates yet-another `libsodium.a`, so the deletion is now recursive. This xcframeworks bug, yikes!
Starting in the 12.0gm (but not 12.0b6) and in 12.2b1, when our Shared.framework has a dependency on Sodium's xcframework-via-SPM, it is both statically linked into the binary of the framework and copied into Frameworks/. This causes codesign to fail, because it is not expecting a binary file inside.
Reproduced this in a sample project and filed FB8721223 -- it is certainly not expected behavior. Doubly fun if is the presence of this .a causes e.g. notarization to fail. This requires manually removing the directory in Shared.framework. This can't be done as a build phase in Shared.framework because Xcode is doing the incorrect file copy _after_ all build phases, so I put it as a post-build scheme script for the Debug and Release schemes.
- Moves Realm & Sodium to Swift Package Manager. Sodium _just_ added support and I fixed a Release issue there.
- Manually removes linking against Lokalise. Their binary distribution hasn't been updated.
- Avoids talking to things not on Mac (NotificationCenter [Today Widget], Core Telephony).
- Fixes registering fonts, which need to specify scope and also avoid complaining if registration occurs twice.
- Hides preferences like Motion, NFC, Apple Watch which are not on Mac.
- Adds a very basic update checker, which looks at the GitHub releases and does an equality check on version info.
This is, of course, not a polished product: settings still open in a form sheet, there's absolutely no useful menu items, no support for multi-window, nor a prettier NSWindow kinda thing.
Adds a new widget: "Actions" which can hold some number of actions: small (1), medium (1-4), large (1-8).Each action displays based on the text, icon, and background configuration that already exists.
When tapped, the actions launch the app and perform the action. This is an Apple restriction - Widgets cannot execute code when interacted with; they can only launch the app when tapped. Apple gives special permission to their Shortcuts widgets to change this behavior, of course, because all developers are equal but some are more equal than others.
I took "inspiration" from the general layout of most Widgets, but I really don't like the wasted space that Apple does with some of their widgets. For example, the Shortcuts widget draws margin after margin after margin around the actions. This does not. They also force you to have a bunch of blank ones if you don't have exactly the number they want. This fills as best as possible, even if it means making widgets (gasp!) larger than the smallest possible size.
- Upgrades the project file format from very old Xcode compatibility to 11.4+.
- Updates to Cocoapods 1.10 beta.
- Removes some overrides of the xcconfig and updates the xcconfig.
- Adds exclusions for the x86_64/64-bit watchOS simulator using new b4 format.
- Updates intents for iOS 14/Xcode 12.
- Adds an Intent-powered Perform Action widget (which does nothing and isn't styled) to make sure the flow works. It's actually not possible to define an empty set of widgets if the extension exists, so it needs something.
This happens because the Mappable-variant encode/decode of an Action requires a write transaction (since ObjectMapper's mapping is `inout`, which triggers the "only set in a write transaction" check in Realm) which then, directly, caused a new update to the Watch.
Worked around this by making Action and WatchComplication sync via ImmutableMappable which does not do anything inout, and thus doesn't require a write transaction.
Fixes a few more issues:
- Setting shortcutItems and syncing to watch is now done entirely in the Actions observer; removed from Settings.
- Fix iPhone-not-connected action sending for Scene-synced Actions, which don't have their RLMScene synced to the watch.
- Fixed the empty state label not hiding if actions go in or out of 0-count after initially.
- Temporarily disables the new 64-bit watchOS simulator, which allows building again until Realm and Sodium are updated to support it.
- Fixes deployment targets set by Cocoapods.
- Fixes recommended warnings and other new flags from the new SDK.
- Rewrites the region monitoring into several smaller, more testable pieces.
- Does a one-shot location update whenever a region's state changes.
- Writes a whole lot of tests around it.
- Still wraps it in the "In-Development Updating" setting flag so I can get beta feedback and iterate.
Replaces #697.
- Adjusts the constraints on the preview image view while it vends so it isn't stretched. Fixes#513 / #167.
- Adds a sample .apns which can be used to trigger a Camera notification more easily.
Looking through the server code, it looks like we can also grab an HLS stream, which is what the frontend is using for previewing the camera. Refs #596. Created a ticket remember this as #649.
- Adds a thin wrapper around the old logic, which allows users to swap between the two, reducing the scariness of this PR.
- Wraps manual location updating in the same background task logic as background ones.
- Adds background time remaining (when available) as a part of the background task logic, so we can pipe that into the location updating logic, too.
This new logic is focused around: how many updates can we get and how much accuracy can we hit if we give Location Services a few more seconds to feed us location data? I've plugged in some random guesses at how long we're willing to tolerate these things.
Indications are that iOS is willing to toss us things like 2500m accuracy in some situations, which is a heck of a lot of drift for a background fetch update. We're being given an opportunity to do some background work, so it feels like a good time to try and use it, too.
It might be worth considering adding some analytics here to try and get a better handle on how often we have either no location, a mediocre location, or a perfect location.