Private message delete and read extracted.

This commit is contained in:
Dessalines 2020-07-20 00:29:44 -04:00
parent dca38d10eb
commit 0a28ffb9c4
12 changed files with 457 additions and 132 deletions

View file

@ -489,6 +489,137 @@ Only the first user will be able to be the admin.
`PUT /user/mention` `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 #### Mark All As Read
Marks all user replies and mentions as read. Marks all user replies and mentions as read.

View file

@ -80,6 +80,50 @@ impl PrivateMessage {
.filter(ap_id.eq(object_id)) .filter(ap_id.eq(object_id))
.first::<Self>(conn) .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)] #[cfg(test)]
@ -180,6 +224,10 @@ mod tests {
let read_private_message = PrivateMessage::read(&conn, inserted_private_message.id).unwrap(); let read_private_message = PrivateMessage::read(&conn, inserted_private_message.id).unwrap();
let updated_private_message = let updated_private_message =
PrivateMessage::update(&conn, inserted_private_message.id, &private_message_form).unwrap(); 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(); let num_deleted = PrivateMessage::delete(&conn, inserted_private_message.id).unwrap();
User_::delete(&conn, inserted_creator.id).unwrap(); User_::delete(&conn, inserted_creator.id).unwrap();
User_::delete(&conn, inserted_recipient.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, read_private_message);
assert_eq!(expected_private_message, updated_private_message); assert_eq!(expected_private_message, updated_private_message);
assert_eq!(expected_private_message, inserted_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); assert_eq!(1, num_deleted);
} }
} }

View file

@ -110,7 +110,7 @@ pub struct GetUserDetailsResponse {
moderates: Vec<CommunityModeratorView>, moderates: Vec<CommunityModeratorView>,
comments: Vec<CommentView>, comments: Vec<CommentView>,
posts: Vec<PostView>, posts: Vec<PostView>,
admins: Vec<UserView>, admins: Vec<UserView>, // TODO why is this necessary, just use GetSite
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -216,9 +216,21 @@ pub struct CreatePrivateMessage {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct EditPrivateMessage { pub struct EditPrivateMessage {
edit_id: i32, edit_id: i32,
content: Option<String>, content: String,
deleted: Option<bool>, auth: String,
read: Option<bool>, }
#[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, auth: String,
} }
@ -974,37 +986,11 @@ impl Perform for Oper<MarkAllAsRead> {
} }
} }
// messages // Mark all private_messages as read
let messages = blocking(pool, move |conn| { let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, user_id);
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() { if blocking(pool, update_pm).await?.is_err() {
return Err(APIError::err("couldnt_update_private_message").into()); return Err(APIError::err("couldnt_update_private_message").into());
} }
}
Ok(GetRepliesResponse { replies: vec![] }) Ok(GetRepliesResponse { replies: vec![] })
} }
@ -1293,59 +1279,25 @@ impl Perform for Oper<EditPrivateMessage> {
let user_id = claims.id; 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 // Check for a site ban
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??; let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
if user.banned { if user.banned {
return Err(APIError::err("site_ban").into()); return Err(APIError::err("site_ban").into());
} }
// Check to make sure they are the creator (or the recipient marking as read // Checking permissions
if !(data.read.is_some() && orig_private_message.recipient_id.eq(&user_id) let edit_id = data.edit_id;
|| orig_private_message.creator_id.eq(&user_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()); return Err(APIError::err("no_private_message_edit_allowed").into());
} }
let content_slurs_removed = match &data.content { // Doing the update
Some(content) => remove_slurs(content), let content_slurs_removed = remove_slurs(&data.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,
}
}
};
let edit_id = data.edit_id; let edit_id = data.edit_id;
let updated_private_message = match blocking(pool, move |conn| { 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? .await?
{ {
@ -1353,9 +1305,76 @@ impl Perform for Oper<EditPrivateMessage> {
Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()), Err(_e) => return Err(APIError::err("couldnt_update_private_message").into()),
}; };
if data.read.is_none() { // Send the apub update
if let Some(deleted) = data.deleted.to_owned() { updated_private_message
if deleted { .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 };
if let Some(ws) = websocket_info {
ws.chatserver.do_send(SendUserRoomMessage {
op: UserOperation::EditPrivateMessage,
response: res.clone(),
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 updated_private_message
.send_delete(&user, &self.client, pool) .send_delete(&user, &self.client, pool)
.await?; .await?;
@ -1364,27 +1383,83 @@ impl Perform for Oper<EditPrivateMessage> {
.send_undo_delete(&user, &self.client, pool) .send_undo_delete(&user, &self.client, pool)
.await?; .await?;
} }
} else {
updated_private_message
.send_update(&user, &self.client, pool)
.await?;
}
} else {
updated_private_message
.send_update(&user, &self.client, pool)
.await?;
}
let edit_id = data.edit_id; let edit_id = data.edit_id;
let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??; let message = blocking(pool, move |conn| PrivateMessageView::read(conn, edit_id)).await??;
let recipient_id = message.recipient_id;
let res = PrivateMessageResponse { message }; let res = PrivateMessageResponse { message };
if let Some(ws) = websocket_info { if let Some(ws) = websocket_info {
ws.chatserver.do_send(SendUserRoomMessage { ws.chatserver.do_send(SendUserRoomMessage {
op: UserOperation::EditPrivateMessage, op: UserOperation::DeletePrivateMessage,
response: res.clone(), 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<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, my_id: ws.id,
}); });
} }

View file

@ -90,7 +90,15 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
.wrap(rate_limit.message()) .wrap(rate_limit.message())
.route("/list", web::get().to(route_get::<GetPrivateMessages>)) .route("/list", web::get().to(route_get::<GetPrivateMessages>))
.route("", web::post().to(route_post::<CreatePrivateMessage>)) .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 // User
.service( .service(

View file

@ -59,6 +59,8 @@ pub enum UserOperation {
PasswordChange, PasswordChange,
CreatePrivateMessage, CreatePrivateMessage,
EditPrivateMessage, EditPrivateMessage,
DeletePrivateMessage,
MarkPrivateMessageAsRead,
GetPrivateMessages, GetPrivateMessages,
UserJoin, UserJoin,
GetComments, GetComments,

View file

@ -448,13 +448,21 @@ impl ChatServer {
UserOperation::DeleteAccount => do_user_operation::<DeleteAccount>(args).await, UserOperation::DeleteAccount => do_user_operation::<DeleteAccount>(args).await,
UserOperation::PasswordReset => do_user_operation::<PasswordReset>(args).await, UserOperation::PasswordReset => do_user_operation::<PasswordReset>(args).await,
UserOperation::PasswordChange => do_user_operation::<PasswordChange>(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 => { UserOperation::CreatePrivateMessage => {
do_user_operation::<CreatePrivateMessage>(args).await do_user_operation::<CreatePrivateMessage>(args).await
} }
UserOperation::EditPrivateMessage => do_user_operation::<EditPrivateMessage>(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::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 // Site ops
UserOperation::GetModlog => do_user_operation::<GetModlog>(args).await, UserOperation::GetModlog => do_user_operation::<GetModlog>(args).await,

View file

@ -9,17 +9,16 @@ import {
FollowCommunityForm, FollowCommunityForm,
CommunityResponse, CommunityResponse,
GetFollowedCommunitiesResponse, GetFollowedCommunitiesResponse,
GetPostForm,
GetPostResponse, GetPostResponse,
CommentForm, CommentForm,
CommentResponse, CommentResponse,
CommunityForm, CommunityForm,
GetCommunityForm,
GetCommunityResponse, GetCommunityResponse,
CommentLikeForm, CommentLikeForm,
CreatePostLikeForm, CreatePostLikeForm,
PrivateMessageForm, PrivateMessageForm,
EditPrivateMessageForm, EditPrivateMessageForm,
DeletePrivateMessageForm,
PrivateMessageResponse, PrivateMessageResponse,
PrivateMessagesResponse, PrivateMessagesResponse,
GetUserMentionsResponse, GetUserMentionsResponse,
@ -1149,16 +1148,16 @@ describe('main', () => {
); );
// lemmy alpha deletes the private message // lemmy alpha deletes the private message
let deletePrivateMessageForm: EditPrivateMessageForm = { let deletePrivateMessageForm: DeletePrivateMessageForm = {
deleted: true, deleted: true,
edit_id: createRes.message.id, edit_id: createRes.message.id,
auth: lemmyAlphaAuth, auth: lemmyAlphaAuth,
}; };
let deleteRes: PrivateMessageResponse = await fetch( let deleteRes: PrivateMessageResponse = await fetch(
`${lemmyAlphaApiUrl}/private_message`, `${lemmyAlphaApiUrl}/private_message/delete`,
{ {
method: 'PUT', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
@ -1182,16 +1181,16 @@ describe('main', () => {
expect(getPrivateMessagesDeletedRes.messages.length).toBe(0); expect(getPrivateMessagesDeletedRes.messages.length).toBe(0);
// lemmy alpha undeletes the private message // lemmy alpha undeletes the private message
let undeletePrivateMessageForm: EditPrivateMessageForm = { let undeletePrivateMessageForm: DeletePrivateMessageForm = {
deleted: false, deleted: false,
edit_id: createRes.message.id, edit_id: createRes.message.id,
auth: lemmyAlphaAuth, auth: lemmyAlphaAuth,
}; };
let undeleteRes: PrivateMessageResponse = await fetch( let undeleteRes: PrivateMessageResponse = await fetch(
`${lemmyAlphaApiUrl}/private_message`, `${lemmyAlphaApiUrl}/private_message/delete`,
{ {
method: 'PUT', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },

View file

@ -446,9 +446,30 @@ export class Inbox extends Component<any, InboxState> {
let found: PrivateMessageI = this.state.messages.find( let found: PrivateMessageI = this.state.messages.find(
m => m.id === data.message.id m => m.id === data.message.id
); );
if (found) {
found.content = data.message.content; found.content = data.message.content;
found.updated = data.message.updated; 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.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 youre in the unread view, just remove it from the list
if (this.state.unreadOrAll == UnreadOrAll.Unread && data.message.read) { if (this.state.unreadOrAll == UnreadOrAll.Unread && data.message.read) {
this.state.messages = this.state.messages.filter( this.state.messages = this.state.messages.filter(
@ -458,10 +479,9 @@ export class Inbox extends Component<any, InboxState> {
let found = this.state.messages.find(c => c.id == data.message.id); let found = this.state.messages.find(c => c.id == data.message.id);
found.read = data.message.read; found.read = data.message.read;
} }
}
this.sendUnreadCount(); this.sendUnreadCount();
window.scrollTo(0, 0);
this.setState(this.state); this.setState(this.state);
setupTippy();
} else if (res.op == UserOperation.MarkAllAsRead) { } else if (res.op == UserOperation.MarkAllAsRead) {
// Moved to be instant // Moved to be instant
} else if (res.op == UserOperation.EditComment) { } else if (res.op == UserOperation.EditComment) {

View file

@ -263,7 +263,11 @@ export class PrivateMessageForm extends Component<
this.state.loading = false; this.state.loading = false;
this.setState(this.state); this.setState(this.state);
return; 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; let data = res.data as PrivateMessageResponse;
this.state.loading = false; this.state.loading = false;
this.props.onEdit(data.message); this.props.onEdit(data.message);

View file

@ -2,7 +2,8 @@ import { Component, linkEvent } from 'inferno';
import { Link } from 'inferno-router'; import { Link } from 'inferno-router';
import { import {
PrivateMessage as PrivateMessageI, PrivateMessage as PrivateMessageI,
EditPrivateMessageForm, DeletePrivateMessageForm,
MarkPrivateMessageAsReadForm,
} from '../interfaces'; } from '../interfaces';
import { WebSocketService, UserService } from '../services'; import { WebSocketService, UserService } from '../services';
import { mdToHtml, pictrsAvatarThumbnail, showAvatars, toast } from '../utils'; import { mdToHtml, pictrsAvatarThumbnail, showAvatars, toast } from '../utils';
@ -243,11 +244,11 @@ export class PrivateMessage extends Component<
} }
handleDeleteClick(i: PrivateMessage) { handleDeleteClick(i: PrivateMessage) {
let form: EditPrivateMessageForm = { let form: DeletePrivateMessageForm = {
edit_id: i.props.privateMessage.id, edit_id: i.props.privateMessage.id,
deleted: !i.props.privateMessage.deleted, deleted: !i.props.privateMessage.deleted,
}; };
WebSocketService.Instance.editPrivateMessage(form); WebSocketService.Instance.deletePrivateMessage(form);
} }
handleReplyCancel() { handleReplyCancel() {
@ -257,11 +258,11 @@ export class PrivateMessage extends Component<
} }
handleMarkRead(i: PrivateMessage) { handleMarkRead(i: PrivateMessage) {
let form: EditPrivateMessageForm = { let form: MarkPrivateMessageAsReadForm = {
edit_id: i.props.privateMessage.id, edit_id: i.props.privateMessage.id,
read: !i.props.privateMessage.read, read: !i.props.privateMessage.read,
}; };
WebSocketService.Instance.editPrivateMessage(form); WebSocketService.Instance.markPrivateMessageAsRead(form);
} }
handleMessageCollapse(i: PrivateMessage) { handleMessageCollapse(i: PrivateMessage) {

21
ui/src/interfaces.ts vendored
View file

@ -40,6 +40,8 @@ export enum UserOperation {
PasswordChange, PasswordChange,
CreatePrivateMessage, CreatePrivateMessage,
EditPrivateMessage, EditPrivateMessage,
DeletePrivateMessage,
MarkPrivateMessageAsRead,
GetPrivateMessages, GetPrivateMessages,
UserJoin, UserJoin,
GetComments, GetComments,
@ -834,9 +836,19 @@ export interface PrivateMessageFormParams {
export interface EditPrivateMessageForm { export interface EditPrivateMessageForm {
edit_id: number; edit_id: number;
content?: string; content: string;
deleted?: boolean; auth?: string;
read?: boolean; }
export interface DeletePrivateMessageForm {
edit_id: number;
deleted: boolean;
auth?: string;
}
export interface MarkPrivateMessageAsReadForm {
edit_id: number;
read: boolean;
auth?: string; auth?: string;
} }
@ -864,7 +876,6 @@ export interface UserJoinResponse {
} }
export type MessageType = export type MessageType =
| EditPrivateMessageForm
| LoginForm | LoginForm
| RegisterForm | RegisterForm
| CommunityForm | CommunityForm
@ -900,6 +911,8 @@ export type MessageType =
| PasswordChangeForm | PasswordChangeForm
| PrivateMessageForm | PrivateMessageForm
| EditPrivateMessageForm | EditPrivateMessageForm
| DeletePrivateMessageForm
| MarkPrivateMessageAsReadForm
| GetPrivateMessagesForm | GetPrivateMessagesForm
| SiteConfigForm; | SiteConfigForm;

View file

@ -36,6 +36,8 @@ import {
PasswordChangeForm, PasswordChangeForm,
PrivateMessageForm, PrivateMessageForm,
EditPrivateMessageForm, EditPrivateMessageForm,
DeletePrivateMessageForm,
MarkPrivateMessageAsReadForm,
GetPrivateMessagesForm, GetPrivateMessagesForm,
GetCommentsForm, GetCommentsForm,
UserJoinForm, UserJoinForm,
@ -315,6 +317,18 @@ export class WebSocketService {
this.ws.send(this.wsSendWrapper(UserOperation.EditPrivateMessage, form)); 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) { public getPrivateMessages(form: GetPrivateMessagesForm) {
this.setAuth(form); this.setAuth(form);
this.ws.send(this.wsSendWrapper(UserOperation.GetPrivateMessages, form)); this.ws.send(this.wsSendWrapper(UserOperation.GetPrivateMessages, form));