contacts_popover.rs

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