diff --git a/public/locales/en/common.json b/public/locales/en/common.json index aa4ef1e5..dddc0286 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -19,6 +19,9 @@ "minutes": "m", "seconds": "s" }, + "network": { + "offline_mode_notification": "Offline mode. Cached data will be displayed" + }, "widget": { "missing_type": "Missing Widget Type: {{type}}", "api_error": "API Error", diff --git a/src/components/topnotification.jsx b/src/components/topnotification.jsx new file mode 100644 index 00000000..3ecee808 --- /dev/null +++ b/src/components/topnotification.jsx @@ -0,0 +1,8 @@ +export default function TopNotification({ icon, children }) { + return ( +
+ {icon ?
{icon}
: null} + {children} +
+ ); +} diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 92833117..44f3bf15 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -8,6 +8,7 @@ import { useEffect, useContext, useState, useMemo } from "react"; import { BiError } from "react-icons/bi"; import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { useRouter } from "next/router"; +import { MdOutlineCloudOff } from "react-icons/md"; import Tab, { slugify } from "components/tab"; import FileContent from "components/filecontent"; @@ -27,6 +28,8 @@ import ErrorBoundary from "components/errorboundry"; import themes from "utils/styles/themes"; import QuickLaunch from "components/quicklaunch"; import { getStoredProvider, searchProviders } from "components/widgets/search/search"; +import useOffline from "utils/hooks/offline"; +import TopNotification from "components/topnotification"; const ThemeToggle = dynamic(() => import("components/toggles/theme"), { ssr: false, @@ -473,6 +476,9 @@ function Home({ initialSettings }) { } export default function Wrapper({ initialSettings, fallback }) { + const { isOffline } = useOffline(); + const { t } = useTranslation(); + const wrappedStyle = {}; let backgroundBlur = false; let backgroundSaturate = false; @@ -507,6 +513,11 @@ export default function Wrapper({ initialSettings, fallback }) { initialSettings.color && `theme-${initialSettings.color}`, )} > + {isOffline ? ( + }> + {t('network.offline_mode_notification')} + + ) : null}
@media (min-width: 1800px) { ... } }, + keyframes: { + 'appear-top': { + '0%': { transform: 'translateY(-100%)', opacity: 0 }, + '100%': { transform: 'translateY(0%)', opacity: 1 }, + } + }, + animation: { + 'appear-top': 'appear-top 250ms ease-out' + } }, }, plugins: [tailwindForms, tailwindScrollbars],