diff --git a/.vscode/launch.json b/.vscode/launch.json
index 0e71c3ba..366b5438 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -16,4 +16,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/src/components/bookmarks/group.jsx b/src/components/bookmarks/group.jsx
index 97a484e9..4cd36b7b 100644
--- a/src/components/bookmarks/group.jsx
+++ b/src/components/bookmarks/group.jsx
@@ -5,44 +5,64 @@ import { MdKeyboardArrowDown } from "react-icons/md";
import ErrorBoundary from "components/errorboundry";
import List from "components/bookmarks/list";
+import ResolvedIcon from "components/resolvedicon";
-export default function BookmarksGroup({ group, disableCollapse }) {
+export default function BookmarksGroup({ bookmarks, layout, disableCollapse }) {
const panel = useRef();
return (
-
-
- {({ open }) => (
- <>
-
- {group.name}
-
-
- {
- panel.current.style.height = `${panel.current.scrollHeight}px`;
- setTimeout(() => {panel.current.style.height = `0`}, 1);
- }}
- beforeEnter={() => {
- panel.current.style.height = `0px`;
- setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1);
- }}
- >
-
-
-
-
-
-
- >
- )}
-
+
+
+ {({ open }) => (
+ <>
+ {layout?.header !== false && (
+
+ {layout?.icon && (
+
+
+
+ )}
+ {bookmarks.name}
+
+
+ )}
+ {
+ panel.current.style.height = `${panel.current.scrollHeight}px`;
+ setTimeout(() => {
+ panel.current.style.height = `0`;
+ }, 1);
+ }}
+ beforeEnter={() => {
+ panel.current.style.height = `0px`;
+ setTimeout(() => {
+ panel.current.style.height = `${panel.current.scrollHeight}px`;
+ }, 1);
+ }}
+ >
+
+
+
+
+
+
+ >
+ )}
+
);
}
diff --git a/src/components/bookmarks/list.jsx b/src/components/bookmarks/list.jsx
index d37b83e7..3e1dd698 100644
--- a/src/components/bookmarks/list.jsx
+++ b/src/components/bookmarks/list.jsx
@@ -1,8 +1,27 @@
+import classNames from "classnames";
+
import Item from "components/bookmarks/item";
-export default function List({ bookmarks }) {
+const columnMap = [
+ "grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
+ "grid-cols-1 md:grid-cols-1 lg:grid-cols-1",
+ "grid-cols-1 md:grid-cols-2 lg:grid-cols-2",
+ "grid-cols-1 md:grid-cols-2 lg:grid-cols-3",
+ "grid-cols-1 md:grid-cols-2 lg:grid-cols-4",
+ "grid-cols-1 md:grid-cols-2 lg:grid-cols-5",
+ "grid-cols-1 md:grid-cols-2 lg:grid-cols-6",
+ "grid-cols-1 md:grid-cols-2 lg:grid-cols-7",
+ "grid-cols-1 md:grid-cols-2 lg:grid-cols-8",
+];
+
+export default function List({ bookmarks, layout }) {
return (
-
+
{bookmarks.map((bookmark) => (
))}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 1d2452db..ef869802 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -4,7 +4,7 @@ import Head from "next/head";
import dynamic from "next/dynamic";
import classNames from "classnames";
import { useTranslation } from "next-i18next";
-import { useEffect, useContext, useState } from "react";
+import { useEffect, useContext, useState, useMemo } from "react";
import { BiError } from "react-icons/bi";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
@@ -209,7 +209,7 @@ function Home({ initialSettings }) {
searchProvider = searchProviders[searchWidget.options?.provider];
}
}
- const headerStyle = initialSettings?.headerStyle || "underlined";
+ const headerStyle = settings?.headerStyle || "underlined";
useEffect(() => {
function handleKeyDown(e) {
@@ -230,15 +230,55 @@ function Home({ initialSettings }) {
}
})
+ const servicesAndBookmarksGroups = useMemo(() => {
+ const mergedGroups = [
+ services?.length > 0 ? (
+
+ {services.map((group) => (
+
+ ))}
+
+ ) : null,
+ bookmarks?.length > 0 ? (
+
+ {bookmarks.map((group) => (
+
+ ))}
+
+ ) : null
+ ];
+
+ return settings.bookmarksOnTop ? mergedGroups.reverse() : mergedGroups;
+ }, [
+ services,
+ bookmarks,
+ settings.layout,
+ settings.fiveColumns,
+ settings.disableCollapse,
+ settings.bookmarksOnTop
+ ]);
+
return (
<>
- {initialSettings.title || "Homepage"}
- {initialSettings.base && }
- {initialSettings.favicon ? (
+ {settings.title || "Homepage"}
+ {settings.base && }
+ {settings.favicon ? (
<>
-
-
+
+
>
) : (
<>
@@ -248,11 +288,8 @@ function Home({ initialSettings }) {
>
)}
-
-
+
+
{widgets && (
@@ -275,7 +312,7 @@ function Home({ initialSettings }) {
{widgets
.filter((widget) => !rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
-
+
))}
rightAlignedWidgets.includes(widget.type))
.map((widget, i) => (
-
+
))}
>
)}
- {services?.length > 0 && (
-
- {services.map((group) => (
-
- ))}
-
- )}
-
- {bookmarks?.length > 0 && (
-
- {bookmarks.map((group) => (
-
- ))}
-
- )}
+ {servicesAndBookmarksGroups}
- {!initialSettings?.color && }
+ {!settings?.color && }
- {!initialSettings?.theme && }
+ {!settings.theme && }
- {!initialSettings?.hideVersion && }
+ {!settings.hideVersion && }
diff --git a/src/utils/config/api-response.js b/src/utils/config/api-response.js
index e00846db..d3c8bb9e 100644
--- a/src/utils/config/api-response.js
+++ b/src/utils/config/api-response.js
@@ -34,6 +34,16 @@ export async function bookmarksResponse() {
if (!bookmarks) return [];
+ let initialSettings;
+
+ try {
+ initialSettings = await getSettings();
+ } catch (e) {
+ console.error("Failed to load settings.yaml, please check for errors");
+ if (e) console.error(e.toString());
+ initialSettings = {};
+ }
+
// map easy to write YAML objects into easy to consume JS arrays
const bookmarksArray = bookmarks.map((group) => ({
name: Object.keys(group)[0],
@@ -43,7 +53,21 @@ export async function bookmarksResponse() {
})),
}));
- return bookmarksArray;
+ const sortedGroups = [];
+ const unsortedGroups = [];
+ const definedLayouts = initialSettings.layout ? Object.keys(initialSettings.layout) : null;
+
+ bookmarksArray.forEach((group) => {
+ if (definedLayouts) {
+ const layoutIndex = definedLayouts.findIndex(layout => layout === group.name);
+ if (layoutIndex > -1) sortedGroups[layoutIndex] = group;
+ else unsortedGroups.push(group);
+ } else {
+ unsortedGroups.push(group);
+ }
+ });
+
+ return [...sortedGroups.filter(g => g), ...unsortedGroups];
}
export async function widgetsResponse() {