diff --git a/src/CONST.js b/src/CONST.js
index b98cf6cf70ec..d1b6a5b52e37 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -171,6 +171,13 @@ const CONST = {
         PHONE_E164_PLUS: /^\+?[1-9]\d{1,14}$/,
         NON_ALPHA_NUMERIC: /[^A-Za-z0-9+]/g,
     },
+
+    GROWL: {
+        SUCCESS: 'success',
+        ERROR: 'error',
+        WARNING: 'warning',
+        DURATION: 2000,
+    },
 };
 
 export default CONST;
diff --git a/src/Expensify.js b/src/Expensify.js
index 6ac9b68a25ea..431db2e8d9a1 100644
--- a/src/Expensify.js
+++ b/src/Expensify.js
@@ -16,6 +16,8 @@ import styles from './styles/styles';
 import PushNotification from './libs/Notification/PushNotification';
 import UpdateAppModal from './components/UpdateAppModal';
 import Visibility from './libs/Visibility';
+import GrowlNotification from './components/GrowlNotification';
+import {growlRef} from './libs/Growl';
 
 // Initialize the store when the app loads for the first time
 Onyx.init({
@@ -156,6 +158,7 @@ class Expensify extends PureComponent {
         }
         return (
             <>
+                <GrowlNotification ref={growlRef} />
                 {/* We include the modal for showing a new update at the top level so the option is always present. */}
                 {this.props.updateAvailable ? <UpdateAppModal /> : null}
                 <NavigationRoot authenticated={Boolean(this.getAuthToken())} />
diff --git a/src/libs/GrowlNotification/GrowlNotificationContainer/GrowlNotificationContainerPropTypes.js b/src/components/GrowlNotification/GrowlNotificationContainer/GrowlNotificationContainerPropTypes.js
similarity index 82%
rename from src/libs/GrowlNotification/GrowlNotificationContainer/GrowlNotificationContainerPropTypes.js
rename to src/components/GrowlNotification/GrowlNotificationContainer/GrowlNotificationContainerPropTypes.js
index fb5d017e984a..1343c11821c1 100644
--- a/src/libs/GrowlNotification/GrowlNotificationContainer/GrowlNotificationContainerPropTypes.js
+++ b/src/components/GrowlNotification/GrowlNotificationContainer/GrowlNotificationContainerPropTypes.js
@@ -1,6 +1,6 @@
 import {Animated} from 'react-native';
 import PropTypes from 'prop-types';
-import {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
+import {windowDimensionsPropTypes} from '../../withWindowDimensions';
 
 const propTypes = {
     /** GrowlNotification content */
diff --git a/src/libs/GrowlNotification/GrowlNotificationContainer/index.js b/src/components/GrowlNotification/GrowlNotificationContainer/index.js
similarity index 89%
rename from src/libs/GrowlNotification/GrowlNotificationContainer/index.js
rename to src/components/GrowlNotification/GrowlNotificationContainer/index.js
index 82b0b68cbf6a..b1b051107ab0 100644
--- a/src/libs/GrowlNotification/GrowlNotificationContainer/index.js
+++ b/src/components/GrowlNotification/GrowlNotificationContainer/index.js
@@ -1,7 +1,7 @@
 import React from 'react';
 import {Animated} from 'react-native';
 import styles from '../../../styles/styles';
-import withWindowDimensions from '../../../components/withWindowDimensions';
+import withWindowDimensions from '../../withWindowDimensions';
 import propTypes from './GrowlNotificationContainerPropTypes';
 
 const GrowlNotificationContainer = ({children, translateY, isSmallScreenWidth}) => (
diff --git a/src/components/GrowlNotification/GrowlNotificationContainer/index.native.js b/src/components/GrowlNotification/GrowlNotificationContainer/index.native.js
new file mode 100644
index 000000000000..f718430f27b7
--- /dev/null
+++ b/src/components/GrowlNotification/GrowlNotificationContainer/index.native.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import {Animated} from 'react-native';
+import {SafeAreaInsetsContext} from 'react-native-safe-area-context';
+import styles, {getSafeAreaPadding} from '../../../styles/styles';
+import propTypes from './GrowlNotificationContainerPropTypes';
+
+const GrowlNotificationContainer = ({children, translateY}) => (
+    <SafeAreaInsetsContext.Consumer>
+        {insets => (
+            <Animated.View
+                style={[
+                    styles.growlNotificationContainer,
+                    getSafeAreaPadding(insets),
+                    styles.growlNotificationTranslateY(translateY),
+                ]}
+            >
+                {children}
+            </Animated.View>
+        )}
+    </SafeAreaInsetsContext.Consumer>
+);
+
+GrowlNotificationContainer.propTypes = propTypes;
+
+export default GrowlNotificationContainer;
diff --git a/src/libs/GrowlNotification/index.js b/src/components/GrowlNotification/index.js
similarity index 90%
rename from src/libs/GrowlNotification/index.js
rename to src/components/GrowlNotification/index.js
index 16f232b498aa..c15ed036e5cf 100644
--- a/src/libs/GrowlNotification/index.js
+++ b/src/components/GrowlNotification/index.js
@@ -6,21 +6,22 @@ import {
     Directions, FlingGestureHandler, State, TouchableWithoutFeedback,
 } from 'react-native-gesture-handler';
 import colors from '../../styles/colors';
-import Icon from '../../components/Icon';
-import {Checkmark, Exclamation} from '../../components/Icon/Expensicons';
+import Icon from '../Icon';
+import {Checkmark, Exclamation} from '../Icon/Expensicons';
 import styles from '../../styles/styles';
 import GrowlNotificationContainer from './GrowlNotificationContainer';
+import CONST from '../../CONST';
 
 const types = {
-    success: {
+    [CONST.GROWL.SUCCESS]: {
         icon: Checkmark,
         iconColor: colors.green,
     },
-    error: {
+    [CONST.GROWL.ERROR]: {
         icon: Exclamation,
         iconColor: colors.red,
     },
-    warning: {
+    [CONST.GROWL.WARNING]: {
         icon: Exclamation,
         iconColor: colors.yellow,
     },
@@ -47,9 +48,9 @@ class GrowlNotification extends Component {
      *
      * @param {String} bodyText
      * @param {String} type
-     * @param {Number} duration - 2000
+     * @param {Number} duration
     */
-    show(bodyText, type, duration = 2000) {
+    show(bodyText, type, duration) {
         this.setState({
             bodyText,
             type,
diff --git a/src/components/TextInputFocusable/index.js b/src/components/TextInputFocusable/index.js
index 4f4ca39b0c60..48329e4a5530 100755
--- a/src/components/TextInputFocusable/index.js
+++ b/src/components/TextInputFocusable/index.js
@@ -3,7 +3,9 @@ import {TextInput, StyleSheet} from 'react-native';
 import PropTypes from 'prop-types';
 import _ from 'underscore';
 import withLocalize, {withLocalizePropTypes} from '../withLocalize';
+import Growl from '../../libs/Growl';
 import themeColors from '../../styles/themes/default';
+import CONST from '../../CONST';
 
 const propTypes = {
     /** Maximum number of lines in the text input */
@@ -108,6 +110,11 @@ class TextInputFocusable extends React.Component {
                 end: initialValue.length,
             },
         };
+        this.selection = {
+            start: initialValue.length,
+            end: initialValue.length,
+        };
+        this.saveSelection = this.saveSelection.bind(this);
     }
 
     componentDidMount() {
@@ -176,6 +183,17 @@ class TextInputFocusable extends React.Component {
         return newNumberOfLines;
     }
 
+    /**
+     * Keeps track of user cursor position on the Composer
+     *
+     * @param {{nativeEvent: {selection: any}}} event
+     * @memberof TextInputFocusable
+     */
+    saveSelection(event) {
+        this.selection = event.nativeEvent.selection;
+        this.props.onSelectionChange(event);
+    }
+
     /**
      * Check the paste event for an attachment, parse the data and
      * call onPasteFile from props with the selected file
@@ -185,6 +203,7 @@ class TextInputFocusable extends React.Component {
     checkForAttachment(event) {
         const {files, types} = event.clipboardData;
         const TEXT_HTML = 'text/html';
+        const TEXT_PLAIN = 'text/plain';
         if (files.length > 0) {
             // Prevent the default so we do not post the file name into the text box
             event.preventDefault();
@@ -192,6 +211,7 @@ class TextInputFocusable extends React.Component {
         } else if (types.includes(TEXT_HTML)) {
             const domparser = new DOMParser();
             const embededImages = domparser.parseFromString(event.clipboardData.getData(TEXT_HTML), TEXT_HTML).images;
+            const pastedText = event.clipboardData.getData(TEXT_PLAIN);
             if (embededImages.length > 0) {
                 event.preventDefault();
                 fetch(embededImages[0].src)
@@ -208,9 +228,23 @@ class TextInputFocusable extends React.Component {
                         return new File([x], `pasted_image.${extension}`, {});
                     })
                     .then(this.props.onPasteFile)
-                    .catch((error) => {
+                    .catch(() => {
                         const errorDesc = this.props.translate('textInputFocusable.problemGettingImageYouPasted');
-                        alert(`${errorDesc}. \n${error.message}`);
+                        Growl.show(errorDesc, CONST.GROWL.ERROR);
+
+                        /*
+                        * Since we intercepted the user-triggered paste event to check for attachments,
+                        * we need to manually set the value and call the `onChangeText` handler.
+                        * Synthetically-triggered paste events do not affect the document's contents.
+                        * See https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event for more details.
+                        */
+                        const beforeCursorText = this.textInput.value.substring(0, this.selection.start);
+                        const afterCursorText = this.textInput.value.substring(this.selection.end);
+                        this.textInput.value = beforeCursorText + pastedText + afterCursorText;
+                        this.updateNumberOfLines();
+                        this.props.onChangeText(this.textInput.value);
+                        const newCursorPosition = beforeCursorText.length + pastedText.length;
+                        this.setState({selection: {start: newCursorPosition, end: newCursorPosition}});
                     });
             }
         }
@@ -247,12 +281,12 @@ class TextInputFocusable extends React.Component {
                 onChange={() => {
                     this.updateNumberOfLines();
                 }}
+                onSelectionChange={this.saveSelection}
                 numberOfLines={this.state.numberOfLines}
                 style={propStyles}
                 /* eslint-disable-next-line react/jsx-props-no-spreading */
                 {...propsWithoutStyles}
                 disabled={this.props.isDisabled}
-                onSelectionChange={this.props.onSelectionChange}
             />
         );
     }
diff --git a/src/libs/Growl.js b/src/libs/Growl.js
new file mode 100644
index 000000000000..9e20dcbcc2a6
--- /dev/null
+++ b/src/libs/Growl.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import CONST from '../CONST';
+
+export const growlRef = React.createRef();
+
+/**
+ * Show the growl notification
+ *
+ * @param {String} bodyText
+ * @param {String} type
+ * @param {Number} [duration]
+*/
+function show(bodyText, type, duration = CONST.GROWL.DURATION) {
+    growlRef.current.show(bodyText, type, duration);
+}
+
+
+export default {show};
diff --git a/src/libs/GrowlNotification/GrowlNotificationContainer/index.native.js b/src/libs/GrowlNotification/GrowlNotificationContainer/index.native.js
deleted file mode 100644
index d6d5a0bc0e8b..000000000000
--- a/src/libs/GrowlNotification/GrowlNotificationContainer/index.native.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react';
-import {Animated} from 'react-native';
-import styles from '../../../styles/styles';
-import propTypes from './GrowlNotificationContainerPropTypes';
-
-const GrowlNotificationContainer = ({children, translateY}) => (
-    <Animated.View
-        style={[
-            styles.growlNotificationContainer,
-            styles.growlNotificationTranslateY(translateY),
-        ]}
-    >
-        {children}
-    </Animated.View>
-);
-
-GrowlNotificationContainer.propTypes = propTypes;
-
-export default GrowlNotificationContainer;
diff --git a/src/pages/settings/Profile/ProfilePage.js b/src/pages/settings/Profile/ProfilePage.js
index 00ea71e257dd..1487e85057b8 100755
--- a/src/pages/settings/Profile/ProfilePage.js
+++ b/src/pages/settings/Profile/ProfilePage.js
@@ -29,8 +29,8 @@ import CreateMenu from '../../../components/CreateMenu';
 import Picker from '../../../components/Picker';
 import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
 import compose from '../../../libs/compose';
-import GrowlNotification from '../../../libs/GrowlNotification';
 import Button from '../../../components/Button';
+import Growl from '../../../libs/Growl';
 
 const propTypes = {
     /* Onyx Props */
@@ -131,7 +131,6 @@ class ProfilePage extends Component {
         this.setAutomaticTimezone = this.setAutomaticTimezone.bind(this);
         this.getLogins = this.getLogins.bind(this);
         this.createMenuItems = this.createMenuItems.bind(this);
-        this.growlNotification = undefined;
     }
 
     componentDidUpdate(prevProps) {
@@ -211,7 +210,7 @@ class ProfilePage extends Component {
             },
         });
 
-        this.growlNotification.show(this.props.translate('profilePage.growlMessageOnSave'), 'success', 3000);
+        Growl.show(this.props.translate('profilePage.growlMessageOnSave'), CONST.GROWL.SUCCESS, 3000);
     }
 
     /**
@@ -261,7 +260,6 @@ class ProfilePage extends Component {
 
         return (
             <ScreenWrapper>
-                <GrowlNotification ref={el => this.growlNotification = el} />
                 <HeaderWithCloseButton
                     title={this.props.translate('common.profile')}
                     shouldShowBackButton
diff --git a/src/styles/styles.js b/src/styles/styles.js
index e7c7c388527b..481be6119c62 100644
--- a/src/styles/styles.js
+++ b/src/styles/styles.js
@@ -1456,12 +1456,12 @@ const styles = {
         justifyContent: 'flex-start',
         position: 'absolute',
         width: '100%',
+        top: 20,
         ...spacing.ph5,
     },
 
     growlNotificationDesktopContainer: {
-        maxWidth: '380px',
-        top: '20px',
+        maxWidth: 380,
         right: 0,
         position: 'fixed',
     },
