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
26 changes: 15 additions & 11 deletions AltStore/App Detail/AppDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ struct AppDetailView: View {
private let inset: CGFloat = 15
private let padding: CGFloat = 20
private let bannerHeight: CGFloat = AppBannerView.standardHeight
private let backButtonSize: CGFloat = 40
private let backButtonSize: CGFloat = 44

var body: some View {
GeometryReader { geo in
Expand Down Expand Up @@ -443,9 +443,9 @@ struct AppDetailView: View {
return HStack {
SwiftUI.Button(action: { model.pop() }) {
Image(systemName: "chevron.backward")
.font(.body.weight(.semibold))
.font(.title3.weight(.semibold))
.foregroundStyle(Color(uiColor: model.app.tintColor ?? .altPrimary))
.frame(width: 40, height: 40)
.frame(width: 44, height: 44)
.background(.ultraThinMaterial, in: Circle())
}
.accessibilityLabel(NSLocalizedString("Back", comment: ""))
Expand Down Expand Up @@ -597,6 +597,9 @@ private struct AppScreenshotsRow: View {
}
.scrollTargetBehavior(.viewAligned)
.frame(height: 400)
// Clip the carousel to its own band so thumbnails never bleed past the rounded
// content card during a scroll/overscroll (they "scrolled off" the card edges).
.clipped()
.padding(.bottom, 20)
}
}
Expand All @@ -606,12 +609,13 @@ private struct DetailScreenshotView: View {

private let preferredHeight: CGFloat = 400

private var aspectRatio: CGFloat {
var r = screenshot.aspectRatio
if r.width > r.height && screenshot.deviceType == .iphone {
r = CGSize(width: r.height, height: r.width)
}
return r.width / r.height
// Uniform display aspect: every thumbnail is framed to the same modern-iPhone
// portrait ratio and aspect-FILLED (scaledToFill + clipped below), so screenshots
// whose real aspect differs from the frame — including any letterbox padding baked
// into the source image — crop to fill instead of showing black bars. A single shared
// width also lets the viewAligned carousel snap cleanly with no per-image width jitter.
private var frameWidth: CGFloat {
preferredHeight * (AppScreenshot.defaultAspectRatio.width / AppScreenshot.defaultAspectRatio.height)
}

@State private var image: UIImage?
Expand All @@ -623,13 +627,13 @@ private struct DetailScreenshotView: View {
Image(uiImage: img)
.resizable()
.scaledToFill()
.frame(width: preferredHeight * aspectRatio, height: preferredHeight)
.frame(width: frameWidth, height: preferredHeight)
.clipped()
} else {
ProgressView()
}
}
.frame(width: preferredHeight * aspectRatio, height: preferredHeight)
.frame(width: frameWidth, height: preferredHeight)
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
.overlay(
RoundedRectangle(cornerRadius: 5, style: .continuous)
Expand Down
10 changes: 5 additions & 5 deletions AltStore/Authentication/InstructionsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ struct InstructionsView: View {

private let steps: [Step] = [
Step(id: 1,
title: NSLocalizedString("Launch SideStore", comment: ""),
detail: NSLocalizedString("Leave SideStore running in the background on your idevice.", comment: "")),
title: NSLocalizedString("Launch MiniStore", comment: ""),
detail: NSLocalizedString("Leave MiniStore running in the background on your idevice.", comment: "")),
Step(id: 2,
title: NSLocalizedString("Connect to Wi-Fi and VPN", comment: ""),
detail: NSLocalizedString("Enable LocalDevVPN and use Sidestore on the go.", comment: "")),
detail: NSLocalizedString("Enable LocalDevVPN and use MiniStore on the go.", comment: "")),
Step(id: 3,
title: NSLocalizedString("Download Apps", comment: ""),
detail: NSLocalizedString("Browse and download apps directly from SideStore.", comment: "")),
detail: NSLocalizedString("Browse and download apps directly from MiniStore.", comment: "")),
Step(id: 4,
title: NSLocalizedString("Apps Refresh Automatically", comment: ""),
detail: NSLocalizedString("Apps are refreshed in the background while you are on SideStore VPN!", comment: "")),
detail: NSLocalizedString("Apps are refreshed in the background while you are on MiniStore VPN!", comment: "")),
]

// Device-fixed: true only on screens under 600 pt tall (e.g. iPhone SE 1st gen).
Expand Down
36 changes: 26 additions & 10 deletions AltStore/My Apps/MyAppsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -460,26 +460,42 @@ private struct MyAppsSectionHeader: View {
SwiftUI.Button {
onButton()
} label: {
if isSpinning {
ProgressView()
.tint(Color(.altPrimary))
.accessibilityLabel(NSLocalizedString("Refreshing", comment: ""))
} else {
// foregroundStyle, not .tint: .tint does not color plain-style
// button text, so the accent never reached these labels.
ZStack {
// Reserve the idle title's footprint (kept in the layout, just
// hidden) so the header's trailing edge doesn't shift when the
// spinner swaps in — the button stays symmetric across the
// idle/refreshing states.
Text(bt)
.font(.subheadline)
.foregroundStyle(Color(.altPrimary))
.font(.subheadline.weight(.semibold))
.opacity(isSpinning ? 0 : 1)
.accessibilityHidden(isSpinning)
if isSpinning {
ProgressView()
.controlSize(.small)
.tint(Color(.altPrimary))
.accessibilityLabel(NSLocalizedString("Refreshing", comment: ""))
}
}
// foregroundStyle, not .tint: .tint does not color plain-style
// button text, so the accent never reached these labels.
.foregroundStyle(Color(.altPrimary))
// Extend the hit area toward the title and vertically without moving
// the glyph, so the small label is easier to press.
.padding(.vertical, 8)
.padding(.leading, 16)
.contentShape(Rectangle())
}
.buttonStyle(.plain)
} else if let icon = buttonIcon {
SwiftUI.Button {
onButton()
} label: {
Image(systemName: icon)
.font(.subheadline)
.font(.subheadline.weight(.semibold))
.foregroundStyle(Color(.altPrimary))
.padding(.vertical, 8)
.padding(.leading, 16)
.contentShape(Rectangle())
}
.buttonStyle(.plain)
}
Expand Down
6 changes: 3 additions & 3 deletions AltStore/Sources/SourceDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ struct SourceDetailView: View {
GeometryReader { geo in
let width = geo.size.width
let safeTop = geo.safeAreaInsets.top
let backButtonSize: CGFloat = 40
let backButtonSize: CGFloat = 44
let minContentHeight = safeTop + backButtonSize + 8 + headerHeight + DetailLayout.padding
let maxContentY = max(width * 0.667, minContentHeight)

Expand Down Expand Up @@ -566,9 +566,9 @@ struct SourceDetailView: View {
model.hostViewController?.navigationController?.popViewController(animated: true)
} label: {
Image(systemName: "chevron.backward")
.font(.body.weight(.semibold))
.font(.title3.weight(.semibold))
.foregroundStyle(Color(uiColor: source.effectiveTintColor?.adjustedForDisplay ?? .altPrimary))
.frame(width: 40, height: 40)
.frame(width: 44, height: 44)
.background(.ultraThinMaterial, in: Circle())
}
.accessibilityLabel(NSLocalizedString("Back", comment: ""))
Expand Down
Loading