]> Untitled Git - lemmy-ui.git/blob - src/shared/components/common/image-upload-form.tsx
Merge branch 'fix/notif_new_fetch_bug' of https://github.com/ernestwisniewski/lemmy...
[lemmy-ui.git] / src / shared / components / common / image-upload-form.tsx
1 import { Option } from "@sniptt/monads";
2 import { Component, linkEvent } from "inferno";
3 import { pictrsUri } from "../../env";
4 import { i18n } from "../../i18next";
5 import { UserService } from "../../services";
6 import { randomStr, toast } from "../../utils";
7 import { Icon } from "./icon";
8
9 interface ImageUploadFormProps {
10   uploadTitle: string;
11   imageSrc: Option<string>;
12   onUpload(url: string): any;
13   onRemove(): any;
14   rounded?: boolean;
15 }
16
17 interface ImageUploadFormState {
18   loading: boolean;
19 }
20
21 export class ImageUploadForm extends Component<
22   ImageUploadFormProps,
23   ImageUploadFormState
24 > {
25   private id = `image-upload-form-${randomStr()}`;
26   private emptyState: ImageUploadFormState = {
27     loading: false,
28   };
29
30   constructor(props: any, context: any) {
31     super(props, context);
32     this.state = this.emptyState;
33   }
34
35   render() {
36     return (
37       <form class="d-inline">
38         <label
39           htmlFor={this.id}
40           class="pointer text-muted small font-weight-bold"
41         >
42           {this.props.imageSrc.match({
43             some: imageSrc => (
44               <span class="d-inline-block position-relative">
45                 <img
46                   src={imageSrc}
47                   height={this.props.rounded ? 60 : ""}
48                   width={this.props.rounded ? 60 : ""}
49                   className={`img-fluid ${
50                     this.props.rounded ? "rounded-circle" : ""
51                   }`}
52                 />
53                 <a
54                   onClick={linkEvent(this, this.handleRemoveImage)}
55                   aria-label={i18n.t("remove")}
56                 >
57                   <Icon icon="x" classes="mini-overlay" />
58                 </a>
59               </span>
60             ),
61             none: (
62               <span class="btn btn-secondary">{this.props.uploadTitle}</span>
63             ),
64           })}
65         </label>
66         <input
67           id={this.id}
68           type="file"
69           accept="image/*,video/*"
70           name={this.id}
71           class="d-none"
72           disabled={UserService.Instance.myUserInfo.isNone()}
73           onChange={linkEvent(this, this.handleImageUpload)}
74         />
75       </form>
76     );
77   }
78
79   handleImageUpload(i: ImageUploadForm, event: any) {
80     event.preventDefault();
81     let file = event.target.files[0];
82     const formData = new FormData();
83     formData.append("images[]", file);
84
85     i.state.loading = true;
86     i.setState(i.state);
87
88     fetch(pictrsUri, {
89       method: "POST",
90       body: formData,
91     })
92       .then(res => res.json())
93       .then(res => {
94         console.log("pictrs upload:");
95         console.log(res);
96         if (res.msg == "ok") {
97           let hash = res.files[0].file;
98           let url = `${pictrsUri}/${hash}`;
99           i.state.loading = false;
100           i.setState(i.state);
101           i.props.onUpload(url);
102         } else {
103           i.state.loading = false;
104           i.setState(i.state);
105           toast(JSON.stringify(res), "danger");
106         }
107       })
108       .catch(error => {
109         i.state.loading = false;
110         i.setState(i.state);
111         console.error(error);
112         toast(error, "danger");
113       });
114   }
115
116   handleRemoveImage(i: ImageUploadForm, event: any) {
117     event.preventDefault();
118     i.state.loading = true;
119     i.setState(i.state);
120     i.props.onRemove();
121   }
122 }