contacts_popover.rs

  1use crate::{
  2    contact_finder::{build_contact_finder, ContactFinder},
  3    contact_list::ContactList,
  4};
  5use client::UserStore;
  6use gpui::{
  7    actions, elements::*, platform::MouseButton, AppContext, Entity, ModelHandle, View,
  8    ViewContext, ViewHandle, WeakViewHandle,
  9};
 10use picker::PickerEvent;
 11use project::Project;
 12use workspace::Workspace;
 13
 14actions!(contacts_popover, [ToggleContactFinder]);
 15
 16pub fn init(cx: &mut AppContext) {
 17    cx.add_action(ContactsPopover::toggle_contact_finder);
 18}
 19
 20pub enum Event {
 21    Dismissed,
 22}
 23
 24enum Child {
 25    ContactList(ViewHandle<ContactList>),
 26    ContactFinder(ViewHandle<ContactFinder>),
 27}
 28
 29pub struct ContactsPopover {
 30    child: Child,
 31    project: ModelHandle<Project>,
 32    user_store: ModelHandle<UserStore>,
 33    workspace: WeakViewHandle<Workspace>,
 34    _subscription: Option<gpui::Subscription>,
 35}
 36
 37impl ContactsPopover {
 38    pub fn new(
 39        project: ModelHandle<Project>,
 40        user_store: ModelHandle<UserStore>,
 41        workspace: WeakViewHandle<Workspace>,
 42        cx: &mut ViewContext<Self>,
 43    ) -> Self {
 44        let mut this = Self {
 45            child: Child::ContactList(cx.add_view(|cx| {
 46                ContactList::new(project.clone(), user_store.clone(), workspace.clone(), cx)
 47            })),
 48            project,
 49            user_store,
 50            workspace,
 51            _subscription: None,
 52        };
 53        this.show_contact_list(String::new(), cx);
 54        this
 55    }
 56
 57    fn toggle_contact_finder(&mut self, _: &ToggleContactFinder, cx: &mut ViewContext<Self>) {
 58        match &self.child {
 59            Child::ContactList(list) => self.show_contact_finder(list.read(cx).editor_text(cx), cx),
 60            Child::ContactFinder(finder) => self.show_contact_list(finder.read(cx).query(cx), cx),
 61        }
 62    }
 63
 64    fn show_contact_finder(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
 65        let child = cx.add_view(|cx| {
 66            let finder = build_contact_finder(self.user_store.clone(), cx);
 67            finder.set_query(editor_text, cx);
 68            finder
 69        });
 70        cx.focus(&child);
 71        self._subscription = Some(cx.subscribe(&child, |_, _, event, cx| match event {
 72            PickerEvent::Dismiss => cx.emit(Event::Dismissed),
 73        }));
 74        self.child = Child::ContactFinder(child);
 75        cx.notify();
 76    }
 77
 78    fn show_contact_list(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
 79        let child = cx.add_view(|cx| {
 80            ContactList::new(
 81                self.project.clone(),
 82                self.user_store.clone(),
 83                self.workspace.clone(),
 84                cx,
 85            )
 86            .with_editor_text(editor_text, cx)
 87        });
 88        cx.focus(&child);
 89        self._subscription = Some(cx.subscribe(&child, |this, _, event, cx| match event {
 90            crate::contact_list::Event::Dismissed => cx.emit(Event::Dismissed),
 91            crate::contact_list::Event::ToggleContactFinder => {
 92                this.toggle_contact_finder(&Default::default(), cx)
 93            }
 94        }));
 95        self.child = Child::ContactList(child);
 96        cx.notify();
 97    }
 98}
 99
100impl Entity for ContactsPopover {
101    type Event = Event;
102}
103
104impl View for ContactsPopover {
105    fn ui_name() -> &'static str {
106        "ContactsPopover"
107    }
108
109    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
110        let theme = theme::current(cx).clone();
111        let child = match &self.child {
112            Child::ContactList(child) => ChildView::new(child, cx),
113            Child::ContactFinder(child) => ChildView::new(child, cx),
114        };
115
116        MouseEventHandler::<ContactsPopover, Self>::new(0, cx, |_, _| {
117            Flex::column()
118                .with_child(child.flex(1., true))
119                .contained()
120                .with_style(theme.contacts_popover.container)
121                .constrained()
122                .with_width(theme.contacts_popover.width)
123                .with_height(theme.contacts_popover.height)
124        })
125        .on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(Event::Dismissed))
126        .into_any()
127    }
128
129    fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
130        if cx.is_self_focused() {
131            match &self.child {
132                Child::ContactList(child) => cx.focus(child),
133                Child::ContactFinder(child) => cx.focus(child),
134            }
135        }
136    }
137}