Skip to content

Commit e0c74cd

Browse files
authored
feat: use_clipboard (#18)
* feat: use_clipboard * remove use_init_clipboard * clean up * clean up x2
1 parent 38dfc96 commit e0c74cd

File tree

4 files changed

+122
-99
lines changed

4 files changed

+122
-99
lines changed

examples/clipboard/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "clipboard"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
dioxus-std = { path="../../", features = ["clipboard"] }
8+
dioxus = "0.4"
9+
dioxus-desktop = "0.4"

examples/clipboard/src/main.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use dioxus::prelude::*;
2+
use dioxus_std::clipboard::use_clipboard;
3+
4+
fn main() {
5+
dioxus_desktop::launch(app);
6+
}
7+
8+
fn app(cx: Scope) -> Element {
9+
let clipboard = use_clipboard(cx);
10+
let text = use_state(cx, String::new);
11+
12+
let oninput = |e: FormEvent| {
13+
text.set(e.data.value.clone());
14+
};
15+
16+
let oncopy = {
17+
to_owned![clipboard];
18+
move |_| match clipboard.set(text.get().clone()) {
19+
Ok(_) => println!("Copied to clipboard: {}", text.get()),
20+
Err(err) => println!("Error on copy: {err:?}"),
21+
}
22+
};
23+
24+
let onpaste = move |_| match clipboard.get() {
25+
Ok(contents) => {
26+
println!("Pasted from clipboard: {contents}");
27+
text.set(contents);
28+
}
29+
Err(err) => println!("Error on paste: {err:?}"),
30+
};
31+
32+
render!(
33+
input {
34+
oninput: oninput,
35+
value: "{text}"
36+
}
37+
button {
38+
onclick: oncopy,
39+
"Copy"
40+
}
41+
button {
42+
onclick: onpaste,
43+
"Paste"
44+
}
45+
)
46+
}

src/clipboard/mod.rs

Lines changed: 2 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,3 @@
1-
//! Provides a clipboard abstraction to access the target system's clipboard.
1+
mod use_clipboard;
22

3-
use copypasta::{ClipboardContext, ClipboardProvider};
4-
use std::fmt;
5-
6-
/// Contains the context for interacting with the clipboard.
7-
///
8-
/// # Examples
9-
///
10-
/// ```
11-
/// use dioxus_std;
12-
///
13-
/// // Access the clipboard abstraction
14-
/// let mut clipboard = dioxus_std::clipboard::Clipboard::new().unwrap();
15-
///
16-
/// // Get clipboard content
17-
/// if let Ok(content) = clipboard.get_content() {
18-
/// println!("{}", content);
19-
/// }
20-
///
21-
/// // Set clipboard content
22-
/// clipboard.set_content("Hello, Dioxus!".to_string());;
23-
///
24-
/// ```
25-
pub struct Clipboard {
26-
ctx: ClipboardContext,
27-
}
28-
29-
impl Clipboard {
30-
/// Creates a new struct to utilize the clipboard abstraction.
31-
pub fn new() -> Result<Self, ClipboardError> {
32-
let ctx = match ClipboardContext::new() {
33-
Ok(ctx) => ctx,
34-
Err(e) => return Err(ClipboardError::FailedToInit(e.to_string())),
35-
};
36-
37-
Ok(Self { ctx })
38-
}
39-
40-
/// Provides a [`String`] of the target system's current clipboard content.
41-
pub fn get_content(&mut self) -> Result<String, ClipboardError> {
42-
match self.ctx.get_contents() {
43-
Ok(content) => Ok(content),
44-
Err(e) => Err(ClipboardError::FailedToFetchContent(e.to_string())),
45-
}
46-
}
47-
48-
/// Set the clipboard's content to the provided [`String`]
49-
pub fn set_content(&mut self, value: String) -> Result<(), ClipboardError> {
50-
match self.ctx.set_contents(value) {
51-
Ok(()) => Ok(()),
52-
Err(e) => Err(ClipboardError::FailedToSetContent(e.to_string())),
53-
}
54-
}
55-
}
56-
57-
/// Represents errors when utilizing the clipboard abstraction.
58-
#[derive(Debug)]
59-
pub enum ClipboardError {
60-
/// Failure when initializing the clipboard.
61-
FailedToInit(String),
62-
/// Failure to retrieve clipboard content.
63-
FailedToFetchContent(String),
64-
/// Failure to set clipboard content.
65-
FailedToSetContent(String),
66-
}
67-
68-
impl std::error::Error for ClipboardError {}
69-
impl fmt::Display for ClipboardError {
70-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71-
match self {
72-
ClipboardError::FailedToInit(s) => write!(f, "{}", s),
73-
ClipboardError::FailedToFetchContent(s) => write!(f, "{}", s),
74-
ClipboardError::FailedToSetContent(s) => write!(f, "{}", s),
75-
}
76-
}
77-
}
78-
79-
// Tests
80-
// This doesn't work in CI.
81-
/*#[test]
82-
fn test_clipboard() {
83-
let mut clipboard = Clipboard::new().unwrap();
84-
85-
// Preserve user's clipboard contents when testing
86-
let initial_content = clipboard.get_content().unwrap();
87-
88-
// Set the content
89-
let new_content = String::from("Hello, Dioxus!");
90-
clipboard.set_content(new_content.clone()).unwrap();
91-
92-
// Get the new content
93-
let content = clipboard.get_content().unwrap();
94-
95-
// Return previous content - For some reason this only works if the test panics..?
96-
clipboard.set_content(initial_content).unwrap();
97-
98-
// Check if the abstraction worked
99-
assert_eq!(new_content, content);
100-
}*/
3+
pub use use_clipboard::*;

src/clipboard/use_clipboard.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//! Provides a clipboard abstraction to access the target system's clipboard.
2+
3+
use copypasta::{ClipboardContext, ClipboardProvider};
4+
use dioxus::prelude::{RefCell, ScopeState};
5+
use std::rc::Rc;
6+
7+
#[derive(Debug, PartialEq, Clone)]
8+
pub enum ClipboardError {
9+
FailedToRead,
10+
FailedToSet,
11+
}
12+
13+
/// Handle to access the ClipboardContext.
14+
#[derive(Clone)]
15+
pub struct UseClipboard {
16+
clipboard: Rc<RefCell<ClipboardContext>>,
17+
}
18+
19+
impl UseClipboard {
20+
// Read from the clipboard
21+
pub fn get(&self) -> Result<String, ClipboardError> {
22+
self.clipboard
23+
.borrow_mut()
24+
.get_contents()
25+
.map_err(|_| ClipboardError::FailedToRead)
26+
}
27+
28+
// Write to the clipboard
29+
pub fn set(&self, contents: String) -> Result<(), ClipboardError> {
30+
self.clipboard
31+
.borrow_mut()
32+
.set_contents(contents)
33+
.map_err(|_| ClipboardError::FailedToSet)
34+
}
35+
}
36+
37+
/// Access the clipboard.
38+
///
39+
/// # Examples
40+
///
41+
/// ```ignore
42+
/// use dioxus_std::clipboard::use_clipboard;
43+
///
44+
/// // Get a handle to the clipboard
45+
/// let clipboard = use_clipboard(cx);
46+
///
47+
/// // Read the clipboard content
48+
/// if let Ok(content) = clipboard.get() {
49+
/// println!("{}", content);
50+
/// }
51+
///
52+
/// // Write to the clipboard
53+
/// clipboard.set("Hello, Dioxus!".to_string());;
54+
///
55+
/// ```
56+
pub fn use_clipboard(cx: &ScopeState) -> UseClipboard {
57+
let clipboard = match cx.consume_context() {
58+
Some(rt) => rt,
59+
None => {
60+
let clipboard = ClipboardContext::new().expect("Cannot create Clipboard.");
61+
cx.provide_root_context(Rc::new(RefCell::new(clipboard)))
62+
}
63+
};
64+
UseClipboard { clipboard }
65+
}

0 commit comments

Comments
 (0)