@@ -2,6 +2,7 @@ ALTER TABLE users
ADD invite_code VARCHAR(64),
ADD invite_count INTEGER NOT NULL DEFAULT 0,
ADD inviter_id INTEGER REFERENCES users (id),
+ADD first_connection BOOLEAN NOT NULL DEFAULT true,
ADD created_at TIMESTAMP NOT NULL DEFAULT NOW();
CREATE UNIQUE INDEX "index_invite_code_users" ON "users" ("invite_code");
@@ -18,6 +18,7 @@ pub trait Db: Send + Sync {
async fn get_users_by_ids(&self, ids: Vec<UserId>) -> Result<Vec<User>>;
async fn get_user_by_github_login(&self, github_login: &str) -> Result<Option<User>>;
async fn set_user_is_admin(&self, id: UserId, is_admin: bool) -> Result<()>;
+ async fn set_user_first_connection(&self, id: UserId, first_connection: bool) -> Result<()>;
async fn destroy_user(&self, id: UserId) -> Result<()>;
async fn set_invite_count(&self, id: UserId, count: u32) -> Result<()>;
@@ -182,6 +183,16 @@ impl Db for PostgresDb {
.map(drop)?)
}
+ async fn set_user_first_connection(&self, id: UserId, first_connection: bool) -> Result<()> {
+ let query = "UPDATE users SET first_connection = $1 WHERE id = $2";
+ Ok(sqlx::query(query)
+ .bind(first_connection)
+ .bind(id.0)
+ .execute(&self.pool)
+ .await
+ .map(drop)?)
+ }
+
async fn destroy_user(&self, id: UserId) -> Result<()> {
let query = "DELETE FROM access_tokens WHERE user_id = $1;";
sqlx::query(query)
@@ -847,6 +858,7 @@ pub struct User {
pub admin: bool,
pub invite_code: Option<String>,
pub invite_count: i32,
+ pub first_connection: bool,
}
id_type!(OrgId);
@@ -1601,6 +1613,7 @@ pub mod tests {
admin,
invite_code: None,
invite_count: 0,
+ first_connection: true,
},
);
Ok(user_id)
@@ -1638,6 +1651,20 @@ pub mod tests {
unimplemented!()
}
+ async fn set_user_first_connection(
+ &self,
+ id: UserId,
+ first_connection: bool,
+ ) -> Result<()> {
+ self.background.simulate_random_delay().await;
+ let mut users = self.users.lock();
+ let mut user = users
+ .get_mut(&id)
+ .ok_or_else(|| anyhow!("user not found"))?;
+ user.first_connection = first_connection;
+ Ok(())
+ }
+
async fn destroy_user(&self, _id: UserId) -> Result<()> {
unimplemented!()
}
@@ -280,6 +280,11 @@ impl Server {
let _ = send_connection_id.send(connection_id).await;
}
+ if user.first_connection {
+ this.peer.send(connection_id, proto::ShowContacts {})?;
+ this.app_state.db.set_user_first_connection(user_id, false).await?;
+ }
+
let (contacts, invite_code) = future::try_join(
this.app_state.db.get_contacts(user_id),
this.app_state.db.get_invite_code_for_user(user_id)
@@ -88,18 +88,19 @@ message Envelope {
UpdateContacts update_contacts = 76;
UpdateInviteInfo update_invite_info = 77;
-
- GetUsers get_users = 78;
- FuzzySearchUsers fuzzy_search_users = 79;
- UsersResponse users_response = 80;
- RequestContact request_contact = 81;
- RespondToContactRequest respond_to_contact_request = 82;
- RemoveContact remove_contact = 83;
-
- Follow follow = 84;
- FollowResponse follow_response = 85;
- UpdateFollowers update_followers = 86;
- Unfollow unfollow = 87;
+ ShowContacts show_contacts = 78;
+
+ GetUsers get_users = 79;
+ FuzzySearchUsers fuzzy_search_users = 80;
+ UsersResponse users_response = 81;
+ RequestContact request_contact = 82;
+ RespondToContactRequest respond_to_contact_request = 83;
+ RemoveContact remove_contact = 84;
+
+ Follow follow = 85;
+ FollowResponse follow_response = 86;
+ UpdateFollowers update_followers = 87;
+ Unfollow unfollow = 88;
}
}
@@ -640,6 +641,8 @@ message UpdateInviteInfo {
uint32 count = 2;
}
+message ShowContacts {}
+
message IncomingContactRequest {
uint64 requester_id = 1;
bool should_notify = 2;
@@ -145,6 +145,7 @@ messages!(
(SearchProjectResponse, Background),
(SendChannelMessage, Foreground),
(SendChannelMessageResponse, Foreground),
+ (ShowContacts, Foreground),
(StartLanguageServer, Foreground),
(Test, Foreground),
(Unfollow, Foreground),