]> Untitled Git - lemmy-ui.git/blob - src/shared/components/common/image-upload-form.tsx
Merge branch 'main' into fix/fix-badges-spacing-componentize
[lemmy-ui.git] / src / shared / components / common / image-upload-form.tsx
1 import { randomStr } from "@utils/helpers";
2 import classNames from "classnames";
3 import { Component, linkEvent } from "inferno";
4 import { HttpService, I18NextService, UserService } from "../../services";
5 import { toast } from "../../toast";
6 import { Icon } from "./icon";
7
8 interface ImageUploadFormProps {
9   uploadTitle: string;
10   imageSrc?: string;
11   onUpload(url: string): any;
12   onRemove(): any;
13   rounded?: boolean;
14 }
15
16 interface ImageUploadFormState {
17   loading: boolean;
18 }
19
20 export class ImageUploadForm extends Component<
21   ImageUploadFormProps,
22   ImageUploadFormState
23 > {
24   private id = `image-upload-form-${randomStr()}`;
25   private emptyState: ImageUploadFormState = {
26     loading: false,
27   };
28
29   constructor(props: any, context: any) {
30     super(props, context);
31     this.state = this.emptyState;
32   }
33
34   render() {
35     return (
36       <form className="image-upload-form d-inline">
37         {this.props.imageSrc && (
38           <span className="d-inline-block position-relative mb-2">
39             {/* TODO: Create "Current Iamge" translation for alt text */}
40             <img
41               alt=""
42               src={this.props.imageSrc}
43               height={this.props.rounded ? 60 : ""}
44               width={this.props.rounded ? 60 : ""}
45               className={classNames({
46                 "rounded-circle object-fit-cover": this.props.rounded,
47                 "img-fluid": !this.props.rounded,
48               })}
49             />
50             <button
51               className="position-absolute d-block p-0 end-0 border-0 top-0 bg-transparent text-white"
52               type="button"
53               onClick={linkEvent(this, this.handleRemoveImage)}
54               aria-label={I18NextService.i18n.t("remove")}
55             >
56               <Icon icon="x" classes="mini-overlay" />
57             </button>
58           </span>
59         )}
60         <input
61           id={this.id}
62           type="file"
63           accept="image/*,video/*"
64           className="small form-control"
65           name={this.id}
66           disabled={!UserService.Instance.myUserInfo}
67           onChange={linkEvent(this, this.handleImageUpload)}
68         />
69       </form>
70     );
71   }
72
73   handleImageUpload(i: ImageUploadForm, event: any) {
74     event.preventDefault();
75     const image = event.target.files[0] as File;
76
77     i.setState({ loading: true });
78
79     HttpService.client.uploadImage({ image }).then(res => {
80       console.log("pictrs upload:");
81       console.log(res);
82       if (res.state === "success") {
83         if (res.data.msg === "ok") {
84           i.props.onUpload(res.data.url as string);
85         } else if (res.data.msg === "too_large") {
86           toast(I18NextService.i18n.t("upload_too_large"), "danger");
87         } else {
88           toast(JSON.stringify(res), "danger");
89         }
90       } else if (res.state === "failed") {
91         console.error(res.msg);
92         toast(res.msg, "danger");
93       }
94
95       i.setState({ loading: false });
96     });
97   }
98
99   handleRemoveImage(i: ImageUploadForm, event: any) {
100     event.preventDefault();
101     i.setState({ loading: true });
102     i.props.onRemove();
103   }
104 }