1use gpui_kit::{
4 AnyElement, App, ElementId, Entity, InteractiveElement as _, IntoElement, ParentElement,
5 RenderOnce, StyleRefinement, Styled, TestSupportExt as _, Window, base::StyledExt as _, div,
6};
7
8mod browser;
9
10pub use browser::{BrowserEvent, BrowserState};
11pub use gpui_webview::{WebView, WebViewHandle};
12
13use crate::ActiveTheme as _;
14
15#[derive(IntoElement)]
38pub struct WebFrame {
39 id: ElementId,
40 style: StyleRefinement,
41 webview: Option<Entity<WebView>>,
42 children: Vec<AnyElement>,
43}
44
45impl WebFrame {
46 pub fn new(id: impl Into<ElementId>) -> Self {
48 Self {
49 id: id.into(),
50 style: StyleRefinement::default(),
51 webview: None,
52 children: Vec::new(),
53 }
54 }
55
56 pub fn webview(mut self, webview: Entity<WebView>) -> Self {
58 self.webview = Some(webview);
59 self
60 }
61
62 pub fn page(&self) -> Option<&Entity<WebView>> {
64 self.webview.as_ref()
65 }
66}
67
68impl Styled for WebFrame {
69 fn style(&mut self) -> &mut StyleRefinement {
70 &mut self.style
71 }
72}
73
74impl ParentElement for WebFrame {
75 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
76 self.children.extend(elements);
77 }
78}
79
80impl RenderOnce for WebFrame {
81 fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
82 let (fill, border, radius, dark) = {
83 let theme = cx.theme();
84 (
85 theme.background(),
86 theme.border(),
87 theme.radius_lg(),
88 theme.is_dark(),
89 )
90 };
91 if let Some(webview) = &self.webview {
92 let scheme = if dark {
93 wry::Theme::Dark
94 } else {
95 wry::Theme::Light
96 };
97 let _ = webview.read(cx).set_theme(scheme);
98 }
99 div()
100 .id(self.id)
101 .test_support()
102 .relative()
103 .overflow_hidden()
104 .border_1()
105 .border_color(border)
106 .rounded(radius)
107 .bg(fill)
108 .refine_style(&self.style)
109 .children(self.webview)
110 .children(self.children)
111 }
112}