Show incoming request notification and implement dismissal
This commit is contained in:
@@ -356,6 +356,24 @@ impl UserStore {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn dismiss_contact_request(
|
||||
&mut self,
|
||||
requester_id: u64,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
let client = self.client.upgrade();
|
||||
cx.spawn_weak(|_, _| async move {
|
||||
client
|
||||
.ok_or_else(|| anyhow!("can't upgrade client reference"))?
|
||||
.request(proto::RespondToContactRequest {
|
||||
requester_id,
|
||||
response: proto::ContactRequestResponse::Dismiss as i32,
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn perform_contact_request<T: RequestMessage>(
|
||||
&mut self,
|
||||
user_id: u64,
|
||||
|
||||
+34
-27
@@ -1023,35 +1023,42 @@ impl Server {
|
||||
.await
|
||||
.user_id_for_connection(request.sender_id)?;
|
||||
let requester_id = UserId::from_proto(request.payload.requester_id);
|
||||
let accept = request.payload.response == proto::ContactRequestResponse::Accept as i32;
|
||||
self.app_state
|
||||
.db
|
||||
.respond_to_contact_request(responder_id, requester_id, accept)
|
||||
.await?;
|
||||
if request.payload.response == proto::ContactRequestResponse::Dismiss as i32 {
|
||||
self.app_state
|
||||
.db
|
||||
.dismiss_contact_request(responder_id, requester_id)
|
||||
.await?;
|
||||
} else {
|
||||
let accept = request.payload.response == proto::ContactRequestResponse::Accept as i32;
|
||||
self.app_state
|
||||
.db
|
||||
.respond_to_contact_request(responder_id, requester_id, accept)
|
||||
.await?;
|
||||
|
||||
let store = self.store().await;
|
||||
// Update responder with new contact
|
||||
let mut update = proto::UpdateContacts::default();
|
||||
if accept {
|
||||
update.contacts.push(store.contact_for_user(requester_id));
|
||||
}
|
||||
update
|
||||
.remove_incoming_requests
|
||||
.push(requester_id.to_proto());
|
||||
for connection_id in store.connection_ids_for_user(responder_id) {
|
||||
self.peer.send(connection_id, update.clone())?;
|
||||
}
|
||||
let store = self.store().await;
|
||||
// Update responder with new contact
|
||||
let mut update = proto::UpdateContacts::default();
|
||||
if accept {
|
||||
update.contacts.push(store.contact_for_user(requester_id));
|
||||
}
|
||||
update
|
||||
.remove_incoming_requests
|
||||
.push(requester_id.to_proto());
|
||||
for connection_id in store.connection_ids_for_user(responder_id) {
|
||||
self.peer.send(connection_id, update.clone())?;
|
||||
}
|
||||
|
||||
// Update requester with new contact
|
||||
let mut update = proto::UpdateContacts::default();
|
||||
if accept {
|
||||
update.contacts.push(store.contact_for_user(responder_id));
|
||||
}
|
||||
update
|
||||
.remove_outgoing_requests
|
||||
.push(responder_id.to_proto());
|
||||
for connection_id in store.connection_ids_for_user(requester_id) {
|
||||
self.peer.send(connection_id, update.clone())?;
|
||||
// Update requester with new contact
|
||||
let mut update = proto::UpdateContacts::default();
|
||||
if accept {
|
||||
update.contacts.push(store.contact_for_user(responder_id));
|
||||
}
|
||||
update
|
||||
.remove_outgoing_requests
|
||||
.push(responder_id.to_proto());
|
||||
for connection_id in store.connection_ids_for_user(requester_id) {
|
||||
self.peer.send(connection_id, update.clone())?;
|
||||
}
|
||||
}
|
||||
|
||||
response.send(proto::Ack {})?;
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
use client::{User, UserStore};
|
||||
use gpui::{color::Color, elements::*, Entity, ModelHandle, View, ViewContext};
|
||||
use gpui::{
|
||||
elements::*, impl_internal_actions, platform::CursorStyle, Entity, ModelHandle,
|
||||
MutableAppContext, RenderContext, View, ViewContext,
|
||||
};
|
||||
use settings::Settings;
|
||||
use std::sync::Arc;
|
||||
use workspace::Notification;
|
||||
|
||||
impl_internal_actions!(contact_notifications, [Dismiss]);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(IncomingRequestNotification::dismiss);
|
||||
}
|
||||
|
||||
pub struct IncomingRequestNotification {
|
||||
user: Arc<User>,
|
||||
user_store: ModelHandle<UserStore>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Dismiss(u64);
|
||||
|
||||
pub enum Event {
|
||||
Dismiss,
|
||||
}
|
||||
@@ -21,12 +34,91 @@ impl View for IncomingRequestNotification {
|
||||
"IncomingRequestNotification"
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
||||
Empty::new()
|
||||
.constrained()
|
||||
.with_height(200.)
|
||||
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||
enum Dismiss {}
|
||||
enum Reject {}
|
||||
enum Accept {}
|
||||
|
||||
let theme = cx.global::<Settings>().theme.clone();
|
||||
let theme = &theme.incoming_request_notification;
|
||||
let user_id = self.user.id;
|
||||
|
||||
Flex::column()
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_children(self.user.avatar.clone().map(|avatar| {
|
||||
Image::new(avatar)
|
||||
.with_style(theme.header_avatar)
|
||||
.aligned()
|
||||
.left()
|
||||
.boxed()
|
||||
}))
|
||||
.with_child(
|
||||
Label::new(
|
||||
format!("{} added you", self.user.github_login),
|
||||
theme.header_message.text.clone(),
|
||||
)
|
||||
.contained()
|
||||
.with_style(theme.header_message.container)
|
||||
.aligned()
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::new::<Dismiss, _, _>(
|
||||
self.user.id as usize,
|
||||
cx,
|
||||
|_, _| {
|
||||
Svg::new("icons/reject.svg")
|
||||
.with_color(theme.dismiss_button.color)
|
||||
.constrained()
|
||||
.with_width(theme.dismiss_button.icon_width)
|
||||
.aligned()
|
||||
.contained()
|
||||
.with_style(theme.dismiss_button.container)
|
||||
.constrained()
|
||||
.with_width(theme.dismiss_button.button_width)
|
||||
.with_height(theme.dismiss_button.button_width)
|
||||
.aligned()
|
||||
.boxed()
|
||||
},
|
||||
)
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(move |_, cx| cx.dispatch_action(Dismiss(user_id)))
|
||||
.flex_float()
|
||||
.boxed(),
|
||||
)
|
||||
.constrained()
|
||||
.with_height(theme.header_height)
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(
|
||||
Label::new(
|
||||
"They won't know if you decline.".to_string(),
|
||||
theme.body_message.text.clone(),
|
||||
)
|
||||
.contained()
|
||||
.with_style(theme.body_message.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new("Decline".to_string(), theme.button.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.button.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(
|
||||
Label::new("Accept".to_string(), theme.button.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.button.container)
|
||||
.boxed(),
|
||||
)
|
||||
.aligned()
|
||||
.right()
|
||||
.boxed(),
|
||||
)
|
||||
.contained()
|
||||
.with_background_color(Color::red())
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
@@ -55,4 +147,13 @@ impl IncomingRequestNotification {
|
||||
|
||||
Self { user, user_store }
|
||||
}
|
||||
|
||||
fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext<Self>) {
|
||||
self.user_store.update(cx, |store, cx| {
|
||||
store
|
||||
.dismiss_contact_request(self.user.id, cx)
|
||||
.detach_and_log_err(cx);
|
||||
});
|
||||
cx.emit(Event::Dismiss);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ pub struct RespondToContactRequest {
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
contact_finder::init(cx);
|
||||
contact_notifications::init(cx);
|
||||
cx.add_action(ContactsPanel::request_contact);
|
||||
cx.add_action(ContactsPanel::remove_contact);
|
||||
cx.add_action(ContactsPanel::respond_to_contact_request);
|
||||
|
||||
@@ -566,6 +566,7 @@ enum ContactRequestResponse {
|
||||
Accept = 0;
|
||||
Reject = 1;
|
||||
Block = 2;
|
||||
Dismiss = 3;
|
||||
}
|
||||
|
||||
message SendChannelMessage {
|
||||
|
||||
@@ -29,6 +29,7 @@ pub struct Theme {
|
||||
pub search: Search,
|
||||
pub project_diagnostics: ProjectDiagnostics,
|
||||
pub breadcrumbs: ContainedText,
|
||||
pub incoming_request_notification: IncomingRequestNotification,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
@@ -354,6 +355,16 @@ pub struct ProjectDiagnostics {
|
||||
pub tab_summary_spacing: f32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
pub struct IncomingRequestNotification {
|
||||
pub header_avatar: ImageStyle,
|
||||
pub header_message: ContainedText,
|
||||
pub header_height: f32,
|
||||
pub body_message: ContainedText,
|
||||
pub button: ContainedText,
|
||||
pub dismiss_button: IconButton,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct Editor {
|
||||
pub text_color: Color,
|
||||
|
||||
Reference in New Issue
Block a user