Adding delete picture via pict-rs delete tokens. Fixes #505
This commit is contained in:
parent
2fbd44c59d
commit
4cf1f080bf
6 changed files with 70 additions and 20 deletions
2
docker/dev/docker-compose.yml
vendored
2
docker/dev/docker-compose.yml
vendored
|
@ -28,7 +28,7 @@ services:
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
pictrs:
|
pictrs:
|
||||||
image: asonix/pictrs:v0.1.0-r13
|
image: asonix/pictrs:v0.1.3-r1
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8537:8080"
|
- "127.0.0.1:8537:8080"
|
||||||
user: 991:991
|
user: 991:991
|
||||||
|
|
|
@ -116,8 +116,8 @@ impl Perform for Oper<CreatePost> {
|
||||||
return Err(APIError::err("site_ban").into());
|
return Err(APIError::err("site_ban").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch Iframely and Pictshare cached image
|
// Fetch Iframely and pictrs cached image
|
||||||
let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
fetch_iframely_and_pictrs_data(data.url.to_owned());
|
fetch_iframely_and_pictrs_data(data.url.to_owned());
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
|
@ -135,7 +135,7 @@ impl Perform for Oper<CreatePost> {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictshare_thumbnail,
|
thumbnail_url: pictrs_thumbnail,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post = match Post::create(&conn, &post_form) {
|
let inserted_post = match Post::create(&conn, &post_form) {
|
||||||
|
@ -450,8 +450,8 @@ impl Perform for Oper<EditPost> {
|
||||||
return Err(APIError::err("site_ban").into());
|
return Err(APIError::err("site_ban").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch Iframely and Pictshare cached image
|
// Fetch Iframely and Pictrs cached image
|
||||||
let (iframely_title, iframely_description, iframely_html, pictshare_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
fetch_iframely_and_pictrs_data(data.url.to_owned());
|
fetch_iframely_and_pictrs_data(data.url.to_owned());
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
|
@ -469,7 +469,7 @@ impl Perform for Oper<EditPost> {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictshare_thumbnail,
|
thumbnail_url: pictrs_thumbnail,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
|
let _updated_post = match Post::update(&conn, data.edit_id, &post_form) {
|
||||||
|
|
29
ui/src/components/comment-form.tsx
vendored
29
ui/src/components/comment-form.tsx
vendored
|
@ -18,6 +18,7 @@ import {
|
||||||
setupTribute,
|
setupTribute,
|
||||||
wsJsonToRes,
|
wsJsonToRes,
|
||||||
emojiPicker,
|
emojiPicker,
|
||||||
|
pictrsDeleteToast,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
import autosize from 'autosize';
|
import autosize from 'autosize';
|
||||||
|
@ -162,8 +163,9 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
</button>
|
</button>
|
||||||
{this.state.commentForm.content && (
|
{this.state.commentForm.content && (
|
||||||
<button
|
<button
|
||||||
className={`btn btn-sm mr-2 btn-secondary ${this.state
|
className={`btn btn-sm mr-2 btn-secondary ${
|
||||||
.previewMode && 'active'}`}
|
this.state.previewMode && 'active'
|
||||||
|
}`}
|
||||||
onClick={linkEvent(this, this.handlePreviewToggle)}
|
onClick={linkEvent(this, this.handlePreviewToggle)}
|
||||||
>
|
>
|
||||||
{i18n.t('preview')}
|
{i18n.t('preview')}
|
||||||
|
@ -306,7 +308,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
|
|
||||||
const imageUploadUrl = `/pictrs/image`;
|
const imageUploadUrl = `/pictrs/image`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('images[]', file);
|
||||||
|
|
||||||
i.state.imageLoading = true;
|
i.state.imageLoading = true;
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
|
@ -317,9 +319,14 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
})
|
})
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
let url = `${window.location.origin}/pictrs/${res.url}`;
|
console.log('pictrs upload:');
|
||||||
let imageMarkdown =
|
console.log(res);
|
||||||
res.filetype == 'mp4' ? `[vid](${url}/raw)` : `![](${url})`;
|
if (res.msg == 'ok') {
|
||||||
|
let hash = res.files[0].file;
|
||||||
|
let url = `${window.location.origin}/pictrs/image/${hash}`;
|
||||||
|
let deleteToken = res.files[0].delete_token;
|
||||||
|
let deleteUrl = `${window.location.origin}/pictrs/image/delete/${deleteToken}/${hash}`;
|
||||||
|
let imageMarkdown = `![](${url})`;
|
||||||
let content = i.state.commentForm.content;
|
let content = i.state.commentForm.content;
|
||||||
content = content ? `${content}\n${imageMarkdown}` : imageMarkdown;
|
content = content ? `${content}\n${imageMarkdown}` : imageMarkdown;
|
||||||
i.state.commentForm.content = content;
|
i.state.commentForm.content = content;
|
||||||
|
@ -327,6 +334,16 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
let textarea: any = document.getElementById(i.id);
|
let textarea: any = document.getElementById(i.id);
|
||||||
autosize.update(textarea);
|
autosize.update(textarea);
|
||||||
|
pictrsDeleteToast(
|
||||||
|
i18n.t('click_to_delete_picture'),
|
||||||
|
i18n.t('picture_deleted'),
|
||||||
|
deleteUrl
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
i.state.imageLoading = false;
|
||||||
|
i.setState(i.state);
|
||||||
|
toast(JSON.stringify(res), 'danger');
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
i.state.imageLoading = false;
|
i.state.imageLoading = false;
|
||||||
|
|
8
ui/src/components/post-form.tsx
vendored
8
ui/src/components/post-form.tsx
vendored
|
@ -35,6 +35,7 @@ import {
|
||||||
setupTribute,
|
setupTribute,
|
||||||
setupTippy,
|
setupTippy,
|
||||||
emojiPicker,
|
emojiPicker,
|
||||||
|
pictrsDeleteToast,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import autosize from 'autosize';
|
import autosize from 'autosize';
|
||||||
import Tribute from 'tributejs/src/Tribute.js';
|
import Tribute from 'tributejs/src/Tribute.js';
|
||||||
|
@ -536,9 +537,16 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
if (res.msg == 'ok') {
|
if (res.msg == 'ok') {
|
||||||
let hash = res.files[0].file;
|
let hash = res.files[0].file;
|
||||||
let url = `${window.location.origin}/pictrs/image/${hash}`;
|
let url = `${window.location.origin}/pictrs/image/${hash}`;
|
||||||
|
let deleteToken = res.files[0].delete_token;
|
||||||
|
let deleteUrl = `${window.location.origin}/pictrs/image/delete/${deleteToken}/${hash}`;
|
||||||
i.state.postForm.url = url;
|
i.state.postForm.url = url;
|
||||||
i.state.imageLoading = false;
|
i.state.imageLoading = false;
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
|
pictrsDeleteToast(
|
||||||
|
i18n.t('click_to_delete_picture'),
|
||||||
|
i18n.t('picture_deleted'),
|
||||||
|
deleteUrl
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
i.state.imageLoading = false;
|
i.state.imageLoading = false;
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
|
|
23
ui/src/utils.ts
vendored
23
ui/src/utils.ts
vendored
|
@ -487,6 +487,29 @@ export function toast(text: string, background: string = 'success') {
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function pictrsDeleteToast(
|
||||||
|
clickToDeleteText: string,
|
||||||
|
deletePictureText: string,
|
||||||
|
deleteUrl: string
|
||||||
|
) {
|
||||||
|
let backgroundColor = `var(--light)`;
|
||||||
|
let toast = Toastify({
|
||||||
|
text: clickToDeleteText,
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
gravity: 'top',
|
||||||
|
position: 'right',
|
||||||
|
duration: 0,
|
||||||
|
onClick: () => {
|
||||||
|
if (toast) {
|
||||||
|
window.location.replace(deleteUrl);
|
||||||
|
alert(deletePictureText);
|
||||||
|
toast.hideToast();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: true,
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
|
||||||
export function messageToastify(
|
export function messageToastify(
|
||||||
creator: string,
|
creator: string,
|
||||||
avatar: string,
|
avatar: string,
|
||||||
|
|
2
ui/translations/en.json
vendored
2
ui/translations/en.json
vendored
|
@ -75,6 +75,8 @@
|
||||||
"delete_account": "Delete Account",
|
"delete_account": "Delete Account",
|
||||||
"delete_account_confirm":
|
"delete_account_confirm":
|
||||||
"Warning: this will permanently delete all your data. Enter your password to confirm.",
|
"Warning: this will permanently delete all your data. Enter your password to confirm.",
|
||||||
|
"click_to_delete_picture": "Click to delete picture.",
|
||||||
|
"picture_deleted": "Picture deleted.",
|
||||||
"restore": "restore",
|
"restore": "restore",
|
||||||
"ban": "ban",
|
"ban": "ban",
|
||||||
"ban_from_site": "ban from site",
|
"ban_from_site": "ban from site",
|
||||||
|
|
Loading…
Reference in a new issue