136 lines
3.8 KiB
Rust
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,
|
|
})
|
|
}
|
|
}
|