diff --git a/assets/themes/cave-dark.json b/assets/themes/cave-dark.json index a2e224ed02..92319af496 100644 --- a/assets/themes/cave-dark.json +++ b/assets/themes/cave-dark.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#e2dfe7", + "size": 14, + "background": "#26232a", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#8b8792", diff --git a/assets/themes/cave-light.json b/assets/themes/cave-light.json index 6ec03294ec..f44069e49f 100644 --- a/assets/themes/cave-light.json +++ b/assets/themes/cave-light.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#26232a", + "size": 14, + "background": "#e2dfe7", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#585260", diff --git a/assets/themes/dark.json b/assets/themes/dark.json index db72fd965c..f50e590fc4 100644 --- a/assets/themes/dark.json +++ b/assets/themes/dark.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#f1f1f1", + "size": 14, + "background": "#2b2b2b", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#9c9c9c", diff --git a/assets/themes/light.json b/assets/themes/light.json index f8754b7ede..08d4326414 100644 --- a/assets/themes/light.json +++ b/assets/themes/light.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#2b2b2b", + "size": 14, + "background": "#eaeaea", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#474747", diff --git a/assets/themes/solarized-dark.json b/assets/themes/solarized-dark.json index c6c9951779..2b75c4364b 100644 --- a/assets/themes/solarized-dark.json +++ b/assets/themes/solarized-dark.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#eee8d5", + "size": 14, + "background": "#073642", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#93a1a1", diff --git a/assets/themes/solarized-light.json b/assets/themes/solarized-light.json index 677bba0070..47758db998 100644 --- a/assets/themes/solarized-light.json +++ b/assets/themes/solarized-light.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#073642", + "size": 14, + "background": "#eee8d5", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#586e75", diff --git a/assets/themes/sulphurpool-dark.json b/assets/themes/sulphurpool-dark.json index b603dccb8d..38761d606e 100644 --- a/assets/themes/sulphurpool-dark.json +++ b/assets/themes/sulphurpool-dark.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#dfe2f1", + "size": 14, + "background": "#293256", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#979db4", diff --git a/assets/themes/sulphurpool-light.json b/assets/themes/sulphurpool-light.json index 3f4983c083..6d3aeadd5f 100644 --- a/assets/themes/sulphurpool-light.json +++ b/assets/themes/sulphurpool-light.json @@ -1255,6 +1255,17 @@ "left": 8 } }, + "edit_contact": { + "family": "Zed Mono", + "color": "#293256", + "size": 14, + "background": "#dfe2f1", + "corner_radius": 12, + "padding": { + "left": 7, + "right": 7 + } + }, "header": { "family": "Zed Mono", "color": "#5e6687", diff --git a/crates/collab/migrations/20220506130724_create_contacts.sql b/crates/collab/migrations/20220506130724_create_contacts.sql new file mode 100644 index 0000000000..a292674ac4 --- /dev/null +++ b/crates/collab/migrations/20220506130724_create_contacts.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS "contacts" ( + "id" SERIAL PRIMARY KEY, + "requesting_user_id" INTEGER REFERENCES users (id) NOT NULL, + "receiving_user_id" INTEGER REFERENCES users (id) NOT NULL, + "accepted" BOOLEAN NOT NULL, + "blocked" BOOLEAN NOT NULL +); + +CREATE UNIQUE INDEX "index_org_contacts_requesting_user_id_and_receiving_user_id" ON "contacts" ("requesting_user_id", "receiving_user_id"); +CREATE UNIQUE INDEX "index_org_contacts_receiving_user" ON "contacts" ("receiving_user_id"); diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 46ca033ee2..9813de7aad 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -905,6 +905,8 @@ impl Server { connection_id, proto::UpdateContacts { contacts: contacts.clone(), + pending_requests_from_user_ids: Default::default(), + pending_requests_to_user_ids: Default::default(), }, ) .trace_err(); diff --git a/crates/contacts_panel/src/contacts_panel.rs b/crates/contacts_panel/src/contacts_panel.rs index 4923e1aa80..7c187ba7ee 100644 --- a/crates/contacts_panel/src/contacts_panel.rs +++ b/crates/contacts_panel/src/contacts_panel.rs @@ -298,6 +298,14 @@ impl ContactsPanel { .left() .boxed(), ) + .with_child( + Label::new("+".to_string(), theme.edit_contact.text.clone()) + .contained() + .with_style(theme.edit_contact.container) + .aligned() + .flex_float() + .boxed(), + ) .constrained() .with_height(theme.row_height) .boxed() diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 267dcb0ba9..73f08345f6 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -89,11 +89,13 @@ message Envelope { GetUsers get_users = 76; FuzzySearchUsers fuzzy_search_users = 77; UsersResponse users_response = 78; + RequestContact request_contact = 79; + RespondToContactRequest respond_to_contact_request = 80; - Follow follow = 79; - FollowResponse follow_response = 80; - UpdateFollowers update_followers = 81; - Unfollow unfollow = 82; + Follow follow = 81; + FollowResponse follow_response = 82; + UpdateFollowers update_followers = 83; + Unfollow unfollow = 84; } } @@ -547,6 +549,21 @@ message UsersResponse { repeated User users = 1; } +message RequestContact { + uint64 to_user_id = 1; +} + +message RespondToContactRequest { + uint64 requesting_user_id = 1; + ContactRequestResponse response = 2; +} + +enum ContactRequestResponse { + Accept = 0; + Reject = 1; + Block = 2; +} + message SendChannelMessage { uint64 channel_id = 1; string body = 2; @@ -574,6 +591,13 @@ message GetChannelMessagesResponse { message UpdateContacts { repeated Contact contacts = 1; + repeated IncomingContactRequest pending_requests_from_user_ids = 2; + repeated uint64 pending_requests_to_user_ids = 3; +} + +message IncomingContactRequest { + uint64 user_id = 1; + bool show_notification = 2; } message UpdateDiagnostics { diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 241cbc8673..1f320bd24c 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -239,6 +239,7 @@ pub struct ContactsPanel { pub row_height: f32, pub contact_avatar: ImageStyle, pub contact_username: ContainedText, + pub edit_contact: ContainedText, pub tree_branch_width: f32, pub tree_branch_color: Color, pub shared_project: ProjectRow, diff --git a/styles/src/styleTree/contactsPanel.ts b/styles/src/styleTree/contactsPanel.ts index dbcc9e4cca..237913c37e 100644 --- a/styles/src/styleTree/contactsPanel.ts +++ b/styles/src/styleTree/contactsPanel.ts @@ -60,6 +60,12 @@ export default function(theme: Theme) { left: 8, }, }, + editContact: { + ...text(theme, "mono", "primary", { size: "sm" }), + background: backgroundColor(theme, 100), + cornerRadius: 12, + padding: { left: 7, right: 7 } + }, header: { ...text(theme, "mono", "secondary", { size: "sm" }), // padding: {