Skip to main content

freya_clipboard/
clipboard.rs

1//! Provides a clipboard abstraction to access the target system's clipboard.
2
3use copypasta::ClipboardProvider;
4use freya_core::prelude::*;
5
6#[derive(Debug, PartialEq, Clone)]
7pub enum ClipboardError {
8    FailedToRead,
9    FailedToSet,
10    NotAvailable,
11}
12
13/// App clipboard.
14///
15/// # Examples
16///
17/// ```rust,no_run
18/// use freya_clipboard::prelude::Clipboard;
19///
20/// // Read the clipboard content
21/// if let Ok(content) = Clipboard::get() {
22///     println!("{}", content);
23/// }
24///
25/// // Write to the clipboard
26/// Clipboard::set("Hello, Freya!".to_string());
27/// ```
28#[derive(Clone, Copy, PartialEq)]
29pub struct Clipboard(State<Option<Box<dyn ClipboardProvider>>>);
30
31impl Clipboard {
32    pub fn create(provider: Option<Box<dyn ClipboardProvider>>) -> Self {
33        Self(State::create_global(provider))
34    }
35
36    /// Read from the clipboard.
37    #[track_caller]
38    pub fn get() -> Result<String, ClipboardError> {
39        Self::with_provider(|provider| provider.get_contents())?
40            .map_err(|_| ClipboardError::FailedToRead)
41    }
42
43    /// Write to the clipboard.
44    #[track_caller]
45    pub fn set(contents: String) -> Result<(), ClipboardError> {
46        Self::with_provider(|provider| provider.set_contents(contents))?
47            .map_err(|_| ClipboardError::FailedToSet)
48    }
49
50    fn with_provider<T>(
51        run: impl FnOnce(&mut dyn ClipboardProvider) -> T,
52    ) -> Result<T, ClipboardError> {
53        let mut clipboard = GlobalContexts::get().get_context::<Clipboard>();
54        let mut provider = clipboard.0.write();
55        let provider = provider.as_mut().ok_or(ClipboardError::NotAvailable)?;
56        Ok(run(provider.as_mut()))
57    }
58}