Add watch view export and update promo video watch display

- Add ExportableWatchViews.swift with exportable versions of watch app views
- Add WatchExporter.swift service to export all watch view variations
- Add export watch screenshots button to Settings (DEBUG)
- Update ConceptB promo: use watch_voting_light.png inside watch frame at 1.2x size

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-30 10:50:48 -06:00
parent 3efb07258d
commit 36ceff32ca
5 changed files with 858 additions and 138 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@@ -139,7 +139,7 @@ const ProblemScene: React.FC = () => {
// Scene 2: Single tap voting - Widget, Watch, In-App
const SingleTapScene: React.FC = () => {
const frame = useCurrentFrame();
const { fps, width } = useVideoConfig();
const { fps, width, height } = useVideoConfig();
// Title animations (matching other scenes)
const line1Progress = spring({ frame, fps, config: { damping: 200 } });
@@ -174,7 +174,7 @@ const SingleTapScene: React.FC = () => {
});
const watchSize = width * 0.27;
const watchSize = width * 0.27 * 1.2;
const widgetSize = width * 0.33;
return (
@@ -239,172 +239,165 @@ const SingleTapScene: React.FC = () => {
</div>
</div>
{/* Three device rows - full width, image at 33%, label at 66% */}
{/* Watch row - top at 33% */}
<div
style={{
position: "absolute",
top: "33%",
left: 0,
right: 0,
top: 450,
bottom: 80,
display: "flex",
flexDirection: "column",
justifyContent: "space-evenly",
alignItems: "center",
}}
>
{/* Watch row */}
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
width: "100%",
position: "absolute",
left: "33%",
transform: "translateX(-50%)",
}}
>
{/* Image at 33% */}
<div
style={{
position: "absolute",
left: "33%",
transform: "translateX(-50%)",
position: "relative",
width: watchSize,
height: watchSize,
}}
>
<div
<Img
src={staticFile("watch_voting_light.png")}
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: "48%",
height: "auto",
borderRadius: 8,
zIndex: 1,
}}
/>
<Img
src={staticFile("watch.png")}
style={{
width: "100%",
height: "100%",
objectFit: "contain",
filter: "drop-shadow(0 10px 30px rgba(0,0,0,0.3))",
position: "relative",
width: watchSize,
height: watchSize,
}}
>
<Img
src={staticFile("watch.png")}
style={{
width: "100%",
height: "100%",
objectFit: "contain",
filter: "drop-shadow(0 10px 30px rgba(0,0,0,0.3))",
}}
/>
<Img
src={staticFile("vote_light_small_notvoted.png")}
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: "62%",
height: "auto",
borderRadius: 8,
}}
/>
</div>
</div>
{/* Label at 66% */}
<div
style={{
position: "absolute",
left: "66%",
fontSize: 58,
fontWeight: 700,
color: "white",
fontFamily: "system-ui, -apple-system, sans-serif",
textShadow: "0 4px 20px rgba(0,0,0,0.3)",
opacity: interpolate(watchLabelProgress, [0, 1], [0, 1]),
transform: `translateX(${interpolate(watchLabelProgress, [0, 1], [30, 0])}px)`,
}}
>
Watch
</div>
</div>
{/* In-App row */}
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
width: "100%",
}}
>
{/* Image at 33% */}
<div
style={{
position: "absolute",
left: "33%",
transform: "translateX(-50%)",
}}
>
<Img
src={staticFile("voting_header.png")}
style={{
width: widgetSize * 1.1,
height: "auto",
borderRadius: 24,
boxShadow: "0 10px 40px rgba(0,0,0,0.3)",
zIndex: 2,
}}
/>
</div>
{/* Label at 66% */}
<div
style={{
position: "absolute",
left: "66%",
fontSize: 58,
fontWeight: 700,
color: "white",
fontFamily: "system-ui, -apple-system, sans-serif",
textShadow: "0 4px 20px rgba(0,0,0,0.3)",
opacity: interpolate(inAppLabelProgress, [0, 1], [0, 1]),
transform: `translateX(${interpolate(inAppLabelProgress, [0, 1], [30, 0])}px)`,
}}
>
In-App
</div>
</div>
{/* Widget row */}
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
width: "100%",
position: "absolute",
left: "66%",
fontSize: 58,
fontWeight: 700,
color: "white",
fontFamily: "system-ui, -apple-system, sans-serif",
textShadow: "0 4px 20px rgba(0,0,0,0.3)",
opacity: interpolate(watchLabelProgress, [0, 1], [0, 1]),
transform: `translateX(${interpolate(watchLabelProgress, [0, 1], [30, 0])}px)`,
}}
>
{/* Image at 33% */}
<div
Watch
</div>
</div>
{/* In-App row - centered at 61.5% (midpoint of 33% and 90%) */}
<div
style={{
position: "absolute",
top: "61.5%",
left: 0,
right: 0,
display: "flex",
alignItems: "center",
transform: "translateY(-50%)",
}}
>
<div
style={{
position: "absolute",
left: "33%",
transform: "translateX(-50%)",
}}
>
<Img
src={staticFile("voting_light_large.png")}
style={{
position: "absolute",
left: "33%",
transform: "translateX(-50%)",
width: widgetSize * 1.1,
height: "auto",
borderRadius: 24,
boxShadow: "0 10px 40px rgba(0,0,0,0.3)",
}}
>
<Img
src={staticFile("vote_dark_medium_notvoted.png")}
style={{
width: widgetSize,
height: "auto",
borderRadius: 24,
boxShadow: "0 10px 40px rgba(0,0,0,0.3)",
}}
/>
</div>
{/* Label at 66% */}
<div
/>
</div>
<div
style={{
position: "absolute",
left: "66%",
fontSize: 58,
fontWeight: 700,
color: "white",
fontFamily: "system-ui, -apple-system, sans-serif",
textShadow: "0 4px 20px rgba(0,0,0,0.3)",
opacity: interpolate(inAppLabelProgress, [0, 1], [0, 1]),
transform: `translateX(${interpolate(inAppLabelProgress, [0, 1], [30, 0])}px)`,
}}
>
In-App
</div>
</div>
{/* Widget row - bottom at 90% (10% from bottom) */}
<div
style={{
position: "absolute",
bottom: "10%",
left: 0,
right: 0,
}}
>
<div
style={{
position: "absolute",
left: "33%",
bottom: 0,
transform: "translateX(-50%)",
}}
>
<Img
src={staticFile("voting_light_medium.png")}
style={{
position: "absolute",
left: "66%",
fontSize: 58,
fontWeight: 700,
color: "white",
fontFamily: "system-ui, -apple-system, sans-serif",
textShadow: "0 4px 20px rgba(0,0,0,0.3)",
opacity: interpolate(widgetLabelProgress, [0, 1], [0, 1]),
transform: `translateX(${interpolate(widgetLabelProgress, [0, 1], [30, 0])}px)`,
width: widgetSize,
height: "auto",
borderRadius: 24,
boxShadow: "0 10px 40px rgba(0,0,0,0.3)",
}}
>
Widget
</div>
/>
</div>
<div
style={{
position: "absolute",
left: "66%",
bottom: 0,
height: widgetSize * 0.47,
display: "flex",
alignItems: "center",
fontSize: 58,
fontWeight: 700,
color: "white",
fontFamily: "system-ui, -apple-system, sans-serif",
textShadow: "0 4px 20px rgba(0,0,0,0.3)",
opacity: interpolate(widgetLabelProgress, [0, 1], [0, 1]),
transform: `translateX(${interpolate(widgetLabelProgress, [0, 1], [30, 0])}px)`,
}}
>
Widget
</div>
</div>
</div>