Phase 6 commit B:SubGameDownloader zip 下载 + 解压

- 新增 Source/Resource/SubGameDownloader.swift(actor):URLSession + ZIPFoundation,
  缓存命中直接复用(看 {Caches}/{gameDir}/{gameStart}/index.html 是否存在),
  未命中下载 → staging 解压 → 原子 rename(与 LobbyZipUpgrader 同思路;
  msext gameController.m:1340-1401 等价,以 staging 替代 msext 直接覆盖避免半残留)
- SubGameViewController.runBootPipelineSteps:接入 ensureReady,splash 实时更新下载进度,
  移除 commit A 占位的 SubGameBootError
- DownloadProgressDelegate 与 LobbyZipUpgrader 同款就地复制(两处用不抽公共,
  三处出现时再合并)
- Plan §5.6.7 / §8 进度已勾选

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
joywayer
2026-06-22 21:01:53 +08:00
co-authored by Claude Opus 4.7
parent 7a5644053d
commit a9eaf86c63
3 changed files with 178 additions and 27 deletions
@@ -164,15 +164,19 @@ public final class SubGameViewController: UIViewController {
}
private func runBootPipelineSteps() async throws {
// 1. zip commit B SubGameDownloader
// commit A FileManager commit B
let indexURL = SandboxPaths.subGameIndex(request.gameDir, request.gameStart)
guard FileManager.default.fileExists(atPath: indexURL.path) else {
throw SubGameBootError.subGameNotInstalled(
dir: request.gameDir,
downloadURL: request.downloadURL
)
}
// 1. zip + + rename
splash.update(text: "准备子游戏...", progress: nil)
_ = try await SubGameDownloader.shared.ensureReady(
request: request,
onProgress: { [weak self] p in
Task { @MainActor in
self?.splash.update(
text: String(format: "下载子游戏 %d%%", Int(p * 100)),
progress: p
)
}
}
)
// 2. 4 app_*.jscontainerRole = .subGameBatteryMonitor / NetworkMonitor
// currentXxx
@@ -187,6 +191,7 @@ public final class SubGameViewController: UIViewController {
// 3. H5allowingReadAccessTo subGameRoot
splash.update(text: "进入子游戏...", progress: nil)
let indexURL = SandboxPaths.subGameIndex(request.gameDir, request.gameStart)
bridgedWebView.webView.loadFileURL(
indexURL,
allowingReadAccessTo: SandboxPaths.subGameRoot(request.gameDir)
@@ -239,23 +244,12 @@ public final class SubGameViewController: UIViewController {
AppLifecycleObserver.shared.onForeground = nil
}
// MARK: - Errors
private enum SubGameBootError: LocalizedError {
case subGameNotInstalled(dir: String, downloadURL: String)
var errorDescription: String? {
switch self {
case .subGameNotInstalled(let dir, _):
return "子游戏未安装(\(dir)),下载流程待 Phase 6.B 接入"
}
}
}
// MARK: - Error alert
private func showFatalAlert(error: Error) {
let alert = UIAlertController(
title: "加载失败",
message: "\(error.localizedDescription)",
message: "\(error)",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "返回大厅", style: .default) { [weak self] _ in