Skip to content

Commit

Permalink
Add onPasteFile to Composer (native)
Browse files Browse the repository at this point in the history
  • Loading branch information
s77rt committed Aug 11, 2024
1 parent cfe382b commit 0e9cd9d
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 4 deletions.
19 changes: 18 additions & 1 deletion src/components/Composer/index.native.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type {MarkdownStyle} from '@expensify/react-native-live-markdown';
import type {ForwardedRef} from 'react';
import React, {useCallback, useMemo, useRef} from 'react';
import type {NativeSyntheticEvent, TextInput, TextInputChangeEventData} from 'react-native';
import type {NativeSyntheticEvent, TextInput, TextInputChangeEventData, TextInputPasteEventData} from 'react-native';
import {StyleSheet} from 'react-native';
import type {FileObject} from '@components/AttachmentModal';
import type {AnimatedMarkdownTextInputRef} from '@components/RNMarkdownTextInput';
import RNMarkdownTextInput from '@components/RNMarkdownTextInput';
import useMarkdownStyle from '@hooks/useMarkdownStyle';
Expand All @@ -20,6 +21,7 @@ const excludeReportMentionStyle: Array<keyof MarkdownStyle> = ['mentionReport'];
function Composer(
{
onClear: onClearProp = () => {},
onPasteFile = () => {},
isDisabled = false,
maxLines,
isComposerFullSize = false,
Expand Down Expand Up @@ -70,6 +72,20 @@ function Composer(
[onClearProp],
);

const pasteFile = useCallback(
(e: NativeSyntheticEvent<TextInputPasteEventData>) => {
const clipboardContent = e.nativeEvent.items[0];
if (clipboardContent.type === 'text/plain') {
return;
}
const fileURI = clipboardContent.data;
const fileName = fileURI.split('/').pop();
const file: FileObject = {uri: fileURI, name: fileName, type: clipboardContent.type};
onPasteFile(file);
},
[onPasteFile],
);

const maxHeightStyle = useMemo(() => StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), [StyleUtils, isComposerFullSize, maxLines]);
const composerStyle = useMemo(() => StyleSheet.flatten([style, textContainsOnlyEmojis ? styles.onlyEmojisTextLineHeight : {}]), [style, textContainsOnlyEmojis, styles]);

Expand All @@ -90,6 +106,7 @@ function Composer(
/* eslint-disable-next-line react/jsx-props-no-spreading */
{...props}
readOnly={isDisabled}
onPaste={pasteFile}
onBlur={(e) => {
if (!isFocused) {
// eslint-disable-next-line react-compiler/react-compiler
Expand Down
3 changes: 2 additions & 1 deletion src/components/Composer/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {NativeSyntheticEvent, StyleProp, TextInputProps, TextInputSelectionChangeEventData, TextStyle} from 'react-native';
import type {FileObject} from '@components/AttachmentModal';

type TextSelection = {
start: number;
Expand Down Expand Up @@ -37,7 +38,7 @@ type ComposerProps = Omit<TextInputProps, 'onClear'> & {
onChangeText?: (numberOfLines: string) => void;

/** Callback method to handle pasting a file */
onPasteFile?: (file: File) => void;
onPasteFile?: (file: FileObject) => void;

/** General styles to apply to the text input */
// eslint-disable-next-line react/forbid-prop-types
Expand Down
5 changes: 3 additions & 2 deletions src/stories/Composer.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {Meta} from '@storybook/react';
import {ExpensiMark} from 'expensify-common';
import React, {useState} from 'react';
import {Image, View} from 'react-native';
import type {FileObject} from '@components/AttachmentModal';
import Composer from '@components/Composer';
import type {ComposerProps} from '@components/Composer/types';
import RenderHTML from '@components/RenderHTML';
Expand All @@ -29,7 +30,7 @@ const parser = new ExpensiMark();

function Default(props: ComposerProps) {
const StyleUtils = useStyleUtils();
const [pastedFile, setPastedFile] = useState<File | null>(null);
const [pastedFile, setPastedFile] = useState<FileObject | null>(null);
const [comment, setComment] = useState(props.defaultValue);
const renderedHTML = parser.replace(comment ?? '');

Expand All @@ -53,7 +54,7 @@ function Default(props: ComposerProps) {
<View style={[defaultStyles.p5, defaultStyles.borderBottom, defaultStyles.borderRight, defaultStyles.borderTop, defaultStyles.flex1]}>
<Text style={[defaultStyles.mb2, defaultStyles.textLabelSupporting]}>Rendered Comment</Text>
{!!renderedHTML && <RenderHTML html={renderedHTML} />}
{!!pastedFile && (
{!!pastedFile && pastedFile instanceof File && (
<View style={defaultStyles.mv3}>
<Image
source={{uri: URL.createObjectURL(pastedFile)}}
Expand Down

0 comments on commit 0e9cd9d

Please sign in to comment.