Skip to content

Commit

Permalink
feat(ui): add copy to clipboard button to texts (#298)
Browse files Browse the repository at this point in the history
  • Loading branch information
hrzlgnm authored Oct 3, 2024
1 parent 909fbf4 commit d9fb592
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 42 deletions.
1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0.128"
tauri = { version = "2.0.0", features = [] }
tauri-plugin-log = "2.0.0"
tauri-plugin-clipboard-manager = "2.0.0"

[lib]
name = "mdns_browser_lib"
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/capabilities/migrated.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
],
"permissions": [
"core:default",
"updater:default"
"updater:default",
"clipboard-manager:allow-write-text"
],
"platforms": [
"macOS",
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/capabilities/mobile.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"main"
],
"permissions": [
"core:default"
"core:default",
"clipboard-manager:allow-write-text"
],
"platforms": [
"android"
Expand Down
12 changes: 12 additions & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use tauri::Emitter;
#[cfg(desktop)]
use tauri::Manager;
use tauri::{State, Window};
use tauri_plugin_clipboard_manager::ClipboardExt;
use tauri_plugin_log::{Target, TargetKind};
use tauri_plugin_updater::UpdaterExt;

Expand Down Expand Up @@ -397,6 +398,15 @@ fn is_desktop() -> bool {
false
}

#[tauri::command]
fn copy_to_clipboard(window: Window, contents: String) {
let app = window.app_handle();
app.clipboard()
.write_text(contents)
.map_err(|err| log::error!("Failed to write to clipboard: {}", err))
.unwrap();
}

async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
if let Some(update) = app.updater()?.check().await? {
let mut downloaded = 0;
Expand Down Expand Up @@ -428,6 +438,7 @@ pub fn run() {
x11_workaround();
let args = Args::parse();
tauri::Builder::default()
.plugin(tauri_plugin_clipboard_manager::init())
.manage(ManagedState::new())
.plugin(
tauri_plugin_log::Builder::default()
Expand Down Expand Up @@ -465,6 +476,7 @@ pub fn run() {
.invoke_handler(tauri::generate_handler![
browse,
browse_types,
copy_to_clipboard,
is_desktop,
#[cfg(desktop)]
open,
Expand Down
156 changes: 116 additions & 40 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use strsim::jaro_winkler;
use tauri_sys::core::invoke;
use tauri_sys::event::listen;
use thaw::{
AutoComplete, AutoCompleteOption, AutoCompleteSuffix, Button, ButtonSize, Card, CardFooter,
CardHeaderExtra, Collapse, CollapseItem, GlobalStyle, Grid, GridItem, Icon, Layout, Modal,
Space, SpaceAlign, Table, Tag, TagVariant, Text, Theme, ThemeProvider,
AutoComplete, AutoCompleteOption, AutoCompleteSuffix, Button, ButtonSize, ButtonVariant, Card,
CardFooter, CardHeaderExtra, Collapse, CollapseItem, GlobalStyle, Grid, GridItem, Icon, Layout,
Modal, Space, SpaceAlign, Table, Tag, TagVariant, Text, Theme, ThemeProvider,
};
use thaw_utils::Model;

Expand All @@ -39,7 +39,7 @@ impl Display for TxtRecord {
}
}

fn default_dead() -> bool {
fn alive() -> bool {
false
}

Expand All @@ -52,7 +52,7 @@ struct ResolvedService {
subtype: Option<String>,
txt: Vec<TxtRecord>,
updated_at_ms: u64,
#[serde(default = "default_dead")]
#[serde(default = "alive")]
dead: bool,
}

Expand Down Expand Up @@ -225,23 +225,25 @@ fn ValuesTable(values: Vec<String>, #[prop(into)] title: String) -> impl IntoVie
.map(|n| {
view! {
<tr>
<td>{n}</td>
<td>
<ToClipBoardCopyable text=Some(n) />
</td>
</tr>
}
})
.collect::<Vec<_>>()}
</tbody>
</Table>
<Style>
"
td
{
max-width: 70vw;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
"
"
td
{
max-width: 70vw;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
"
</Style>
}
.into_view()
Expand Down Expand Up @@ -321,12 +323,52 @@ fn AutoCompleteServiceType(
attr:autocapitalize="none"
>
<AutoCompleteSuffix slot>
<Icon icon=icondata::CgSearchLoading/>
<Icon icon=icondata::CgSearchLoading />
</AutoCompleteSuffix>
</AutoComplete>
}
}

#[derive(Serialize, Deserialize)]
struct CopyToClipboardArgs<'a> {
contents: &'a str,
}

async fn copy_to_clipboard(contents: String) {
let _ = invoke::<()>(
"copy_to_clipboard",
&CopyToClipboardArgs {
contents: &contents,
},
)
.await;
}

/// Component that allows to copy the shown text to the clipboard
#[component]
fn ToClipBoardCopyable(text: Option<String>) -> impl IntoView {
let (text_to_copy, _) = create_signal(text.clone().unwrap_or(String::from("")));
let copy_to_clipboard_action = create_action(|input: &String| {
let input = input.clone();
async move { copy_to_clipboard(input.clone()).await }
});

let on_copy_to_clibboard_click = move |_| {
let text = text_to_copy.get();
copy_to_clipboard_action.dispatch(text);
};

view! {
{text}
<Button
on_click=on_copy_to_clibboard_click
variant=ButtonVariant::Text
icon=icondata::TbClipboardText
size=ButtonSize::Tiny
/>
}
}

/// Component that shows a service as a card
#[component]
fn ResolvedServiceGridItem(resolved_service: ResolvedService) -> impl IntoView {
Expand Down Expand Up @@ -373,16 +415,22 @@ fn ResolvedServiceGridItem(resolved_service: ResolvedService) -> impl IntoView {
<Space align=SpaceAlign::Center>
<Tag variant=hostname_variant>{hostname}</Tag>
<Tag variant=port_variant>{resolved_service.port}</Tag>
<Button size=ButtonSize::Tiny disabled=resolved_service.dead on_click=move |_| show_details.set(true)>
<Button
size=ButtonSize::Tiny
disabled=resolved_service.dead
on_click=move |_| show_details.set(true)
>
"Details"
</Button>
<Modal width="90vw" title=details_title show=show_details>
<ValuesTable values=subtype title="subtype"/>
<ValuesTable values=addrs title="IPs"/>
<ValuesTable values=txts title="txt"/>
<ValuesTable values=subtype title="subtype" />
<ValuesTable values=addrs title="IPs" />
<ValuesTable values=txts title="txt" />
</Modal>
</Space>
<CardFooter slot>{addrs_footer.first()}</CardFooter>
<CardFooter slot>
<ToClipBoardCopyable text=addrs_footer.first().cloned() />
</CardFooter>
</Card>
</GridItem>
}
Expand Down Expand Up @@ -610,21 +658,25 @@ fn Browse() -> impl IntoView {
<Layout style="padding: 10px;">
<Space>
<Layout class="auto-complete-320">
<AutoCompleteServiceType value=service_type disabled=browsing invalid=service_type_invalid/>
<AutoCompleteServiceType
value=service_type
disabled=browsing
invalid=service_type_invalid
/>
</Layout>
<Button on_click=on_browse_click disabled=browsing_or_service_type_invalid>
"Browse"
</Button>
<Button on_click=on_stop_click disabled=not_browsing>
"Stop"
</Button>
</Space>
"Browse"
</Button>
<Button on_click=on_stop_click disabled=not_browsing>
"Stop"
</Button>
</Space>
<Grid class="responsivegrid">
<For
each=move || resolved.get()
key=|rs| format!("{}{}", rs.instance_name.clone(), rs.updated_at_ms)
children=move |resolved_service| {
view! { <ResolvedServiceGridItem resolved_service/> }
view! { <ResolvedServiceGridItem resolved_service /> }
}
/>
</Grid>
Expand Down Expand Up @@ -716,13 +768,37 @@ pub fn About() -> impl IntoView {
<Layout style="padding: 10px;">
<Collapse accordion=true>
<CollapseItem title="About" key="about">
<Space>
<Text>"Version "{move || version.get()}</Text>
<Button size=ButtonSize::Tiny on_click=on_release_notes_click icon=icondata::AiGithubOutlined>"Release Notes"</Button>
<Button size=ButtonSize::Tiny on_click=on_report_issue_click icon=icondata::AiGithubOutlined>"Report an Issue"</Button>
<Button size=ButtonSize::Tiny on_click=on_issues_click icon=icondata::AiGithubOutlined>"Known Issues"</Button>
<Button size=ButtonSize::Tiny on_click=on_releases_click icon=icondata::AiGithubOutlined>"Releases"</Button>
</Space>
<Space>
<Text>"Version "{move || version.get()}</Text>
<Button
size=ButtonSize::Tiny
on_click=on_release_notes_click
icon=icondata::AiGithubOutlined
>
"Release Notes"
</Button>
<Button
size=ButtonSize::Tiny
on_click=on_report_issue_click
icon=icondata::AiGithubOutlined
>
"Report an Issue"
</Button>
<Button
size=ButtonSize::Tiny
on_click=on_issues_click
icon=icondata::AiGithubOutlined
>
"Known Issues"
</Button>
<Button
size=ButtonSize::Tiny
on_click=on_releases_click
icon=icondata::AiGithubOutlined
>
"Releases"
</Button>
</Space>
</CollapseItem>
</Collapse>
</Layout>
Expand Down Expand Up @@ -787,10 +863,10 @@ pub fn App() -> impl IntoView {
provide_context(ServiceTypesSignal(service_type));
view! {
<ThemeProvider theme>
<GlobalStyle/>
<About/>
<Metrics/>
<Browse/>
<GlobalStyle />
<About />
<Metrics />
<Browse />
</ThemeProvider>
}
}

0 comments on commit d9fb592

Please sign in to comment.