fix drop target
This commit is contained in:
parent
3849d6b447
commit
b2b849695b
@ -15,7 +15,7 @@
|
|||||||
// TODO: make this nicer
|
// TODO: make this nicer
|
||||||
color: theme.$text-normal;
|
color: theme.$text-normal;
|
||||||
background-color: theme.$background-primary;
|
background-color: theme.$background-primary;
|
||||||
padding: 16px;
|
padding: 32px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -28,9 +28,15 @@
|
|||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drop-message {
|
.drop-description {
|
||||||
font-size: 2em;
|
|
||||||
color: theme.$header-primary;
|
color: theme.$header-primary;
|
||||||
|
.drop-title {
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.drop-message {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ $borderRadius: 8px;
|
|||||||
.attachment-preview {
|
.attachment-preview {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 16px 16px 0 16px;
|
margin: 16px 16px 0 16px;
|
||||||
padding: 8px;
|
padding: 12px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
max-width: calc(100% - 32px);
|
max-width: calc(100% - 32px);
|
||||||
@ -40,6 +40,8 @@ $borderRadius: 8px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
|
color: theme.$interactive-hover;
|
||||||
|
/* font-weight: 600; */
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -6,6 +6,7 @@ const LOG = Logger.create(__filename, electronConsole);
|
|||||||
import React, { Dispatch, DragEvent, FC, SetStateAction, useCallback, useRef } from 'react';
|
import React, { Dispatch, DragEvent, FC, SetStateAction, useCallback, useRef } from 'react';
|
||||||
|
|
||||||
export interface FileDropTargetProps {
|
export interface FileDropTargetProps {
|
||||||
|
title: string;
|
||||||
message: string;
|
message: string;
|
||||||
setBuff: Dispatch<SetStateAction<Buffer | null>>;
|
setBuff: Dispatch<SetStateAction<Buffer | null>>;
|
||||||
setName: Dispatch<SetStateAction<string | null>>;
|
setName: Dispatch<SetStateAction<string | null>>;
|
||||||
@ -13,7 +14,7 @@ export interface FileDropTargetProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const FileDropTarget: FC<FileDropTargetProps> = (props: FileDropTargetProps) => {
|
const FileDropTarget: FC<FileDropTargetProps> = (props: FileDropTargetProps) => {
|
||||||
const { setBuff, setName, close, message } = props;
|
const { setBuff, setName, close, title, message } = props;
|
||||||
|
|
||||||
const rootRef = useRef<HTMLDivElement>(null);
|
const rootRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@ -64,7 +65,10 @@ const FileDropTarget: FC<FileDropTargetProps> = (props: FileDropTargetProps) =>
|
|||||||
<div className="file-drop" ref={rootRef} onDrop={onDrop} onDragOver={onDragOver} onDragLeave={onDragLeave}>
|
<div className="file-drop" ref={rootRef} onDrop={onDrop} onDragOver={onDragOver} onDragLeave={onDragLeave}>
|
||||||
<div className="panel">
|
<div className="panel">
|
||||||
<img className="drop-icon" src="./img/file-improved.svg" alt="file" />
|
<img className="drop-icon" src="./img/file-improved.svg" alt="file" />
|
||||||
<div className="drop-message">{message}</div>
|
<div className="drop-description">
|
||||||
|
<div className="drop-title">{title}</div>
|
||||||
|
<div className="drop-message">{message}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -21,7 +21,7 @@ export interface ImageContextMenuProps {
|
|||||||
const ImageContextMenu: FC<ImageContextMenuProps> = (props: ImageContextMenuProps) => {
|
const ImageContextMenu: FC<ImageContextMenuProps> = (props: ImageContextMenuProps) => {
|
||||||
const { relativeToPos, close, resourceName, resourceBuff, isPreview } = props;
|
const { relativeToPos, close, resourceName, resourceBuff, isPreview } = props;
|
||||||
|
|
||||||
const previewText = isPreview ? ' Preview' : '';
|
const previewText = isPreview ? ' Preview' : ' Image';
|
||||||
|
|
||||||
// TODO: Integrate shaking
|
// TODO: Integrate shaking
|
||||||
|
|
||||||
@ -44,23 +44,33 @@ const ImageContextMenu: FC<ImageContextMenuProps> = (props: ImageContextMenuProp
|
|||||||
},
|
},
|
||||||
[resourceBuff],
|
[resourceBuff],
|
||||||
{
|
{
|
||||||
start: 'Copy Image' + previewText,
|
start: 'Copy ' + previewText,
|
||||||
pending: 'Copying' + previewText,
|
pending: 'Copying' + previewText,
|
||||||
error: 'Copy Failed. Click to Try Again',
|
error: 'Copy Failed. Click to Try Again',
|
||||||
done: 'Copied to Clipboard',
|
done: 'Copied to Clipboard',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const [saveCallable, saveText, _saveShaking] = useDownloadButton(resourceName + (isPreview ? '-preview.jpg' : ''), async () => resourceBuff, [resourceBuff], {
|
const [saveCallable, saveText, _saveShaking] = useDownloadButton(
|
||||||
start: 'Save Image' + previewText,
|
resourceName + (isPreview ? '-preview.jpg' : ''),
|
||||||
pendingSave: 'Saving' + previewText + '...',
|
async () => resourceBuff,
|
||||||
errorSave: 'Save Failed. Click to Try Again',
|
[resourceBuff],
|
||||||
});
|
{
|
||||||
|
start: 'Save ' + previewText,
|
||||||
|
pendingSave: 'Saving' + previewText + '...',
|
||||||
|
errorSave: 'Save Failed. Click to Try Again',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const alignment = useMemo(() => ({ top: 'centerY', left: 'centerX' }), []);
|
const alignment = useMemo(() => ({ top: 'centerY', left: 'centerX' }), []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu alignment={alignment} relativeToPos={relativeToPos} realignDeps={[copyText, saveText]} close={close}>
|
<ContextMenu
|
||||||
|
alignment={alignment}
|
||||||
|
relativeToPos={relativeToPos}
|
||||||
|
realignDeps={[copyText, saveText]}
|
||||||
|
close={close}
|
||||||
|
>
|
||||||
<div className="image">
|
<div className="image">
|
||||||
<div className="item copy-image" onClick={copyCallable}>
|
<div className="item copy-image" onClick={copyCallable}>
|
||||||
{copyText}
|
{copyText}
|
||||||
|
@ -573,6 +573,7 @@ export function useContextHover(
|
|||||||
|
|
||||||
/** creates a drop target element that will appear when you drag a file over the document */
|
/** creates a drop target element that will appear when you drag a file over the document */
|
||||||
export function useDocumentDropTarget(
|
export function useDocumentDropTarget(
|
||||||
|
title: string,
|
||||||
message: string,
|
message: string,
|
||||||
setBuff: Dispatch<SetStateAction<Buffer | null>>,
|
setBuff: Dispatch<SetStateAction<Buffer | null>>,
|
||||||
setName: Dispatch<SetStateAction<string | null>>,
|
setName: Dispatch<SetStateAction<string | null>>,
|
||||||
@ -599,8 +600,16 @@ export function useDocumentDropTarget(
|
|||||||
|
|
||||||
const dropTarget = useMemo(() => {
|
const dropTarget = useMemo(() => {
|
||||||
if (!dragEnabled) return null;
|
if (!dragEnabled) return null;
|
||||||
return <FileDropTarget close={closeDragOverlay} message={message} setBuff={setBuff} setName={setName} />;
|
return (
|
||||||
}, [closeDragOverlay, dragEnabled, message, setBuff, setName]);
|
<FileDropTarget
|
||||||
|
close={closeDragOverlay}
|
||||||
|
title={title}
|
||||||
|
message={message}
|
||||||
|
setBuff={setBuff}
|
||||||
|
setName={setName}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}, [closeDragOverlay, dragEnabled, title, message, setBuff, setName]);
|
||||||
|
|
||||||
return [dropTarget];
|
return [dropTarget];
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,23 @@
|
|||||||
import React, { ClipboardEvent, FC, FormEvent, KeyboardEvent, RefObject, useCallback, useMemo, useRef, useState } from 'react';
|
import React, {
|
||||||
|
ClipboardEvent,
|
||||||
|
FC,
|
||||||
|
FormEvent,
|
||||||
|
KeyboardEvent,
|
||||||
|
RefObject,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import { Channel } from '../../data-types';
|
import { Channel } from '../../data-types';
|
||||||
import CombinedGuild from '../../guild-combined';
|
import CombinedGuild from '../../guild-combined';
|
||||||
import BaseElements from '../require/base-elements';
|
import BaseElements from '../require/base-elements';
|
||||||
import { useAsyncVoidCallback, useDocumentDropTarget, useIsMountedRef, useOneTimeAsyncAction } from '../require/react-helper';
|
import {
|
||||||
|
useAsyncVoidCallback,
|
||||||
|
useDocumentDropTarget,
|
||||||
|
useIsMountedRef,
|
||||||
|
useOneTimeAsyncAction,
|
||||||
|
} from '../require/react-helper';
|
||||||
import * as FileType from 'file-type';
|
import * as FileType from 'file-type';
|
||||||
import ElementsUtil from '../require/elements-util';
|
import ElementsUtil from '../require/elements-util';
|
||||||
import FileInput from '../components/input-file';
|
import FileInput from '../components/input-file';
|
||||||
@ -66,7 +81,12 @@ const SendMessage: FC<SendMessageProps> = (props: SendMessageProps) => {
|
|||||||
|
|
||||||
// TODO: Deal with errors (toasts are probably the best way)
|
// TODO: Deal with errors (toasts are probably the best way)
|
||||||
if (attachmentBuff && attachmentName) {
|
if (attachmentBuff && attachmentName) {
|
||||||
await guild.requestSendMessageWithResource(channel.id, text === '' ? null : text, attachmentBuff, attachmentName);
|
await guild.requestSendMessageWithResource(
|
||||||
|
channel.id,
|
||||||
|
text === '' ? null : text,
|
||||||
|
attachmentBuff,
|
||||||
|
attachmentName,
|
||||||
|
);
|
||||||
if (!isMounted.current) return;
|
if (!isMounted.current) return;
|
||||||
setAttachmentBuff(null);
|
setAttachmentBuff(null);
|
||||||
setAttachmentName(null);
|
setAttachmentName(null);
|
||||||
@ -122,11 +142,22 @@ const SendMessage: FC<SendMessageProps> = (props: SendMessageProps) => {
|
|||||||
setAttachmentName(null);
|
setAttachmentName(null);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const [attachmentDropTarget] = useDocumentDropTarget('Upload to #' + channel.name, setAttachmentBuff, setAttachmentName);
|
const [attachmentDropTarget] = useDocumentDropTarget(
|
||||||
|
'Drop to Attach',
|
||||||
|
'#' + channel.name,
|
||||||
|
setAttachmentBuff,
|
||||||
|
setAttachmentName,
|
||||||
|
);
|
||||||
|
|
||||||
const attachmentPreview = useMemo(() => {
|
const attachmentPreview = useMemo(() => {
|
||||||
if (!attachmentBuff || !attachmentName) return null;
|
if (!attachmentBuff || !attachmentName) return null;
|
||||||
return <AttachmentPreview attachmentBuff={attachmentBuff} attachmentName={attachmentName} remove={removeAttachment} />;
|
return (
|
||||||
|
<AttachmentPreview
|
||||||
|
attachmentBuff={attachmentBuff}
|
||||||
|
attachmentName={attachmentName}
|
||||||
|
remove={removeAttachment}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}, [attachmentBuff, attachmentName, removeAttachment]);
|
}, [attachmentBuff, attachmentName, removeAttachment]);
|
||||||
|
|
||||||
// WARNING: The types on this are funky because of react's lack of explicit support for 'plaintext-only'
|
// WARNING: The types on this are funky because of react's lack of explicit support for 'plaintext-only'
|
||||||
@ -149,7 +180,15 @@ const SendMessage: FC<SendMessageProps> = (props: SendMessageProps) => {
|
|||||||
{BaseElements.SEND_MESSAGE_ATTACH}
|
{BaseElements.SEND_MESSAGE_ATTACH}
|
||||||
</FileInput>
|
</FileInput>
|
||||||
</div>
|
</div>
|
||||||
<div ref={contentEditableRef} className={textInputClassName} contentEditable={contentEditableType} data-placeholder={`Message #${channel.name}`} onInput={onTextInput} onKeyDown={onTextKeyDown} onPaste={onPaste} />
|
<div
|
||||||
|
ref={contentEditableRef}
|
||||||
|
className={textInputClassName}
|
||||||
|
contentEditable={contentEditableType}
|
||||||
|
data-placeholder={`Message #${channel.name}`}
|
||||||
|
onInput={onTextInput}
|
||||||
|
onKeyDown={onTextKeyDown}
|
||||||
|
onPaste={onPaste}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{attachmentDropTarget}
|
{attachmentDropTarget}
|
||||||
|
@ -9,7 +9,5 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="preload">
|
<body class="preload">
|
||||||
<div id="react-root"></div>
|
<div id="react-root"></div>
|
||||||
<!-- it's important that this comes at the end so that these take prescedence over the other absolutely positioned objects-->
|
|
||||||
<div id="react-overlays"></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user