From 48f5a2ee5e44f381e86b11f148f2e2a99ac94ef6 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 6 May 2022 17:37:53 -0400 Subject: [PATCH] Add pending, and change use specific API response for FollowCommunity. Fixes #2246 --- crates/api/src/community/follow.rs | 25 +++++++--------- crates/api_common/src/community.rs | 12 +++++++- .../src/community_follower_view.rs | 29 ++++++++++++++++++- crates/db_views_actor/src/structs.rs | 1 + 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/crates/api/src/community/follow.rs b/crates/api/src/community/follow.rs index aab21a9c2..df9fae3cf 100644 --- a/crates/api/src/community/follow.rs +++ b/crates/api/src/community/follow.rs @@ -1,7 +1,7 @@ use crate::Perform; use actix_web::web::Data; use lemmy_api_common::{ - community::{CommunityResponse, FollowCommunity}, + community::{FollowCommunity, FollowCommunityResponse}, utils::{ blocking, check_community_ban, @@ -20,20 +20,20 @@ use lemmy_db_schema::{ source::community::{Community, CommunityFollower, CommunityFollowerForm}, traits::{Crud, Followable}, }; -use lemmy_db_views_actor::structs::CommunityView; +use lemmy_db_views_actor::structs::CommunityFollowerView; use lemmy_utils::{ConnectionId, LemmyError}; use lemmy_websocket::LemmyContext; #[async_trait::async_trait(?Send)] impl Perform for FollowCommunity { - type Response = CommunityResponse; + type Response = FollowCommunityResponse; #[tracing::instrument(skip(context, _websocket_id))] async fn perform( &self, context: &Data, _websocket_id: Option, - ) -> Result { + ) -> Result { let data: &FollowCommunity = self; let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?; @@ -47,7 +47,7 @@ impl Perform for FollowCommunity { let community_follower_form = CommunityFollowerForm { community_id: data.community_id, person_id: local_user_view.person.id, - pending: false, + pending: false, // Don't worry, this form isn't used for remote follows }; if community.local { @@ -82,18 +82,13 @@ impl Perform for FollowCommunity { let community_id = data.community_id; let person_id = local_user_view.person.id; - let mut community_view = blocking(context.pool(), move |conn| { - CommunityView::read(conn, community_id, Some(person_id)) + let community_follower_view = blocking(context.pool(), move |conn| { + CommunityFollowerView::read(conn, community_id, person_id) }) .await??; - // TODO: this needs to return a "pending" state, until Accept is received from the remote server - // For now, just assume that remote follows are accepted. - // Otherwise, the subscribed will be null - if !community.local { - community_view.subscribed = data.follow; - } - - Ok(CommunityResponse { community_view }) + Ok(Self::Response { + community_follower_view, + }) } } diff --git a/crates/api_common/src/community.rs b/crates/api_common/src/community.rs index 90c86f1c2..a4b5e2e6f 100644 --- a/crates/api_common/src/community.rs +++ b/crates/api_common/src/community.rs @@ -5,7 +5,12 @@ use lemmy_db_schema::{ ListingType, SortType, }; -use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView, PersonViewSafe}; +use lemmy_db_views_actor::structs::{ + CommunityFollowerView, + CommunityModeratorView, + CommunityView, + PersonViewSafe, +}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -41,6 +46,11 @@ pub struct CommunityResponse { pub community_view: CommunityView, } +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct FollowCommunityResponse { + pub community_follower_view: CommunityFollowerView, +} + #[derive(Debug, Serialize, Deserialize, Clone, Default)] pub struct ListCommunities { pub type_: Option, diff --git a/crates/db_views_actor/src/community_follower_view.rs b/crates/db_views_actor/src/community_follower_view.rs index 6d5d94a59..7e37e446a 100644 --- a/crates/db_views_actor/src/community_follower_view.rs +++ b/crates/db_views_actor/src/community_follower_view.rs @@ -10,7 +10,7 @@ use lemmy_db_schema::{ traits::{ToSafe, ViewToVec}, }; -type CommunityFollowerViewTuple = (CommunitySafe, PersonSafe); +type CommunityFollowerViewTuple = (CommunitySafe, PersonSafe, Option); impl CommunityFollowerView { pub fn for_community(conn: &PgConnection, community_id: CommunityId) -> Result, Error> { @@ -20,6 +20,7 @@ impl CommunityFollowerView { .select(( Community::safe_columns_tuple(), Person::safe_columns_tuple(), + community_follower::pending, )) .filter(community_follower::community_id.eq(community_id)) .order_by(community::title) @@ -35,6 +36,7 @@ impl CommunityFollowerView { .select(( Community::safe_columns_tuple(), Person::safe_columns_tuple(), + community_follower::pending, )) .filter(community_follower::person_id.eq(person_id)) .order_by(community::title) @@ -42,6 +44,30 @@ impl CommunityFollowerView { Ok(Self::from_tuple_to_vec(res)) } + + pub fn read( + conn: &PgConnection, + community_id: CommunityId, + person_id: PersonId, + ) -> Result { + let (community, follower, pending) = community_follower::table + .inner_join(community::table) + .inner_join(person::table) + .select(( + Community::safe_columns_tuple(), + Person::safe_columns_tuple(), + community_follower::pending, + )) + .filter(community_follower::person_id.eq(person_id)) + .filter(community_follower::community_id.eq(community_id)) + .first::(conn)?; + + Ok(Self { + community, + follower, + pending, + }) + } } impl ViewToVec for CommunityFollowerView { @@ -52,6 +78,7 @@ impl ViewToVec for CommunityFollowerView { .map(|a| Self { community: a.0.to_owned(), follower: a.1.to_owned(), + pending: a.2.to_owned(), }) .collect::>() } diff --git a/crates/db_views_actor/src/structs.rs b/crates/db_views_actor/src/structs.rs index a6ec9710e..25d2c178e 100644 --- a/crates/db_views_actor/src/structs.rs +++ b/crates/db_views_actor/src/structs.rs @@ -20,6 +20,7 @@ pub struct CommunityBlockView { pub struct CommunityFollowerView { pub community: CommunitySafe, pub follower: PersonSafe, + pub pending: Option, } #[derive(Debug, Serialize, Deserialize, Clone)]