Files
el/ui/vessels/el-publish/src/screenshot.rs
T

136 lines
3.8 KiB
Rust

//! Screenshot pipeline — captures app screenshots for each store target size.
use crate::PublishResult;
/// A screenshot target device/size specification.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScreenshotTarget {
/// Display name (e.g. "iPhone 6.7\"")
pub name: String,
/// Target identifier used in el.toml (e.g. "iphone-6.7")
pub id: String,
pub width: u32,
pub height: u32,
pub platform: ScreenshotPlatform,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ScreenshotPlatform {
Ios,
Android,
}
impl ScreenshotTarget {
/// All standard screenshot targets, matching Apple and Google requirements.
pub fn all_standard() -> Vec<Self> {
vec![
Self {
name: "iPhone 6.7\"".into(),
id: "iphone-6.7".into(),
width: 1290,
height: 2796,
platform: ScreenshotPlatform::Ios,
},
Self {
name: "iPhone 6.1\"".into(),
id: "iphone-6.1".into(),
width: 1179,
height: 2556,
platform: ScreenshotPlatform::Ios,
},
Self {
name: "iPad 13\"".into(),
id: "ipad-13".into(),
width: 2064,
height: 2752,
platform: ScreenshotPlatform::Ios,
},
Self {
name: "Android Phone".into(),
id: "android-phone".into(),
width: 1080,
height: 1920,
platform: ScreenshotPlatform::Android,
},
]
}
/// Find a target by its ID.
pub fn find(id: &str) -> Option<Self> {
Self::all_standard().into_iter().find(|t| t.id == id)
}
}
/// A captured screenshot.
#[derive(Debug, Clone)]
pub struct Screenshot {
pub target: ScreenshotTarget,
pub locale: String,
pub scenario: String,
/// Path to the PNG file.
pub path: String,
}
/// Trait for screenshot capture backends.
///
/// Implementations might use:
/// - `xcrun simctl` for iOS Simulator screenshots
/// - Android Emulator ADB screenshots
/// - Puppeteer/Playwright for web screenshots
pub trait ScreenshotCapture: Send + Sync {
/// Capture a screenshot for the given scenario and target.
fn capture(
&self,
scenario: &str,
target: &ScreenshotTarget,
locale: &str,
output_dir: &str,
) -> PublishResult<Screenshot>;
/// Capture all scenarios for all targets and locales.
fn capture_all(
&self,
scenarios: &[String],
targets: &[ScreenshotTarget],
locales: &[String],
output_dir: &str,
) -> PublishResult<Vec<Screenshot>> {
let mut screenshots = Vec::new();
for scenario in scenarios {
for target in targets {
for locale in locales {
let shot = self.capture(scenario, target, locale, output_dir)?;
screenshots.push(shot);
}
}
}
Ok(screenshots)
}
}
/// Stub screenshot capture (produces placeholder paths without actually
/// launching a simulator). A future agent fills in the real capture logic.
pub struct StubScreenshotCapture;
impl ScreenshotCapture for StubScreenshotCapture {
fn capture(
&self,
scenario: &str,
target: &ScreenshotTarget,
locale: &str,
output_dir: &str,
) -> PublishResult<Screenshot> {
let filename = format!(
"{}/{}/{}-{}.png",
output_dir, locale, target.id, scenario
);
// TODO: actually launch simulator/emulator, navigate to scenario, capture PNG
Ok(Screenshot {
target: target.clone(),
locale: locale.to_string(),
scenario: scenario.to_string(),
path: filename,
})
}
}