Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dbb3d1a15 | ||
|
|
6e534ed5b7 | ||
|
|
73db893f4f | ||
|
|
7da09928ca |
@@ -118,12 +118,92 @@ struct StationDetailView: View {
|
|||||||
.accessibilityHint(String(localized: "Opens Apple Maps with driving directions",
|
.accessibilityHint(String(localized: "Opens Apple Maps with driving directions",
|
||||||
comment: "Accessibility hint for the tappable map preview in the More info sheet"))
|
comment: "Accessibility hint for the tappable map preview in the More info sheet"))
|
||||||
}
|
}
|
||||||
.listRowInsets(EdgeInsets())
|
// No hairline between the map and the Address row: the map
|
||||||
}
|
// already reads as its own block, so the line only added
|
||||||
// The two station actions live in their OWN section, so they
|
// clutter. The Address/Distance and Distance/actions lines
|
||||||
// render as a separate card BELOW the map instead of sharing the
|
// stay.
|
||||||
// map's card and looking attached to the map tap target.
|
.listRowSeparator(.hidden, edges: .bottom)
|
||||||
Section {
|
// The map, the address, the distance, any notices and the two
|
||||||
|
// station actions all share ONE card (the list's own row
|
||||||
|
// hairlines separate them), so no hand-rolled Divider here —
|
||||||
|
// adding one would double the line.
|
||||||
|
//
|
||||||
|
// The station name is NOT repeated: the sheet header already
|
||||||
|
// shows it.
|
||||||
|
//
|
||||||
|
// The whole row is a copy control: it puts JUST the postcode
|
||||||
|
// on the clipboard so it can be pasted into another
|
||||||
|
// navigation app. The copy glyph sits ON the address line,
|
||||||
|
// and the "Copied" confirmation is a capsule that floats OVER
|
||||||
|
// THIS ROW — it confirms the address, so it must not hover
|
||||||
|
// over the map. It is an overlay, so nothing moves while it is
|
||||||
|
// up, and `allowsHitTesting(false)` keeps the row tappable
|
||||||
|
// through the capsule.
|
||||||
|
Button {
|
||||||
|
copyPostcode()
|
||||||
|
} label: {
|
||||||
|
HStack(alignment: .firstTextBaseline, spacing: 8) {
|
||||||
|
Text("Address")
|
||||||
|
Spacer(minLength: 8)
|
||||||
|
Text(addressLine)
|
||||||
|
.multilineTextAlignment(.trailing)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
// Stays the plain copy glyph — the capsule carries
|
||||||
|
// the confirmation, so swapping this to a checkmark
|
||||||
|
// would say it twice.
|
||||||
|
Image(systemName: "doc.on.doc")
|
||||||
|
.font(.footnote.weight(.semibold))
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.disabled(postcodeForCopying.isEmpty)
|
||||||
|
.accessibilityLabel(String(localized: "Address: \(addressLine)",
|
||||||
|
comment: "Accessibility label for the address row in the More info sheet"))
|
||||||
|
.accessibilityHint(postcodeForCopying.isEmpty
|
||||||
|
? ""
|
||||||
|
: String(localized: "Copies the postcode",
|
||||||
|
comment: "Accessibility hint for the address row in the More info sheet"))
|
||||||
|
// Horizontally centred over the address line itself.
|
||||||
|
.overlay(alignment: .center) {
|
||||||
|
if showingCopied {
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
Text("Copied")
|
||||||
|
}
|
||||||
|
.font(.footnote.weight(.semibold))
|
||||||
|
.foregroundStyle(.green)
|
||||||
|
.padding(.horizontal, 10)
|
||||||
|
.padding(.vertical, 6)
|
||||||
|
// A material base keeps it legible where the tint
|
||||||
|
// alone (the notice-capsule recipe) washes out.
|
||||||
|
.background {
|
||||||
|
Capsule()
|
||||||
|
.fill(.regularMaterial)
|
||||||
|
.overlay(Capsule().fill(Color.green.opacity(0.22)))
|
||||||
|
}
|
||||||
|
.allowsHitTesting(false)
|
||||||
|
.accessibilityHidden(true)
|
||||||
|
.transition(.opacity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let location {
|
||||||
|
let distance = FuelStore.stationDistanceDisplay(
|
||||||
|
station: station, userLat: location.lat, userLng: location.lng
|
||||||
|
)
|
||||||
|
LabeledContent("Distance", value: distance.labelWithReturn(unit: distanceUnit))
|
||||||
|
.monospacedDigit()
|
||||||
|
}
|
||||||
|
ForEach(StationNotice.notices(for: station)) { notice in
|
||||||
|
Label(notice.title, systemImage: notice.symbolName)
|
||||||
|
.font(.subheadline.weight(.semibold))
|
||||||
|
.foregroundStyle(.orange)
|
||||||
|
.padding(.horizontal, 10)
|
||||||
|
.padding(.vertical, 6)
|
||||||
|
.background(Capsule().fill(Color.orange.opacity(0.14)))
|
||||||
|
}
|
||||||
|
// The two station actions are the LAST row of the card: half
|
||||||
|
// the width each, on one line, below Address and Distance.
|
||||||
HStack(spacing: 12) {
|
HStack(spacing: 12) {
|
||||||
Button {
|
Button {
|
||||||
openDirections()
|
openDirections()
|
||||||
@@ -145,65 +225,6 @@ struct StationDetailView: View {
|
|||||||
// button its own hit area — the half-row frame above.
|
// button its own hit area — the half-row frame above.
|
||||||
.buttonStyle(.borderless)
|
.buttonStyle(.borderless)
|
||||||
}
|
}
|
||||||
Section {
|
|
||||||
// The station name is NOT repeated here: the sheet header
|
|
||||||
// (navigationTitle, inline) already shows it, and the address
|
|
||||||
// line below has any leading repeat of the name stripped, so
|
|
||||||
// a "Name" row only said it twice.
|
|
||||||
//
|
|
||||||
// The whole row is a copy control: it puts JUST the postcode
|
|
||||||
// on the clipboard so it can be pasted into another
|
|
||||||
// navigation app. The copy glyph and its "Copied"
|
|
||||||
// confirmation share a SECOND line that is always there, so
|
|
||||||
// the confirmation can never reflow the address above it.
|
|
||||||
Button {
|
|
||||||
copyPostcode()
|
|
||||||
} label: {
|
|
||||||
VStack(alignment: .leading, spacing: 6) {
|
|
||||||
HStack(alignment: .firstTextBaseline, spacing: 8) {
|
|
||||||
Text("Address")
|
|
||||||
Spacer(minLength: 8)
|
|
||||||
Text(addressLine)
|
|
||||||
.multilineTextAlignment(.trailing)
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
}
|
|
||||||
HStack(spacing: 4) {
|
|
||||||
Spacer(minLength: 0)
|
|
||||||
if showingCopied {
|
|
||||||
Text("Copied")
|
|
||||||
.foregroundStyle(.green)
|
|
||||||
.transition(.opacity)
|
|
||||||
}
|
|
||||||
Image(systemName: showingCopied ? "checkmark" : "doc.on.doc")
|
|
||||||
.foregroundStyle(showingCopied ? Color.green : Color.secondary)
|
|
||||||
}
|
|
||||||
.font(.footnote.weight(.semibold))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
.disabled(postcodeForCopying.isEmpty)
|
|
||||||
.accessibilityLabel(String(localized: "Address: \(addressLine)",
|
|
||||||
comment: "Accessibility label for the address row in the More info sheet"))
|
|
||||||
.accessibilityHint(postcodeForCopying.isEmpty
|
|
||||||
? ""
|
|
||||||
: String(localized: "Copies the postcode",
|
|
||||||
comment: "Accessibility hint for the address row in the More info sheet"))
|
|
||||||
if let location {
|
|
||||||
let distance = FuelStore.stationDistanceDisplay(
|
|
||||||
station: station, userLat: location.lat, userLng: location.lng
|
|
||||||
)
|
|
||||||
LabeledContent("Distance", value: distance.labelWithReturn(unit: distanceUnit))
|
|
||||||
.monospacedDigit()
|
|
||||||
}
|
|
||||||
ForEach(StationNotice.notices(for: station)) { notice in
|
|
||||||
Label(notice.title, systemImage: notice.symbolName)
|
|
||||||
.font(.subheadline.weight(.semibold))
|
|
||||||
.foregroundStyle(.orange)
|
|
||||||
.padding(.horizontal, 10)
|
|
||||||
.padding(.vertical, 6)
|
|
||||||
.background(Capsule().fill(Color.orange.opacity(0.14)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Only shown while Fuel Savings backs it. `fuelSavings` is nil
|
// Only shown while Fuel Savings backs it. `fuelSavings` is nil
|
||||||
// when the feature is off — `savingsLookup` returns nil when it
|
// when the feature is off — `savingsLookup` returns nil when it
|
||||||
// is not configured — so the heading cannot be left dangling
|
// is not configured — so the heading cannot be left dangling
|
||||||
|
|||||||
Reference in New Issue
Block a user