Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f04a0fe0f5 | ||
|
|
f35f605b58 | ||
|
|
7da277547b |
@@ -98,7 +98,7 @@ struct OnboardingView: View {
|
|||||||
private var welcomePage: some View {
|
private var welcomePage: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
Spacer()
|
Spacer()
|
||||||
AnimatedOnboardingIcon(tint: .accentColor) {
|
AnimatedOnboardingIcon(tint: .accentColor, showsHalo: false) {
|
||||||
// The app icon itself, with the standard iOS rounded-corner
|
// The app icon itself, with the standard iOS rounded-corner
|
||||||
// treatment (~22% of the size), so onboarding matches the
|
// treatment (~22% of the size), so onboarding matches the
|
||||||
// Home Screen.
|
// Home Screen.
|
||||||
@@ -393,6 +393,9 @@ struct AnimatedOnboardingIcon<Content: View>: View {
|
|||||||
|
|
||||||
let tint: Color
|
let tint: Color
|
||||||
var motion: Motion = .gentle
|
var motion: Motion = .gentle
|
||||||
|
/// The soft circle behind the glyph. The welcome page turns it off: it shows
|
||||||
|
/// the app icon itself and reads better with no container around it.
|
||||||
|
var showsHalo: Bool = true
|
||||||
@ViewBuilder var content: Content
|
@ViewBuilder var content: Content
|
||||||
|
|
||||||
@State private var settled = false
|
@State private var settled = false
|
||||||
@@ -402,6 +405,7 @@ struct AnimatedOnboardingIcon<Content: View>: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
|
if showsHalo {
|
||||||
Circle()
|
Circle()
|
||||||
.fill(tint.opacity(0.10))
|
.fill(tint.opacity(0.10))
|
||||||
.frame(width: 108, height: 108)
|
.frame(width: 108, height: 108)
|
||||||
@@ -412,6 +416,7 @@ struct AnimatedOnboardingIcon<Content: View>: View {
|
|||||||
.frame(width: 118, height: 118)
|
.frame(width: 118, height: 118)
|
||||||
.scaleEffect(settled ? 1.03 : 0.97)
|
.scaleEffect(settled ? 1.03 : 0.97)
|
||||||
.opacity(settled ? 1.0 : 0.55)
|
.opacity(settled ? 1.0 : 0.55)
|
||||||
|
}
|
||||||
|
|
||||||
content
|
content
|
||||||
.scaleEffect(iconScale)
|
.scaleEffect(iconScale)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ struct StationDetailView: View {
|
|||||||
var onToggleFavourite: (() -> Void)? = nil
|
var onToggleFavourite: (() -> Void)? = nil
|
||||||
@Environment(\.dismiss) private var dismiss
|
@Environment(\.dismiss) private var dismiss
|
||||||
@State private var showingReportIssueConfirmation = false
|
@State private var showingReportIssueConfirmation = false
|
||||||
/// Transient "Copied" confirmation on the Address row. Cleared by a task so
|
/// Transient "Postcode copied" confirmation on the Address row. Cleared by a task so
|
||||||
/// the caption fades out on its own.
|
/// the caption fades out on its own.
|
||||||
@State private var showingCopied = false
|
@State private var showingCopied = false
|
||||||
@State private var copyResetTask: Task<Void, Never>?
|
@State private var copyResetTask: Task<Void, Never>?
|
||||||
@@ -137,7 +137,7 @@ struct StationDetailView: View {
|
|||||||
// The whole row is a copy control: it puts JUST the postcode
|
// The whole row is a copy control: it puts JUST the postcode
|
||||||
// on the clipboard so it can be pasted into another
|
// on the clipboard so it can be pasted into another
|
||||||
// navigation app. The copy glyph sits ON the address line,
|
// navigation app. The copy glyph sits ON the address line,
|
||||||
// and the "Copied" confirmation is a capsule that floats OVER
|
// and the "Postcode copied" confirmation is a capsule that floats OVER
|
||||||
// THIS ROW — it confirms the address, so it must not hover
|
// THIS ROW — it confirms the address, so it must not hover
|
||||||
// over the map. It is an overlay, so nothing moves while it is
|
// over the map. It is an overlay, so nothing moves while it is
|
||||||
// up, and `allowsHitTesting(false)` keeps the row tappable
|
// up, and `allowsHitTesting(false)` keeps the row tappable
|
||||||
@@ -172,7 +172,7 @@ struct StationDetailView: View {
|
|||||||
if showingCopied {
|
if showingCopied {
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Image(systemName: "checkmark")
|
Image(systemName: "checkmark")
|
||||||
Text("Copied")
|
Text("Postcode copied")
|
||||||
}
|
}
|
||||||
.font(.footnote.weight(.semibold))
|
.font(.footnote.weight(.semibold))
|
||||||
.foregroundStyle(.green)
|
.foregroundStyle(.green)
|
||||||
@@ -296,12 +296,12 @@ struct StationDetailView: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The "Copied" fade-out task must not outlive the sheet.
|
// The "Postcode copied" fade-out task must not outlive the sheet.
|
||||||
.onDisappear { copyResetTask?.cancel() }
|
.onDisappear { copyResetTask?.cancel() }
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
// QA hook: `-qaCopyPostcode` runs the REAL copy on open, so the
|
// QA hook: `-qaCopyPostcode` runs the REAL copy on open, so the
|
||||||
// clipboard value (read back with `xcrun simctl pbpaste`) and the
|
// clipboard value (read back with `xcrun simctl pbpaste`) and the
|
||||||
// "Copied" confirmation can be verified without a tap — simctl
|
// "Postcode copied" confirmation can be verified without a tap — simctl
|
||||||
// cannot drive taps into the Simulator.
|
// cannot drive taps into the Simulator.
|
||||||
.task {
|
.task {
|
||||||
guard ProcessInfo.processInfo.arguments.contains("-qaCopyPostcode") else { return }
|
guard ProcessInfo.processInfo.arguments.contains("-qaCopyPostcode") else { return }
|
||||||
|
|||||||
@@ -317,13 +317,16 @@ struct StationsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The explanation is its own sheet now, opened from this
|
// The explanation is its own sheet now, opened from this
|
||||||
// row. Deliberately NOT gated by Best Value: the Key sheet
|
// row. Gated exactly like the More info row and the Best
|
||||||
// is the legend and is reachable whatever the feature is
|
// Value card itself: `isConfigured` is the same condition
|
||||||
// doing.
|
// `savingsForStation` uses, so the row appears and
|
||||||
|
// disappears with the feature.
|
||||||
|
if fuelSavingsSettings.isConfigured {
|
||||||
Section {
|
Section {
|
||||||
HowBestValueRow { showBestValueInfo = true }
|
HowBestValueRow { showBestValueInfo = true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.navigationTitle("Key")
|
.navigationTitle("Key")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
|
|||||||
@@ -71,8 +71,8 @@
|
|||||||
"Name" = "Name";
|
"Name" = "Name";
|
||||||
"Address" = "Address";
|
"Address" = "Address";
|
||||||
"Distance" = "Distance";
|
"Distance" = "Distance";
|
||||||
"Copied" = "Copied";
|
|
||||||
"Copies the postcode" = "Copies the postcode";
|
"Copies the postcode" = "Copies the postcode";
|
||||||
|
"Postcode copied" = "Postcode copied";
|
||||||
"Address: %@" = "Address: %@";
|
"Address: %@" = "Address: %@";
|
||||||
"Directions to %@" = "Directions to %@";
|
"Directions to %@" = "Directions to %@";
|
||||||
"Opens Apple Maps with driving directions" = "Opens Apple Maps with driving directions";
|
"Opens Apple Maps with driving directions" = "Opens Apple Maps with driving directions";
|
||||||
|
|||||||
Reference in New Issue
Block a user