diff --git a/packages/apps/stock/src/screens/loader/LoaderScreen.js b/packages/apps/stock/src/screens/loader/LoaderScreen.js
index 77c352ffdc..a48110b161 100644
--- a/packages/apps/stock/src/screens/loader/LoaderScreen.js
+++ b/packages/apps/stock/src/screens/loader/LoaderScreen.js
@@ -37,7 +37,7 @@
import React from 'react';
import {Button, View} from 'react-native';
import {Screen} from '@axelor/aos-mobile-ui';
-import {useLoaderListner} from '@axelor/aos-mobile-core';
+import {LoaderPopup, useLoaderListner} from '@axelor/aos-mobile-core';
// Screen for test Loader functionnalities
const LoaderScreen = () => {
@@ -55,12 +55,14 @@ const LoaderScreen = () => {
const {loading, listener} = useLoaderListner({
process,
onSuccess: handleCustomAction,
+ disabled: true,
});
return (
+
);
diff --git a/packages/core/src/components/templates/Loader/LoaderPopup.tsx b/packages/core/src/components/templates/Loader/LoaderPopup.tsx
new file mode 100644
index 0000000000..4e37dfc4ec
--- /dev/null
+++ b/packages/core/src/components/templates/Loader/LoaderPopup.tsx
@@ -0,0 +1,118 @@
+/*
+ * Axelor Business Solutions
+ *
+ * Copyright (C) 2024 Axelor ().
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import React, {useCallback, useEffect, useState} from 'react';
+import {
+ BlockInteractionScreen,
+ Button,
+ Card,
+ Label,
+ Text,
+ useConfig,
+ useThemeColor,
+} from '@axelor/aos-mobile-ui';
+import {ActivityIndicator, Dimensions, StyleSheet, View} from 'react-native';
+import {useTranslator} from '../../../i18n';
+import {useNavigation} from '@react-navigation/native';
+
+interface LoaderPopupProps {
+ loading: boolean;
+ timeout: number;
+ onSuccess: () => void;
+ onError: () => void;
+}
+
+const LoaderPopup = ({loading, timeout = 100}: LoaderPopupProps) => {
+ const navigation = useNavigation();
+ const I18n = useTranslator();
+ const Colors = useThemeColor();
+ const {setActivityIndicator} = useConfig();
+
+ const [showPopup, setShowPopup] = useState(false);
+
+ const handleGoBack = useCallback(() => {
+ navigation.goBack();
+ }, [navigation]);
+
+ useEffect(() => {
+ if (loading && !showPopup) {
+ setActivityIndicator(true);
+ }
+
+ const timerId = setTimeout(() => {
+ setActivityIndicator(false);
+ setShowPopup(true);
+ }, timeout);
+
+ return () => clearTimeout(timerId);
+ }, [timeout, loading, showPopup, setActivityIndicator]);
+
+ if (!loading || !showPopup) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+
+ {I18n.t('Base_Loader_LoadingInProgress')}
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ popupContainer: {
+ position: 'absolute',
+ width: 350,
+ top: Dimensions.get('window').height * 0.2,
+ left: Dimensions.get('window').width * 0.06,
+ elevation: 24,
+ shadowOpacity: 12,
+ paddingVertical: 10,
+ },
+ activityIndicatorContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginHorizontal: 30,
+ },
+ loadingLabel: {
+ fontWeight: 'bold',
+ },
+});
+
+export default LoaderPopup;
diff --git a/packages/core/src/components/templates/Loader/index.ts b/packages/core/src/components/templates/Loader/index.ts
index b23ccd9918..cc746f2088 100644
--- a/packages/core/src/components/templates/Loader/index.ts
+++ b/packages/core/src/components/templates/Loader/index.ts
@@ -16,4 +16,5 @@
* along with this program. If not, see .
*/
+export {default as LoaderPopup} from './LoaderPopup';
export {default as useLoaderListner} from './use-loader-listener';
diff --git a/packages/core/src/components/templates/Loader/use-loader-listener.ts b/packages/core/src/components/templates/Loader/use-loader-listener.ts
index bf98bcc2b1..d68d42c87a 100644
--- a/packages/core/src/components/templates/Loader/use-loader-listener.ts
+++ b/packages/core/src/components/templates/Loader/use-loader-listener.ts
@@ -24,12 +24,14 @@ interface LoaderListenerProps {
process: () => Promise;
onSuccess?: () => void;
onError?: () => void;
+ disabled?: boolean;
}
const useLoaderListner = ({
process,
onSuccess = () => console.log('Process successfully completed.'),
onError = () => console.warn('An error has occurred!'),
+ disabled = false,
}: LoaderListenerProps) => {
const I18n = useTranslator();
@@ -49,7 +51,7 @@ const useLoaderListner = ({
topOffset: 30,
text1: I18n.t('Base_Success'),
text2: response || I18n.t('Base_Loader_ProccessSuccessMessage'),
- onPress: onSuccess,
+ onPress: !disabled ? onSuccess : () => {},
});
} catch (error) {
showToastMessage({
@@ -58,12 +60,12 @@ const useLoaderListner = ({
topOffset: 30,
text1: I18n.t('Base_Error'),
text2: error || I18n.t('Base_Loader_ProccessErrorMessage'),
- onPress: onError,
+ onPress: !disabled ? onError : () => {},
});
} finally {
setLoading(false);
}
- }, [process, onSuccess, onError, I18n]);
+ }, [process, disabled, onSuccess, onError, I18n]);
useEffect(() => {
if (start && !loading) {