new app store assets ready for relese ui updates
This commit is contained in:
+2
-2
@@ -144,12 +144,12 @@ struct TorrentRow: View {
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
(dynamicTypeSize.isAccessibilitySize ? AnyLayout(VStackLayout(alignment: .leading, spacing: 6)) : AnyLayout(HStackLayout(alignment: .top))) {
|
||||
Image(systemName: torrent.complete ? "checkmark.circle.fill" : "arrow.down.circle.fill").foregroundStyle(torrent.complete ? .green : .yellow).font(.title2)
|
||||
Image(systemName: torrent.complete ? "checkmark.circle.fill" : "arrow.down.circle.fill").foregroundStyle(torrent.statusColor).font(.title2)
|
||||
Text(torrent.name).font(.headline).lineLimit(dynamicTypeSize.isAccessibilitySize ? nil : 2)
|
||||
if !dynamicTypeSize.isAccessibilitySize { Spacer() }
|
||||
Text(torrent.progress, format: .percent.precision(.fractionLength(1))).font(.subheadline.monospacedDigit()).foregroundStyle(.secondary)
|
||||
}
|
||||
ProgressView(value: torrent.complete ? 1 : min(max(torrent.progress, 0), 1)).tint(torrent.complete ? .green : .yellow).accessibilityLabel("Download progress")
|
||||
ProgressView(value: torrent.complete ? 1 : min(max(torrent.progress, 0), 1)).tint(torrent.statusColor).accessibilityLabel("Download progress")
|
||||
(dynamicTypeSize.isAccessibilitySize ? AnyLayout(VStackLayout(alignment: .leading, spacing: 6)) : AnyLayout(HStackLayout())) {
|
||||
Label(bytes(torrent.dlspeed) + "/s", systemImage: "arrow.down").accessibilityLabel("Download speed").accessibilityValue(bytes(torrent.dlspeed) + " per second")
|
||||
Label(bytes(torrent.upspeed) + "/s", systemImage: "arrow.up").accessibilityLabel("Upload speed").accessibilityValue(bytes(torrent.upspeed) + " per second")
|
||||
|
||||
@@ -43,6 +43,13 @@ struct Torrent: Decodable, Identifiable, Hashable {
|
||||
var ratio: Double; var category: String; var tags: String
|
||||
var id: String { hash }
|
||||
var complete: Bool { progress >= 1 || ["uploading", "stalledUP", "forcedUP", "queuedUP", "pausedUP", "stoppedUP"].contains(state) }
|
||||
var statusColor: Color {
|
||||
if ["error", "missingFiles"].contains(state) || state.hasPrefix("stalled") { return .red }
|
||||
if paused { return .pink }
|
||||
if state.hasPrefix("queued") { return .orange }
|
||||
if ["uploading", "forcedUP"].contains(state) { return .purple }
|
||||
return complete ? .green : .yellow
|
||||
}
|
||||
var paused: Bool { state.hasPrefix("paused") || state.hasPrefix("stopped") }
|
||||
var active: Bool { ["downloading", "forcedDL", "metaDL", "forcedMetaDL"].contains(state) }
|
||||
}
|
||||
|
||||
+30
-10
@@ -21,10 +21,11 @@ struct DetailView: View {
|
||||
List {
|
||||
Section { TorrentRow(torrent: live) }
|
||||
Section {
|
||||
ViewThatFits(in: .horizontal) {
|
||||
HStack { primaryControls }
|
||||
VStack(alignment: .leading) { primaryControls }
|
||||
}.buttonStyle(.bordered).controlSize(.regular)
|
||||
if dynamicTypeSize.isAccessibilitySize {
|
||||
VStack(spacing: 8) { primaryControls }
|
||||
} else {
|
||||
HStack(spacing: 8) { primaryControls }
|
||||
}
|
||||
if model.pendingActions.contains(torrent.hash) { ProgressView("Applying action…") }
|
||||
if let feedback = model.actionFeedback { Text(feedback).font(.callout) }
|
||||
}
|
||||
@@ -71,12 +72,15 @@ struct DetailView: View {
|
||||
}
|
||||
}
|
||||
@ViewBuilder var primaryControls: some View {
|
||||
Button("Resume", systemImage: "play.fill") { Task { await model.action("resume", hash: torrent.hash) } }
|
||||
.frame(minHeight: 44).disabled(!live.paused || model.pendingActions.contains(torrent.hash))
|
||||
Button("Pause", systemImage: "pause.fill") { Task { await model.action("pause", hash: torrent.hash) } }
|
||||
.frame(minHeight: 44).disabled(live.paused || model.pendingActions.contains(torrent.hash))
|
||||
Menu("More", systemImage: "ellipsis.circle") { controls }
|
||||
.frame(minHeight: 44).disabled(model.pendingActions.contains(torrent.hash) || !model.connected)
|
||||
Button("Resume") { Task { await model.action("resume", hash: torrent.hash) } }
|
||||
.buttonStyle(TorrentActionButtonStyle())
|
||||
.disabled(!live.paused || model.pendingActions.contains(torrent.hash) || !model.connected)
|
||||
Button("Pause") { Task { await model.action("pause", hash: torrent.hash) } }
|
||||
.buttonStyle(TorrentActionButtonStyle())
|
||||
.disabled(live.paused || model.pendingActions.contains(torrent.hash) || !model.connected)
|
||||
Menu { controls } label: { Text("More") }
|
||||
.buttonStyle(TorrentActionButtonStyle())
|
||||
.disabled(model.pendingActions.contains(torrent.hash) || !model.connected)
|
||||
}
|
||||
var controls: some View {
|
||||
Group {
|
||||
@@ -194,3 +198,19 @@ struct KeyValues: View {
|
||||
}
|
||||
}
|
||||
import CoreFoundation
|
||||
|
||||
// Identical label frames keep the two buttons and the menu the same size.
|
||||
private struct TorrentActionButtonStyle: ButtonStyle {
|
||||
@Environment(\.isEnabled) private var isEnabled
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
configuration.label
|
||||
.font(.subheadline.weight(.medium))
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal, 4)
|
||||
.frame(maxWidth: .infinity, minHeight: 44)
|
||||
.foregroundStyle(isEnabled ? Color.accentColor : Color.secondary)
|
||||
.background(Color.accentColor.opacity(configuration.isPressed ? 0.24 : 0.10), in: RoundedRectangle(cornerRadius: 10))
|
||||
.contentShape(RoundedRectangle(cornerRadius: 10))
|
||||
.opacity(isEnabled ? 1 : 0.55)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,3 +105,7 @@ Build 7 adds blue/indigo/violet download strokes, teal dashed upload strokes, in
|
||||
Device acceptance still required: narrow iPhone/iPad widths and largest Dynamic Type, live server actions, Settings navigation under poor connectivity, background/relaunch graph restoration, notification permission denial and successful completion delivery. No signed deployment performed for this update.
|
||||
|
||||
Final verification: unsigned generic iOS device Debug build **BUILD SUCCEEDED**; **91 executable model/transport/persistence/formatting contract checks passed**, including Settings view cancellation and real-error reporting; three provisioning-profile tests passed; project/Info.plist validation and diff whitespace checks passed. Logs: ~/Developer/Scratch/Tarnax/build-verified.log and tests-verified.log. Physical-device and live-server verification remain outstanding.
|
||||
|
||||
### Status colours and detail controls — 5 November 2026
|
||||
|
||||
Shared torrent icons and bars now use yellow for downloads, purple for active seeding, red for stalled/error/missing files, pink for paused/stopped, orange for queued, and green for other completed transfers. Status-specific colours take priority over completion. Detail Resume/Pause/More share one button style with equal widths, 44-point minimum touch height, smaller subheadline labels and pressed feedback. Accessibility text sizes stack the controls vertically. Unsigned generic iOS Debug build succeeded; physical-device visual verification remains outstanding. Temporary build files and log are under ~/Developer/Scratch/Tarnax.
|
||||
|
||||
Reference in New Issue
Block a user