sesame/
clipboard.rs

1use comfy_table::{Table, presets::UTF8_FULL};
2use core_types::{EventKind, SecurityLevel, TrustProfileName};
3use owo_colors::OwoColorize;
4
5use crate::ipc::{connect, rpc};
6
7pub(crate) async fn cmd_clipboard_history(profile: &str, limit: u32) -> anyhow::Result<()> {
8    let client = connect().await?;
9    let profile = TrustProfileName::try_from(profile).map_err(|e| anyhow::anyhow!("{e}"))?;
10
11    let event = EventKind::ClipboardHistory { profile, limit };
12
13    match rpc(&client, event, SecurityLevel::Internal).await? {
14        EventKind::ClipboardHistoryResponse { entries } => {
15            if entries.is_empty() {
16                println!("{}", "No clipboard history.".dimmed());
17            } else {
18                let mut table = Table::new();
19                table.load_preset(UTF8_FULL);
20                table.set_header(vec!["ID", "Type", "Sensitivity", "Preview"]);
21
22                for e in &entries {
23                    table.add_row(vec![
24                        &e.entry_id.to_string(),
25                        &e.content_type,
26                        &format!("{:?}", e.sensitivity),
27                        &e.preview,
28                    ]);
29                }
30
31                println!("{table}");
32            }
33        }
34        other => anyhow::bail!("unexpected response: {other:?}"),
35    }
36
37    Ok(())
38}
39
40pub(crate) async fn cmd_clipboard_clear(profile: &str) -> anyhow::Result<()> {
41    let client = connect().await?;
42    let profile = TrustProfileName::try_from(profile).map_err(|e| anyhow::anyhow!("{e}"))?;
43
44    match rpc(
45        &client,
46        EventKind::ClipboardClear { profile },
47        SecurityLevel::Internal,
48    )
49    .await?
50    {
51        EventKind::ClipboardClearResponse { success: true } => {
52            println!("{}", "Clipboard history cleared.".green());
53        }
54        EventKind::ClipboardClearResponse { success: false } => {
55            anyhow::bail!("failed to clear clipboard history");
56        }
57        other => anyhow::bail!("unexpected response: {other:?}"),
58    }
59
60    Ok(())
61}
62
63pub(crate) async fn cmd_clipboard_get(entry_id: &str) -> anyhow::Result<()> {
64    let client = connect().await?;
65
66    let uuid = entry_id.strip_prefix("clip-").unwrap_or(entry_id);
67    let uuid: uuid::Uuid = uuid
68        .parse()
69        .map_err(|_| anyhow::anyhow!("invalid clipboard entry ID: {entry_id}"))?;
70    let entry_id_parsed = core_types::ClipboardEntryId::from_uuid(uuid);
71
72    match rpc(
73        &client,
74        EventKind::ClipboardGet {
75            entry_id: entry_id_parsed,
76        },
77        SecurityLevel::Internal,
78    )
79    .await?
80    {
81        EventKind::ClipboardGetResponse {
82            content: Some(c),
83            content_type,
84        } => {
85            if let Some(ct) = content_type {
86                eprintln!("Content-Type: {ct}");
87            }
88            println!("{c}");
89        }
90        EventKind::ClipboardGetResponse { content: None, .. } => {
91            anyhow::bail!("clipboard entry not found or expired");
92        }
93        other => anyhow::bail!("unexpected response: {other:?}"),
94    }
95
96    Ok(())
97}