合并 resolveAudio 进 resolve():所有 RemoteConfig 字段走单一入口 + 同款 4 层 fallback

【动机】
上个 commit 把 audio_domain/audio_bucket 改成 4 层 fallback,但用了独立的
resolveAudio() 入口 —— 与 resolve() 并存意味着调用方要记两个 API,违反
"统一接口"原则。

【方案】
- ResolvedVersion 加 audioDomain / audioBucket 两个字段(扁平结构)
- resolve() 内直接 pickString(chain, \.audioDomain) ?? config.audioDomain 一次解出
- 删除 resolveAudio() 公开入口
- WebContainerViewController parsed 分支:单次 resolve() 调用 + 同一 r 取所有字段

【硬约束(Plan ADR-009 同步)】
远端 RemoteConfig 所有字段必须走 VersionResolver.resolve(...) 单一入口、
同一套 4 层 fallback;新增字段时加进协议 + 节点 struct + ResolvedVersion +
一行 pickString,不允许为某字段单独写 if 链或 helper。

BuildProject 通过。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
joywayer
2026-06-27 21:32:57 +08:00
co-authored by Claude Opus 4.7
parent a54d1511be
commit 485f0c6679
3 changed files with 27 additions and 50 deletions
@@ -19,7 +19,7 @@ import Foundation
// MARK: -
/// 4 fallback 5
/// 4 fallback chain + pickString/Int
public struct ResolvedVersion: Sendable, Equatable {
/// IPA BundleConfig.appVersion 0
public let appVersion: Int
@@ -31,6 +31,10 @@ public struct ResolvedVersion: Sendable, Equatable {
public let gameZip: String?
/// msext #2
public let showmessage: String?
/// CDN http:// 访 URL nil
public let audioDomain: String?
/// bucket putPolicy.scopenil
public let audioBucket: String?
}
// MARK: - 4
@@ -82,35 +86,10 @@ public enum VersionResolver {
appDownload: pickString(chain, \.appDownload),
gameVersion: pickInt(chain, \.gameVersion),
gameZip: pickString(chain, \.gameZip),
// showmessage: 退 config.showmessage
showmessage: pickString(chain, \.showmessage) ?? config.showmessage
)
}
// MARK: - 4 fallback +
/// CDN / bucket 4 fallback
/// agent game channel market `audio_domain` / `audio_bucket`
/// fallback RemoteConfig `audio_domain` / `audio_bucket`
///
/// - Returns: `(domain, bucket)` + nil
public static func resolveAudio(
config: RemoteConfig,
agentId: String,
channelId: String,
marketId: String,
gameId: String
) -> (domain: String?, bucket: String?) {
let chain = buildChain(
config: config,
agentId: agentId,
gameId: gameId,
channelId: channelId,
marketId: marketId
)
return (
domain: pickString(chain, \.audioDomain) ?? config.audioDomain,
bucket: pickString(chain, \.audioBucket) ?? config.audioBucket
// showmessage / audioDomain / audioBucket: 退 config
showmessage: pickString(chain, \.showmessage) ?? config.showmessage,
audioDomain: pickString(chain, \.audioDomain) ?? config.audioDomain,
audioBucket: pickString(chain, \.audioBucket) ?? config.audioBucket
)
}