Skip to main content

web_capture/
themed_image.rs

1//! Dual-themed screenshot capture module (R3).
2//!
3//! Captures screenshots in both light and dark themes in a single operation.
4//! Uses separate browser contexts for reliable `colorScheme` application.
5//!
6//! Note: Full browser automation requires browser-commander.
7//! This module provides the types and options; browser integration is stubbed
8//! until browser-commander is fully available.
9//!
10//! Based on reference implementation from:
11//! <https://github.com/link-foundation/meta-theory/blob/main/scripts/download.mjs>
12
13use serde::{Deserialize, Serialize};
14
15/// Color theme for screenshot capture.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(rename_all = "lowercase")]
18pub enum Theme {
19    Light,
20    Dark,
21}
22
23impl std::fmt::Display for Theme {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        match self {
26            Self::Light => write!(f, "light"),
27            Self::Dark => write!(f, "dark"),
28        }
29    }
30}
31
32impl std::str::FromStr for Theme {
33    type Err = String;
34
35    fn from_str(s: &str) -> Result<Self, Self::Err> {
36        match s.to_lowercase().as_str() {
37            "light" => Ok(Self::Light),
38            "dark" => Ok(Self::Dark),
39            _ => Err(format!("Unknown theme: {s}. Use 'light' or 'dark'")),
40        }
41    }
42}
43
44/// Options for themed screenshot capture.
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct ThemedImageOptions {
47    pub width: u32,
48    pub height: u32,
49    pub full_page: bool,
50    pub dismiss_popups: bool,
51}
52
53impl Default for ThemedImageOptions {
54    fn default() -> Self {
55        Self {
56            width: 1920,
57            height: 1080,
58            full_page: true,
59            dismiss_popups: true,
60        }
61    }
62}
63
64/// Result of dual-theme screenshot capture.
65#[derive(Debug, Clone, Serialize)]
66pub struct DualThemeResult {
67    /// Light theme screenshot PNG data.
68    #[serde(skip)]
69    pub light: Vec<u8>,
70    /// Dark theme screenshot PNG data.
71    #[serde(skip)]
72    pub dark: Vec<u8>,
73    pub url: String,
74    pub width: u32,
75    pub height: u32,
76    pub light_size: usize,
77    pub dark_size: usize,
78}
79
80/// Capture screenshots in both light and dark themes.
81///
82/// Note: Full browser automation requires browser-commander.
83/// This implementation returns an error indicating the requirement.
84#[allow(clippy::unused_async)]
85pub async fn capture_dual_theme_screenshots(
86    url: &str,
87    _options: &ThemedImageOptions,
88) -> crate::Result<DualThemeResult> {
89    let _absolute_url = if url.starts_with("http") {
90        url.to_string()
91    } else {
92        format!("https://{url}")
93    };
94
95    Err(crate::WebCaptureError::ScreenshotError(
96        "Dual-theme screenshot capture requires Chrome/Chromium. Install it and enable browser-commander features.".to_string()
97    ))
98}