diff --git a/src/ConfigView.swift b/src/ConfigView.swift index 7f2c1c8..f6c9b42 100644 --- a/src/ConfigView.swift +++ b/src/ConfigView.swift @@ -46,7 +46,8 @@ struct ConfigView: View { data: child, onUpdate: { value in setConfig(uri, child["Option"] as! String, value) - viewModel.refresh(uri) + // Don't call viewModel.refresh here because view may be in a temporary invalid state, + // e.g. having removed key of punctuation map but not put anything yet. }) } } diff --git a/src/config/ListView.swift b/src/config/ListView.swift index 19945e3..79dca2c 100644 --- a/src/config/ListView.swift +++ b/src/config/ListView.swift @@ -14,6 +14,7 @@ private func serialize(_ value: [Any]) -> [String: Any] { } private struct ListSectionHeader: View { + let children: Any? @Binding var value: Any var body: some View { @@ -21,7 +22,14 @@ private struct ListSectionHeader: View { Spacer() Button { var list = deserialize(value) - list.append("") + if let children = children as? [[String: Any]] { + list.append( + children.reduce(into: [:]) { result, child in + result[child["Option"] as! String] = child["DefaultValue"] ?? "" + } as NSDictionary) + } else { + list.append("") + } value = serialize(list) } label: { Image(systemName: "plus") @@ -40,7 +48,7 @@ struct ListSubView: OptionViewProtocol { let optionViewType = toOptionViewType(["Type": String(type.suffix(type.count - "List|".count))]) var list = deserialize(value) List { - Section(header: ListSectionHeader(value: $value)) { + Section(header: ListSectionHeader(children: data["Children"], value: $value)) { ForEach(list.indices, id: \.self) { i in AnyView( optionViewType.init( diff --git a/src/config/StringView.swift b/src/config/StringView.swift index 2e9aac1..ac1881e 100644 --- a/src/config/StringView.swift +++ b/src/config/StringView.swift @@ -14,7 +14,12 @@ struct StringView: View, OptionViewProtocol { "", text: Binding( get: { value as! String }, - set: { value = $0 } + set: { + // Avoid unnecessary write. + if value as! String != $0 { + value = $0 + } + } ) ) // Leading for List item, trailing for String option.