Skip to content

Commit 39481ec

Browse files
committed
feat: open with
Does not work yet
1 parent dd49980 commit 39481ec

File tree

6 files changed

+133
-4
lines changed

6 files changed

+133
-4
lines changed

Cargo.lock

+50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ tracing-journald = "0.3"
4040
constcat = "0.5"
4141
nucleo = "0.5"
4242
futures = "0.3"
43+
freedesktop-desktop-entry = "0.7.4"
44+
memchr = "2.7.4"
4345

4446
[dependencies.libcosmic]
4547
git = "https://github.com/pop-os/libcosmic"

src/app.rs

+2
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,8 @@ impl cosmic::Application for AppState {
387387
config_set!(horizontal, horizontal);
388388
}
389389
},
390+
AppMsg::Open(_) => todo!(),
391+
AppMsg::OpenWith { entry, desktop_entry } => todo!(),
390392
}
391393
Command::none()
392394
}

src/message.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use cosmic::iced::window::Id;
2+
use freedesktop_desktop_entry::DesktopEntry;
23

34
use crate::{
45
clipboard::{self, ClipboardMessage},
@@ -24,6 +25,12 @@ pub enum AppMsg {
2425
ShowQrCode(Entry),
2526
ReturnToClipboard,
2627
Config(ConfigMsg),
28+
Open(Entry),
29+
OpenWith {
30+
entry: Entry,
31+
desktop_entry: DesktopEntry<'static>,
32+
},
33+
2734
}
2835

2936
#[derive(Clone, Debug)]

src/utils.rs

+26
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,29 @@ pub fn remove_dir_contents(dir: &Path) {
9999

100100
let _ = inner(dir);
101101
}
102+
103+
pub fn find_x_scheme_handler<'a>(a: &'a str) -> Option<&'a str> {
104+
// Use memchr to find the first occurrence of ':' in the input string.
105+
if let Some(colon_index) = memchr::memchr(b':', a.as_bytes()) {
106+
// Check if the colon is followed by "//" to validate the scheme.
107+
if a[colon_index..].starts_with("://") {
108+
// If valid, return the scheme as a slice from the start up to the colon.
109+
return Some(&a[..colon_index]);
110+
}
111+
}
112+
// If no scheme is found, return None.
113+
None
114+
}
115+
116+
#[test]
117+
fn find_x_scheme_handler_test() {
118+
assert_eq!(
119+
find_x_scheme_handler("https://github.com/wiiznokes/clipboard-manager"),
120+
Some("https")
121+
);
122+
123+
assert_eq!(
124+
find_x_scheme_handler("ddg://query%20terms"),
125+
Some("ddg")
126+
);
127+
}

src/view.rs

+46-4
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ use cosmic::{
1515
button::{self},
1616
column, container, context_menu, flex_row, grid,
1717
icon::{self, Handle},
18-
image, menu, mouse_area, row, text, text_input, toggler, Column, Container, Icon,
18+
image, menu, mouse_area, row, text, text_input, toggler, Column, Container, Icon, Lazy,
1919
MouseArea, Space, Text, TextEditor,
2020
},
2121
Element,
2222
};
2323

24+
use freedesktop_desktop_entry as fde;
25+
2426
use anyhow::{anyhow, bail, Result};
2527

2628
use crate::{
@@ -29,7 +31,7 @@ use crate::{
2931
db::{Content, Entry},
3032
fl,
3133
message::{AppMsg, ConfigMsg},
32-
utils::{formatted_value, horizontal_padding, vertical_padding},
34+
utils::{find_x_scheme_handler, formatted_value, horizontal_padding, vertical_padding},
3335
};
3436

3537
impl AppState {
@@ -327,6 +329,43 @@ impl AppState {
327329
btn.width(Length::Fill).into()
328330
};
329331

332+
let open_with = Lazy::new(entry, |entry| {
333+
println!("lazy");
334+
335+
let mut mimes = vec![entry.mime.as_ref()];
336+
337+
if let Ok(Content::Text(content)) = entry.get_content() {
338+
if let Some(m) = find_x_scheme_handler(content) {
339+
mimes.push(m);
340+
}
341+
}
342+
343+
let res = fde::DesktopEntry::from_paths::<&str>(
344+
fde::Iter::new(fde::default_paths()),
345+
Some(&[]),
346+
)
347+
.filter_map(|e| {
348+
e.ok().and_then(|e| {
349+
e.mime_type()
350+
.unwrap_or_default()
351+
.iter()
352+
.any(|e| mimes.contains(e))
353+
.then_some(
354+
button(text(e.appid.clone()))
355+
.on_press(AppMsg::OpenWith {
356+
entry: (*entry).clone(),
357+
desktop_entry: e,
358+
})
359+
.width(Length::Fill)
360+
.into(),
361+
)
362+
})
363+
})
364+
.collect::<Vec<_>>();
365+
366+
Column::with_children(res)
367+
});
368+
330369
context_menu(
331370
btn,
332371
Some(vec![
@@ -339,8 +378,11 @@ impl AppState {
339378
menu::Tree::new(
340379
button::text(fl!("show_qr_code"))
341380
.on_press(AppMsg::ShowQrCode(entry.clone()))
342-
.width(Length::Fill)
343-
.style(Button::Destructive),
381+
.width(Length::Fill),
382+
),
383+
menu::Tree::with_children(
384+
text("Open with").width(Length::Fill),
385+
vec![menu::Tree::new(open_with)],
344386
),
345387
]),
346388
)

0 commit comments

Comments
 (0)