From 67e1801bb57b4d6fce696734b92a2b3aa0edb09c Mon Sep 17 00:00:00 2001 From: AmirHossein Mahmoodi Date: Wed, 27 Sep 2023 10:15:01 +0330 Subject: [PATCH] TF-102 Add network config --- public/locales/fa/app.json | 2 + src/core/components/GlobalHead.jsx | 58 ++++++++++++++++++ src/core/components/NetworkComponent.jsx | 34 +++++++++++ src/layouts/AppLayout.jsx | 75 ++++-------------------- src/lib/app/hooks/useNetwork.jsx | 58 ++++++++++++++++++ src/lib/app/hooks/useRequest.js | 26 ++++---- 6 files changed, 176 insertions(+), 77 deletions(-) create mode 100644 src/core/components/GlobalHead.jsx create mode 100644 src/core/components/NetworkComponent.jsx create mode 100644 src/lib/app/hooks/useNetwork.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 435a0c7..c91dc84 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -15,6 +15,8 @@ "Resend_code_in": "ارسال مجدد کد در", "seconds_later": "ثانیه دیگر", "upload_file_text": "بارگذاری فایل", + "online_message": "شما به اینترنت وصل هستید", + "offline_message": "اتصال شما به اینترنت قطع شده است", "header": { "open_profile": "پروفایل", "edit_profile": "ویرایش پروفایل", diff --git a/src/core/components/GlobalHead.jsx b/src/core/components/GlobalHead.jsx new file mode 100644 index 0000000..5d6186d --- /dev/null +++ b/src/core/components/GlobalHead.jsx @@ -0,0 +1,58 @@ +import Head from "next/head"; + +const GlobalHead = () => { + return ( + + + + + + + + + + + + + + + + + + + + + ) +} + +export default GlobalHead \ No newline at end of file diff --git a/src/core/components/NetworkComponent.jsx b/src/core/components/NetworkComponent.jsx new file mode 100644 index 0000000..8ebbb68 --- /dev/null +++ b/src/core/components/NetworkComponent.jsx @@ -0,0 +1,34 @@ +import useNetwork from "@/lib/app/hooks/useNetwork"; +import {useEffect, useRef} from "react"; +import {toast} from "react-toastify"; +import WifiIcon from '@mui/icons-material/Wifi'; +import WifiOffIcon from '@mui/icons-material/WifiOff'; +import {useTranslations} from "next-intl"; + +const NetworkComponent = () => { + const toastId = useRef(null); + const network = useNetwork() + const t = useTranslations() + + useEffect(() => { + if (network.online) { + toast.update(toastId.current, { + type: toast.TYPE.SUCCESS, + render: t('online_message'), + autoClose: 2000, + closeButton: true, + closeOnClick: true, + icon: + }); + return + } + toast.dismiss() + toastId.current = toast.warn(t('offline_message'), { + autoClose: false, closeButton: false, closeOnClick: false, icon: + }) + }, [network.online]); + + return '' +} + +export default NetworkComponent \ No newline at end of file diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx index 611e707..2b4593b 100644 --- a/src/layouts/AppLayout.jsx +++ b/src/layouts/AppLayout.jsx @@ -2,12 +2,13 @@ import theme from "@/core/utils/theme"; import useLanguage from "@/lib/app/hooks/useLanguage"; import useLoading from "@/lib/app/hooks/useLoading"; import useUser from "@/lib/app/hooks/useUser"; -import Head from "next/head"; import NextNProgress from "nextjs-progressbar"; import {useEffect} from "react"; import {ToastContainer} from "react-toastify"; import useDirection from "@/lib/app/hooks/useDirection"; import "react-toastify/dist/ReactToastify.css"; +import NetworkComponent from "@/core/components/NetworkComponent"; +import GlobalHead from "@/core/components/GlobalHead"; function AppLayout({children, isBot}) { const {languageIsReady} = useLanguage(); @@ -40,66 +41,16 @@ function AppLayout({children, isBot}) { if (!languageIsReady) return; } - return ( - <> - - - - - - - - - - - - - - - - - - - - - - - {children} - - ); + return (<> + + + + + {children} + ); } -export default AppLayout; +export default AppLayout; \ No newline at end of file diff --git a/src/lib/app/hooks/useNetwork.jsx b/src/lib/app/hooks/useNetwork.jsx new file mode 100644 index 0000000..4fff7fe --- /dev/null +++ b/src/lib/app/hooks/useNetwork.jsx @@ -0,0 +1,58 @@ +import {useEffect, useState} from "react"; + +function getNetworkConnection() { + return ( + navigator.connection || + navigator.mozConnection || + navigator.webkitConnection || + null + ); +} + +function getNetworkConnectionInfo() { + const connection = getNetworkConnection(); + if (!connection) { + return {}; + } + return { + rtt: connection.rtt, + type: connection.type, + saveData: connection.saveData, + downLink: connection.downLink, + downLinkMax: connection.downLinkMax, + effectiveType: connection.effectiveType, + }; +} + +function useNetwork() { + const [state, setState] = useState(() => { + return { + online: navigator.onLine, + }; + }); + useEffect(() => { + const handleOnline = () => { + setState((prevState) => ({ + ...prevState, + online: true, + })); + }; + const handleOffline = () => { + setState((prevState) => ({ + ...prevState, + online: false, + })); + }; + + window.addEventListener("online", handleOnline); + window.addEventListener("offline", handleOffline); + return () => { + window.removeEventListener("online", handleOnline); + window.removeEventListener("offline", handleOffline); + }; + }, []); + + return state; +} + +export default useNetwork; \ No newline at end of file diff --git a/src/lib/app/hooks/useRequest.js b/src/lib/app/hooks/useRequest.js index 5c567ca..d361e08 100644 --- a/src/lib/app/hooks/useRequest.js +++ b/src/lib/app/hooks/useRequest.js @@ -4,27 +4,23 @@ import PendingNotification from "@/core/components/notifications/PendingNotifica import {useTranslations} from "next-intl"; import useUser from "@/lib/app/hooks/useUser"; import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler"; +import useNetwork from "@/lib/app/hooks/useNetwork"; const defaultOptions = { - auth: false, - data: {}, - requestOptions: { + auth: false, data: {}, requestOptions: { headers: {} - }, - notification: true, - pending: true, - success: { + }, notification: true, pending: true, success: { notification: { show: true, }, - }, - failed: { + }, failed: { notification: { show: true, }, }, } const useRequest = (initOptions) => { + const network = useNetwork() const t = useTranslations() const {token, clearToken} = useUser() let _options = {...defaultOptions, ...initOptions} @@ -32,20 +28,20 @@ const useRequest = (initOptions) => { function requestServer(url = '', method = 'get', options) { _options = {..._options, ...options} if (_options.auth) _options = { - ..._options, - requestOptions: { + ..._options, requestOptions: { ..._options.requestOptions, headers: {..._options.requestOptions.headers, authorization: `Bearer ${token}`} } } return new Promise((resolve, reject) => { + if (!network.online) { + reject() + return + } if (_options.notification && _options.failed.notification.show && _options.pending) PendingNotification(t) axios({ - url: url, - method: method, - data: _options.data, - ..._options.requestOptions + url: url, method: method, data: _options.data, ..._options.requestOptions }) .then(response => { successRequest(response, t, _options)