-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to combine attachments and message text in a single activity #5084
Conversation
Please get sign off from designer. |
@compulim I've updated this PR to match the new design here: https://www.figma.com/file/ccXBJpMPQZCfE9nV8RjIfO/Test-Chat-for-Build?type=design&node-id=4269-20068&mode=design&t=K3emilPqELja2jEQ-0 |
setFiles(files); | ||
|
||
if (combineAttachmentsAndText) { | ||
current.blur(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't just blur the focus. It will impact accessibility.
const focus = useFocus(); | ||
const localize = useLocalizer(); | ||
const scrollToEnd = useScrollToEnd(); | ||
const styleToEmotionObject = useStyleToEmotionObject(); | ||
const submitErrorMessageId = useUniqueId('webchat__send-box__error-message-id'); | ||
const timeoutRef = useRef<readonly [Timeout, Timeout] | undefined>(undefined); | ||
const [{ combineAttachmentsAndText }] = useStyleOptions(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sort.
sendFiles(files, sendBoxValue); | ||
setFiles([]); | ||
setSendBoxValue(''); | ||
if (uploadButtonRef?.current) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't expose DOM element using hooks.
setFiles([]); | ||
setSendBoxValue(''); | ||
if (uploadButtonRef?.current) { | ||
uploadButtonRef.current.value = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why set the upload file value to null
when setFiles([])
remove all the files?
: undefined | ||
: // If combineAttachments is enabled, allow sending if either there is a message or files | ||
// Otherwise, require message text only | ||
(combineAttachmentsAndText && (sendBoxValue || files.length)) || (!combineAttachmentsAndText && sendBoxValue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic seems too complicated.
@@ -1,9 +1,9 @@ | |||
const SEND_FILES = 'WEB_CHAT/SEND_FILES'; | |||
|
|||
export default function sendFiles(files) { | |||
export default function sendFiles(files, text) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please convert this file to TypeScript.
role="button" | ||
tabIndex={-1} | ||
type="file" | ||
/> | ||
<IconButton alt={uploadFileString} aria-label={uploadFileString} disabled={disabled} onClick={handleClick}> | ||
<AttachmentIcon /> | ||
{/* When a file is attached, overlay the check icon */} | ||
{uploadButtonRef.current?.value && <CheckIcon />} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Build an icon, don't overlay.
const apiSubmitSendBox = useSubmitSendBox(); | ||
const [{ files, setFiles }] = useFiles(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sort.
apiSubmitSendBox, | ||
clearTimeout, | ||
combineAttachmentsAndText, | ||
files, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any changes to files
should not recreate the callback.
Use ref.
packages/api/src/StyleOptions.ts
Outdated
@@ -270,6 +270,10 @@ type StyleOptions = { | |||
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#multiple | |||
*/ | |||
uploadMultiple?: boolean; | |||
/** | |||
* Send the attachments and message text together as a single activity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Send the attachments and message text together as a single activity | |
* Send the attachments and message text together as a single activity. |
role="button" | ||
tabIndex={-1} | ||
type="file" | ||
/> | ||
<IconButton alt={uploadFileString} aria-label={uploadFileString} disabled={disabled} onClick={handleClick}> | ||
<AttachmentIcon /> | ||
{/* When a file is attached, overlay the check icon */} | ||
{uploadButtonRef.current?.value && <CheckIcon />} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using uploadButtonRef.current?.value
to check if a file is pending upload, is probably the reason why you need to set uploadButtonRef.current.value
to null
after send.
It seems useFiles
hook was added much later and not really used.
packages/api/src/hooks/useFiles.ts
Outdated
/** | ||
* This is a hook that returns the files and setFiles from the context. | ||
*/ | ||
export default function useFiles(): [{ files: File[]; setFiles: (files: File[]) => void }] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useFiles
should follow the pattern of other state hooks:
useFiles(): [readonly File[], (readonly File[]) => void]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to useSendBoxAttachments
.
packages/api/src/hooks/useFiles.ts
Outdated
import useWebChatAPIContext from './internal/useWebChatAPIContext'; | ||
|
||
/** | ||
* This is a hook that returns the files and setFiles from the context. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add more context.
packages/api/src/hooks/useFiles.ts
Outdated
/** | ||
* This is a hook that returns the files and setFiles from the context. | ||
*/ | ||
export default function useFiles(): [{ files: File[]; setFiles: (files: File[]) => void }] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name "file" is very vague. It could be files from an incoming activity. Or files to send out.
focus('sendBox'); | ||
return; | ||
} | ||
|
||
sendFiles(files); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use the SendBoxComposer.useSubmit()
hook to send files. This will simplify lots of code.
@@ -116,10 +132,33 @@ const SendBoxComposer = ({ children }: PropsWithChildren<{}>) => { | |||
]) as readonly [Timeout, Timeout]; | |||
} else { | |||
scrollToEndRef.current?.(); | |||
apiSubmitSendBox(); | |||
if (combineAttachmentsAndText && files.length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old logic use Redux to send, while the new logic use the hook directly. This is inconsistent.
@@ -116,10 +132,33 @@ const SendBoxComposer = ({ children }: PropsWithChildren<{}>) => { | |||
]) as readonly [Timeout, Timeout]; | |||
} else { | |||
scrollToEndRef.current?.(); | |||
apiSubmitSendBox(); | |||
if (combineAttachmentsAndText && files.length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few lines above, it already checked if there are any errors. One type of error is "no files attached".
The check here (files.length
) is meaningless.
packages/api/src/hooks/Composer.tsx
Outdated
@@ -540,6 +540,12 @@ const ComposerCore = ({ | |||
[scrollToEndButtonMiddleware] | |||
); | |||
|
|||
// For useFiles hook | |||
const [files, setFiles] = useState<File[]>([]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using useState
here, instead of Redux, will complicate the code later.
In your latter code, sometimes, it call useSendFiles
, and in other times, it call, useAPISubmitSendBox
. This complicate testing.
If the attachment list is maintained inside Redux, the latter code will not need to call useSendFiles
.
We could move away from Redux too. But we should select one path. Doing 1 thing with 2 ways will slowly introduce branching/versioning issue.
@@ -12,14 +12,14 @@ type PostActivityFile = { | |||
url: string; | |||
}; | |||
|
|||
export default function useSendFiles(): (files: PostActivityFile[]) => void { | |||
export default function useSendFiles(): (files: PostActivityFile[], text?: string) => void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When text
argument is introduced to useSendFiles
, it almost act the same as useSendMessage
.
Instead of adding text
argument to useSendFiles
, should add attachments
to useSendMessage
instead. Then, useSendFiles
can be deprecated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added deprecation notes. Still need a warn once.
Obsoleted by PR #5123. |
Changelog Entry
sendAttachmentOn
style option to send attachments and text in a single activity, by @ms-jbDescription
Added a new
styleOption
that enables attachments and message text to be sent in a single activity. If enabled, uploaded files are retained until the Send button is pressed to allow for message text to be optionally included. Standalone text works as before.Design
Sample implementation:
Specific Changes
combineAttachmentsAndText
style option to send attachments and text in a single activityCHANGELOG.md
Review Checklist
z-index
)package.json
andpackage-lock.json
reviewed