freya_webview/
component.rs

1use freya_core::{
2    events::data::{
3        Event,
4        SizedEventData,
5    },
6    prelude::*,
7};
8
9use crate::{
10    element::webview,
11    lifecycle::WebViewLifecycleEvent,
12    prelude::{
13        WebViewConfig,
14        WebViewId,
15    },
16    registry::WebViewCallback,
17};
18
19#[derive(Clone)]
20pub struct WebView {
21    webview_id: WebViewId,
22    url: String,
23    close_on_drop: bool,
24    on_created: Option<WebViewCallback>,
25    layout: LayoutData,
26}
27
28impl PartialEq for WebView {
29    fn eq(&self, other: &Self) -> bool {
30        self.webview_id == other.webview_id
31            && self.url == other.url
32            && self.close_on_drop == other.close_on_drop
33            && match (&self.on_created, &other.on_created) {
34                (None, None) => true,
35                (Some(a), Some(b)) => std::sync::Arc::ptr_eq(a, b),
36                _ => false,
37            }
38            && self.layout == other.layout
39    }
40}
41
42impl WebView {
43    pub fn new(url: impl Into<String>) -> Self {
44        Self {
45            webview_id: WebViewId::new(),
46            url: url.into(),
47            close_on_drop: true,
48            on_created: None,
49            layout: LayoutData::default(),
50        }
51    }
52
53    pub fn url(mut self, url: impl Into<String>) -> Self {
54        self.url = url.into();
55        self
56    }
57
58    pub fn id(mut self, id: WebViewId) -> Self {
59        self.webview_id = id;
60        self
61    }
62
63    /// If you decide to not close the webview on drop you will need to manually close it with [WebViewManager::close](crate::lifecycle::WebViewManager::close).
64    pub fn close_on_drop(mut self, close: bool) -> Self {
65        self.close_on_drop = close;
66        self
67    }
68
69    pub fn on_created(
70        mut self,
71        on_created: impl Fn(wry::WebViewBuilder) -> wry::WebViewBuilder + Send + 'static,
72    ) -> Self {
73        self.on_created = Some(WebViewCallback::new(Box::new(on_created)));
74        self
75    }
76}
77
78impl LayoutExt for WebView {
79    fn get_layout(&mut self) -> &mut LayoutData {
80        &mut self.layout
81    }
82}
83impl ContainerExt for WebView {}
84
85impl Component for WebView {
86    fn render(&self) -> impl IntoElement {
87        let events = consume_root_context::<crate::lifecycle::WebViewEvents>();
88
89        let webview_id = self.webview_id;
90        let url = self.url.clone();
91        let close_on_drop = self.close_on_drop;
92        let on_created = self.on_created.clone();
93
94        let config = WebViewConfig {
95            url: url.clone(),
96            transparent: false,
97            user_agent: None,
98            on_created,
99        };
100
101        use_drop({
102            let events = events.clone();
103            move || {
104                events.lock().unwrap().push(if close_on_drop {
105                    WebViewLifecycleEvent::Close { id: webview_id }
106                } else {
107                    WebViewLifecycleEvent::Hide { id: webview_id }
108                });
109            }
110        });
111
112        webview(&url)
113            .layout(self.layout.clone())
114            .on_sized(move |event: Event<SizedEventData>| {
115                events.lock().unwrap().push(WebViewLifecycleEvent::Resized {
116                    id: webview_id,
117                    area: event.area,
118                    config: config.clone(),
119                });
120            })
121    }
122
123    fn render_key(&self) -> DiffKey {
124        DiffKey::from(&self.webview_id)
125    }
126}