mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-12-28 02:40:34 +00:00
Private message delete and read extracted.
This commit is contained in:
parent
dca38d10eb
commit
0a28ffb9c4
12 changed files with 457 additions and 132 deletions
131
docs/src/contributing_websocket_http_api.md
vendored
131
docs/src/contributing_websocket_http_api.md
vendored
|
@ -489,6 +489,137 @@ Only the first user will be able to be the admin.
|
|||
|
||||
`PUT /user/mention`
|
||||
|
||||
#### Get Private Messages
|
||||
##### Request
|
||||
```rust
|
||||
{
|
||||
op: "GetPrivateMessages",
|
||||
data: {
|
||||
unread_only: bool,
|
||||
page: Option<i64>,
|
||||
limit: Option<i64>,
|
||||
auth: String,
|
||||
}
|
||||
}
|
||||
```
|
||||
##### Response
|
||||
```rust
|
||||
{
|
||||
op: "GetPrivateMessages",
|
||||
data: {
|
||||
messages: Vec<PrivateMessageView>,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### HTTP
|
||||
|
||||
`GET /private_message/list`
|
||||
|
||||
#### Create Private Message
|
||||
##### Request
|
||||
```rust
|
||||
{
|
||||
op: "CreatePrivateMessage",
|
||||
data: {
|
||||
content: String,
|
||||
recipient_id: i32,
|
||||
auth: String,
|
||||
}
|
||||
}
|
||||
```
|
||||
##### Response
|
||||
```rust
|
||||
{
|
||||
op: "CreatePrivateMessage",
|
||||
data: {
|
||||
message: PrivateMessageView,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### HTTP
|
||||
|
||||
`POST /private_message`
|
||||
|
||||
#### Edit Private Message
|
||||
##### Request
|
||||
```rust
|
||||
{
|
||||
op: "EditPrivateMessage",
|
||||
data: {
|
||||
edit_id: i32,
|
||||
content: String,
|
||||
auth: String,
|
||||
}
|
||||
}
|
||||
```
|
||||
##### Response
|
||||
```rust
|
||||
{
|
||||
op: "EditPrivateMessage",
|
||||
data: {
|
||||
message: PrivateMessageView,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### HTTP
|
||||
|
||||
`PUT /private_message`
|
||||
|
||||
#### Delete Private Message
|
||||
##### Request
|
||||
```rust
|
||||
{
|
||||
op: "DeletePrivateMessage",
|
||||
data: {
|
||||
edit_id: i32,
|
||||
deleted: bool,
|
||||
auth: String,
|
||||
}
|
||||
}
|
||||
```
|
||||
##### Response
|
||||
```rust
|
||||
{
|
||||
op: "DeletePrivateMessage",
|
||||
data: {
|
||||
message: PrivateMessageView,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### HTTP
|
||||
|
||||
`POST /private_message/delete`
|
||||
|
||||
#### Mark Private Message as Read
|
||||
##### Request
|
||||
```rust
|
||||
{
|
||||
op: "MarkPrivateMessageAsRead",
|
||||
data: {
|
||||
edit_id: i32,
|
||||
read: bool,
|
||||
auth: String,
|
||||
}
|
||||
}
|
||||
```
|
||||
##### Response
|
||||
```rust
|
||||
{
|
||||
op: "MarkPrivateMessageAsRead",
|
||||
data: {
|
||||
message: PrivateMessageView,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### HTTP
|
||||
|
||||
`POST /private_message/mark_as_read`
|
||||
|
||||
#### Mark All As Read
|
||||
|
||||
Marks all user replies and mentions as read.
|
||||
|
|
|
@ -80,6 +80,50 @@ impl PrivateMessage {
|
|||
.filter(ap_id.eq(object_id))
|
||||
.first::<Self>(conn)
|
||||
}
|
||||
|
||||
pub fn update_content(
|
||||
conn: &PgConnection,
|
||||
private_message_id: i32,
|
||||
new_content: &str,
|
||||
) -> Result<Self, Error> {
|
||||
use crate::schema::private_message::dsl::*;
|
||||
diesel::update(private_message.find(private_message_id))
|
||||
.set(content.eq(new_content))
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
|
||||
pub fn update_deleted(
|
||||
conn: &PgConnection,
|
||||
private_message_id: i32,
|
||||
new_deleted: bool,
|
||||
) -> Result<Self, Error> {
|
||||
use crate::schema::private_message::dsl::*;
|
||||
diesel::update(private_message.find(private_message_id))
|
||||
.set(deleted.eq(new_deleted))
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
|
||||
pub fn update_read(
|
||||
conn: &PgConnection,
|
||||
private_message_id: i32,
|
||||
new_read: bool,
|
||||
) -> Result<Self, Error> {
|
||||
use crate::schema::private_message::dsl::*;
|
||||
diesel::update(private_message.find(private_message_id))
|
||||
.set(read.eq(new_read))
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
|
||||
pub fn mark_all_as_read(conn: &PgConnection, for_recipient_id: i32) -> Result<Vec<Self>, Error> {
|
||||
use crate::schema::private_message::dsl::*;
|
||||
diesel::update(
|
||||
private_message
|
||||
.filter(recipient_id.eq(for_recipient_id))
|
||||
.filter(read.eq(false)),
|
||||
)
|
||||
.set(read.eq(true))
|
||||
.get_results::<Self>(conn)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -180,6 +224,10 @@ mod tests {
|
|||
let read_private_message = PrivateMessage::read(&conn, inserted_private_message.id).unwrap();
|
||||
let updated_private_message =
|
||||
PrivateMessage::update(&conn, inserted_private_message.id, &private_message_form).unwrap();
|
||||
let deleted_private_message =
|
||||
PrivateMessage::update_deleted(&conn, inserted_private_message.id, true).unwrap();
|
||||
let marked_read_private_message =
|
||||
PrivateMessage::update_read(&conn, inserted_private_message.id, true).unwrap();
|
||||
let num_deleted = PrivateMessage::delete(&conn, inserted_private_message.id).unwrap();
|
||||
User_::delete(&conn, inserted_creator.id).unwrap();
|
||||
User_::delete(&conn, inserted_recipient.id).unwrap();
|
||||
|
@ -187,6 +235,8 @@ mod tests {
|
|||
assert_eq!(expected_private_message, read_private_message);
|
||||
assert_eq!(expected_private_message, updated_private_message);
|
||||
assert_eq!(expected_private_message, inserted_private_message);
|
||||
assert!(deleted_private_message.deleted);
|
||||
assert!(marked_read_private_message.read);
|
||||
assert_eq!(1, num_deleted);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ pub struct GetUserDetailsResponse {
|
|||
moderates: Vec<CommunityModeratorView>,
|
||||
comments: Vec<CommentView>,
|
||||
posts: Vec<PostView>,
|
||||
admins: Vec<UserView>,
|
||||
admins: Vec<UserView>, // TODO why is this necessary, just use GetSite
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -216,9 +216,21 @@ pub struct CreatePrivateMessage {
|
|||
#[derive(Serialize, Deserialize)]
|
||||
pub struct EditPrivateMessage {
|
||||
edit_id: i32,
|
||||
content: Option<String>,
|
||||
deleted: Option<bool>,
|
||||
read: Option<bool>,
|
||||
content: String,
|
||||
auth: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct DeletePrivateMessage {
|
||||
edit_id: i32,
|
||||
deleted: bool,
|
||||
auth: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MarkPrivateMessageAsRead {
|
||||
edit_id: i32,
|
||||
read: bool,
|
||||
auth: String,
|
||||
}
|
||||
|
||||
|
@ -974,36 +986,10 @@ impl Perform for Oper<MarkAllAsRead> {
|
|||
}
|
||||
}
|
||||
|
||||
// messages
|
||||
let messages = blocking(pool, move |conn| {
|
||||
PrivateMessageQueryBuilder::create(conn, user_id)
|
||||
.page(1)
|
||||
.limit(999)
|
||||
.unread_only(true)
|
||||
.list()
|
||||
})
|
||||
.await??;
|
||||
|
||||
// TODO: this should probably be a bulk operation
|
||||
for message in &messages {
|
||||
let private_message_form = PrivateMessageForm {
|
||||
content: message.to_owned().content,
|
||||
creator_id: message.to_owned().creator_id,
|
||||
recipient_id: message.to_owned().recipient_id,
|
||||
deleted: None,
|
||||
read: Some(true),
|
||||
updated: None,
|
||||
ap_id: message.to_owned().ap_id,
|
||||
local: message.local,
|
||||
published: None,
|
||||
};
|
||||
|
||||
let message_id = message.id;
|
||||
let update_pm =
|
||||
move |conn: &'_ _| PrivateMessage::update(conn, message_id, &private_message_form);
|
||||
if blocking(pool, update_pm).await?.is_err() {
|
||||
return Err(APIError::err("couldnt_update_private_message").into());
|
||||
}
|
||||
// Mark all private_messages as read
|
||||
let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, user_id);
|
||||
if blocking(pool, update_pm).await?.is_err() {
|
||||
return Err(APIError::err("couldnt_update_private_message").into());
|
||||
}
|
||||
|
||||
Ok(GetRepliesResponse { replies: vec![] })
|
||||
|
@ -1293,59 +1279,25 @@ impl Perform for Oper<EditPrivateMessage> {
|
|||
|
||||
let user_id = claims.id;
|
||||
|
||||
let edit_id = data.edit_id;
|
||||
let orig_private_message =
|
||||
blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??;
|
||||
|
||||
// Check for a site ban
|
||||
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||
if user.banned {
|
||||
return Err(APIError::err("site_ban").into());
|
||||
}
|
||||
|
||||
// Check to make sure they are the creator (or the recipient marking as read
|
||||
if !(data.read.is_some() && orig_private_message.recipient_id.eq(&user_id)
|
||||
|| orig_private_message.creator_id.eq(&user_id))
|
||||
{
|
||||
// Checking permissions
|
||||
let edit_id = data.edit_id;
|
||||
let orig_private_message =
|
||||
blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??;
|
||||
if user_id != orig_private_message.creator_id {
|
||||
return Err(APIError::err("no_private_message_edit_allowed").into());
|
||||
}
|
||||
|
||||
let content_slurs_removed = match &data.content {
|
||||
Some(content) => remove_slurs(content),
|
||||
None => orig_private_message.content.clone(),
|
||||
};
|
||||
|
||||
let private_message_form = {
|
||||
if data.read.is_some() {
|
||||
PrivateMessageForm {
|
||||
content: orig_private_message.content.to_owned(),
|
||||
creator_id: orig_private_message.creator_id,
|
||||
recipient_id: orig_private_message.recipient_id,
|
||||
read: data.read.to_owned(),
|
||||
updated: orig_private_message.updated,
|
||||
deleted: Some(orig_private_message.deleted),
|
||||
ap_id: orig_private_message.ap_id,
|
||||
local: orig_private_message.local,
|
||||
published: None,
|
||||
}
|
||||
} else {
|
||||
PrivateMessageForm {
|
||||
content: content_slurs_removed,
|
||||
creator_id: orig_private_message.creator_id,
|
||||
recipient_id: orig_private_message.recipient_id,
|
||||
deleted: data.deleted.to_owned(),
|
||||
read: Some(orig_private_message.read),
|
||||
updated: Some(naive_now()),
|
||||
ap_id: orig_private_message.ap_id,
|
||||
local: orig_private_message.local,
|
||||
published: None,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Doing the update
|
||||
let content_slurs_removed = remove_slurs(&data.content);
|
||||
let edit_id = data.edit_id;
|
||||
let updated_private_message = match blocking(pool, move |conn| {
|
||||
PrivateMessage::update(conn, edit_id, &private_message_form)
|
||||
PrivateMessage::update_content(conn, edit_id, &content_slurs_removed)
|
||||
})
|
||||
.await?
|
||||
{
|
||||
|
@ -1353,30 +1305,14 @@ impl Perform for Oper<EditPrivateMessage> {
|
|||
Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()),
|
||||
};
|
||||
|
||||
if data.read.is_none() {
|
||||
if let Some(deleted) = data.deleted.to_owned() {
|
||||
if deleted {
|
||||
updated_private_message
|
||||
.send_delete(&user, &self.client, pool)
|
||||
.await?;
|
||||
} else {
|
||||
updated_private_message
|
||||
.send_undo_delete(&user, &self.client, pool)
|
||||
.await?;
|
||||
}
|
||||
} else {
|
||||
updated_private_message
|
||||
.send_update(&user, &self.client, pool)
|
||||
.await?;
|
||||
}
|
||||
} else {
|
||||
updated_private_message
|
||||
.send_update(&user, &self.client, pool)
|
||||
.await?;
|
||||
}
|
||||
// Send the apub update
|
||||
updated_private_message
|
||||
.send_update(&user, &self.client, pool)
|
||||
.await?;
|
||||
|
||||
let edit_id = data.edit_id;
|
||||
let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??;
|
||||
let recipient_id = message.recipient_id;
|
||||
|
||||
let res = PrivateMessageResponse { message };
|
||||
|
||||
|
@ -1384,7 +1320,146 @@ impl Perform for Oper<EditPrivateMessage> {
|
|||
ws.chatserver.do_send(SendUserRoomMessage {
|
||||
op: UserOperation::EditPrivateMessage,
|
||||
response: res.clone(),
|
||||
recipient_id: orig_private_message.recipient_id,
|
||||
recipient_id,
|
||||
my_id: ws.id,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for Oper<DeletePrivateMessage> {
|
||||
type Response = PrivateMessageResponse;
|
||||
|
||||
async fn perform(
|
||||
&self,
|
||||
pool: &DbPool,
|
||||
websocket_info: Option<WebsocketInfo>,
|
||||
) -> Result<PrivateMessageResponse, LemmyError> {
|
||||
let data: &DeletePrivateMessage = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
||||
let user_id = claims.id;
|
||||
|
||||
// Check for a site ban
|
||||
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||
if user.banned {
|
||||
return Err(APIError::err("site_ban").into());
|
||||
}
|
||||
|
||||
// Checking permissions
|
||||
let edit_id = data.edit_id;
|
||||
let orig_private_message =
|
||||
blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??;
|
||||
if user_id != orig_private_message.creator_id {
|
||||
return Err(APIError::err("no_private_message_edit_allowed").into());
|
||||
}
|
||||
|
||||
// Doing the update
|
||||
let edit_id = data.edit_id;
|
||||
let deleted = data.deleted;
|
||||
let updated_private_message = match blocking(pool, move |conn| {
|
||||
PrivateMessage::update_deleted(conn, edit_id, deleted)
|
||||
})
|
||||
.await?
|
||||
{
|
||||
Ok(private_message) => private_message,
|
||||
Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()),
|
||||
};
|
||||
|
||||
// Send the apub update
|
||||
if data.deleted {
|
||||
updated_private_message
|
||||
.send_delete(&user, &self.client, pool)
|
||||
.await?;
|
||||
} else {
|
||||
updated_private_message
|
||||
.send_undo_delete(&user, &self.client, pool)
|
||||
.await?;
|
||||
}
|
||||
|
||||
let edit_id = data.edit_id;
|
||||
let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??;
|
||||
let recipient_id = message.recipient_id;
|
||||
|
||||
let res = PrivateMessageResponse { message };
|
||||
|
||||
if let Some(ws) = websocket_info {
|
||||
ws.chatserver.do_send(SendUserRoomMessage {
|
||||
op: UserOperation::DeletePrivateMessage,
|
||||
response: res.clone(),
|
||||
recipient_id,
|
||||
my_id: ws.id,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for Oper<MarkPrivateMessageAsRead> {
|
||||
type Response = PrivateMessageResponse;
|
||||
|
||||
async fn perform(
|
||||
&self,
|
||||
pool: &DbPool,
|
||||
websocket_info: Option<WebsocketInfo>,
|
||||
) -> Result<PrivateMessageResponse, LemmyError> {
|
||||
let data: &MarkPrivateMessageAsRead = &self.data;
|
||||
|
||||
let claims = match Claims::decode(&data.auth) {
|
||||
Ok(claims) => claims.claims,
|
||||
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||
};
|
||||
|
||||
let user_id = claims.id;
|
||||
|
||||
// Check for a site ban
|
||||
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||
if user.banned {
|
||||
return Err(APIError::err("site_ban").into());
|
||||
}
|
||||
|
||||
// Checking permissions
|
||||
let edit_id = data.edit_id;
|
||||
let orig_private_message =
|
||||
blocking(pool, move |conn| PrivateMessage::read(conn, edit_id)).await??;
|
||||
if user_id != orig_private_message.recipient_id {
|
||||
return Err(APIError::err("couldnt_update_private_message").into());
|
||||
}
|
||||
|
||||
// Doing the update
|
||||
let edit_id = data.edit_id;
|
||||
let read = data.read;
|
||||
match blocking(pool, move |conn| {
|
||||
PrivateMessage::update_read(conn, edit_id, read)
|
||||
})
|
||||
.await?
|
||||
{
|
||||
Ok(private_message) => private_message,
|
||||
Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()),
|
||||
};
|
||||
|
||||
// No need to send an apub update
|
||||
|
||||
let edit_id = data.edit_id;
|
||||
let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??;
|
||||
let recipient_id = message.recipient_id;
|
||||
|
||||
let res = PrivateMessageResponse { message };
|
||||
|
||||
if let Some(ws) = websocket_info {
|
||||
ws.chatserver.do_send(SendUserRoomMessage {
|
||||
op: UserOperation::MarkPrivateMessageAsRead,
|
||||
response: res.clone(),
|
||||
recipient_id,
|
||||
my_id: ws.id,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -90,7 +90,15 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
|
|||
.wrap(rate_limit.message())
|
||||
.route("/list", web::get().to(route_get::<GetPrivateMessages>))
|
||||
.route("", web::post().to(route_post::<CreatePrivateMessage>))
|
||||
.route("", web::put().to(route_post::<EditPrivateMessage>)),
|
||||
.route("", web::put().to(route_post::<EditPrivateMessage>))
|
||||
.route(
|
||||
"/delete",
|
||||
web::post().to(route_post::<DeletePrivateMessage>),
|
||||
)
|
||||
.route(
|
||||
"/mark_as_read",
|
||||
web::post().to(route_post::<MarkPrivateMessageAsRead>),
|
||||
),
|
||||
)
|
||||
// User
|
||||
.service(
|
||||
|
|
|
@ -59,6 +59,8 @@ pub enum UserOperation {
|
|||
PasswordChange,
|
||||
CreatePrivateMessage,
|
||||
EditPrivateMessage,
|
||||
DeletePrivateMessage,
|
||||
MarkPrivateMessageAsRead,
|
||||
GetPrivateMessages,
|
||||
UserJoin,
|
||||
GetComments,
|
||||
|
|
|
@ -448,13 +448,21 @@ impl ChatServer {
|
|||
UserOperation::DeleteAccount => do_user_operation::<DeleteAccount>(args).await,
|
||||
UserOperation::PasswordReset => do_user_operation::<PasswordReset>(args).await,
|
||||
UserOperation::PasswordChange => do_user_operation::<PasswordChange>(args).await,
|
||||
UserOperation::UserJoin => do_user_operation::<UserJoin>(args).await,
|
||||
UserOperation::SaveUserSettings => do_user_operation::<SaveUserSettings>(args).await,
|
||||
|
||||
// Private Message ops
|
||||
UserOperation::CreatePrivateMessage => {
|
||||
do_user_operation::<CreatePrivateMessage>(args).await
|
||||
}
|
||||
UserOperation::EditPrivateMessage => do_user_operation::<EditPrivateMessage>(args).await,
|
||||
UserOperation::DeletePrivateMessage => {
|
||||
do_user_operation::<DeletePrivateMessage>(args).await
|
||||
}
|
||||
UserOperation::MarkPrivateMessageAsRead => {
|
||||
do_user_operation::<MarkPrivateMessageAsRead>(args).await
|
||||
}
|
||||
UserOperation::GetPrivateMessages => do_user_operation::<GetPrivateMessages>(args).await,
|
||||
UserOperation::UserJoin => do_user_operation::<UserJoin>(args).await,
|
||||
UserOperation::SaveUserSettings => do_user_operation::<SaveUserSettings>(args).await,
|
||||
|
||||
// Site ops
|
||||
UserOperation::GetModlog => do_user_operation::<GetModlog>(args).await,
|
||||
|
|
15
ui/src/api_tests/api.spec.ts
vendored
15
ui/src/api_tests/api.spec.ts
vendored
|
@ -9,17 +9,16 @@ import {
|
|||
FollowCommunityForm,
|
||||
CommunityResponse,
|
||||
GetFollowedCommunitiesResponse,
|
||||
GetPostForm,
|
||||
GetPostResponse,
|
||||
CommentForm,
|
||||
CommentResponse,
|
||||
CommunityForm,
|
||||
GetCommunityForm,
|
||||
GetCommunityResponse,
|
||||
CommentLikeForm,
|
||||
CreatePostLikeForm,
|
||||
PrivateMessageForm,
|
||||
EditPrivateMessageForm,
|
||||
DeletePrivateMessageForm,
|
||||
PrivateMessageResponse,
|
||||
PrivateMessagesResponse,
|
||||
GetUserMentionsResponse,
|
||||
|
@ -1149,16 +1148,16 @@ describe('main', () => {
|
|||
);
|
||||
|
||||
// lemmy alpha deletes the private message
|
||||
let deletePrivateMessageForm: EditPrivateMessageForm = {
|
||||
let deletePrivateMessageForm: DeletePrivateMessageForm = {
|
||||
deleted: true,
|
||||
edit_id: createRes.message.id,
|
||||
auth: lemmyAlphaAuth,
|
||||
};
|
||||
|
||||
let deleteRes: PrivateMessageResponse = await fetch(
|
||||
`${lemmyAlphaApiUrl}/private_message`,
|
||||
`${lemmyAlphaApiUrl}/private_message/delete`,
|
||||
{
|
||||
method: 'PUT',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
|
@ -1182,16 +1181,16 @@ describe('main', () => {
|
|||
expect(getPrivateMessagesDeletedRes.messages.length).toBe(0);
|
||||
|
||||
// lemmy alpha undeletes the private message
|
||||
let undeletePrivateMessageForm: EditPrivateMessageForm = {
|
||||
let undeletePrivateMessageForm: DeletePrivateMessageForm = {
|
||||
deleted: false,
|
||||
edit_id: createRes.message.id,
|
||||
auth: lemmyAlphaAuth,
|
||||
};
|
||||
|
||||
let undeleteRes: PrivateMessageResponse = await fetch(
|
||||
`${lemmyAlphaApiUrl}/private_message`,
|
||||
`${lemmyAlphaApiUrl}/private_message/delete`,
|
||||
{
|
||||
method: 'PUT',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
|
|
46
ui/src/components/inbox.tsx
vendored
46
ui/src/components/inbox.tsx
vendored
|
@ -446,22 +446,42 @@ export class Inbox extends Component<any, InboxState> {
|
|||
let found: PrivateMessageI = this.state.messages.find(
|
||||
m => m.id === data.message.id
|
||||
);
|
||||
found.content = data.message.content;
|
||||
found.updated = data.message.updated;
|
||||
found.deleted = data.message.deleted;
|
||||
// If youre in the unread view, just remove it from the list
|
||||
if (this.state.unreadOrAll == UnreadOrAll.Unread && data.message.read) {
|
||||
this.state.messages = this.state.messages.filter(
|
||||
r => r.id !== data.message.id
|
||||
);
|
||||
} else {
|
||||
let found = this.state.messages.find(c => c.id == data.message.id);
|
||||
found.read = data.message.read;
|
||||
if (found) {
|
||||
found.content = data.message.content;
|
||||
found.updated = data.message.updated;
|
||||
}
|
||||
this.setState(this.state);
|
||||
} else if (res.op == UserOperation.DeletePrivateMessage) {
|
||||
let data = res.data as PrivateMessageResponse;
|
||||
let found: PrivateMessageI = this.state.messages.find(
|
||||
m => m.id === data.message.id
|
||||
);
|
||||
if (found) {
|
||||
found.deleted = data.message.deleted;
|
||||
found.updated = data.message.updated;
|
||||
}
|
||||
this.setState(this.state);
|
||||
} else if (res.op == UserOperation.MarkPrivateMessageAsRead) {
|
||||
let data = res.data as PrivateMessageResponse;
|
||||
let found: PrivateMessageI = this.state.messages.find(
|
||||
m => m.id === data.message.id
|
||||
);
|
||||
|
||||
if (found) {
|
||||
found.updated = data.message.updated;
|
||||
|
||||
// If youre in the unread view, just remove it from the list
|
||||
if (this.state.unreadOrAll == UnreadOrAll.Unread && data.message.read) {
|
||||
this.state.messages = this.state.messages.filter(
|
||||
r => r.id !== data.message.id
|
||||
);
|
||||
} else {
|
||||
let found = this.state.messages.find(c => c.id == data.message.id);
|
||||
found.read = data.message.read;
|
||||
}
|
||||
}
|
||||
this.sendUnreadCount();
|
||||
window.scrollTo(0, 0);
|
||||
this.setState(this.state);
|
||||
setupTippy();
|
||||
} else if (res.op == UserOperation.MarkAllAsRead) {
|
||||
// Moved to be instant
|
||||
} else if (res.op == UserOperation.EditComment) {
|
||||
|
|
6
ui/src/components/private-message-form.tsx
vendored
6
ui/src/components/private-message-form.tsx
vendored
|
@ -263,7 +263,11 @@ export class PrivateMessageForm extends Component<
|
|||
this.state.loading = false;
|
||||
this.setState(this.state);
|
||||
return;
|
||||
} else if (res.op == UserOperation.EditPrivateMessage) {
|
||||
} else if (
|
||||
res.op == UserOperation.EditPrivateMessage ||
|
||||
res.op == UserOperation.DeletePrivateMessage ||
|
||||
res.op == UserOperation.MarkPrivateMessageAsRead
|
||||
) {
|
||||
let data = res.data as PrivateMessageResponse;
|
||||
this.state.loading = false;
|
||||
this.props.onEdit(data.message);
|
||||
|
|
11
ui/src/components/private-message.tsx
vendored
11
ui/src/components/private-message.tsx
vendored
|
@ -2,7 +2,8 @@ import { Component, linkEvent } from 'inferno';
|
|||
import { Link } from 'inferno-router';
|
||||
import {
|
||||
PrivateMessage as PrivateMessageI,
|
||||
EditPrivateMessageForm,
|
||||
DeletePrivateMessageForm,
|
||||
MarkPrivateMessageAsReadForm,
|
||||
} from '../interfaces';
|
||||
import { WebSocketService, UserService } from '../services';
|
||||
import { mdToHtml, pictrsAvatarThumbnail, showAvatars, toast } from '../utils';
|
||||
|
@ -243,11 +244,11 @@ export class PrivateMessage extends Component<
|
|||
}
|
||||
|
||||
handleDeleteClick(i: PrivateMessage) {
|
||||
let form: EditPrivateMessageForm = {
|
||||
let form: DeletePrivateMessageForm = {
|
||||
edit_id: i.props.privateMessage.id,
|
||||
deleted: !i.props.privateMessage.deleted,
|
||||
};
|
||||
WebSocketService.Instance.editPrivateMessage(form);
|
||||
WebSocketService.Instance.deletePrivateMessage(form);
|
||||
}
|
||||
|
||||
handleReplyCancel() {
|
||||
|
@ -257,11 +258,11 @@ export class PrivateMessage extends Component<
|
|||
}
|
||||
|
||||
handleMarkRead(i: PrivateMessage) {
|
||||
let form: EditPrivateMessageForm = {
|
||||
let form: MarkPrivateMessageAsReadForm = {
|
||||
edit_id: i.props.privateMessage.id,
|
||||
read: !i.props.privateMessage.read,
|
||||
};
|
||||
WebSocketService.Instance.editPrivateMessage(form);
|
||||
WebSocketService.Instance.markPrivateMessageAsRead(form);
|
||||
}
|
||||
|
||||
handleMessageCollapse(i: PrivateMessage) {
|
||||
|
|
21
ui/src/interfaces.ts
vendored
21
ui/src/interfaces.ts
vendored
|
@ -40,6 +40,8 @@ export enum UserOperation {
|
|||
PasswordChange,
|
||||
CreatePrivateMessage,
|
||||
EditPrivateMessage,
|
||||
DeletePrivateMessage,
|
||||
MarkPrivateMessageAsRead,
|
||||
GetPrivateMessages,
|
||||
UserJoin,
|
||||
GetComments,
|
||||
|
@ -834,9 +836,19 @@ export interface PrivateMessageFormParams {
|
|||
|
||||
export interface EditPrivateMessageForm {
|
||||
edit_id: number;
|
||||
content?: string;
|
||||
deleted?: boolean;
|
||||
read?: boolean;
|
||||
content: string;
|
||||
auth?: string;
|
||||
}
|
||||
|
||||
export interface DeletePrivateMessageForm {
|
||||
edit_id: number;
|
||||
deleted: boolean;
|
||||
auth?: string;
|
||||
}
|
||||
|
||||
export interface MarkPrivateMessageAsReadForm {
|
||||
edit_id: number;
|
||||
read: boolean;
|
||||
auth?: string;
|
||||
}
|
||||
|
||||
|
@ -864,7 +876,6 @@ export interface UserJoinResponse {
|
|||
}
|
||||
|
||||
export type MessageType =
|
||||
| EditPrivateMessageForm
|
||||
| LoginForm
|
||||
| RegisterForm
|
||||
| CommunityForm
|
||||
|
@ -900,6 +911,8 @@ export type MessageType =
|
|||
| PasswordChangeForm
|
||||
| PrivateMessageForm
|
||||
| EditPrivateMessageForm
|
||||
| DeletePrivateMessageForm
|
||||
| MarkPrivateMessageAsReadForm
|
||||
| GetPrivateMessagesForm
|
||||
| SiteConfigForm;
|
||||
|
||||
|
|
14
ui/src/services/WebSocketService.ts
vendored
14
ui/src/services/WebSocketService.ts
vendored
|
@ -36,6 +36,8 @@ import {
|
|||
PasswordChangeForm,
|
||||
PrivateMessageForm,
|
||||
EditPrivateMessageForm,
|
||||
DeletePrivateMessageForm,
|
||||
MarkPrivateMessageAsReadForm,
|
||||
GetPrivateMessagesForm,
|
||||
GetCommentsForm,
|
||||
UserJoinForm,
|
||||
|
@ -315,6 +317,18 @@ export class WebSocketService {
|
|||
this.ws.send(this.wsSendWrapper(UserOperation.EditPrivateMessage, form));
|
||||
}
|
||||
|
||||
public deletePrivateMessage(form: DeletePrivateMessageForm) {
|
||||
this.setAuth(form);
|
||||
this.ws.send(this.wsSendWrapper(UserOperation.DeletePrivateMessage, form));
|
||||
}
|
||||
|
||||
public markPrivateMessageAsRead(form: MarkPrivateMessageAsReadForm) {
|
||||
this.setAuth(form);
|
||||
this.ws.send(
|
||||
this.wsSendWrapper(UserOperation.MarkPrivateMessageAsRead, form)
|
||||
);
|
||||
}
|
||||
|
||||
public getPrivateMessages(form: GetPrivateMessagesForm) {
|
||||
this.setAuth(form);
|
||||
this.ws.send(this.wsSendWrapper(UserOperation.GetPrivateMessages, form));
|
||||
|
|
Loading…
Reference in a new issue