clipboard: Removed content method from Clipboard. (#1520)
## Break Change - The `content` method has been removed from `Clipboard`, if you want display something, you can wrap it in a h_flex.
This commit is contained in:
parent
d3ec1f29f8
commit
2093046942
3 changed files with 77 additions and 89 deletions
|
|
@ -6,6 +6,7 @@ use gpui::{
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
ContextModal,
|
ContextModal,
|
||||||
clipboard::Clipboard,
|
clipboard::Clipboard,
|
||||||
|
h_flex,
|
||||||
input::{Input, InputState},
|
input::{Input, InputState},
|
||||||
label::Label,
|
label::Label,
|
||||||
v_flex,
|
v_flex,
|
||||||
|
|
@ -60,18 +61,25 @@ impl Render for ClipboardStory {
|
||||||
.gap_6()
|
.gap_6()
|
||||||
.child(
|
.child(
|
||||||
section("Clipboard").max_w_md().child(
|
section("Clipboard").max_w_md().child(
|
||||||
|
h_flex()
|
||||||
|
.gap_2()
|
||||||
|
.child(Label::new("A clipboard button"))
|
||||||
|
.child(
|
||||||
Clipboard::new("clipboard1")
|
Clipboard::new("clipboard1")
|
||||||
.content(|_, _| Label::new("A clipboard button"))
|
|
||||||
.value_fn({
|
.value_fn({
|
||||||
let view = cx.entity().clone();
|
let view = cx.entity().clone();
|
||||||
move |_, cx| {
|
move |_, cx| {
|
||||||
SharedString::from(format!("masked :{}", view.read(cx).masked))
|
SharedString::from(format!(
|
||||||
|
"masked :{}",
|
||||||
|
view.read(cx).masked
|
||||||
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on_copied(|value, window, cx| {
|
.on_copied(|value, window, cx| {
|
||||||
window.push_notification(format!("Copied value: {}", value), cx)
|
window.push_notification(format!("Copied value: {}", value), cx)
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
section("With in an Input").max_w_md().child(
|
section("With in an Input").max_w_md().child(
|
||||||
|
|
|
||||||
|
|
@ -2,33 +2,34 @@ use std::{cell::Cell, rc::Rc, time::Duration};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
prelude::FluentBuilder, AnyElement, App, ClipboardItem, Element, ElementId, GlobalElementId,
|
prelude::FluentBuilder, AnyElement, App, ClipboardItem, Element, ElementId, GlobalElementId,
|
||||||
IntoElement, LayoutId, ParentElement, SharedString, Styled, Window,
|
IntoElement, LayoutId, SharedString, Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
button::{Button, ButtonVariants as _},
|
button::{Button, ButtonVariants as _},
|
||||||
h_flex, IconName, Sizable as _,
|
IconName, Sizable as _,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An element that provides clipboard copy functionality.
|
||||||
pub struct Clipboard {
|
pub struct Clipboard {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
value: SharedString,
|
value: SharedString,
|
||||||
value_fn: Option<Rc<dyn Fn(&mut Window, &mut App) -> SharedString>>,
|
value_fn: Option<Rc<dyn Fn(&mut Window, &mut App) -> SharedString>>,
|
||||||
content_builder: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyElement>>,
|
|
||||||
copied_callback: Option<Rc<dyn Fn(SharedString, &mut Window, &mut App)>>,
|
copied_callback: Option<Rc<dyn Fn(SharedString, &mut Window, &mut App)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clipboard {
|
impl Clipboard {
|
||||||
|
/// Create a new Clipboard element with the given ID.
|
||||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
value: SharedString::default(),
|
value: SharedString::default(),
|
||||||
value_fn: None,
|
value_fn: None,
|
||||||
content_builder: None,
|
|
||||||
copied_callback: None,
|
copied_callback: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the value for copying to the clipboard. Default is an empty string.
|
||||||
pub fn value(mut self, value: impl Into<SharedString>) -> Self {
|
pub fn value(mut self, value: impl Into<SharedString>) -> Self {
|
||||||
self.value = value.into();
|
self.value = value.into();
|
||||||
self
|
self
|
||||||
|
|
@ -45,6 +46,7 @@ impl Clipboard {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set a callback to be invoked when the content is copied to the clipboard.
|
||||||
pub fn on_copied<F>(mut self, handler: F) -> Self
|
pub fn on_copied<F>(mut self, handler: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(SharedString, &mut Window, &mut App) + 'static,
|
F: Fn(SharedString, &mut Window, &mut App) + 'static,
|
||||||
|
|
@ -52,17 +54,6 @@ impl Clipboard {
|
||||||
self.copied_callback = Some(Rc::new(handler));
|
self.copied_callback = Some(Rc::new(handler));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn content<E, F>(mut self, builder: F) -> Self
|
|
||||||
where
|
|
||||||
E: IntoElement,
|
|
||||||
F: Fn(&mut Window, &mut App) -> E + 'static,
|
|
||||||
{
|
|
||||||
self.content_builder = Some(Box::new(move |window, cx| {
|
|
||||||
builder(window, cx).into_any_element()
|
|
||||||
}));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoElement for Clipboard {
|
impl IntoElement for Clipboard {
|
||||||
|
|
@ -73,6 +64,7 @@ impl IntoElement for Clipboard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ClipboardState {
|
pub struct ClipboardState {
|
||||||
copied: Cell<bool>,
|
copied: Cell<bool>,
|
||||||
|
|
@ -101,10 +93,6 @@ impl Element for Clipboard {
|
||||||
window.with_element_state::<ClipboardState, _>(global_id.unwrap(), |state, window| {
|
window.with_element_state::<ClipboardState, _>(global_id.unwrap(), |state, window| {
|
||||||
let state = state.unwrap_or_default();
|
let state = state.unwrap_or_default();
|
||||||
|
|
||||||
let content_element = self
|
|
||||||
.content_builder
|
|
||||||
.as_ref()
|
|
||||||
.map(|builder| builder(window, cx).into_any_element());
|
|
||||||
let value = self.value.clone();
|
let value = self.value.clone();
|
||||||
let clipboard_id = self.id.clone();
|
let clipboard_id = self.id.clone();
|
||||||
let copied_callback = self.copied_callback.as_ref().map(|c| c.clone());
|
let copied_callback = self.copied_callback.as_ref().map(|c| c.clone());
|
||||||
|
|
@ -112,12 +100,7 @@ impl Element for Clipboard {
|
||||||
let copide_value = copied.get();
|
let copide_value = copied.get();
|
||||||
let value_fn = self.value_fn.clone();
|
let value_fn = self.value_fn.clone();
|
||||||
|
|
||||||
let mut element = h_flex()
|
let mut element = Button::new(clipboard_id)
|
||||||
.gap_1()
|
|
||||||
.items_center()
|
|
||||||
.when_some(content_element, |this, element| this.child(element))
|
|
||||||
.child(
|
|
||||||
Button::new(clipboard_id)
|
|
||||||
.icon(if copide_value {
|
.icon(if copide_value {
|
||||||
IconName::Check
|
IconName::Check
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -147,8 +130,7 @@ impl Element for Clipboard {
|
||||||
callback(value.clone(), window, cx);
|
callback(value.clone(), window, cx);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
.into_any_element();
|
.into_any_element();
|
||||||
|
|
||||||
((element.request_layout(window, cx), element), state)
|
((element.request_layout(window, cx), element), state)
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,12 @@ Clipboard::new("my-clipboard")
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### With Dynamic Content
|
### Using Dynamic Values
|
||||||
|
|
||||||
```rust
|
The `value_fn` method allows you to provide a closure that generates the content to be copied at the time of the copy action.
|
||||||
Clipboard::new("clipboard")
|
|
||||||
.content(|_, _| Label::new("Copy this text"))
|
|
||||||
.value("Hello, World!")
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using Value Function
|
- This is useful when the content to be copied depends on the current state of the application.
|
||||||
|
- And in some cases, it may have a larger overhead to compute, so you only want to do it when the user actually clicks the copy button.
|
||||||
For dynamic values that should be computed when the copy action occurs:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let state = some_state.clone();
|
let state = some_state.clone();
|
||||||
|
|
@ -53,14 +48,14 @@ Clipboard::new("dynamic-clipboard")
|
||||||
```rust
|
```rust
|
||||||
use gpui_component::label::Label;
|
use gpui_component::label::Label;
|
||||||
|
|
||||||
Clipboard::new("custom-clipboard")
|
|
||||||
.content(|_, _|
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(Label::new("Share URL"))
|
.child(Label::new("Share URL"))
|
||||||
.child(Icon::new(IconName::Share))
|
.child(Icon::new(IconName::Share))
|
||||||
)
|
.child(
|
||||||
|
Clipboard::new("custom-clipboard")
|
||||||
.value("https://example.com")
|
.value("https://example.com")
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### In Input Fields
|
### In Input Fields
|
||||||
|
|
@ -101,12 +96,16 @@ Clipboard::new("simple")
|
||||||
### With User Feedback
|
### With User Feedback
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
h_flex()
|
||||||
|
.gap_2()
|
||||||
|
.child(Label::new("Your API Key:"))
|
||||||
|
.child(
|
||||||
Clipboard::new("feedback")
|
Clipboard::new("feedback")
|
||||||
.content(|_, _| Label::new("API Key"))
|
|
||||||
.value("sk-1234567890abcdef")
|
.value("sk-1234567890abcdef")
|
||||||
.on_copied(|_, window, cx| {
|
.on_copied(|_, window, cx| {
|
||||||
window.push_notification("API key copied to clipboard", cx)
|
window.push_notification("API key copied to clipboard", cx)
|
||||||
})
|
})
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Form Field Integration
|
### Form Field Integration
|
||||||
|
|
@ -149,7 +148,6 @@ let app_state = cx.new(|_| AppState {
|
||||||
});
|
});
|
||||||
|
|
||||||
Clipboard::new("current-url")
|
Clipboard::new("current-url")
|
||||||
.content(|_, _| Label::new("Share current page"))
|
|
||||||
.value_fn({
|
.value_fn({
|
||||||
let state = app_state.clone();
|
let state = app_state.clone();
|
||||||
move |_, cx| {
|
move |_, cx| {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue