Skip to content

Commit

Permalink
[iOS] Pull down cue sheet shows remaining steps
Browse files Browse the repository at this point in the history
Also added some test fixture factories - am I going overboard?
  • Loading branch information
michaelkirk committed Sep 28, 2024
1 parent f9e91fb commit 71a6ba1
Show file tree
Hide file tree
Showing 15 changed files with 609 additions and 87 deletions.
92 changes: 92 additions & 0 deletions apple/Sources/FerrostarCore/Mock/TestFixtureFactory.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import FerrostarCoreFFI
import Foundation

public protocol TestFixtureFactory {
associatedtype Output
func build(_ n: Int) -> Output
}

public extension TestFixtureFactory {
func buildMany(_ n: Int) -> [Output] {
(0 ... n).map { build($0) }
}
}

public struct VisualInstructionContentFactory: TestFixtureFactory {
public init() {}

public var textBuilder: (Int) -> String = { n in RoadNameFactory().build(n) }
public func text(_ builder: @escaping (Int) -> String) -> Self {
var copy = self
copy.textBuilder = builder
return copy
}

public func build(_ n: Int = 0) -> VisualInstructionContent {
VisualInstructionContent(
text: textBuilder(n),
maneuverType: .turn,
maneuverModifier: .left,
roundaboutExitDegrees: nil
)
}
}

public struct VisualInstructionFactory: TestFixtureFactory {
public init() {}

public var primaryContentBuilder: (Int) -> VisualInstructionContent = { n in
VisualInstructionContentFactory().build(n)
}

public var secondaryContentBuilder: (Int) -> VisualInstructionContent? = { _ in nil }

public func secondaryContent(_ builder: @escaping (Int) -> VisualInstructionContent) -> Self {
var copy = self
copy.secondaryContentBuilder = builder
return copy
}

public func build(_ n: Int = 0) -> VisualInstruction {
VisualInstruction(
primaryContent: primaryContentBuilder(n),
secondaryContent: secondaryContentBuilder(n),
triggerDistanceBeforeManeuver: 42.0
)
}
}

public struct RouteStepFactory: TestFixtureFactory {
public init() {}
public var visualInstructionBuilder: (Int) -> VisualInstruction = { n in VisualInstructionFactory().build(n) }
public var roadNameBuilder: (Int) -> String = { n in RoadNameFactory().build(n) }

public func build(_ n: Int = 0) -> RouteStep {
RouteStep(
geometry: [],
distance: 100,
duration: 99,
roadName: roadNameBuilder(n),
instruction: "Walk west on \(roadNameBuilder(n))",
visualInstructions: [visualInstructionBuilder(n)],
spokenInstructions: []
)
}
}

public struct RoadNameFactory: TestFixtureFactory {
public init() {}
public var baseNameBuilder: (Int) -> String = { _ in "Ave" }

public func baseName(_ builder: @escaping (Int) -> String) -> Self {
var copy = self
copy.baseNameBuilder = builder
return copy
}

public func build(_ n: Int = 0) -> String {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .ordinal
return "\(numberFormatter.string(from: NSNumber(value: n + 1))!) \(baseNameBuilder(n))"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,33 @@ struct LandscapeNavigationOverlayView: View, CustomizableNavigatingInnerGridView

var body: some View {
HStack {
VStack {
if case let .navigating(_, _, _, _, progress: progress, _, visualInstruction: visualInstruction,
_) = navigationState?.tripState,
ZStack(alignment: .top) {
VStack {
Spacer()
if case let .navigating(_, _, _, _, progress: progress, _, _, _) = navigationState?.tripState {
ArrivalView(
progress: progress,
onTapExit: onTapExit
)
}
}
if case let .navigating(
_,
_,
remainingSteps: remainingSteps,
_,
progress: progress,
_,
visualInstruction: visualInstruction,
_
) = navigationState?.tripState,
let visualInstruction
{
InstructionsView(
visualInstruction: visualInstruction,
distanceFormatter: formatterCollection.distanceFormatter,
distanceToNextManeuver: progress.distanceToNextManeuver
)
}

Spacer()

if case let .navigating(_, _, _, _, progress: progress, _, _, _) = navigationState?.tripState {
ArrivalView(
progress: progress,
onTapExit: onTapExit
distanceToNextManeuver: progress.distanceToNextManeuver,
remainingSteps: remainingSteps
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ struct PortraitNavigationOverlayView: View, CustomizableNavigatingInnerGridView

var speedLimit: Measurement<UnitSpeed>?
var showZoom: Bool
@State
private var instructionsViewSizeWhenNotExpanded: CGSize = .zero
var onZoomIn: () -> Void
var onZoomOut: () -> Void
var showCentering: Bool
Expand Down Expand Up @@ -45,44 +47,58 @@ struct PortraitNavigationOverlayView: View, CustomizableNavigatingInnerGridView
}

var body: some View {
VStack {
if case let .navigating(_, _, _, _, progress: progress, _, visualInstruction: visualInstruction,
_) = navigationState?.tripState,
ZStack(alignment: .top) {
VStack {
Spacer()

// The inner content is displayed vertically full screen
// when both the visualInstructions and progress are nil.
// It will automatically reduce height if and when either
// view appears
NavigatingInnerGridView(
speedLimit: speedLimit,
showZoom: showZoom,
onZoomIn: onZoomIn,
onZoomOut: onZoomOut,
showCentering: showCentering,
onCenter: onCenter
)
.innerGrid {
topCenter?()
} topTrailing: {
topTrailing?()
} midLeading: {
midLeading?()
} bottomTrailing: {
bottomTrailing?()
}

if case let .navigating(_, _, _, _, progress: progress, _, _, _) = navigationState?.tripState {
ArrivalView(
progress: progress,
onTapExit: onTapExit
)
}
}.padding(.top, instructionsViewSizeWhenNotExpanded.height)

if case let .navigating(
_,
_,
remainingSteps: remainingSteps,
_,
progress: progress,
_,
visualInstruction: visualInstruction,
_
) = navigationState?.tripState,
let visualInstruction
{
InstructionsView(
visualInstruction: visualInstruction,
distanceFormatter: formatterCollection.distanceFormatter,
distanceToNextManeuver: progress.distanceToNextManeuver
)
}

// The inner content is displayed vertically full screen
// when both the visualInstructions and progress are nil.
// It will automatically reduce height if and when either
// view appears
NavigatingInnerGridView(
speedLimit: speedLimit,
showZoom: showZoom,
onZoomIn: onZoomIn,
onZoomOut: onZoomOut,
showCentering: showCentering,
onCenter: onCenter
)
.innerGrid {
topCenter?()
} topTrailing: {
topTrailing?()
} midLeading: {
midLeading?()
} bottomTrailing: {
bottomTrailing?()
}

if case let .navigating(_, _, _, _, progress: progress, _, _, _) = navigationState?.tripState {
ArrivalView(
progress: progress,
onTapExit: onTapExit
distanceToNextManeuver: progress.distanceToNextManeuver,
remainingSteps: remainingSteps,
sizeWhenNotExpanded: $instructionsViewSizeWhenNotExpanded
)
}
}
Expand Down
Loading

0 comments on commit 71a6ba1

Please sign in to comment.