1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Access the clipboard.
use window_clipboard::mime::{AllowedMimeTypes, AsMimeTypes};

use crate::core::clipboard::Kind;
use crate::futures::futures::channel::oneshot;
use crate::task::{self, Task};

/// A clipboard action to be performed by some [`Task`].
///
/// [`Task`]: crate::Task
pub enum Action {
    /// Read the clipboard and produce `String` with the result.
    Read {
        /// The clipboard target.
        target: Kind,
        /// The channel to send the read contents.
        channel: oneshot::Sender<Option<String>>,
    },

    /// Write the given contents to the clipboard.
    Write {
        /// The clipboard target.
        target: Kind,
        /// The contents to be written.
        contents: String,
    },

    /// Write the given contents to the clipboard.
    WriteData(Box<dyn AsMimeTypes + Send + Sync + 'static>, Kind),

    #[allow(clippy::type_complexity)]
    /// Read the clipboard and produce `T` with the result.
    ReadData(
        Vec<String>,
        oneshot::Sender<Option<(Vec<u8>, String)>>,
        // Box<dyn Fn(Option<(Vec<u8>, String)>) -> T + Send + 'static>,
        Kind,
    ),
}

impl std::fmt::Debug for Action {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Read { channel: _, target } => {
                write!(f, "Action::Read{target:?}")
            }
            Self::Write {
                contents: _,
                target,
            } => {
                write!(f, "Action::Write({target:?})")
            }
            Self::WriteData(_, target) => {
                write!(f, "Action::WriteData({target:?})")
            }
            Self::ReadData(_, _, target) => {
                write!(f, "Action::ReadData({target:?})")
            }
        }
    }
}

/// Read the current contents of the clipboard.
pub fn read() -> Task<Option<String>> {
    task::oneshot(|channel| {
        crate::Action::Clipboard(Action::Read {
            target: Kind::Standard,
            channel,
        })
    })
}

/// Read the current contents of the primary clipboard.
pub fn read_primary() -> Task<Option<String>> {
    task::oneshot(|channel| {
        crate::Action::Clipboard(Action::Read {
            target: Kind::Primary,
            channel,
        })
    })
}

/// Write the given contents to the clipboard.
pub fn write<T>(contents: String) -> Task<T> {
    task::effect(crate::Action::Clipboard(Action::Write {
        target: Kind::Standard,
        contents,
    }))
}

/// Write the given contents to the primary clipboard.
pub fn write_primary<Message>(contents: String) -> Task<Message> {
    task::effect(crate::Action::Clipboard(Action::Write {
        target: Kind::Primary,
        contents,
    }))
}
/// Read the current contents of the clipboard.
pub fn read_data<T: AllowedMimeTypes>() -> Task<Option<T>> {
    task::oneshot(|tx| {
        crate::Action::Clipboard(Action::ReadData(
            T::allowed().into(),
            tx,
            Kind::Standard,
        ))
    })
    .map(|d| d.and_then(|d| T::try_from(d).ok()))
}

/// Write the given contents to the clipboard.
pub fn write_data<Message>(
    contents: impl AsMimeTypes + std::marker::Sync + std::marker::Send + 'static,
) -> Task<Message> {
    task::effect(crate::Action::Clipboard(Action::WriteData(
        Box::new(contents),
        Kind::Standard,
    )))
}

/// Read from the primary clipboard
pub fn read_primary_data<T: AllowedMimeTypes>() -> Task<Option<T>> {
    task::oneshot(|tx| {
        crate::Action::Clipboard(Action::ReadData(
            T::allowed().into(),
            tx,
            // Box::new(move |d| f(d.and_then(|d| T::try_from(d).ok()))),
            Kind::Primary,
        ))
    })
    .map(|d| d.and_then(|d| T::try_from(d).ok()))
}

/// Write the given contents to the clipboard.
pub fn write_primary_data<Message>(
    contents: impl AsMimeTypes + std::marker::Sync + std::marker::Send + 'static,
) -> Task<Message> {
    task::effect(crate::Action::Clipboard(Action::WriteData(
        Box::new(contents),
        Kind::Primary,
    )))
}