diff --git a/crates/app/src/langs/en-US.toml b/crates/app/src/langs/en-US.toml index 48bb07f..3c9556c 100644 --- a/crates/app/src/langs/en-US.toml +++ b/crates/app/src/langs/en-US.toml @@ -22,10 +22,13 @@ version = "1.0.0" "auth:action.logout" = "Logout" "auto:action.follow" = "Follow" "auto:action.unfollow" = "Unfollow" +"auto:action.block" = "Block" +"auto:action.unblock" = "Unblock" "auth:link.my_profile" = "My profile" "auth:link.settings" = "Settings" "auth:label.followers" = "Followers" "auth:label.following" = "Following" +"auth:label.relationship" = "Relationship" "auth:label.joined_communities" = "Joined communities" "auth:label.recent_posts" = "Recent posts" diff --git a/crates/app/src/public/css/style.css b/crates/app/src/public/css/style.css index 41e9f50..5ba777c 100644 --- a/crates/app/src/public/css/style.css +++ b/crates/app/src/public/css/style.css @@ -85,7 +85,7 @@ main { } article { - margin-top: 1rem; + margin: 1rem 0; } @media screen and (max-width: 900px) { diff --git a/crates/app/src/public/html/communities/settings.html b/crates/app/src/public/html/communities/settings.html index 911fa7c..fb15aeb 100644 --- a/crates/app/src/public/html/communities/settings.html +++ b/crates/app/src/public/html/communities/settings.html @@ -25,9 +25,24 @@
@@ -39,9 +54,24 @@
diff --git a/crates/app/src/public/html/profile/base.html b/crates/app/src/public/html/profile/base.html index 56aa060..e7be6fd 100644 --- a/crates/app/src/public/html/profile/base.html +++ b/crates/app/src/public/html/profile/base.html @@ -31,21 +31,23 @@ -
- -

{{ profile.follower_count }}

- {{ text "auth:label.followers" }} -
- -

{{ profile.following_count }}

- {{ text "auth:label.following" }} -
+
+
@@ -73,6 +75,90 @@ + {% if not is_self %} +
+
+ {{ text "auth:label.relationship" }} +
+ +
+ {% if not is_blocking %} {% if not is_following %} + + {% else %} + + {% endif %} + + + {% else %} + + {% endif %} + + +
+
+ {% endif %} +
{{ icon "users-round" }} diff --git a/crates/app/src/public/js/atto.js b/crates/app/src/public/js/atto.js index 4c48fbf..ea3985a 100644 --- a/crates/app/src/public/js/atto.js +++ b/crates/app/src/public/js/atto.js @@ -34,6 +34,10 @@ media_theme_pref(); (() => { const self = reg_ns("atto"); + for (const element of document.querySelectorAll('[selected="false"]')) { + element.removeAttribute("selected"); + } + // init use("me", () => {}); diff --git a/crates/app/src/routes/api/v1/auth/social.rs b/crates/app/src/routes/api/v1/auth/social.rs index 8692875..fd68a3a 100644 --- a/crates/app/src/routes/api/v1/auth/social.rs +++ b/crates/app/src/routes/api/v1/auth/social.rs @@ -4,7 +4,7 @@ use crate::{ }; use axum::{Extension, Json, extract::Path, response::IntoResponse}; use axum_extra::extract::CookieJar; -use tetratto_core::model::auth::{UserBlock, UserFollow}; +use tetratto_core::model::auth::{Notification, UserBlock, UserFollow}; /// Toggle following on the given user. pub async fn follow_request( @@ -20,7 +20,7 @@ pub async fn follow_request( if let Ok(userfollow) = data.get_userfollow_by_initiator_receiver(user.id, id).await { // delete - match data.delete_userfollow(userfollow.id, user).await { + match data.delete_userfollow(userfollow.id, &user).await { Ok(_) => Json(ApiReturn { ok: true, message: "User unfollowed".to_string(), @@ -31,11 +31,27 @@ pub async fn follow_request( } else { // create match data.create_userfollow(UserFollow::new(user.id, id)).await { - Ok(_) => Json(ApiReturn { - ok: true, - message: "User followed".to_string(), - payload: (), - }), + Ok(_) => { + if let Err(e) = data + .create_notification(Notification::new( + "Somebody has followed you!".to_string(), + format!( + "You have been followed by [@{}](/api/v1/auth/profile/find/{}).", + user.username, user.id + ), + id, + )) + .await + { + return Json(e.into()); + }; + + Json(ApiReturn { + ok: true, + message: "User followed".to_string(), + payload: (), + }) + } Err(e) => Json(e.into()), } } @@ -70,10 +86,22 @@ pub async fn block_request( if let Ok(userfollow) = data.get_userfollow_by_initiator_receiver(user.id, id).await { // automatically unfollow - match data.delete_userfollow(userfollow.id, user).await { + match data.delete_userfollow(userfollow.id, &user).await { Ok(_) => Json(ApiReturn { ok: true, - message: "User unfollowed".to_string(), + message: "User blocked".to_string(), + payload: (), + }), + Err(e) => Json(e.into()), + } + } else if let Ok(userfollow) = + data.get_userfollow_by_receiver_initiator(user.id, id).await + { + // automatically unfollow + match data.delete_userfollow(userfollow.id, &user).await { + Ok(_) => Json(ApiReturn { + ok: true, + message: "User blocked".to_string(), payload: (), }), Err(e) => Json(e.into()), diff --git a/crates/app/src/routes/pages/profile.rs b/crates/app/src/routes/pages/profile.rs index 6b56d78..9a9aa7e 100644 --- a/crates/app/src/routes/pages/profile.rs +++ b/crates/app/src/routes/pages/profile.rs @@ -55,11 +55,15 @@ pub fn profile_context( communities: &Vec, is_self: bool, is_following: bool, + is_following_you: bool, + is_blocking: bool, ) { context.insert("profile", &profile); context.insert("communities", &communities); context.insert("is_self", &is_self); context.insert("is_following", &is_following); + context.insert("is_following_you", &is_following_you); + context.insert("is_blocking", &is_blocking); } /// `/user/{username}` @@ -94,15 +98,17 @@ pub async fn posts_request( // check for private profile if other_user.settings.private_profile { if let Some(ref ua) = user { - if data - .0 - .get_userfollow_by_initiator_receiver(other_user.id, ua.id) - .await - .is_err() - { - return Err(Html( - render_error(Error::NotAllowed, &jar, &data, &user).await, - )); + if ua.id != other_user.id { + if data + .0 + .get_userfollow_by_initiator_receiver(other_user.id, ua.id) + .await + .is_err() + { + return Err(Html( + render_error(Error::NotAllowed, &jar, &data, &user).await, + )); + } } } else { return Err(Html( @@ -151,6 +157,24 @@ pub async fn posts_request( false }; + let is_following_you = if let Some(ref ua) = user { + data.0 + .get_userfollow_by_receiver_initiator(ua.id, other_user.id) + .await + .is_ok() + } else { + false + }; + + let is_blocking = if let Some(ref ua) = user { + data.0 + .get_userblock_by_initiator_receiver(ua.id, other_user.id) + .await + .is_ok() + } else { + false + }; + context.insert("posts", &posts); profile_context( &mut context, @@ -158,6 +182,8 @@ pub async fn posts_request( &communities, is_self, is_following, + is_following_you, + is_blocking, ); // return diff --git a/crates/core/src/database/userfollows.rs b/crates/core/src/database/userfollows.rs index 1a65811..f3d51ba 100644 --- a/crates/core/src/database/userfollows.rs +++ b/crates/core/src/database/userfollows.rs @@ -181,7 +181,7 @@ impl DataManager { Ok(()) } - pub async fn delete_userfollow(&self, id: usize, user: User) -> Result<()> { + pub async fn delete_userfollow(&self, id: usize, user: &User) -> Result<()> { let follow = self.get_userfollow_by_id(id).await?; if (user.id != follow.initiator) && (user.id != follow.receiver) { @@ -208,11 +208,11 @@ impl DataManager { self.2.remove(format!("atto.userfollow:{}", id)).await; // decr counts - self.incr_user_following_count(follow.initiator) + self.decr_user_following_count(follow.initiator) .await .unwrap(); - self.incr_user_follower_count(follow.receiver) + self.decr_user_follower_count(follow.receiver) .await .unwrap();