pub mod helpers; mod placeholder; use gpui::{ AppContext as _, Context, Entity, IntoElement, ParentElement as _, Render, Styled as _, Subscription, Window, div, }; use gpui_native_kit::icons::IconRole; use gpui_native_kit::layout::dock::{Dock, DockState}; use gpui_native_kit::layout::shell::{LayoutState, Shell, SidebarToggles}; use gpui_native_kit::theme::ActiveTheme as _; use gpui_native_kit::toast::Toast; use helpers::apply_appearance; use settings::SettingsStore; use signed_state::{Backend, BackendEvent}; use crate::app::placeholder::PlaceholderView; use crate::identity; use crate::shared::dialogs::DialogHost; use crate::sidebar::SidebarView; pub struct AppRoot { layout: Entity, dock: Entity, sidebar: Entity, dialogs: Entity, _subscriptions: Vec, } impl AppRoot { pub fn new(window: &mut Window, cx: &mut Context) -> Self { let dock = DockState::new(cx); let layout = LayoutState::new(cx); layout.update(cx, |layout, cx| { layout.set_sidebar_toggles(SidebarToggles::Hidden, cx); }); dock.update(cx, |dock, cx| { dock.register_panel("welcome", |_, cx| { cx.new(|_| PlaceholderView::new("Welcome")) }); dock.register_panel("profile", |_, cx| { cx.new(|_| PlaceholderView::new("Profile")) }); dock.register_panel("relays", |_, cx| cx.new(|_| PlaceholderView::new("Relays"))); dock.open_panel("welcome", window, cx); }); let sidebar = cx.new(|cx| SidebarView::new(dock.downgrade(), cx)); let dialogs = cx.new(DialogHost::new); DialogHost::set_global(dialogs.clone(), cx); let backend = Backend::global(cx); let settings = SettingsStore::global(cx); let mut subscriptions = Vec::new(); subscriptions.push( cx.subscribe(&backend, |this, _backend, event, cx| match event { BackendEvent::PassphraseRequired => identity::helpers::open_passphrase(cx), BackendEvent::Error(message) => { this.layout.update(cx, |layout, cx| { layout.push_toast(Toast::new(message.clone()).icon(IconRole::Warning), cx); }); } _ => {} }), ); subscriptions.push(cx.observe(&settings, |_this, store, cx| { let settings = store.read(cx).settings().clone(); apply_appearance(&settings, cx); })); window.defer(cx, move |_window, cx| { if backend.read(cx).passphrase_required() { identity::helpers::open_passphrase(cx); } }); Self { layout, dock, sidebar, dialogs, _subscriptions: subscriptions, } } } impl Render for AppRoot { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { let theme = cx.theme(); div() .size_full() .font_family(".SystemUIFont") .text_color(theme.colors.foreground) .child( Shell::new("signed-shell", self.layout.clone()) .left_sidebar(self.sidebar.read(cx).build(cx)) .center( Dock::new("signed-dock", self.dock.clone()) .window_controls(true) .traffic_light_pad(!self.layout.read(cx).is_left_sidebar_visible()) .sidebar_toggles(self.layout.clone()), ), ) .child(self.dialogs.clone()) } }