diff --git a/apps/mobile/app/components/toast/index.js b/apps/mobile/app/components/toast/index.js
deleted file mode 100644
index 399fdd004..000000000
--- a/apps/mobile/app/components/toast/index.js
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
-This file is part of the Notesnook project (https://notesnook.com/)
-
-Copyright (C) 2023 Streetwriters (Private) Limited
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-import React, { useCallback, useEffect, useRef, useState } from "react";
-import { TouchableOpacity, View } from "react-native";
-import Icon from "react-native-vector-icons/MaterialCommunityIcons";
-import { notesnook } from "../../../e2e/test.ids";
-import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
-import { DDS } from "../../services/device-detection";
-import {
- eSubscribeEvent,
- eUnSubscribeEvent
-} from "../../services/event-manager";
-import { useThemeColors } from "@notesnook/theme";
-import { getElevationStyle } from "../../utils/elevation";
-import { eHideToast, eShowToast } from "../../utils/events";
-import { SIZE } from "../../utils/size";
-import { Button } from "../ui/button";
-import Heading from "../ui/typography/heading";
-import Paragraph from "../ui/typography/paragraph";
-export const Toast = ({ context = "global" }) => {
- const { colors } = useThemeColors();
- const [data, setData] = useState({});
- const insets = useGlobalSafeAreaInsets();
- const hideTimeout = useRef();
- const [visible, setVisible] = useState(false);
- const toastMessages = useRef([]);
-
- const show = useCallback(
- async (data) => {
- if (!data) return;
- if (data.context !== context) return;
- if (
- toastMessages.current.findIndex((m) => m.message === data.message) >= 0
- ) {
- return;
- }
- toastMessages.current.push(data);
- if (toastMessages.current?.length > 1) return;
- setData(data);
-
- setVisible(true);
- if (hideTimeout.current) {
- clearTimeout(hideTimeout.current);
- }
- hideTimeout.current = setTimeout(() => {
- hide();
- }, data.duration);
- },
- [context, hide]
- );
-
- const next = useCallback(
- (data) => {
- if (!data) {
- hide();
- return;
- }
- setData(data);
- if (hideTimeout.current) {
- clearTimeout(hideTimeout.current);
- }
- hideTimeout.current = setTimeout(() => {
- hide();
- }, data?.duration);
- },
- [hide]
- );
-
- const hide = useCallback(() => {
- if (hideTimeout.current) {
- clearTimeout(hideTimeout.current);
- }
- let msg =
- toastMessages.current.length > 1 ? toastMessages.current.shift() : null;
-
- if (msg) {
- setVisible(false);
- next(msg);
- setTimeout(() => {
- setVisible(true);
- }, 300);
- } else {
- setVisible(false);
- toastMessages.current.shift();
- setTimeout(() => {
- setData({});
- if (hideTimeout.current) {
- clearTimeout(hideTimeout.current);
- }
- }, 100);
- }
- }, [next]);
-
- useEffect(() => {
- eSubscribeEvent(eShowToast, show);
- eSubscribeEvent(eHideToast, hide);
- return () => {
- toastMessages.current = [];
- eUnSubscribeEvent(eShowToast, show);
- eUnSubscribeEvent(eHideToast, hide);
- };
- }, [hide, show]);
-
- return (
- visible && (
-
-
-
-
-
-
-
-
- {data?.heading ? (
- {
- hide();
- }}
- >
- {data.heading}
-
- ) : null}
-
- {data?.message ? (
- {
- hide();
- }}
- >
- {data.message}
-
- ) : null}
-
-
-
- {data.func ? (
-
- ) : null}
-
-
- )
- );
-};
diff --git a/apps/mobile/app/components/toast/index.tsx b/apps/mobile/app/components/toast/index.tsx
new file mode 100644
index 000000000..b3b26c9f7
--- /dev/null
+++ b/apps/mobile/app/components/toast/index.tsx
@@ -0,0 +1,221 @@
+/*
+This file is part of the Notesnook project (https://notesnook.com/)
+
+Copyright (C) 2023 Streetwriters (Private) Limited
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+import { useThemeColors } from "@notesnook/theme";
+import React, { useCallback, useEffect, useRef, useState } from "react";
+import { TouchableOpacity, useWindowDimensions, View } from "react-native";
+import Icon from "react-native-vector-icons/MaterialCommunityIcons";
+import { notesnook } from "../../../e2e/test.ids";
+import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
+import useKeyboard from "../../hooks/use-keyboard";
+import { DDS } from "../../services/device-detection";
+import {
+ eSubscribeEvent,
+ eUnSubscribeEvent,
+ ToastOptions
+} from "../../services/event-manager";
+import { getElevationStyle } from "../../utils/elevation";
+import { eHideToast, eShowToast } from "../../utils/events";
+import { SIZE } from "../../utils/size";
+import { Button } from "../ui/button";
+import Heading from "../ui/typography/heading";
+import Paragraph from "../ui/typography/paragraph";
+
+export const Toast = ({ context = "global" }) => {
+ const { colors, isDark } = useThemeColors();
+ const [toastOptions, setToastOptions] = useState(
+ undefined
+ );
+ const hideTimeout = useRef();
+ const keyboard = useKeyboard();
+ const insets = useGlobalSafeAreaInsets();
+ const [visible, setVisible] = useState(false);
+ const toastMessages = useRef([]);
+ const dimensions = useWindowDimensions();
+
+ const hideToast = useCallback(() => {
+ const nextToastMessage = toastMessages.current.shift();
+ if (nextToastMessage) {
+ if (hideTimeout.current) {
+ clearTimeout(hideTimeout.current);
+ }
+ setVisible(true);
+ setToastOptions(nextToastMessage);
+ hideTimeout.current = setTimeout(() => {
+ hideToast();
+ }, nextToastMessage?.duration);
+ } else {
+ setVisible(false);
+ setToastOptions(undefined);
+ if (hideTimeout.current) {
+ clearTimeout(hideTimeout.current);
+ }
+ }
+ }, []);
+
+ const showToast = useCallback(
+ (data?: ToastOptions) => {
+ if (
+ !data ||
+ data.context !== context ||
+ toastMessages.current.findIndex((m) => m.message === data.message) != -1
+ )
+ return;
+
+ toastMessages.current.push(data);
+ if (toastMessages.current?.length > 1) return;
+
+ if (hideTimeout.current) {
+ clearTimeout(hideTimeout.current);
+ }
+ setVisible(true);
+ const nextToastMessage = toastMessages.current.shift();
+ setToastOptions(nextToastMessage);
+ hideTimeout.current = setTimeout(() => {
+ hideToast();
+ }, nextToastMessage?.duration);
+ },
+ [context, hideToast]
+ );
+
+ useEffect(() => {
+ eSubscribeEvent(eShowToast, showToast);
+ eSubscribeEvent(eHideToast, hideToast);
+ return () => {
+ eUnSubscribeEvent(eShowToast, showToast);
+ eUnSubscribeEvent(eHideToast, hideToast);
+ };
+ }, [hideToast, showToast]);
+
+ const isFullToastMessage = toastOptions?.heading && toastOptions?.message;
+
+ return visible && toastOptions ? (
+
+
+
+
+
+
+ {isFullToastMessage ? (
+ {
+ hideToast();
+ }}
+ >
+ {toastOptions.heading}
+
+ ) : null}
+
+ {toastOptions.message || toastOptions.heading ? (
+ {
+ hideToast();
+ }}
+ >
+ {toastOptions.message || toastOptions.heading}
+
+ ) : null}
+
+
+
+ {toastOptions.func ? (
+
+ ) : null}
+
+
+ ) : null;
+};