mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-11 03:24:16 +00:00
rewrited PostCreator
to fix upload behaviors
This commit is contained in:
parent
1fa52ae9f5
commit
557901dfe0
@ -5,6 +5,7 @@ import { DateTime } from "luxon"
|
|||||||
import humanSize from "@tsmx/human-readable"
|
import humanSize from "@tsmx/human-readable"
|
||||||
|
|
||||||
import { Icons } from "components/Icons"
|
import { Icons } from "components/Icons"
|
||||||
|
import clipboardEventFileToFile from "utils/clipboardEventFileToFile"
|
||||||
|
|
||||||
import PostModel from "models/post"
|
import PostModel from "models/post"
|
||||||
|
|
||||||
@ -17,34 +18,54 @@ const DEFAULT_POST_POLICY = {
|
|||||||
maximunFilesPerRequest: 10
|
maximunFilesPerRequest: 10
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (props) => {
|
export default class PostCreator extends React.Component {
|
||||||
const api = window.app.cores.api.withEndpoints()
|
state = {
|
||||||
|
pending: [],
|
||||||
|
loading: false,
|
||||||
|
uploaderVisible: false,
|
||||||
|
|
||||||
const creatorRef = React.useRef(null)
|
postMessage: "",
|
||||||
|
postAttachments: [],
|
||||||
|
|
||||||
const [pending, setPending] = React.useState([])
|
fileList: [],
|
||||||
const [loading, setLoading] = React.useState(false)
|
postingPolicy: DEFAULT_POST_POLICY
|
||||||
const [uploaderVisible, setUploaderVisible] = React.useState(false)
|
|
||||||
|
|
||||||
const [postMessage, setPostMessage] = React.useState("")
|
|
||||||
const [postAttachments, setPostAttachments] = React.useState([])
|
|
||||||
const [fileList, setFileList] = React.useState([])
|
|
||||||
|
|
||||||
const [postingPolicy, setPostingPolicy] = React.useState(DEFAULT_POST_POLICY)
|
|
||||||
|
|
||||||
const cleanPostData = () => {
|
|
||||||
setPostMessage("")
|
|
||||||
setPostAttachments([])
|
|
||||||
setFileList([])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchUploadPolicy = async () => {
|
creatorRef = React.createRef()
|
||||||
const policy = await api.get.postingPolicy()
|
|
||||||
|
|
||||||
setPostingPolicy(policy)
|
api = window.app.cores.api.withEndpoints()
|
||||||
|
|
||||||
|
cleanPostData = () => {
|
||||||
|
this.setState({
|
||||||
|
postMessage: "",
|
||||||
|
postAttachments: [],
|
||||||
|
fileList: []
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const canSubmit = () => {
|
toogleUploaderVisibility = (to) => {
|
||||||
|
to = to ?? !this.state.uploaderVisible
|
||||||
|
|
||||||
|
if (to === this.state.uploaderVisible) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
uploaderVisible: to
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchUploadPolicy = async () => {
|
||||||
|
const policy = await this.api.get.postingPolicy()
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
postingPolicy: policy
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
canSubmit = () => {
|
||||||
|
const { postMessage, postAttachments, pending, postingPolicy } = this.state
|
||||||
|
|
||||||
const messageLengthValid = postMessage.length !== 0 && postMessage.length < postingPolicy.maxMessageLength
|
const messageLengthValid = postMessage.length !== 0 && postMessage.length < postingPolicy.maxMessageLength
|
||||||
|
|
||||||
if (pending.length !== 0) {
|
if (pending.length !== 0) {
|
||||||
@ -58,11 +79,15 @@ export default (props) => {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const submit = async () => {
|
submit = async () => {
|
||||||
if (!canSubmit()) return
|
if (!this.canSubmit()) return
|
||||||
|
|
||||||
setLoading(true)
|
this.setState({
|
||||||
setUploaderVisible(false)
|
loading: true,
|
||||||
|
uploaderVisible: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const { postMessage, postAttachments } = this.state
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
message: postMessage,
|
message: postMessage,
|
||||||
@ -77,31 +102,35 @@ export default (props) => {
|
|||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
setLoading(false)
|
this.setState({
|
||||||
|
loading: false
|
||||||
|
})
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
cleanPostData()
|
this.cleanPostData()
|
||||||
|
|
||||||
if (typeof props.onPost === "function") {
|
if (typeof this.props.onPost === "function") {
|
||||||
props.onPost()
|
this.props.onPost()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUploadFile = async (req) => {
|
uploadFile = async (req) => {
|
||||||
// hide uploader
|
// hide uploader
|
||||||
toogleUploaderVisibility(false)
|
this.toogleUploaderVisibility(false)
|
||||||
|
|
||||||
// get file data
|
// get file data
|
||||||
const file = req.file
|
const file = req.file
|
||||||
|
|
||||||
|
console.log(`Uploading file >`, file)
|
||||||
|
|
||||||
// append to form data
|
// append to form data
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
|
||||||
formData.append("files", file)
|
formData.append("files", file)
|
||||||
|
|
||||||
// send request
|
// send request
|
||||||
const request = await api.post.upload(formData, undefined).catch((error) => {
|
const request = await this.api.post.upload(formData, undefined).catch((error) => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
antd.message.error(error)
|
antd.message.error(error)
|
||||||
|
|
||||||
@ -111,23 +140,31 @@ export default (props) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (request) {
|
if (request) {
|
||||||
|
console.log(`Upload done >`, request)
|
||||||
|
|
||||||
return req.onSuccess(request)
|
return req.onSuccess(request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeAttachment = (file_uid) => {
|
removeAttachment = (file_uid) => {
|
||||||
setPostAttachments(postAttachments.filter((file) => file.uid !== file_uid))
|
this.setState({
|
||||||
|
postAttachments: this.state.postAttachments.filter((file) => file.uid !== file_uid)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const addAttachment = (file) => {
|
addAttachment = (file) => {
|
||||||
if (Array.isArray(file)) {
|
if (Array.isArray(file)) {
|
||||||
return setPostAttachments([...postAttachments, ...file])
|
return this.setState({
|
||||||
|
postAttachments: [...this.state.postAttachments, ...file]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return setPostAttachments([...postAttachments, file])
|
return this.setState({
|
||||||
|
postAttachments: [...this.state.postAttachments, file]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploaderScrollToEnd = () => {
|
uploaderScrollToEnd = () => {
|
||||||
// scroll to max right
|
// scroll to max right
|
||||||
const element = document.querySelector(".ant-upload-list-picture-card")
|
const element = document.querySelector(".ant-upload-list-picture-card")
|
||||||
|
|
||||||
@ -143,37 +180,50 @@ export default (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUploaderChange = (change) => {
|
onUploaderChange = (change) => {
|
||||||
setFileList(change.fileList)
|
if (this.state.fileList !== change.fileList) {
|
||||||
|
this.setState({
|
||||||
|
fileList: change.fileList
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(change)
|
||||||
|
|
||||||
switch (change.file.status) {
|
switch (change.file.status) {
|
||||||
case "uploading": {
|
case "uploading": {
|
||||||
toogleUploaderVisibility(false)
|
this.toogleUploaderVisibility(false)
|
||||||
|
|
||||||
setPending([...pending, change.file.uid])
|
this.setState({
|
||||||
|
pending: [...this.state.pending, change.file.uid]
|
||||||
|
})
|
||||||
|
|
||||||
uploaderScrollToEnd()
|
this.uploaderScrollToEnd()
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
case "done": {
|
case "done": {
|
||||||
// remove pending file
|
// remove pending file
|
||||||
setPending(pending.filter(uid => uid !== change.file.uid))
|
this.setState({
|
||||||
|
pending: this.state.pending.filter(uid => uid !== change.file.uid)
|
||||||
|
})
|
||||||
|
|
||||||
// update post data
|
// update post data
|
||||||
addAttachment(change.file.response.files)
|
this.addAttachment(change.file.response.files)
|
||||||
|
|
||||||
// scroll to end
|
// scroll to end
|
||||||
uploaderScrollToEnd()
|
this.uploaderScrollToEnd()
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case "error": {
|
case "error": {
|
||||||
// remove pending file
|
// remove pending file
|
||||||
setPending(pending.filter(uid => uid !== change.file.uid))
|
this.setState({
|
||||||
|
pending: this.state.pending.filter(uid => uid !== change.file.uid)
|
||||||
|
})
|
||||||
|
|
||||||
removeAttachment(change.file.uid)
|
// remove file from list
|
||||||
|
this.removeAttachment(change.file.uid)
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
break
|
break
|
||||||
@ -181,70 +231,127 @@ export default (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onChangeMessageInput = (event) => {
|
onChangeMessageInput = (event) => {
|
||||||
// if the fist character is a space or a whitespace remove it
|
// if the fist character is a space or a whitespace remove it
|
||||||
if (event.target.value[0] === " " || event.target.value[0] === "\n") {
|
if (event.target.value[0] === " " || event.target.value[0] === "\n") {
|
||||||
event.target.value = event.target.value.slice(1)
|
event.target.value = event.target.value.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
setPostMessage(event.target.value)
|
this.setState({
|
||||||
|
postMessage: event.target.value
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const toogleUploaderVisibility = (to) => {
|
handleKeyDown = (e) => {
|
||||||
to = to ?? !uploaderVisible
|
|
||||||
|
|
||||||
if (to === uploaderVisible) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setUploaderVisible(to ?? !uploaderVisible)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleKeyDown = (e) => {
|
|
||||||
// detect if the user pressed `enter` key and submit the form, but only if the `shift` key is not pressed
|
// 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) {
|
if (e.keyCode === 13 && !e.shiftKey) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
submit()
|
this.submit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePaste = ({ clipboardData }) => {
|
updateFileList = (uid, newValue) => {
|
||||||
|
let updatedFileList = this.state.fileList
|
||||||
|
|
||||||
|
// find the file in the list
|
||||||
|
const index = updatedFileList.findIndex(file => file.uid === uid)
|
||||||
|
|
||||||
|
// update the file
|
||||||
|
updatedFileList[index] = newValue
|
||||||
|
|
||||||
|
// update the state
|
||||||
|
this.setState({
|
||||||
|
fileList: updatedFileList
|
||||||
|
})
|
||||||
|
|
||||||
|
return updatedFileList
|
||||||
|
}
|
||||||
|
|
||||||
|
handleManualUpload = async (file) => {
|
||||||
|
if (!file) {
|
||||||
|
throw new Error(`No file provided`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const isValidFormat = (fileType) => {
|
||||||
|
return this.state.postingPolicy.acceptedMimeTypes.includes(fileType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValidFormat(file.type)) {
|
||||||
|
throw new Error(`Invalid file format`)
|
||||||
|
}
|
||||||
|
|
||||||
|
file.thumbUrl = URL.createObjectURL(file)
|
||||||
|
file.uid = `${file.name}-${Math.random() * 1000}`
|
||||||
|
|
||||||
|
file.status = "uploading"
|
||||||
|
|
||||||
|
// add file to the uploader
|
||||||
|
this.onUploaderChange({
|
||||||
|
file,
|
||||||
|
fileList: [...this.state.fileList, file],
|
||||||
|
})
|
||||||
|
|
||||||
|
// upload the file
|
||||||
|
await this.uploadFile({
|
||||||
|
file,
|
||||||
|
onSuccess: (response) => {
|
||||||
|
file.status = "done"
|
||||||
|
file.response = response
|
||||||
|
|
||||||
|
this.onUploaderChange({
|
||||||
|
file: file,
|
||||||
|
fileList: this.updateFileList(file.uid, file)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
file.status = "error"
|
||||||
|
file.error = error
|
||||||
|
|
||||||
|
this.onUploaderChange({
|
||||||
|
file: file,
|
||||||
|
fileList: this.updateFileList(file.uid, file)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePaste = async ({ clipboardData }) => {
|
||||||
if (clipboardData && clipboardData.items.length > 0) {
|
if (clipboardData && clipboardData.items.length > 0) {
|
||||||
const isValidFormat = (fileType) => DEFAULT_ACCEPTED_FILES.includes(fileType)
|
// check if the clipboard contains a file
|
||||||
|
const hasFile = Array.from(clipboardData.items).some(item => item.kind === "file")
|
||||||
|
|
||||||
|
if (!hasFile) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for (let index = 0; index < clipboardData.items.length; index++) {
|
for (let index = 0; index < clipboardData.items.length; index++) {
|
||||||
if (!isValidFormat(clipboardData.items[index].type)) {
|
const item = clipboardData.items[index]
|
||||||
throw new Error(`Sorry, that's not a format we support ${clipboardData.items[index].type}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
let file = clipboardData.items[index].getAsFile()
|
let file = await clipboardEventFileToFile(item).catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
app.message.error(`Failed to upload file:`, error.message)
|
||||||
|
|
||||||
app.message.info("Uploading file...")
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
file.thumbUrl = URL.createObjectURL(file)
|
this.handleManualUpload(file).catch((error) => {
|
||||||
|
console.error(error)
|
||||||
file.uid = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
|
return false
|
||||||
|
|
||||||
// upload file
|
|
||||||
onUploadFile({
|
|
||||||
file,
|
|
||||||
onSuccess: (response) => {
|
|
||||||
setFileList([...fileList, file])
|
|
||||||
addAttachment(response)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderUploadPreviewItem = (item, file, list, actions) => {
|
renderUploadPreviewItem = (item, file, list, actions) => {
|
||||||
const uploading = file.status === "uploading"
|
const uploading = file.status === "uploading"
|
||||||
|
|
||||||
const onClickDelete = () => {
|
const onClickDelete = () => {
|
||||||
actions.remove()
|
actions.remove()
|
||||||
removeAttachment(file.uid)
|
this.removeAttachment(file.uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className={classnames("file", { ["uploading"]: uploading })}>
|
return <div className={classnames("file", { ["uploading"]: uploading })}>
|
||||||
@ -267,23 +374,23 @@ export default (props) => {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDrag = (event) => {
|
handleDrag = (event) => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
||||||
console.log(event)
|
console.log(event)
|
||||||
|
|
||||||
if (event.type === "dragenter") {
|
if (event.type === "dragenter") {
|
||||||
toogleUploaderVisibility(true)
|
this.toogleUploaderVisibility(true)
|
||||||
} else if (event.type === "dragleave") {
|
} else if (event.type === "dragleave") {
|
||||||
// check if mouse is over the uploader or outside the creatorRef
|
// check if mouse is over the uploader or outside the creatorRef
|
||||||
if (uploaderVisible && !creatorRef.current.contains(event.target)) {
|
if (this.state.uploaderVisible && !this.creatorRef.current.contains(event.target)) {
|
||||||
toogleUploaderVisibility(false)
|
this.toogleUploaderVisibility(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUploadClick = () => {
|
handleUploadClick = () => {
|
||||||
// create a new dialog
|
// create a new dialog
|
||||||
const dialog = document.createElement("input")
|
const dialog = document.createElement("input")
|
||||||
|
|
||||||
@ -291,105 +398,124 @@ export default (props) => {
|
|||||||
dialog.type = "file"
|
dialog.type = "file"
|
||||||
|
|
||||||
// set the dialog accept to the accepted files
|
// set the dialog accept to the accepted files
|
||||||
dialog.accept = postingPolicy.acceptedMimeTypes
|
dialog.accept = this.state.postingPolicy.acceptedMimeTypes
|
||||||
|
|
||||||
dialog.multiple = true
|
dialog.multiple = true
|
||||||
|
|
||||||
// add a listener to the dialog
|
// add a listener to the dialog
|
||||||
dialog.addEventListener("change", (event) => {
|
dialog.addEventListener("change", (event) => {
|
||||||
console.log(event)
|
// get the files
|
||||||
|
const files = event.target.files
|
||||||
|
|
||||||
|
// loop through the files
|
||||||
|
for (let index = 0; index < files.length; index++) {
|
||||||
|
const file = files[index]
|
||||||
|
|
||||||
|
this.handleManualUpload(file).catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// click the dialog
|
// click the dialog
|
||||||
dialog.click()
|
dialog.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
componentDidMount() {
|
||||||
fetchUploadPolicy()
|
// fetch the posting policy
|
||||||
|
this.fetchUploadPolicy()
|
||||||
|
|
||||||
document.addEventListener("paste", handlePaste)
|
// add a listener to the window
|
||||||
|
document.addEventListener("paste", this.handlePaste)
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
componentWillUnmount() {
|
||||||
document.removeEventListener("paste", handlePaste)
|
document.removeEventListener("paste", this.handlePaste)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps, prevState) {
|
||||||
|
// if pending is not empty and is not loading
|
||||||
|
if (this.state.pending.length > 0 && !this.state.loading) {
|
||||||
|
this.setState({ loading: true })
|
||||||
|
} else if (this.state.pending.length === 0 && this.state.loading) {
|
||||||
|
this.setState({ loading: false })
|
||||||
}
|
}
|
||||||
}, [])
|
}
|
||||||
|
|
||||||
// set loading to true menwhile pending is not empty
|
render() {
|
||||||
React.useEffect(() => {
|
const { postMessage, fileList, loading, uploaderVisible, postingPolicy } = this.state
|
||||||
setLoading(pending.length !== 0)
|
|
||||||
}, [pending])
|
|
||||||
|
|
||||||
return <div
|
return <div
|
||||||
className={"postCreator"}
|
className={"postCreator"}
|
||||||
ref={creatorRef}
|
ref={this.creatorRef}
|
||||||
onDragEnter={handleDrag}
|
onDragEnter={this.handleDrag}
|
||||||
onDragLeave={handleDrag}
|
onDragLeave={this.handleDrag}
|
||||||
>
|
>
|
||||||
<div className="textInput">
|
<div className="textInput">
|
||||||
<div className="avatar">
|
<div className="avatar">
|
||||||
<img src={app.userData?.avatar} />
|
<img src={app.userData?.avatar} />
|
||||||
|
</div>
|
||||||
|
<antd.Input.TextArea
|
||||||
|
placeholder="What are you thinking?"
|
||||||
|
value={postMessage}
|
||||||
|
autoSize={{ minRows: 3, maxRows: 6 }}
|
||||||
|
maxLength={postingPolicy.maxMessageLength}
|
||||||
|
onChange={this.onChangeMessageInput}
|
||||||
|
onKeyDown={this.handleKeyDown}
|
||||||
|
disabled={loading}
|
||||||
|
draggable={false}
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<antd.Button
|
||||||
|
type="primary"
|
||||||
|
disabled={loading || !this.canSubmit()}
|
||||||
|
onClick={this.submit}
|
||||||
|
icon={loading ? <Icons.LoadingOutlined spin /> : <Icons.Send />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<antd.Input.TextArea
|
|
||||||
placeholder="What are you thinking?"
|
<div className={classnames("uploader", { ["visible"]: uploaderVisible })}>
|
||||||
value={postMessage}
|
<antd.Upload.Dragger
|
||||||
autoSize={{ minRows: 3, maxRows: 6 }}
|
openFileDialogOnClick={false}
|
||||||
maxLength={postingPolicy.maxMessageLength}
|
maxCount={postingPolicy.maximunFilesPerRequest}
|
||||||
onChange={onChangeMessageInput}
|
onChange={this.onUploaderChange}
|
||||||
onKeyDown={handleKeyDown}
|
customRequest={this.uploadFile}
|
||||||
disabled={loading}
|
accept={postingPolicy.acceptedMimeTypes}
|
||||||
draggable={false}
|
fileList={fileList}
|
||||||
allowClear
|
listType="picture-card"
|
||||||
/>
|
itemRender={this.renderUploadPreviewItem}
|
||||||
<div>
|
multiple
|
||||||
|
>
|
||||||
|
<div className="hint">
|
||||||
|
<h3>Drag and drop files here</h3>
|
||||||
|
<span>Max {humanSize.fromBytes(postingPolicy.maximumFileSize)}</span>
|
||||||
|
</div>
|
||||||
|
</antd.Upload.Dragger>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="actions">
|
||||||
<antd.Button
|
<antd.Button
|
||||||
type="primary"
|
type="primary"
|
||||||
disabled={loading || !canSubmit()}
|
disabled={loading}
|
||||||
onClick={submit}
|
onClick={this.handleUploadClick}
|
||||||
icon={loading ? <Icons.LoadingOutlined spin /> : <Icons.Send />}
|
icon={<Icons.Upload />}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<antd.Button
|
||||||
|
type="primary"
|
||||||
|
disabled={loading}
|
||||||
|
icon={<Icons.MdPoll />}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<antd.Button
|
||||||
|
type="primary"
|
||||||
|
disabled={loading}
|
||||||
|
icon={<Icons.MdPrivacyTip />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
<div className={classnames("uploader", { ["visible"]: uploaderVisible })}>
|
}
|
||||||
<antd.Upload.Dragger
|
|
||||||
openFileDialogOnClick={false}
|
|
||||||
maxCount={postingPolicy.maximunFilesPerRequest}
|
|
||||||
onChange={onUploaderChange}
|
|
||||||
customRequest={onUploadFile}
|
|
||||||
accept={postingPolicy.acceptedMimeTypes}
|
|
||||||
fileList={fileList}
|
|
||||||
listType="picture-card"
|
|
||||||
itemRender={renderUploadPreviewItem}
|
|
||||||
multiple
|
|
||||||
>
|
|
||||||
<div className="hint">
|
|
||||||
<h3>Drag and drop files here</h3>
|
|
||||||
<span>Max {humanSize.fromBytes(postingPolicy.maximumFileSize)}</span>
|
|
||||||
</div>
|
|
||||||
</antd.Upload.Dragger>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="actions">
|
|
||||||
<antd.Button
|
|
||||||
type="primary"
|
|
||||||
disabled={loading}
|
|
||||||
onClick={handleUploadClick}
|
|
||||||
icon={<Icons.Upload />}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<antd.Button
|
|
||||||
type="primary"
|
|
||||||
disabled={loading}
|
|
||||||
icon={<Icons.MdPoll />}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<antd.Button
|
|
||||||
type="primary"
|
|
||||||
disabled={loading}
|
|
||||||
icon={<Icons.MdPrivacyTip />}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
58
packages/app/src/utils/clipboardEventFileToFile/index.js
Normal file
58
packages/app/src/utils/clipboardEventFileToFile/index.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
export default async (eventFile) => {
|
||||||
|
if (!eventFile) {
|
||||||
|
throw new Error("Missing eventFile")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventFile.type === "text/html") {
|
||||||
|
eventFile.getAsString((data) => {
|
||||||
|
const parser = new DOMParser()
|
||||||
|
const doc = parser.parseFromString(data, "text/html")
|
||||||
|
const img = doc.querySelector("img")
|
||||||
|
|
||||||
|
// TODO: Support multiple mime types
|
||||||
|
|
||||||
|
if (!img) {
|
||||||
|
return reject(new Error("No image found in clipboard. Only images are supported."))
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = new Image()
|
||||||
|
|
||||||
|
const finalExtension = "png" //img.src.split(".").pop()
|
||||||
|
|
||||||
|
image.crossOrigin = "Anonymous"
|
||||||
|
|
||||||
|
image.src = img.src
|
||||||
|
|
||||||
|
image.onload = () => {
|
||||||
|
const canvas = document.createElement("canvas")
|
||||||
|
|
||||||
|
canvas.width = image.width
|
||||||
|
canvas.height = image.height
|
||||||
|
|
||||||
|
const context = canvas.getContext("2d")
|
||||||
|
|
||||||
|
context.drawImage(image, 0, 0, image.width, image.height)
|
||||||
|
|
||||||
|
canvas.toBlob((blob) => {
|
||||||
|
blob.lastModifiedDate = new Date()
|
||||||
|
blob.name = img.src.split("/").pop()
|
||||||
|
|
||||||
|
// remove the extension
|
||||||
|
blob.name = blob.name.split(".").slice(0, -1).join(".")
|
||||||
|
|
||||||
|
// set in the name the extension
|
||||||
|
blob.name = `${blob.name}.${finalExtension}`
|
||||||
|
|
||||||
|
blob.filename = blob.name
|
||||||
|
|
||||||
|
return resolve(new File([blob], blob.name, {
|
||||||
|
type: blob.type,
|
||||||
|
lastModified: blob.lastModifiedDate
|
||||||
|
}))
|
||||||
|
}, `image/${finalExtension}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return eventFile.getAsFile()
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user