Skip to content

Watch folders PR with fixed pbxproj#4396

Merged
bgoncal merged 50 commits intohome-assistant:mainfrom
joelhawksley:watch-folders
Mar 1, 2026
Merged

Watch folders PR with fixed pbxproj#4396
bgoncal merged 50 commits intohome-assistant:mainfrom
joelhawksley:watch-folders

Conversation

@joelhawksley
Copy link
Contributor

#4376, but with pbxproj rebuilt with minimum changes.

joelhawksley and others added 30 commits January 23, 2026 14:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ew.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…rationView.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…rationView.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds “folder” support to the Apple Watch Magic Items configuration, allowing users to group items into folders in the iOS configuration UI and navigate into those folders in the watchOS app.

Changes:

  • Extend MagicItem/MagicItemProvider/watch communication to support a new .folder item type and include folder children when sending watch config metadata.
  • Add iOS configuration UI for creating folders and managing folder contents (add/reorder/delete items, edit folder appearance).
  • Add watchOS UI to render folders as rows and show folder contents in a dedicated view, plus update tests.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Tests/App/Watch/WatchConfig.test.swift Adds unit tests covering folder operations in WatchConfigurationViewModel.
Sources/Watch/WatchCommunicatorService.swift Includes folder children when collecting magicItemsInfo; prevents executing folder “items”.
Sources/Shared/Resources/Swiftgen/Strings.swift Adds generated SwiftGen accessors for new watch folder strings.
Sources/Shared/MagicItem/MagicItemProvider.swift Adds getInfo(for:) support for .folder.
Sources/Shared/MagicItem/MagicItem.swift Adds items (children) and new .folder item type.
Sources/Extensions/Watch/Home/WatchHomeViewModel.swift Replaces list refresh workaround with a config version UUID.
Sources/Extensions/Watch/Home/WatchHomeView.swift Adds folder navigation behavior and uses configVersion to force list refresh.
Sources/Extensions/Watch/Home/WatchFolderContentView.swift New watchOS view to display folder contents.
Sources/Extensions/Watch/Home/MagicItemRow/WatchMagicViewRow.swift Refactors icon color usage to avoid repeated hex parsing.
Sources/Extensions/Watch/Home/MagicItemRow/WatchFolderRow.swift New watchOS row UI for folders.
Sources/App/Settings/AppleWatch/HomeCustomization/WatchConfigurationViewModel.swift Adds folder CRUD/move logic in config view model.
Sources/App/Settings/AppleWatch/HomeCustomization/WatchConfigurationView.swift Adds “Add Folder” sheet and folder detail navigation; updates icon coloring logic.
Sources/App/Settings/AppleWatch/HomeCustomization/FolderEditView.swift New iOS view to edit folder name/icon/colors.
Sources/App/Settings/AppleWatch/HomeCustomization/FolderDetailView.swift New iOS view to manage items inside a folder.
Sources/App/Resources/en.lproj/Localizable.strings Adds new English localization keys for folder UI.
HomeAssistant.xcodeproj/project.pbxproj Registers new Swift source files in the Xcode project/targets.

Comment on lines +116 to +133
func moveItemToFolder(itemId: String, serverId: String, toFolderId: String) {
// Remove from root if present
if let rootIndex = watchConfig.items.firstIndex(where: { $0.id == itemId && $0.serverId == serverId }) {
let item = watchConfig.items.remove(at: rootIndex)
addItemToFolder(folderId: toFolderId, item: item)
return
}
// Remove from any folder if present
for (folderIndex, folder) in watchConfig.items.enumerated() where folder.type == .folder {
if var items = folder.items,
let index = items.firstIndex(where: { $0.id == itemId && $0.serverId == serverId }) {
let item = items.remove(at: index)
var updatedFolder = folder
updatedFolder.items = items
watchConfig.items[folderIndex] = updatedFolder
addItemToFolder(folderId: toFolderId, item: item)
return
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moveItemToFolder removes the item from the root / source folder before verifying that toFolderId exists. If the destination folder ID is invalid (or the folder was deleted concurrently), addItemToFolder will no-op and the item is effectively lost. Consider first validating the destination folder index (or making addItemToFolder return a Bool) and only removing the item when the destination write succeeds; otherwise, keep the item in its original location.

Copilot uses AI. Check for mistakes.
Comment on lines +210 to +216
case .folder:
return .init(
id: item.serverUniqueId,
name: item.displayText ?? L10n.Watch.Configuration.Folder.defaultName,
iconName: MaterialDesignIcons.folderIcon.name,
customization: item.customization
)
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Folders introduce nested MagicItems, but the watch-config migration (migrateItemsIfNeeded) only considers the root items array. This means any server-ID repair/migration logic will be skipped for items inside folder.items, and those children can remain broken after server re-add/ID changes. Consider updating the migration logic to recursively migrate children of .folder items (and then persist the updated config).

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +33
.onChange(of: useCustomColors) { newValue in
if newValue {
folder.customization?.backgroundColor = folder.customization?.backgroundColor ?? UIColor.black
.hexString()
folder.customization?.textColor = folder.customization?.textColor ?? UIColor.white.hexString()
} else {
folder.customization?.backgroundColor = nil
folder.customization?.textColor = nil
}
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

folder.customization is optional, but several setters here use optional chaining (e.g., folder.customization?.backgroundColor = ...). If customization is nil (which can happen when decoding older configs), toggling custom colors and the color pickers will silently do nothing. Initializing folder.customization in init (or inside the onChange before writing) would make the edit screen robust without relying on onAppear timing.

Copilot uses AI. Check for mistakes.
@codecov
Copy link

codecov bot commented Mar 1, 2026

Codecov Report

❌ Patch coverage is 15.38462% with 11 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@b8bd9ba). Learn more about missing BASE report.

Files with missing lines Patch % Lines
Sources/Shared/MagicItem/MagicItemProvider.swift 14.28% 6 Missing ⚠️
Sources/Shared/MagicItem/MagicItem.swift 16.66% 5 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4396   +/-   ##
=======================================
  Coverage        ?   42.75%           
=======================================
  Files           ?      265           
  Lines           ?    15505           
  Branches        ?        0           
=======================================
  Hits            ?     6629           
  Misses          ?     8876           
  Partials        ?        0           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bgoncal bgoncal merged commit fff4731 into home-assistant:main Mar 1, 2026
16 of 18 checks passed
@joelhawksley joelhawksley deleted the watch-folders branch March 2, 2026 02:17
@bgoncal
Copy link
Member

bgoncal commented Mar 3, 2026

@joelhawksley It's in TestFlight already, thank you for your contribution! Quite cool feature 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants