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 settings::Settings;
 13use workspace::Workspace;
 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    workspace: WeakViewHandle<Workspace>,
 35    _subscription: Option<gpui::Subscription>,
 36}
 37
 38impl ContactsPopover {
 39    pub fn new(
 40        project: ModelHandle<Project>,
 41        user_store: ModelHandle<UserStore>,
 42        workspace: WeakViewHandle<Workspace>,
 43        cx: &mut ViewContext<Self>,
 44    ) -> Self {
 45        let mut this = Self {
 46            child: Child::ContactList(cx.add_view(|cx| {
 47                ContactList::new(project.clone(), user_store.clone(), workspace.clone(), cx)
 48            })),
 49            project,
 50            user_store,
 51            workspace,
 52            _subscription: None,
 53        };
 54        this.show_contact_list(String::new(), cx);
 55        this
 56    }
 57
 58    fn toggle_contact_finder(&mut self, _: &ToggleContactFinder, cx: &mut ViewContext<Self>) {
 59        match &self.child {
 60            Child::ContactList(list) => self.show_contact_finder(list.read(cx).editor_text(cx), cx),
 61            Child::ContactFinder(finder) => self.show_contact_list(finder.read(cx).query(cx), cx),
 62        }
 63    }
 64
 65    fn show_contact_finder(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
 66        let child = cx.add_view(|cx| {
 67            let finder = build_contact_finder(self.user_store.clone(), cx);
 68            finder.set_query(editor_text, cx);
 69            finder
 70        });
 71        cx.focus(&child);
 72        self._subscription = Some(cx.subscribe(&child, |_, _, event, cx| match event {
 73            PickerEvent::Dismiss => cx.emit(Event::Dismissed),
 74        }));
 75        self.child = Child::ContactFinder(child);
 76        cx.notify();
 77    }
 78
 79    fn show_contact_list(&mut self, editor_text: String, cx: &mut ViewContext<ContactsPopover>) {
 80        let child = cx.add_view(|cx| {
 81            ContactList::new(
 82                self.project.clone(),
 83                self.user_store.clone(),
 84                self.workspace.clone(),
 85                cx,
 86            )
 87            .with_editor_text(editor_text, cx)
 88        });
 89        cx.focus(&child);
 90        self._subscription = Some(cx.subscribe(&child, |this, _, event, cx| match event {
 91            crate::contact_list::Event::Dismissed => cx.emit(Event::Dismissed),
 92            crate::contact_list::Event::ToggleContactFinder => {
 93                this.toggle_contact_finder(&Default::default(), cx)
 94            }
 95        }));
 96        self.child = Child::ContactList(child);
 97        cx.notify();
 98    }
 99}
100
101impl Entity for ContactsPopover {
102    type Event = Event;
103}
104
105impl View for ContactsPopover {
106    fn ui_name() -> &'static str {
107        "ContactsPopover"
108    }
109
110    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
111        let theme = cx.global::<Settings>().theme.clone();
112        let child = match &self.child {
113            Child::ContactList(child) => ChildView::new(child, cx),
114            Child::ContactFinder(child) => ChildView::new(child, cx),
115        };
116
117        MouseEventHandler::<ContactsPopover, Self>::new(0, cx, |_, _| {
118            Flex::column()
119                .with_child(child.flex(1., true))
120                .contained()
121                .with_style(theme.contacts_popover.container)
122                .constrained()
123                .with_width(theme.contacts_popover.width)
124                .with_height(theme.contacts_popover.height)
125        })
126        .on_down_out(MouseButton::Left, move |_, _, cx| cx.emit(Event::Dismissed))
127        .into_any()
128    }
129
130    fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
131        if cx.is_self_focused() {
132            match &self.child {
133                Child::ContactList(child) => cx.focus(child),
134                Child::ContactFinder(child) => cx.focus(child),
135            }
136        }
137    }
138}