iOS/Sources/Shared/API/WebSocket/HAPanel.swift

137 lines
4.3 KiB
Swift

import HAKit
public extension HACachesContainer {
var panels: HACache<HAPanels> { self[HAPanelsCacheKey.self] }
}
public struct HAPanel: HADataDecodable, Codable, Equatable {
public var icon: String?
public var title: String
public var path: String
public var component: String
public var showInSidebar: Bool
public init(data: HAData) throws {
let component: String = try data.decode("component_name")
self.component = component
let fallbackIcon: String? = { () -> String? in
switch component {
case "profile": return "mdi:account"
case "lovelace": return "mdi:view-dashboard"
default: return nil
}
}()
self.showInSidebar = data.decode("show_in_sidebar", fallback: true)
self.icon = data.decode("icon", fallback: fallbackIcon)
self.path = try data.decode("url_path")
let title: String = data.decode("title", fallback: component)
let possibleFrontendKey: String
if path == "lovelace" {
possibleFrontendKey = "panel::states"
} else {
possibleFrontendKey = "panel::\(title)"
}
self.title = Current.localized.frontend(possibleFrontendKey) ?? title
}
public init(icon: String?, title: String, path: String, component: String, showInSidebar: Bool) {
self.icon = icon
self.title = title
self.path = path
self.component = component
self.showInSidebar = showInSidebar
}
}
public struct HAPanels: HADataDecodable, Codable, Equatable {
public var panelsByPath: [String: HAPanel]
public var allPanels: [HAPanel]
public init(panelsByPath: [String: HAPanel]) {
self.panelsByPath = panelsByPath
self.allPanels = panelsByPath.values.sorted(by: {
let sortedByTitle = $0.title.localizedCaseInsensitiveCompare($1.title) == .orderedAscending
switch ($0.component, $1.component) {
case ("lovelace", "lovelace"):
return sortedByTitle
case ("lovelace", _):
return true
case (_, "lovelace"):
return false
default:
// from the frontend as of 9a928259549b255ae79fbdb412538109e31d62d2 2021-07-28
// https://github.com/home-assistant/frontend/blob/b26c44b2/src/components/ha-sidebar.ts#L55-L63
let pathSortValue = [
"energy": 1,
"map": 2,
"logbook": 3,
"history": 4,
"developer-tools": 9,
"hassio": 10,
"config": 11,
]
let sort0 = pathSortValue[$0.path, default: -1]
let sort1 = pathSortValue[$1.path, default: -1]
if sort0 == sort1 {
return sortedByTitle
} else {
return sort0 < sort1
}
}
})
}
public init(data: HAData) throws {
guard case let .dictionary(dictionary) = data else {
throw HADataError.missingKey("root")
}
try self.init(
panelsByPath: dictionary
.compactMapKeys {
if $0.hasPrefix("_") {
return nil
} else {
return $0
}
}
.mapValues {
try HAPanel(data: .init(value: $0))
}
// non-show_in_sidebar dashboards have badly-named titles
.filter(\.value.showInSidebar)
)
}
}
public extension HATypedRequest {
static func panels() -> HATypedRequest<HAPanels> {
.init(request: .init(type: "get_panels"))
}
}
private struct HAPanelsCacheKey: HACacheKey {
static func create(connection: HAConnection) -> HACache<HAPanels> {
HACache(
connection: connection,
populate: .init(
request: .panels(),
transform: { $0.incoming }
),
subscribe: [
HACacheSubscribeInfo(
subscription: .events("panels_updated"),
transform: { _ in .reissuePopulate }
),
]
)
}
}