mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-11 03:24:16 +00:00
improve PostCreator
uploader
This commit is contained in:
parent
4b9dfe2919
commit
8a9c802dcb
@ -18,14 +18,13 @@ const DEFAULT_POST_POLICY = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default (props) => {
|
export default (props) => {
|
||||||
const api = window.app.api.withEndpoints("main")
|
const api = window.app.cores.api.withEndpoints("main")
|
||||||
|
|
||||||
const creatorRef = React.useRef(null)
|
const creatorRef = React.useRef(null)
|
||||||
|
|
||||||
const [pending, setPending] = React.useState([])
|
const [pending, setPending] = React.useState([])
|
||||||
const [loading, setLoading] = React.useState(false)
|
const [loading, setLoading] = React.useState(false)
|
||||||
const [uploaderVisible, setUploaderVisible] = React.useState(false)
|
const [uploaderVisible, setUploaderVisible] = React.useState(false)
|
||||||
const [focused, setFocused] = React.useState(false)
|
|
||||||
|
|
||||||
const [postMessage, setPostMessage] = React.useState("")
|
const [postMessage, setPostMessage] = React.useState("")
|
||||||
const [postAttachments, setPostAttachments] = React.useState([])
|
const [postAttachments, setPostAttachments] = React.useState([])
|
||||||
@ -45,12 +44,25 @@ export default (props) => {
|
|||||||
setPostingPolicy(policy)
|
setPostingPolicy(policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canSubmit = () => {
|
||||||
|
const messageLengthValid = postMessage.length !== 0 && postMessage.length < postingPolicy.maxMessageLength
|
||||||
|
|
||||||
|
if (pending.length !== 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!messageLengthValid && postAttachments.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
if (!canSubmit()) return
|
if (!canSubmit()) return
|
||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setUploaderVisible(false)
|
setUploaderVisible(false)
|
||||||
setFocused(false)
|
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
message: postMessage,
|
message: postMessage,
|
||||||
@ -78,7 +90,7 @@ export default (props) => {
|
|||||||
|
|
||||||
const onUploadFile = async (req) => {
|
const onUploadFile = async (req) => {
|
||||||
// hide uploader
|
// hide uploader
|
||||||
//setUploaderVisible(false)
|
toogleUploaderVisibility(false)
|
||||||
|
|
||||||
// get file data
|
// get file data
|
||||||
const file = req.file
|
const file = req.file
|
||||||
@ -103,20 +115,6 @@ export default (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const canSubmit = () => {
|
|
||||||
const messageLengthValid = postMessage.length !== 0 && postMessage.length < postingPolicy.maxMessageLength
|
|
||||||
|
|
||||||
if (pending.length !== 0) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!messageLengthValid && postAttachments.length === 0) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeAttachment = (file_uid) => {
|
const removeAttachment = (file_uid) => {
|
||||||
setPostAttachments(postAttachments.filter((file) => file.uid !== file_uid))
|
setPostAttachments(postAttachments.filter((file) => file.uid !== file_uid))
|
||||||
}
|
}
|
||||||
@ -145,22 +143,13 @@ export default (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDrop = (event) => {
|
|
||||||
event.preventDefault()
|
|
||||||
setUploaderVisible(true)
|
|
||||||
|
|
||||||
console.log(event)
|
|
||||||
|
|
||||||
const files = event.dataTransfer.files
|
|
||||||
|
|
||||||
console.log(files)
|
|
||||||
}
|
|
||||||
|
|
||||||
const onUploaderChange = (change) => {
|
const onUploaderChange = (change) => {
|
||||||
setFileList(change.fileList)
|
setFileList(change.fileList)
|
||||||
|
|
||||||
switch (change.file.status) {
|
switch (change.file.status) {
|
||||||
case "uploading": {
|
case "uploading": {
|
||||||
|
toogleUploaderVisibility(false)
|
||||||
|
|
||||||
setPending([...pending, change.file.uid])
|
setPending([...pending, change.file.uid])
|
||||||
|
|
||||||
uploaderScrollToEnd()
|
uploaderScrollToEnd()
|
||||||
@ -175,6 +164,7 @@ export default (props) => {
|
|||||||
// update post data
|
// update post data
|
||||||
addAttachment(change.file.response.files)
|
addAttachment(change.file.response.files)
|
||||||
|
|
||||||
|
// scroll to end
|
||||||
uploaderScrollToEnd()
|
uploaderScrollToEnd()
|
||||||
|
|
||||||
break
|
break
|
||||||
@ -200,12 +190,14 @@ export default (props) => {
|
|||||||
setPostMessage(event.target.value)
|
setPostMessage(event.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggleUploader = (to) => {
|
const toogleUploaderVisibility = (to) => {
|
||||||
setUploaderVisible(to ?? !uploaderVisible)
|
to = to ?? !uploaderVisible
|
||||||
}
|
|
||||||
|
|
||||||
const toggleFocus = (to) => {
|
if (to === uploaderVisible) {
|
||||||
setFocused(to ?? !focused)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setUploaderVisible(to ?? !uploaderVisible)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyDown = (e) => {
|
const handleKeyDown = (e) => {
|
||||||
@ -221,7 +213,6 @@ export default (props) => {
|
|||||||
const handlePaste = ({ clipboardData }) => {
|
const handlePaste = ({ clipboardData }) => {
|
||||||
if (clipboardData && clipboardData.items.length > 0) {
|
if (clipboardData && clipboardData.items.length > 0) {
|
||||||
const isValidFormat = (fileType) => DEFAULT_ACCEPTED_FILES.includes(fileType)
|
const isValidFormat = (fileType) => DEFAULT_ACCEPTED_FILES.includes(fileType)
|
||||||
toggleUploader(true)
|
|
||||||
|
|
||||||
for (let index = 0; index < clipboardData.items.length; index++) {
|
for (let index = 0; index < clipboardData.items.length; index++) {
|
||||||
if (!isValidFormat(clipboardData.items[index].type)) {
|
if (!isValidFormat(clipboardData.items[index].type)) {
|
||||||
@ -276,13 +267,50 @@ export default (props) => {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDrag = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
console.log(event)
|
||||||
|
|
||||||
|
if (event.type === "dragenter") {
|
||||||
|
toogleUploaderVisibility(true)
|
||||||
|
} else if (event.type === "dragleave") {
|
||||||
|
// check if mouse is over the uploader or outside the creatorRef
|
||||||
|
if (uploaderVisible && !creatorRef.current.contains(event.target)) {
|
||||||
|
toogleUploaderVisibility(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUploadClick = () => {
|
||||||
|
// create a new dialog
|
||||||
|
const dialog = document.createElement("input")
|
||||||
|
|
||||||
|
// set the dialog type to file
|
||||||
|
dialog.type = "file"
|
||||||
|
|
||||||
|
// set the dialog accept to the accepted files
|
||||||
|
dialog.accept = postingPolicy.acceptedMimeTypes
|
||||||
|
|
||||||
|
dialog.multiple = true
|
||||||
|
|
||||||
|
// add a listener to the dialog
|
||||||
|
dialog.addEventListener("change", (event) => {
|
||||||
|
console.log(event)
|
||||||
|
})
|
||||||
|
|
||||||
|
// click the dialog
|
||||||
|
dialog.click()
|
||||||
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
fetchUploadPolicy()
|
fetchUploadPolicy()
|
||||||
|
|
||||||
creatorRef.current.addEventListener("paste", handlePaste)
|
document.addEventListener("paste", handlePaste)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
creatorRef.current.removeEventListener("paste", handlePaste)
|
document.removeEventListener("paste", handlePaste)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@ -292,15 +320,10 @@ export default (props) => {
|
|||||||
}, [pending])
|
}, [pending])
|
||||||
|
|
||||||
return <div
|
return <div
|
||||||
className="postCreator"
|
className={"postCreator"}
|
||||||
ref={creatorRef}
|
ref={creatorRef}
|
||||||
onDrop={onDrop}
|
onDragEnter={handleDrag}
|
||||||
onMouseEnter={() => {
|
onDragLeave={handleDrag}
|
||||||
toggleFocus(true)
|
|
||||||
}}
|
|
||||||
onMouseLeave={() => {
|
|
||||||
toggleFocus(false)
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="textInput">
|
<div className="textInput">
|
||||||
<div className="avatar">
|
<div className="avatar">
|
||||||
@ -327,36 +350,46 @@ export default (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classnames("actions", { ["hided"]: !focused && !uploaderVisible })}>
|
<div className={classnames("uploader", { ["visible"]: uploaderVisible })}>
|
||||||
<div>
|
<antd.Upload.Dragger
|
||||||
<antd.Button
|
openFileDialogOnClick={false}
|
||||||
type={uploaderVisible ? "default" : "primary"}
|
|
||||||
disabled={loading}
|
|
||||||
onClick={() => {
|
|
||||||
toggleUploader()
|
|
||||||
}}
|
|
||||||
icon={<Icons.Upload />}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={classnames("uploader", { ["hided"]: !uploaderVisible })}>
|
|
||||||
<antd.Upload
|
|
||||||
maxCount={postingPolicy.maximunFilesPerRequest}
|
maxCount={postingPolicy.maximunFilesPerRequest}
|
||||||
onChange={onUploaderChange}
|
onChange={onUploaderChange}
|
||||||
customRequest={onUploadFile}
|
customRequest={onUploadFile}
|
||||||
listType="picture-card"
|
|
||||||
accept={postingPolicy.acceptedMimeTypes}
|
accept={postingPolicy.acceptedMimeTypes}
|
||||||
itemRender={renderUploadPreviewItem}
|
|
||||||
fileList={fileList}
|
fileList={fileList}
|
||||||
|
listType="picture-card"
|
||||||
|
itemRender={renderUploadPreviewItem}
|
||||||
multiple
|
multiple
|
||||||
>
|
>
|
||||||
<Icons.Plus />
|
<div className="hint">
|
||||||
</antd.Upload>
|
<h3>Drag and drop files here</h3>
|
||||||
|
<span>Max {humanSize.fromBytes(postingPolicy.maximumFileSize)}</span>
|
||||||
|
</div>
|
||||||
|
</antd.Upload.Dragger>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="hint">
|
<div className="actions">
|
||||||
<span>Max {humanSize.fromBytes(postingPolicy.maximumFileSize)}</span>
|
<antd.Button
|
||||||
</div>
|
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>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,28 +1,35 @@
|
|||||||
.postCreator {
|
.postCreator {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 15px;
|
z-index: 55;
|
||||||
background-color: var(--background-color-accent);
|
|
||||||
|
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
|
|
||||||
|
background-color: var(--background-color-accent);
|
||||||
|
padding: 15px;
|
||||||
|
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
height: 40px;
|
width: 100%;
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
transition: all 150ms ease-in-out;
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
color: var(--text-color) !important;
|
color: var(--text-color) !important;
|
||||||
|
|
||||||
>div {
|
.ant-btn {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
|
||||||
@ -31,75 +38,112 @@
|
|||||||
color: var(--text-color) !important;
|
color: var(--text-color) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hided {
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.uploader {
|
.uploader {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
overflow-x: scroll;
|
||||||
|
|
||||||
transition: all 150ms ease-in-out;
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
border: 1px solid var(--border-color);
|
&.visible {
|
||||||
padding: 10px;
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
opacity: 1;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
>div {
|
z-index: 150;
|
||||||
margin-left: 10px;
|
|
||||||
font-size: 1rem;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hided {
|
|
||||||
height: 0px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.ant-upload {
|
|
||||||
span {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.ant-upload-select-picture-card {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-upload.ant-upload-select-picture-card {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-self: center;
|
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
width: 10vw;
|
border: 0;
|
||||||
height: 10vw;
|
|
||||||
|
|
||||||
margin-bottom: 0;
|
.ant-upload-drag {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
border-color: var(--border-color);
|
opacity: 1;
|
||||||
background-color: transparent !important;
|
}
|
||||||
|
|
||||||
|
.ant-upload-list {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-upload-list-picture-card .ant-upload-list-item-uploading.ant-upload-list-item {
|
.ant-upload-drag {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-upload-wrapper {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
background-color: transparent;
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.ant-upload-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
.ant-upload-list-item-container {
|
||||||
|
background-color: black;
|
||||||
|
|
||||||
|
width: 10vw;
|
||||||
|
height: 10vw;
|
||||||
|
|
||||||
|
margin-left: 10px;
|
||||||
|
|
||||||
|
border-radius: 7px;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-upload-list-item-actions {
|
.ant-upload-list-item-actions {
|
||||||
@ -113,30 +157,7 @@
|
|||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-upload-list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-upload-list-picture-card-container {
|
|
||||||
width: 10vw;
|
|
||||||
height: 10vw;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
@ -144,9 +165,6 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
|
||||||
width: 10vw;
|
|
||||||
height: 10vw;
|
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@ -235,9 +253,10 @@
|
|||||||
|
|
||||||
.textInput {
|
.textInput {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: height 150ms ease-in-out;
|
|
||||||
background-color: var(--background-color-accent);
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
@ -256,8 +275,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-input {
|
textarea {
|
||||||
color: var(--background-color-contrast);
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea::placeholder {
|
||||||
|
color: rgb(var(--bg_color_4));
|
||||||
}
|
}
|
||||||
|
|
||||||
.textArea {
|
.textArea {
|
||||||
@ -301,12 +324,12 @@
|
|||||||
background-color: var(--background-color-accent);
|
background-color: var(--background-color-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-input:hover {
|
|
||||||
border-color: #1890ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-input-affix-wrapper {
|
.ant-input-affix-wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user