iOS/Sources/App/Settings/EntityPicker/EntityRowView.swift
Bruno Pantaleão Gonçalves cd502a3ee1
Display entity picker as bottom sheet (#4278)
<!-- 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="1658" height="1142" alt="CleanShot 2026-01-30 at 11 00
58@2x"
src="https://github.com/user-attachments/assets/a06062c9-f373-499e-b42a-1b07b244019c"
/>


## 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. -->
2026-01-30 10:38:18 +00:00

82 lines
2.8 KiB
Swift

import SFSafeSymbols
import Shared
import SwiftUI
struct EntityRowView: View {
// This avoids lag while loading a screen with several rows
@State private var showIcon = false
@State private var subtitle = ""
@State private var title = ""
@State private var icon: UIImage?
private let entity: HAAppEntity?
private let optionalTitle: String?
private let accessoryImageSystemSymbol: SFSymbol?
private let isSelected: Bool
private let iconSize: CGSize = .init(width: 24, height: 24)
init(
entity: HAAppEntity? = nil,
optionalTitle: String? = nil,
accessoryImageSystemSymbol: SFSymbol? = nil,
isSelected: Bool = false
) {
self.entity = entity
self.optionalTitle = optionalTitle
self.accessoryImageSystemSymbol = accessoryImageSystemSymbol
self.isSelected = isSelected
}
var body: some View {
HStack(spacing: DesignSystem.Spaces.two) {
HStack {
if showIcon, let icon {
Image(uiImage: icon)
}
}
.frame(width: iconSize.width, height: iconSize.height)
VStack(alignment: .leading, spacing: 2) {
Text(title)
.frame(maxWidth: .infinity, alignment: .leading)
if !subtitle.isEmpty {
Text(subtitle)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.footnote)
.foregroundStyle(Color.secondary)
}
}
if isSelected {
Image(systemSymbol: .checkmark)
.foregroundStyle(.haPrimary)
} else if let accessoryImageSystemSymbol {
Image(systemSymbol: accessoryImageSystemSymbol)
.foregroundStyle(.white, .green)
.font(.title3)
}
}
.animation(.easeInOut, value: showIcon)
.onAppear {
title = optionalTitle ?? entity?.registryTitle ?? entity?.name ?? ""
subtitle = (entity?.contextualSubtitle).orEmpty
let fallbackIcon = Domain(entityId: (entity?.entityId).orEmpty)?.icon(deviceClass: entity?.rawDeviceClass)
if let entity {
icon = MaterialDesignIcons(
serversideValueNamed: entity.icon.orEmpty,
fallback: fallbackIcon ?? .dotsGridIcon
).image(
ofSize: .init(width: iconSize.width, height: iconSize.height),
color: UIColor(Color.gray)
)
}
showIcon = true
}
.onDisappear {
showIcon = false
}
}
}
#Preview {
EntityRowView(optionalTitle: "Example Entity")
}