fotos_lib/capture/
portal.rs1use anyhow::{bail, Context, Result};
6
7pub async fn capture_via_portal() -> Result<image::DynamicImage> {
8 use ashpd::desktop::screenshot::Screenshot;
9
10 tracing::info!("portal: sending screenshot request (interactive=true)");
14
15 let request = Screenshot::request()
16 .interactive(true)
17 .send()
18 .await
19 .map_err(|e| {
20 tracing::error!("portal: send() failed: {e}");
21 anyhow::anyhow!("Portal unavailable: {e}")
22 })?;
23
24 tracing::info!("portal: request sent, awaiting user confirmation");
25
26 let response = request.response().map_err(|e| {
27 tracing::error!("portal: response() failed: {e}");
28 anyhow::anyhow!("Screenshot portal request failed: {e}")
29 })?;
30
31 let uri = response.uri();
32 tracing::info!("portal: got URI {uri}");
33
34 if uri.scheme() != "file" {
35 bail!(
36 "Portal returned unsupported URI scheme '{}' (expected file://)",
37 uri.scheme()
38 );
39 }
40
41 let path = uri
42 .to_file_path()
43 .map_err(|_| anyhow::anyhow!("Portal URI is not a valid file path: {uri}"))?;
44
45 tracing::info!("portal: loading image from {}", path.display());
46
47 let img = image::open(&path)
48 .with_context(|| format!("Failed to load portal screenshot from {}", path.display()))?;
49
50 tracing::info!(
51 "portal: image loaded ({}x{}), cleaning up temp file",
52 img.width(),
53 img.height()
54 );
55
56 let _ = std::fs::remove_file(&path);
58
59 Ok(img)
60}