fix: ControlSchema tolerate missing options field (Filler etc)

This commit is contained in:
yumoqing 2026-06-21 23:18:53 +08:00
parent 5ba2ae163b
commit c72a018764
5 changed files with 57 additions and 35 deletions

View File

@ -80,11 +80,13 @@ struct MenuControl: View {
} }
@ViewBuilder @ViewBuilder
private func menuItemView(_ item: MenuItemSchema, depth: Int) -> some View { private func menuItemView(_ item: MenuItemSchema, depth: Int) -> AnyView {
let hasChildren = !(item.submenu?.isEmpty ?? true) let hasChildren = !(item.submenu?.isEmpty ?? true)
let isExpanded = expandedItems.contains(item.name) let isExpanded = expandedItems.contains(item.name)
let isSelected = selectedItem == item.name let isSelected = selectedItem == item.name
return AnyView(
VStack(alignment: .leading, spacing: 0) {
Button(action: { handleMenuClick(item, hasChildren: hasChildren) }) { Button(action: { handleMenuClick(item, hasChildren: hasChildren) }) {
HStack(spacing: 8) { HStack(spacing: 8) {
if let icon = item.icon { if let icon = item.icon {
@ -118,6 +120,8 @@ struct MenuControl: View {
} }
} }
} }
)
}
private func handleMenuClick(_ item: MenuItemSchema, hasChildren: Bool) { private func handleMenuClick(_ item: MenuItemSchema, hasChildren: Bool) {
if hasChildren { if hasChildren {
@ -173,7 +177,11 @@ struct PopupWindowControl: View {
.padding(12) .padding(12)
} }
} }
#if os(iOS)
.background(Color(.systemBackground)) .background(Color(.systemBackground))
#else
.background(Color(nsColor: .windowBackgroundColor))
#endif
.cornerRadius(12) .cornerRadius(12)
.shadow(radius: 8) .shadow(radius: 8)
} }

View File

@ -140,7 +140,7 @@ public final class BricksEngine: ObservableObject {
} }
/// bind /// bind
public func handleBind(_ bind: BindSchema, sourceId: String, eventData: EventData = [:]) async { public func handleBind(_ bind: BindSchema, sourceId: String, eventData: EventData = EventData()) async {
guard let actionType = ActionType(rawValue: bind.actiontype) else { guard let actionType = ActionType(rawValue: bind.actiontype) else {
print("[SwiftBricks] Invalid actiontype: \(bind.actiontype)") print("[SwiftBricks] Invalid actiontype: \(bind.actiontype)")
return return
@ -306,7 +306,7 @@ public final class BricksEngine: ObservableObject {
// MARK: - // MARK: -
/// widget /// widget
public func triggerEvent(widgetId: String, event: String, data: EventData = [:]) async { public func triggerEvent(widgetId: String, event: String, data: EventData = EventData()) async {
await eventBus.dispatch("\(widgetId).\(event)", data: data) await eventBus.dispatch("\(widgetId).\(event)", data: data)
} }

View File

@ -34,7 +34,7 @@ public final class BricksEventBus: ObservableObject {
// MARK: - // MARK: -
/// ///
public func dispatch(_ eventName: String, data: EventData = [:]) async { public func dispatch(_ eventName: String, data: EventData = EventData()) async {
// //
eventLog.append((name: eventName, data: data, timestamp: Date())) eventLog.append((name: eventName, data: data, timestamp: Date()))
if eventLog.count > maxLogSize { if eventLog.count > maxLogSize {
@ -50,7 +50,7 @@ public final class BricksEventBus: ObservableObject {
} }
/// UI /// UI
public func dispatchSync(_ eventName: String, data: EventData = [:]) { public func dispatchSync(_ eventName: String, data: EventData = EventData()) {
Task { @MainActor in Task { @MainActor in
await dispatch(eventName, data: data) await dispatch(eventName, data: data)
} }

View File

@ -131,7 +131,7 @@ public final class BricksRPC: ObservableObject {
throw BricksRPCError.invalidResponse throw BricksRPCError.invalidResponse
} }
let responseHeaders = Dictionary( let responseHeaders: [String: String] = Dictionary(
uniqueKeysWithValues: httpResponse.allHeaderFields.compactMap { key, value in uniqueKeysWithValues: httpResponse.allHeaderFields.compactMap { key, value in
guard let keyStr = key as? String, let valStr = value as? String else { return nil } guard let keyStr = key as? String, let valStr = value as? String else { return nil }
return (keyStr, valStr) return (keyStr, valStr)

View File

@ -30,6 +30,20 @@ public struct ControlSchema: Codable, Identifiable, Sendable {
self.binds = binds self.binds = binds
self.subwidgets = subwidgets self.subwidgets = subwidgets
} }
/// optionsFilleroptionswidget
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decodeIfPresent(String.self, forKey: .id)
self.widgettype = try container.decode(String.self, forKey: .widgettype)
self.options = try container.decodeIfPresent(ControlOptions.self, forKey: .options) ?? ControlOptions()
self.binds = try container.decodeIfPresent([BindSchema].self, forKey: .binds)
self.subwidgets = try container.decodeIfPresent([ControlSchema].self, forKey: .subwidgets)
}
private enum CodingKeys: String, CodingKey {
case id, widgettype, options, binds, subwidgets
}
} }
/// 使+Codable /// 使+Codable