diff --git a/src/components/tab.jsx b/src/components/tab.jsx
new file mode 100644
index 00000000..ba5c52af
--- /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 e99303ab..7b93b005 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 cf82eafb..b144d403 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 servicesAndBookmarksGroups = useMemo(() => {
- const layoutGroups = settings.layout ? Object.keys(settings.layout).map(
- (groupName) => services?.find(g => g.name === groupName) ?? bookmarks?.find(b => b.name === groupName)
- ).filter(g => g) : [];
+ const tabs = useMemo( () => [
+ ...new Set(
+ Object.keys(settings.layout ?? {}).map(
+ (groupName) => settings.layout[groupName]?.tab
+ ).filter(group => group)
+ )
+ ], [settings.layout]);
- const serviceGroups = services?.filter(group => settings.layout?.[group.name] === undefined);
- const bookmarkGroups = bookmarks.filter(group => settings.layout?.[group.name] === undefined);
+ if (!activeTab) {
+ const initialTab = decodeURI(asPath.substring(asPath.indexOf("#") + 1));
+ if (initialTab !== '/') {
+ setActiveTab(initialTab)
+ } else {
+ setActiveTab(tabs['0'] ?? false)
+ }
+ }
+
+ const servicesAndBookmarksGroups = useMemo(() => {
+ 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(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(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 00000000..8cd5d520
--- /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};
+}