diff --git a/src/components/tab.jsx b/src/components/tab.jsx new file mode 100644 index 000000000..ba5c52af8 --- /dev/null +++ b/src/components/tab.jsx @@ -0,0 +1,24 @@ +import { useContext } from "react"; +import classNames from "classnames"; + +import { TabContext } from "utils/contexts/tab"; + +export default function Tab({ tab }) { + const { activeTab, setActiveTab } = useContext(TabContext); + + return ( +
  • + +
  • + ); +} diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index e99303abc..7b93b0050 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -11,6 +11,7 @@ import nextI18nextConfig from "../../next-i18next.config"; import { ColorProvider } from "utils/contexts/color"; import { ThemeProvider } from "utils/contexts/theme"; import { SettingsProvider } from "utils/contexts/settings"; +import { TabProvider } from "utils/contexts/tab"; function MyApp({ Component, pageProps }) { return ( @@ -26,7 +27,9 @@ function MyApp({ Component, pageProps }) { - + + + diff --git a/src/pages/index.jsx b/src/pages/index.jsx index cf82eafbb..b144d4037 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -7,7 +7,9 @@ import { useTranslation } from "next-i18next"; 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 Tab from "components/tab"; import FileContent from "components/filecontent"; import ServicesGroup from "components/services/group"; import BookmarksGroup from "components/bookmarks/group"; @@ -19,6 +21,7 @@ import { getSettings } from "utils/config/config"; import { ColorContext } from "utils/contexts/color"; import { ThemeContext } from "utils/contexts/theme"; import { SettingsContext } from "utils/contexts/settings"; +import { TabContext } from "utils/contexts/tab"; import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/config/api-response"; import ErrorBoundary from "components/errorboundry"; import themes from "utils/styles/themes"; @@ -169,6 +172,8 @@ function Home({ initialSettings }) { const { theme, setTheme } = useContext(ThemeContext); const { color, setColor } = useContext(ColorContext); const { settings, setSettings } = useContext(SettingsContext); + const { activeTab, setActiveTab } = useContext(TabContext); + const { asPath } = useRouter(); useEffect(() => { setSettings(initialSettings); @@ -231,18 +236,51 @@ function Home({ initialSettings }) { } }) + const tabs = useMemo( () => [ + ...new Set( + Object.keys(settings.layout ?? {}).map( + (groupName) => settings.layout[groupName]?.tab + ).filter(group => group) + ) + ], [settings.layout]); + + if (!activeTab) { + const initialTab = decodeURI(asPath.substring(asPath.indexOf("#") + 1)); + if (initialTab !== '/') { + setActiveTab(initialTab) + } else { + setActiveTab(tabs['0'] ?? false) + } + } + const servicesAndBookmarksGroups = useMemo(() => { - const layoutGroups = settings.layout ? Object.keys(settings.layout).map( + const tabGroupFilter = g => g && [activeTab, undefined].includes(settings.layout?.[g.name]?.tab); + const undefinedGroupFilter = g => settings.layout?.[g.name] === undefined; + + const layoutGroups = Object.keys(settings.layout ?? {}).map( (groupName) => services?.find(g => g.name === groupName) ?? bookmarks?.find(b => b.name === groupName) - ).filter(g => g) : []; + ).filter(tabGroupFilter); + + if (!settings.layout || !layoutGroups) { + // wait for settings to populate, otherwise all the widgets will be requested initially even if we are on a single tab + return
    ; + } - const serviceGroups = services?.filter(group => settings.layout?.[group.name] === undefined); - const bookmarkGroups = bookmarks.filter(group => settings.layout?.[group.name] === undefined); + const serviceGroups = services?.filter(tabGroupFilter).filter(undefinedGroupFilter); + const bookmarkGroups = bookmarks.filter(tabGroupFilter).filter(undefinedGroupFilter); return <> + {tabs.length > 0 &&
    + +
    } {layoutGroups.length > 0 &&
    {layoutGroups.map((group) => ( - group.services ? + group.services ? (} }, [ + tabs, + activeTab, services, bookmarks, settings.layout, settings.fiveColumns, - settings.disableCollapse + settings.disableCollapse, + settings.cardBlur ]); return ( diff --git a/src/utils/contexts/tab.jsx b/src/utils/contexts/tab.jsx new file mode 100644 index 000000000..8cd5d5201 --- /dev/null +++ b/src/utils/contexts/tab.jsx @@ -0,0 +1,15 @@ +import { createContext, useState, useMemo } from "react"; + +export const TabContext = createContext(); + +export function TabProvider({ initialTab, children }) { + const [activeTab, setActiveTab] = useState(false); + + if (initialTab) { + setActiveTab(initialTab); + } + + const value = useMemo(() => ({ activeTab, setActiveTab }), [activeTab]); + + return {children}; +}