feat: add marketing video mode and Remotion marketing video project

Add debug-only Marketing Video Mode toggle that enables hands-free
screen recording across the app: auto-scrolling Featured Trips carousel,
auto-filling trip wizard, smooth trip detail scrolling via CADisplayLink,
and trip options auto-sort with scroll.

Add Remotion marketing video project with 6 scene compositions using
image sequences extracted from screen recordings, varied phone entrance
animations, and deduped frames for smooth playback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-02-13 12:07:35 -06:00
parent 67965cbac6
commit 5f5b137e64
655 changed files with 4008 additions and 63 deletions

View File

@@ -254,32 +254,49 @@ struct TripDetailView: View {
.ignoresSafeArea(edges: .bottom)
} else {
// Non-editable scroll view for unsaved trips
ScrollView {
VStack(spacing: 0) {
heroMapSection
.frame(height: 280)
ScrollViewReader { proxy in
ScrollView {
VStack(spacing: 0) {
heroMapSection
.frame(height: 280)
VStack(spacing: Theme.Spacing.lg) {
tripHeader
.padding(.top, Theme.Spacing.lg)
VStack(spacing: Theme.Spacing.lg) {
tripHeader
.padding(.top, Theme.Spacing.lg)
statsRow
statsRow
if let score = trip.score {
scoreCard(score)
if let score = trip.score {
scoreCard(score)
}
itinerarySection
}
.padding(.horizontal, Theme.Spacing.lg)
.padding(.bottom, Theme.Spacing.xxl)
itinerarySection
Color.clear
.frame(height: 1)
.id("tripDetailBottom")
}
.onDrop(of: [.text, .plainText, .utf8PlainText], isTargeted: .constant(false)) { _ in
draggedTravelId = nil
draggedItem = nil
dropTargetId = nil
return true
}
.padding(.horizontal, Theme.Spacing.lg)
.padding(.bottom, Theme.Spacing.xxl)
}
.onDrop(of: [.text, .plainText, .utf8PlainText], isTargeted: .constant(false)) { _ in
draggedTravelId = nil
draggedItem = nil
dropTargetId = nil
return true
#if DEBUG
.onAppear {
if UserDefaults.standard.bool(forKey: "marketingVideoMode") {
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
withAnimation(.easeInOut(duration: 6.0)) {
proxy.scrollTo("tripDetailBottom", anchor: .bottom)
}
}
}
}
#endif
}
}
}