import React from "react" import * as antd from "antd" import { Icons } from "components/Icons" import { User } from "models" import classnames from "classnames" import { PostAdditions } from "components/PostCard" import "./index.less" // TODO: Handle `cntr+v` to paste data from the clipboard to the post additions // TODO: Fetch `maxMessageLength` value from server API const maxMessageLength = 512 export default (props) => { const api = window.app.api.withEndpoints("main") const additionsRef = React.useRef(null) const [pending, setPending] = React.useState([]) const [loading, setLoading] = React.useState(false) const [uploaderVisible, setUploaderVisible] = React.useState(false) const [focused, setFocused] = React.useState(false) const [userData, setUserData] = React.useState(null) const [postData, setPostData] = React.useState({ message: "", additions: [] }) const updatePostData = (update) => { setPostData({ ...postData, ...update }) } const cleanPostData = () => { setPostData({ message: "", additions: [] }) } const submit = () => { if (!canSubmit()) return setLoading(true) setUploaderVisible(false) setFocused(false) const response = api.post.post({ ...postData }).catch(error => { console.error(error) antd.message.error(error) return false }) setLoading(false) if (response) { cleanPostData() if (typeof props.onPost === "function") { props.onPost() } } } const onUploadFile = async (req) => { // hide uploader setUploaderVisible(false) // get file data const file = req.file // append to form data const formData = new FormData() formData.append("files", file) // send request const request = await api.post.upload(formData, undefined).catch((error) => { console.error(error) antd.message.error(error) req.onError(error) return false }) if (request) { return req.onSuccess(request) } } const canSubmit = () => { const messageLengthValid = postData.message.length !== 0 && postData.message.length < maxMessageLength return Boolean(messageLengthValid) && Boolean(pending.length === 0) } const onDraggerChange = (change) => { console.log(change) switch (change.file.status) { case "uploading": { setPending([...pending, change.file.uid]) break } case "done": { let additions = postData.additions ?? [] additions.push(...change.file.response) // remove pending file setPending(pending.filter(uid => uid !== change.file.uid)) // update post data updatePostData({ additions }) // force update additions if (additionsRef.current) { additionsRef.current.forceUpdate() } break } default: { break } } } const onChangeMessageInput = (event) => { updatePostData({ message: event.target.value }) } const toggleUploader = (to) => { setUploaderVisible(to ?? !uploaderVisible) } const toggleFocus = (to) => { setFocused(to ?? !focused) } const handleKeyDown = (e) => { // detect if the user pressed `enter` key and submit the form, but only if the `shift` key is not pressed if (e.keyCode === 13 && !e.shiftKey) { e.preventDefault() e.stopPropagation() submit() } } React.useEffect(() => { User.data().then(user => { setUserData(user) }) }, []) // set loading to true menwhile pending is not empty React.useEffect(() => { console.log(pending) setLoading(pending.length !== 0) }, [pending]) return <div className="postCreator" onDragOver={(e) => { e.preventDefault() toggleUploader(true) }} onDragLeave={(e) => { e.preventDefault() toggleUploader(false) }} onMouseEnter={() => { toggleFocus(true) }} onMouseLeave={() => { toggleFocus(false) }} > <div className="textInput"> <div className="avatar"> <img src={userData?.avatar} /> </div> <antd.Input.TextArea placeholder="What are you thinking?" disabled={loading} onKeyDown={handleKeyDown} onChange={onChangeMessageInput} autoSize={{ minRows: 3, maxRows: 6 }} maxLength={maxMessageLength} dragable={false} value={postData.message} allowClear /> <div> <antd.Button type="primary" disabled={loading || !canSubmit()} onClick={submit} icon={loading ? <Icons.LoadingOutlined spin /> : <Icons.Send />} /> </div> </div> {postData.additions.length > 0 && <PostAdditions ref={additionsRef} additions={postData.additions} />} <div className={classnames("actions", { ["hided"]: !focused && !uploaderVisible })}> <div> <antd.Button type={uploaderVisible ? "default" : "primary"} disabled={loading} onClick={() => { toggleUploader() }} icon={<Icons.Upload />} /> </div> </div> <div className={classnames("uploader", { ["hided"]: !uploaderVisible })}> <antd.Upload.Dragger maxCount={20} multiple={true} onChange={onDraggerChange} customRequest={onUploadFile} > <p >Click or drag file to this area to upload</p> </antd.Upload.Dragger> </div> </div> }