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
use crate::Result;
use quicklook::QuickLookHandle;
use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Manager, Runtime};
use crate::{models::*, Error, PANEL};
pub fn init<R: Runtime, C: DeserializeOwned>(
app: &AppHandle<R>,
quicklook_handle: QuickLookHandle,
_api: PluginApi<R, C>,
) -> crate::Result<Quicklook<R>> {
Ok(Quicklook {
app_handle: app.clone(),
quicklook_handle,
})
}
/// Access to the quicklook APIs.
pub struct Quicklook<R: Runtime> {
app_handle: AppHandle<R>,
quicklook_handle: QuickLookHandle,
}
impl<R: Runtime> Quicklook<R> {
/// Sets the preview pane's items and reloads the pane.
///
/// **IMPORTANT**: If you change the URLs or order of the items you MUST
/// call [`Quicklook::queue_reload_if_dirty`] after for your changes to take visual effect.
/// However, if you are only updating the source frames of pre-existing items you
/// can safely avoid reloading.
pub fn set_items(&self, items: Vec<PreviewItem>) -> Result<()> {
self.set_items_raw(
items
.into_iter()
.map(|i| {
let frame = match i.src_frame {
Some(SourceFrame::Screen(rect)) => {
Some(quicklook::SourceFrame::Screen(rect))
}
Some(SourceFrame::Window { window_label, rect }) => self
.app_handle
.get_webview_window(&window_label)
.and_then(|w| {
quicklook::SourceFrame::window(
&w,
rect.x,
rect.y,
rect.width,
rect.height,
)
}),
None => None,
};
quicklook::PreviewItem::from_url_string(i.url, frame)
.ok_or(Error::NSURLMalformedURLString)
})
.collect::<Result<Vec<quicklook::PreviewItem>>>()?,
)?;
Ok(())
}
/// Sets the preview pane's items using [`quicklook::PreviewItem`] and reloads
/// the pane. This is useful if you want to manually initialize `NSURL`s yourself.
///
/// **IMPORTANT**: If you change the URLs or order of the items you MUST
/// call [`Quicklook::queue_reload_if_dirty`] after for your changes to take visual effect.
/// However, if you are only updating the source frames of pre-existing items you
/// can safely avoid reloading.
///
/// ## See Also
/// - [`quicklook::PreviewItem`]
/// - [`NSURL`](https://docs.rs/objc2-foundation/latest/objc2_foundation/struct.NSURL.html)
pub fn set_items_raw(&self, items: Vec<quicklook::PreviewItem>) -> Result<()> {
self.quicklook_handle.set_items(items);
Ok(())
}
/// Queues a panel reload that will be executed if the list of items has
/// been modified.
pub fn queue_reload_if_dirty(&self) -> Result<()> {
self.app_handle
.run_on_main_thread(|| {
PANEL.with(|p| {
// SAFETY: OnceCell is initialized in `setup`
p.get().unwrap().reload_if_dirty();
});
})
.map_err(|_| Error::MainThreadDispatchFailed)?;
Ok(())
}
/// Queues the preview panel to be shown.
pub fn queue_show(&self) -> Result<()> {
self.app_handle
.run_on_main_thread(|| {
PANEL.with(|p| {
p.get().unwrap().show();
})
})
.map_err(|_| Error::MainThreadDispatchFailed)?;
Ok(())
}
/// Queues the preview panel to be hidden.
pub fn queue_hide(&self) -> Result<()> {
self.app_handle
.run_on_main_thread(|| {
PANEL.with(|p| {
p.get().unwrap().hide();
})
})
.map_err(|_| Error::MainThreadDispatchFailed)?;
Ok(())
}
/// Queues the preview pane to be hidden if its currently
/// visible, and vice versa if its currently shown.
pub fn queue_toggle_visible(&self) -> Result<()> {
self.app_handle
.run_on_main_thread(|| {
PANEL.with(|p| {
p.get().unwrap().toggle_visible();
})
})
.map_err(|_| Error::MainThreadDispatchFailed)?;
Ok(())
}
}