Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions assets/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@
}
}
},
"%lld updated, %lld failed, %lld canceled": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "%1$lld updated, %2$lld failed, %3$lld canceled"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "%1$lld 个已更新,%2$lld 个失败,%3$lld 个已取消"
}
}
}
},
"A New Nightly Is Available": {
"localizations": {
"en": {
Expand Down Expand Up @@ -401,6 +417,22 @@
}
}
},
"Cancel All": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Cancel All"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "全部取消"
}
}
}
},
"Canceling…": {
"localizations": {
"en": {
Expand Down Expand Up @@ -817,6 +849,22 @@
}
}
},
"Dismiss": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Dismiss"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "关闭"
}
}
}
},
"Done": {
"localizations": {
"en": {
Expand Down Expand Up @@ -897,6 +945,22 @@
}
}
},
"Failed Updates": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Failed Updates"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "更新失败的应用"
}
}
}
},
"Games": {
"localizations": {
"en": {
Expand Down Expand Up @@ -1905,6 +1969,22 @@
}
}
},
"Some Updates Failed": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Some Updates Failed"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "部分应用更新失败"
}
}
}
},
"Source Repository": {
"localizations": {
"en": {
Expand Down Expand Up @@ -2001,6 +2081,22 @@
}
}
},
"Stopping Updates…": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Stopping Updates…"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "正在停止更新…"
}
}
}
},
"The app catalog is invalid. Try refreshing it again later.": {
"localizations": {
"en": {
Expand Down Expand Up @@ -2449,6 +2545,22 @@
}
}
},
"Update All": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Update All"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "全部更新"
}
}
}
},
"Update SimStore to read this app catalog.": {
"localizations": {
"en": {
Expand Down Expand Up @@ -2497,6 +2609,70 @@
}
}
},
"Updates Canceled": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Updates Canceled"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "更新已取消"
}
}
}
},
"Updates Complete": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Updates Complete"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "更新完成"
}
}
}
},
"Updating Apps": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Updating Apps"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "正在更新应用"
}
}
}
},
"Updating…": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Updating…"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "正在更新…"
}
}
}
},
"Utilities": {
"localizations": {
"en": {
Expand Down Expand Up @@ -2577,6 +2753,22 @@
}
}
},
"Waiting…": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Waiting…"
}
},
"zh-Hans": {
"stringUnit": {
"state": "translated",
"value": "等待中…"
}
}
}
},
"Xcode did not provide a valid developer directory.": {
"localizations": {
"en": {
Expand Down
2 changes: 2 additions & 0 deletions docs/cache.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ App archives are streamed to a separate, randomly named directory under `URL.tem

The archive's size and SHA-256 must match the selected catalog version before extraction. The temporary archive and extracted app are removed when the operation succeeds, fails, or finishes canceling. Cancellation during preparation waits for any running archive command to finish before cleanup; once `simctl install` starts, it is allowed to finish. A process exit can leave temporary files for the operating system to reclaim.

Update All snapshots all compatible pending updates for the selected simulator, independently of search and category filters, and runs them one at a time through the same installation pipeline. Apps already running another operation are omitted. Queued apps have no downloaded files, reserve their per-app/device operation slots, and retain their selected version, size, and checksum even if the catalog refreshes. Each simulator has its own queue and results, which remain in memory when navigating or switching devices. A failure records its diagnostic and the next app proceeds; another Update All action retries only apps that still need updates. Canceling a queued item releases it immediately. Cancel All cancels pending downloads/preparation and removes the remaining queue, while an installation already handed to `simctl` finishes normally. Completed updates retain their usual Open actions until navigation, catalog refresh, or opening removes them from the update list.

## SimStore updates

The client's own `version.json` feed is fetched on each explicit update check with the local HTTP cache bypassed and `Cache-Control: no-cache`. It has no disk cache, ETag storage, expiry timer, or offline fallback. The most recent result and selected release are kept in memory for the current application session. Before downloading a nightly, SimStore checks the current feed again and asks for another update check if the offered build has changed.
Expand Down
2 changes: 1 addition & 1 deletion src/AppInstallButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct AppInstallButton: View {

private var action: AppInstallationAction {
switch phase {
case .downloading, .verifying, .extracting: .cancel
case .queued, .downloading, .verifying, .extracting: .cancel
case .installing: .installing
case .canceling: .canceling
case .opening: .opening
Expand Down
4 changes: 3 additions & 1 deletion src/AppInstallationPhase.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Foundation

enum AppInstallationPhase: Equatable, Sendable {
case queued
case downloading(Int64)
case verifying
case extracting
Expand All @@ -11,13 +12,14 @@ enum AppInstallationPhase: Equatable, Sendable {

var canCancel: Bool {
switch self {
case .downloading, .verifying, .extracting: true
case .queued, .downloading, .verifying, .extracting: true
case .installing, .canceling, .opening, .uninstalling: false
}
}

var title: String {
switch self {
case .queued: String(localized: "Waiting…")
case .downloading: String(localized: "Downloading…")
case .verifying: String(localized: "Verifying…")
case .extracting: String(localized: "Preparing App…")
Expand Down
Loading