Migrate Notification category/action editors to SwiftUI#4563
Merged
Conversation
This was referenced Apr 24, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Migrates the notification category/action configuration UI from Eureka/UIKit to SwiftUI, adding reusable SwiftUI components for Realm observation, identifier input, and YAML previews, while temporarily embedding the new list view from the existing NotificationSettingsViewController.
Changes:
- Replace legacy Eureka-based notification category/action editors with SwiftUI
NotificationCategoryListView,NotificationCategoryEditorView, andNotificationActionEditorView. - Add reusable SwiftUI components:
YamlPreviewSection,NotificationIdentifierField/NotificationIdentifierTextField, andRealmResultsObserver. - Remove the old
*Configurator.swift/*ViewController.swiftfiles and the Eureka identifier row; update the Xcode project to include new sources.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| Sources/App/Utilities/NotificationIdentifierEurekaRow.swift | Deletes legacy Eureka identifier row implementation. |
| Sources/App/Settings/Notifications/NotificationSettingsViewController.swift | Embeds new SwiftUI category list via UIHostingController. |
| Sources/App/Settings/Notifications/NotificationCategoryListViewController.swift | Removes legacy Eureka category list controller. |
| Sources/App/Settings/Notifications/NotificationCategoryListView.swift | Adds SwiftUI category list with local/server sections and sheet-based navigation to editor. |
| Sources/App/Settings/Notifications/NotificationCategoryEditorView.swift | Adds SwiftUI category editor with validation, action management, YAML preview, help, and preview notification. |
| Sources/App/Settings/Notifications/NotificationCategoryConfigurator.swift | Removes legacy Eureka category configurator. |
| Sources/App/Settings/Notifications/NotificationActionEditorView.swift | Adds SwiftUI action editor with validation, conditional text input, toggles, and YAML preview. |
| Sources/App/Settings/Notifications/NotificationActionConfigurator.swift | Removes legacy Eureka action configurator. |
| Sources/App/Settings/Components/YamlPreviewSection.swift | Adds reusable SwiftUI YAML preview + share + full-screen view. |
| Sources/App/Settings/Components/RealmResultsObserver.swift | Adds ObservableObject wrapper for Realm collection updates. |
| Sources/App/Settings/Components/NotificationIdentifierField.swift | Adds sanitization/validation + SwiftUI text field wrapper for identifiers. |
| HomeAssistant.xcodeproj/project.pbxproj | Wires in new SwiftUI files and removes deleted legacy files. |
898f5c9 to
b829432
Compare
bgoncal
added a commit
that referenced
this pull request
Apr 28, 2026
## Summary Replace the Eureka-based location settings screen with a SwiftUI `LocationSettingsView` + `LocationSettingsViewModel`. Includes permission status rows, background refresh, location history link, manual location update, update-source toggles, and per-zone read-only sections. Zone detail now uses an `MKMapView`-backed SwiftUI preview with the zone radius overlay. `PermissionStatusRow.swift` and `EurekaLocationRow.swift` are removed; permission/disabled-state logic moves into the view model. `SettingsItem.location` is routed directly to the SwiftUI view and the location setup (~270 lines) is trimmed from `SettingsDetailViewController`. ## Screenshots ## Link to pull request in Documentation repository Documentation: home-assistant/companion.home-assistant# ## Any other notes Part of a five-PR Eureka → SwiftUI migration tracked in `UIKitToSwiftUIMigration.md`. The `Eureka`, `ColorPickerRow`, and `ViewRow` pods stay until the remaining four slices land: actions (#4561), notification settings (#4562), notification categories (#4563), watch complications (#4564). Build-verified locally on iOS simulator. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
6a0dd4c to
46098d7
Compare
bgoncal
added a commit
that referenced
this pull request
Apr 28, 2026
## Summary Replace the Eureka actions list with `ActionsSettingsView` + `ActionsSettingsViewModel` (value-type Realm snapshots, delete/reorder, scene toggle + customize flow, server refresh). Replace `ActionConfigurator` with `ActionConfiguratorView` using SwiftUI `Form`, `IconPicker`, SwiftUI `ColorPicker`, the existing `WidgetBasicButtonView` preview, and a new inline `ActionServerPicker`. `SettingsItem.actions` is wired directly to the SwiftUI view and the Eureka actions code is removed from `SettingsDetailViewController`. ## Screenshots _Pending — to be added before merge._ ## Link to pull request in Documentation repository Documentation: home-assistant/companion.home-assistant# ## Any other notes Part of a five-PR Eureka → SwiftUI migration tracked in `UIKitToSwiftUIMigration.md` (siblings: #4560, #4562, #4563, #4564). The `Eureka`, `ColorPickerRow`, and `ViewRow` pods stay until all slices land. `ServerSelectRow.swift` is intentionally kept in-tree because `ComplicationEditViewController` still uses it — both come out once the complications slice (#4564) merges. Not build-verified locally yet; may surface access-level fixes (e.g. internal synthesized initializers on Shared types) during build. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
bgoncal
added a commit
that referenced
this pull request
Apr 28, 2026
## Summary Migrate the notification settings screen and its three leaf screens to SwiftUI: - `NotificationSettingsView`: permission status, learn-more link, sounds / categories / rate-limit / debug navigation, badge reset + auto-clear, push ID share, push ID reset. - `NotificationSoundsView`: imported / bundled / system segmented lists, audio playback, swipe delete, `.fileImporter`, file-sharing + system import, AKConverter progress HUD, alert handling. - `NotificationRateLimitView`: pull-to-refresh on iOS, toolbar refresh on Catalyst, 1-second reset countdown, retry state, parent remaining-count callback. - `NotificationDebugNotificationsView`: `UserDefaults`-backed toggles. Removes the Eureka `row(for:)` extensions in `NotificationRateLimitsAPI.swift`, deletes the four old `*ViewController.swift` files, and rewires `SettingsItem.notifications` and `NotificationManager.openSettingsFor` to the SwiftUI view. ## Screenshots _Pending — to be added before merge._ ## Link to pull request in Documentation repository Documentation: home-assistant/companion.home-assistant# ## Any other notes Part of a five-PR Eureka → SwiftUI migration tracked in `UIKitToSwiftUIMigration.md` (siblings: #4560, #4561, #4563, #4564). The `Eureka`, `ColorPickerRow`, and `ViewRow` pods stay until all slices land. **Reconciliation with #4563:** the categories PR temporarily embeds `NotificationCategoryListView` inside the old `NotificationSettingsViewController` via `UIHostingController`. This PR deletes that controller entirely; after both merge, the `categoriesDestination` in `NotificationSettingsView` should link directly to `NotificationCategoryListView` from the categories PR. `bundle exec fastlane lint` passes. Not build-verified locally yet. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the Eureka-based NotificationCategoryListViewController, NotificationCategoryConfigurator, and NotificationActionConfigurator with SwiftUI equivalents (NotificationCategoryListView, NotificationCategoryEditorView, NotificationActionEditorView). Adds three new reusable helpers under Sources/App/Settings/Components: - YamlPreviewSection: replaces Eureka YamlSection for this slice, generalising the preview/share pattern already used in NFCTagView. - NotificationIdentifierField: SwiftUI text-field/formatter replacement for the old NotificationIdentifierEurekaRow, enforcing identifier casing and validation. - RealmResultsObserver: ObservableObject wrapper around AnyRealmCollection using a Realm notification token, avoiding direct Realm access in view bodies. Wires the categories list into NotificationSettingsViewController via a UIHostingController and removes the migrated Eureka helpers exclusive to this slice. YamlSection and RealmSection are retained since they are still used by other (out-of-scope) controllers. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Update YamlPreviewSection doc to reflect that yaml is a String value rather than a closure. - Update sanitize doc to match implementation: spaces become underscores and other invalid characters are dropped. - Pass the hosting view controller as presenter to openURLInBrowser from NotificationCategoryListView and NotificationCategoryEditorView so the SafariInApp browser preference works (was crashing on nil presenter). - Embed NotificationCategoryListView via embeddedInHostingController so it has a ViewControllerProvider in scope, and forward the provider to the editor sheet. - Uppercase the categoryIdentifier in the preview notification so it matches the registered UNNotificationCategory. - Make RealmResultsObserver MainActor-isolated, snapshot synchronously and hop to MainActor to publish, matching the doc comment. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`if` directly inside a `@ToolbarContentBuilder` body requires the iOS 16+ ToolbarContentBuilder. Always emit each `ToolbarItem` and gate its content on `!isServerControlled` instead — that puts the conditional in a regular ViewBuilder context which compiles on iOS 15. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
46098d7 to
fb91def
Compare
The rebase carried forward duplicate group entries and PBXBuildFile / PBXFileReference rows for the legacy `*ViewController.swift` and `*Configurator.swift` files. Two of those reused the same UUIDs as their renamed `*View.swift` replacements, so Xcode's parser resolved the UUID to the deleted `*ViewController.swift` path and the build failed with "Build input files cannot be found" for `NotificationRateLimitViewController.swift` and `NotificationDebugNotificationsViewController.swift`. Drops every reference to: - NotificationCategoryConfigurator.swift - NotificationActionConfigurator.swift - NotificationCategoryListViewController.swift - NotificationSoundsViewController.swift (duplicate UUID) - NotificationSettingsViewController.swift (duplicate UUID) - NotificationRateLimitViewController.swift (duplicate UUID) - NotificationDebugNotificationsViewController.swift (duplicate UUID) - the duplicated NotificationRateLimitsAPI.swift group entry Co-Authored-By: Claude <noreply@anthropic.com>
3 tasks
The category-list slice still embedded the legacy `NotificationCategoryListViewController` via the temporary `embed(...)` UIKit bridge. With that controller deleted in this PR, build was failing with "cannot find 'NotificationCategoryListViewController' in scope". Swap the destination to `NotificationCategoryListView()`, which already sets its own navigation title. Co-Authored-By: Claude <noreply@anthropic.com>
bgoncal
added a commit
that referenced
this pull request
Apr 28, 2026
The Eureka-based settings tree was fully replaced by SwiftUI across PRs #4560–#4564. Every remaining Eureka file on main is dead code: `SettingsRootDataSource.swift` has no inbound references, the active settings root (`SettingsItem.swift`) routes directly to the SwiftUI views (`NFCListView`, `ComplicationListView`, etc.), and the legacy `*ViewController.swift` / Eureka helper-row files are reachable only from each other. Tests don't import Eureka, and the `ColorPickerRow` and `ViewRow` add-on pods aren't referenced anywhere either. Removes: - `Sources/App/Settings/Eureka/` (14 helper rows + form VC + utils) - `Sources/App/Settings/MaterialDesignIcons+Eureka.swift` (`SearchItem` conformance for the now-deleted `SearchPushRow`) - `Sources/App/Settings/SettingsRootDataSource.swift` - `Sources/App/Settings/Settings/SettingsDetailViewController.swift` - `Sources/App/Settings/AppleWatch/Complication{List,FamilySelect,Edit}ViewController.swift` - `Sources/App/Settings/NFC/NFC{List,Tag}ViewController.swift` - `Sources/App/Utilities/{SearchPushRow,WebSocketStatusRow}.swift` - `Eureka`, `ColorPickerRow`, `ViewRow` pods from `Podfile`/`Podfile.lock` - `import Eureka` and `-framework "Eureka"` LDFLAGS from project files No behavior change — pure dead-code removal. Stacked on #4563. Co-Authored-By: Claude <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4563 +/- ##
=======================================
Coverage ? 43.24%
=======================================
Files ? 275
Lines ? 16700
Branches ? 0
=======================================
Hits ? 7222
Misses ? 9478
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
bgoncal
added a commit
that referenced
this pull request
Apr 29, 2026
The Eureka-based settings tree was fully replaced by SwiftUI across PRs #4560–#4564. Every remaining Eureka file on main is dead code: `SettingsRootDataSource.swift` has no inbound references, the active settings root (`SettingsItem.swift`) routes directly to the SwiftUI views (`NFCListView`, `ComplicationListView`, etc.), and the legacy `*ViewController.swift` / Eureka helper-row files are reachable only from each other. Tests don't import Eureka, and the `ColorPickerRow` and `ViewRow` add-on pods aren't referenced anywhere either. Removes: - `Sources/App/Settings/Eureka/` (14 helper rows + form VC + utils) - `Sources/App/Settings/MaterialDesignIcons+Eureka.swift` (`SearchItem` conformance for the now-deleted `SearchPushRow`) - `Sources/App/Settings/SettingsRootDataSource.swift` - `Sources/App/Settings/Settings/SettingsDetailViewController.swift` - `Sources/App/Settings/AppleWatch/Complication{List,FamilySelect,Edit}ViewController.swift` - `Sources/App/Settings/NFC/NFC{List,Tag}ViewController.swift` - `Sources/App/Utilities/{SearchPushRow,WebSocketStatusRow}.swift` - `Eureka`, `ColorPickerRow`, `ViewRow` pods from `Podfile`/`Podfile.lock` - `import Eureka` and `-framework "Eureka"` LDFLAGS from project files No behavior change — pure dead-code removal. Stacked on #4563. Co-Authored-By: Claude <noreply@anthropic.com>
bgoncal
added a commit
that referenced
this pull request
Apr 29, 2026
## Summary Now that PRs #4560–#4564 have migrated every Eureka-based settings screen to SwiftUI, every remaining Eureka file on `main` is dead code. This PR removes them, the Eureka pod, and the two Eureka-community add-on pods. **Reachability check before deleting:** - `SettingsRootDataSource.swift` (the legacy Eureka settings root) has zero inbound references. The active settings root is `SettingsItem.swift`, which already routes to SwiftUI views (`NFCListView()`, `ComplicationListView()`, etc.). - The legacy `*ViewController.swift` files (`NFCListViewController`, `ComplicationListViewController`, `SettingsDetailViewController`, etc.) are reachable only from `SettingsRootDataSource` and from each other. - The Eureka helper-row library (`Sources/App/Settings/Eureka/`) is used only by those legacy view controllers. - A handful of doc-comment mentions in active SwiftUI code (e.g. `// SwiftUI replacement for ButtonRowWithLoading`) are not real references. - Tests don't import Eureka. `ColorPickerRow` and `ViewRow` (Eureka community pods) aren't referenced anywhere. ## What's removed - `Sources/App/Settings/Eureka/` — 14 files (`HAFormViewController`, helper rows, `AccountInitialsImage`) - `Sources/App/Settings/MaterialDesignIcons+Eureka.swift` — `SearchItem` conformance for the now-deleted `SearchPushRow` - `Sources/App/Settings/SettingsRootDataSource.swift` - `Sources/App/Settings/Settings/SettingsDetailViewController.swift` - `Sources/App/Settings/AppleWatch/Complication{List,FamilySelect,Edit}ViewController.swift` - `Sources/App/Settings/NFC/NFC{List,Tag}ViewController.swift` - `Sources/App/Utilities/{SearchPushRow,WebSocketStatusRow}.swift` - `Eureka`, `ColorPickerRow`, `ViewRow` pods (Podfile + Podfile.lock) - `import Eureka` from `SettingsSceneDelegate.swift` - `-framework "Eureka"` from inlined `OTHER_LDFLAGS` in `project.pbxproj` 24 files deleted, 4 modified. Pure dead-code removal — no behavior changes. ## Stacked on #4563 This PR targets `claude/eureka-notification-categories-swiftui` (PR #4563). After #4563 merges, GitHub will auto-rebase the base to `main`. ## Test plan - [ ] CI lint + test passes - [ ] Build succeeds with the smaller pod set - [ ] Manual smoke test: open Settings → NFC, Settings → Complications, Notifications → Categories — all SwiftUI screens still functional 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrate the notification category list and the category/action editors to SwiftUI:
NotificationCategoryListView: local insert/delete, Realm-observed server categories section, navigation to editor.NotificationCategoryEditorView: required fields, server-controlled read-only mode, hidden preview/summary text areas, reorder/insert/delete action rows, YAML service-call preview, toolbar help, preview-notification action.NotificationActionEditorView: required title/identifier, conditional text-input fields, foreground/destructive/authentication toggles, server-controlled read-only mode, YAML trigger preview.Also adds three reusable components:
YamlPreviewSection— replaces EurekaYamlSectionwithin this slice; generalises the inline version previously inNFCTagView.NotificationIdentifierField— SwiftUI text-field helper enforcing identifier casing/validation (replacesNotificationIdentifierEurekaRow).RealmResultsObserver—ObservableObjectwrappingAnyRealmCollectionwith a notification token (reusable by future slices).Deletes the three old
*Configurator.swift/*ViewController.swiftfiles plusNotificationIdentifierEurekaRow.swift.Screenshots
Pending — to be added before merge.
Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
Any other notes
Part of a five-PR Eureka → SwiftUI migration tracked in
UIKitToSwiftUIMigration.md(siblings: #4560, #4561, #4562, #4564). TheEureka,ColorPickerRow, andViewRowpods stay until all slices land.Reconciliation with #4562: this PR embeds
NotificationCategoryListViewinside the oldNotificationSettingsViewControllerviaUIHostingControllerso the list is reachable while the parent screen is still Eureka. Once #4562 merges,NotificationSettingsViewshould link directly toNotificationCategoryListView— the hosting-controller wrapper becomes unnecessary.YamlSection.swiftandRealmSection.swiftare retained — still used byActionConfigurator,NFCTagViewController,SettingsDetailViewController, andComplicationListViewController.bundle exec fastlane lintpasses. Not build-verified locally yet.🤖 Generated with Claude Code