

























@@ -37,6 +37,38 @@ extension ChannelsStore {
3737}
3838}
393940+@discardableResult
41+func loadConfigSchemaLookup(path: String, force: Bool = false) async -> ConfigSchemaLookupNode? {
42+let sourceKey = self.currentConfigCacheSourceKey()
43+self.resetConfigSchemaCacheIfSourceChanged(sourceKey)
44+let normalizedPath = Self.normalizeConfigLookupPath(path)
45+if !force, let cached = self.configLookupNode(path: normalizedPath) {
46+return cached
47+}
48+if self.configLookupLoadingPaths.contains(normalizedPath) {
49+return self.configLookupNode(path: normalizedPath)
50+}
51+52+self.configLookupLoadingPaths.insert(normalizedPath)
53+defer { self.configLookupLoadingPaths.remove(normalizedPath) }
54+55+do {
56+let res: ConfigSchemaLookupResult = try await GatewayConnection.shared.requestDecoded(
57+ method: .configSchemaLookup,
58+ params: ["path": AnyCodable(normalizedPath)],
59+ timeoutMs: 5000)
60+guard let node = self.makeConfigLookupNode(res) else {
61+self.configStatus = "Config schema lookup returned an unsupported payload."
62+return nil
63+}
64+self.applyConfigLookupNode(node, sourceKey: sourceKey)
65+return node
66+} catch {
67+self.configStatus = error.localizedDescription
68+return nil
69+}
70+}
71+4072func loadConfig(force: Bool = true) async {
4173let sourceKey = self.currentConfigCacheSourceKey()
4274self.resetConfigCacheIfSourceChanged(sourceKey)
@@ -100,6 +132,44 @@ extension ChannelsStore {
100132self.configSchemaSourceKey = sourceKey
101133}
102134135+func configLookupNode(path: String) -> ConfigSchemaLookupNode? {
136+let normalizedPath = Self.normalizeConfigLookupPath(path)
137+if normalizedPath == "." {
138+return self.configLookupRoot
139+}
140+return self.configLookupCache[normalizedPath]
141+}
142+143+func makeConfigLookupNode(_ res: ConfigSchemaLookupResult) -> ConfigSchemaLookupNode? {
144+let schemaValue = res.schema.foundationValue
145+guard let schema = ConfigSchemaNode(raw: schemaValue) else { return nil }
146+let hint = res.hint.map { ConfigUiHint(raw: $0.mapValues(\.foundationValue)) }
147+let children = res.children.compactMap(ConfigSchemaLookupChild.init(raw:))
148+return ConfigSchemaLookupNode(
149+ path: Self.normalizeConfigLookupPath(res.path),
150+ schema: schema,
151+ hint: hint,
152+ hintPath: res.hintpath,
153+ children: children)
154+}
155+156+func applyConfigLookupNode(_ node: ConfigSchemaLookupNode, sourceKey: String) {
157+guard self.configSchemaSourceKey == sourceKey else { return }
158+if node.path == "." {
159+self.configLookupRoot = node
160+} else {
161+self.configLookupCache[node.path] = node
162+}
163+if let hint = node.hint {
164+self.configUiHints[node.path] = hint
165+}
166+for child in node.children {
167+if let hint = child.hint {
168+self.configUiHints[child.path] = hint
169+}
170+}
171+}
172+103173private func applyUIConfig(_ snap: ConfigSnapshot) {
104174let ui = snap.config?["ui"]?.dictionaryValue
105175let rawSeam = ui?["seamColor"]?.stringValue?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
@@ -154,6 +224,9 @@ extension ChannelsStore {
154224}
155225guard cachedSourceKey != sourceKey else { return }
156226self.configSchema = nil
227+self.configLookupRoot = nil
228+self.configLookupCache.removeAll(keepingCapacity: true)
229+self.configLookupLoadingPaths.removeAll(keepingCapacity: true)
157230self.configUiHints = [:]
158231self.configSchemaSourceKey = sourceKey
159232}
@@ -204,6 +277,11 @@ extension ChannelsStore {
204277].joined(separator: "|")
205278}
206279280+static func normalizeConfigLookupPath(_ path: String) -> String {
281+let trimmed = path.trimmingCharacters(in: .whitespacesAndNewlines)
282+return trimmed.isEmpty ? "." : trimmed
283+}
284+207285private static func configFingerprint(_ value: Any?) -> String {
208286guard let value else { return "nil" }
209287if JSONSerialization.isValidJSONObject(value),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。