浏览代码

background images, document title

Ben Phelps 2 年之前
父节点
当前提交
0c8bbdf02b

+ 2 - 2
src/components/bookmarks/item.jsx

@@ -6,10 +6,10 @@ export default function Item({ bookmark }) {
       <button
         type="button"
         onClick={() => window.open(bookmark.href, "_blank").focus()}
-        className="w-full text-left mb-3 cursor-pointer rounded-md font-medium text-theme-700 hover:text-theme-800 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/50 bg-white/50 hover:bg-theme-300/10 dark:bg-white/5 dark:hover:bg-white/10"
+        className="w-full text-left mb-3 cursor-pointer rounded-md font-medium text-theme-700 hover:text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-black/10 dark:shadow-black/20 bg-white/50 hover:bg-theme-300/10 dark:bg-white/10 dark:hover:bg-white/20"
       >
         <div className="flex">
-          <div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md">
+          <div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md">
             {bookmark.abbr}
           </div>
           <div className="flex-1 flex items-center justify-between rounded-r-md ">

+ 3 - 2
src/components/color-toggle.jsx

@@ -27,6 +27,7 @@ const colors = [
   "pink",
   "rose",
   "red",
+  "white",
 ];
 
 export default function ColorToggle() {
@@ -56,13 +57,13 @@ export default function ColorToggle() {
         >
           <Popover.Panel className="absolute -top-[75px] left-0">
             <div className="rounded-md shadow-lg ring-1 ring-black ring-opacity-5">
-              <div className="relative grid gap-2 p-2 grid-cols-11 shadow-theme-900/10 dark:shadow-theme-900 rounded-md shadow-md">
+              <div className="relative grid gap-2 p-2 grid-cols-11 bg-white/50 dark:bg-white/10 shadow-black/10 dark:shadow-black/20 rounded-md shadow-md">
                 {colors.map((color) => (
                   <button type="button" onClick={() => setColor(color)} key={color}>
                     <div
                       className={classNames(
                         active === color ? "border-2" : "border-0",
-                        `rounded-md w-5 h-5 border-black/50 dark:border-white/50 theme-${color} bg-theme-500`
+                        `rounded-md w-5 h-5 border-black/50 dark:border-white/50 theme-${color} bg-theme-400`
                       )}
                     />
                   </button>

+ 17 - 0
src/components/revalidate.jsx

@@ -0,0 +1,17 @@
+import { MdRefresh } from "react-icons/md";
+
+export default function Revalidate() {
+  const revalidate = () => {
+    fetch("/api/revalidate").then((res) => {
+      if (res.ok) {
+        window.location.reload();
+      }
+    });
+  };
+
+  return (
+    <div className="rounded-full flex align-middle self-center mr-3">
+      <MdRefresh onClick={() => revalidate()} className="text-theme-800 dark:text-theme-200 w-6 h-6 cursor-pointer" />
+    </div>
+  );
+}

+ 1 - 1
src/components/services/item.jsx

@@ -28,7 +28,7 @@ export default function Item({ service }) {
         <div
           className={`${
             service.href && service.href !== "#" ? "cursor-pointer " : "cursor-default "
-          }transition-all h-15 overflow-hidden mb-3 p-1 rounded-md font-medium text-theme-700 hover:text-theme-800 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/40 bg-white/50 hover:bg-theme-300/10 dark:bg-white/5 dark:hover:bg-white/10`}
+          }transition-all h-15 overflow-hidden mb-3 p-1 rounded-md font-medium text-theme-700 hover:text-theme-700/70 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-black/10 dark:shadow-black/20 bg-white/50 hover:bg-theme-300/20 dark:bg-white/10 dark:hover:bg-white/20`}
         >
           <div className="flex">
             {service.icon && (

+ 1 - 6
src/components/theme-toggle.jsx

@@ -1,10 +1,5 @@
 import { useContext } from "react";
-import {
-  MdDarkMode,
-  MdLightMode,
-  MdToggleOff,
-  MdToggleOn,
-} from "react-icons/md";
+import { MdDarkMode, MdLightMode, MdToggleOff, MdToggleOn } from "react-icons/md";
 
 import { ThemeContext } from "utils/theme-context";
 

+ 2 - 8
src/components/widgets/resources/cpu.jsx

@@ -2,6 +2,7 @@ import useSWR from "swr";
 import { FiCpu } from "react-icons/fi";
 import { BiError } from "react-icons/bi";
 import { useTranslation } from "react-i18next";
+import UsageBar from "./usage-bar";
 
 export default function Cpu() {
   const { t } = useTranslation();
@@ -41,14 +42,7 @@ export default function Cpu() {
         <div className="text-theme-800 dark:text-theme-200 text-xs">
           {t("common.number", { value: data.cpu.usage, style: "unit", unit: "percent", maximumFractionDigits: 0 })}
         </div>
-        <div className="w-full bg-gray-200 rounded-full h-1 dark:bg-gray-700">
-          <div
-            className="bg-theme-600 h-1 rounded-full dark:bg-theme-500"
-            style={{
-              width: `${percent}%`,
-            }}
-          />
-        </div>
+        <UsageBar percent={percent} />
       </div>
     </div>
   );

+ 2 - 8
src/components/widgets/resources/disk.jsx

@@ -2,6 +2,7 @@ import useSWR from "swr";
 import { FiHardDrive } from "react-icons/fi";
 import { BiError } from "react-icons/bi";
 import { useTranslation } from "react-i18next";
+import UsageBar from "./usage-bar";
 
 export default function Disk({ options }) {
   const { t } = useTranslation();
@@ -44,14 +45,7 @@ export default function Disk({ options }) {
         <span className="text-theme-800 dark:text-theme-200 text-xs hidden group-hover:block">
           {t("common.bytes", { value: data.drive.totalGb * 1024 * 1024 * 1024 })} {t("resources.total")}
         </span>
-        <div className="w-full bg-gray-200 rounded-full h-1 dark:bg-gray-700">
-          <div
-            className="bg-theme-600 h-1 rounded-full dark:bg-theme-500"
-            style={{
-              width: `${percent}%`,
-            }}
-          />
-        </div>
+        <UsageBar percent={percent} />
       </div>
     </div>
   );

+ 2 - 8
src/components/widgets/resources/memory.jsx

@@ -2,6 +2,7 @@ import useSWR from "swr";
 import { FaMemory } from "react-icons/fa";
 import { BiError } from "react-icons/bi";
 import { useTranslation } from "react-i18next";
+import UsageBar from "./usage-bar";
 
 export default function Memory() {
   const { t } = useTranslation();
@@ -44,14 +45,7 @@ export default function Memory() {
         <span className="text-theme-800 dark:text-theme-200 text-xs hidden group-hover:block">
           {t("common.bytes", { value: data.memory.usedMemMb * 1024 * 1024 })} {t("resources.used")}
         </span>
-        <div className="w-full bg-gray-200 rounded-full h-1 dark:bg-gray-700">
-          <div
-            className="bg-theme-600 h-1 rounded-full dark:bg-theme-500"
-            style={{
-              width: `${percent}%`,
-            }}
-          />
-        </div>
+        <UsageBar percent={percent} />
       </div>
     </div>
   );

+ 12 - 0
src/components/widgets/resources/usage-bar.jsx

@@ -0,0 +1,12 @@
+export default function UsageBar({ percent }) {
+  return (
+    <div className="mt-0.5 w-full bg-theme-800/30 rounded-full h-1 dark:bg-white/20">
+      <div
+        className="bg-theme-800/70 h-1 rounded-full dark:bg-white/50"
+        style={{
+          width: `${percent}%`,
+        }}
+      />
+    </div>
+  );
+}

+ 19 - 5
src/components/widgets/search/search.jsx

@@ -52,19 +52,33 @@ export default function Search({ options }) {
 
   return (
     <form className="flex-col relative h-8 my-4 min-w-full md:min-w-fit grow" onSubmit={handleSubmit}>
-      <div className="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none w-full text-theme-800 dark:text-theme-200" />
+      <div className="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none w-full text-theme-800 dark:text-white" />
       <input
-        type="search"
-        className="overflow-hidden w-full placeholder-theme-900 text-xs text-theme-900 bg-theme-50 rounded-md border border-theme-300 focus:ring-theme-500 focus:border-theme-500 dark:bg-theme-800 dark:border-theme-600 dark:placeholder-theme-400 dark:text-white dark:focus:ring-theme-500 dark:focus:border-theme-500 h-full"
+        type="text"
+        className="
+          overflow-hidden w-full h-full rounded-md
+          text-xs text-theme-900 dark:text-white
+          placeholder-theme-900 dark:placeholder-white/80
+          bg-white/50 dark:bg-white/10
+          focus:ring-theme-500 dark:focus:ring-white/50
+          focus:border-theme-500 dark:focus:border-white/50
+          border border-theme-300 dark:border-theme-200/50"
         placeholder={t("search.placeholder")}
         onChange={(s) => setQuery(s.currentTarget.value)}
         required
+        autoCapitalize="off"
+        autoCorrect="off"
+        autoComplete="off"
       />
       <button
         type="submit"
-        className="text-white absolute right-0.5 bottom-0.5 bg-theme-700 hover:bg-theme-800 border-1 focus:ring-2 focus:ring-theme-300 font-medium rounded-r-md text-sm px-4 py-2 dark:bg-theme-600 dark:hover:bg-theme-700 dark:focus:ring-theme-500"
+        className="
+        absolute right-0.5 bottom-0.5 rounded-r-md px-4 py-2 border-1
+        text-white font-medium text-sm
+        bg-theme-600/40 dark:bg-white/10
+        focus:ring-theme-500 dark:focus:ring-white/50"
       >
-        <provider.icon className="text-theme-800 dark:text-theme-200 w-3 h-3" />
+        <provider.icon className="text-white w-3 h-3" />
       </button>
     </form>
   );

+ 1 - 1
src/pages/_document.jsx

@@ -11,7 +11,7 @@ export default function Document() {
           rel="stylesheet"
         />
       </Head>
-      <body className="w-full h-full bg-theme-50 dark:bg-theme-800 transition duration-150 ease-in-out">
+      <body className="relative w-full h-full bg-theme-50 dark:bg-theme-800 transition duration-150 ease-in-out">
         <Main />
         <NextScript />
       </body>

+ 8 - 0
src/pages/api/revalidate.js

@@ -0,0 +1,8 @@
+export default async function handler(req, res) {
+  try {
+    await res.revalidate("/");
+    return res.json({ revalidated: true });
+  } catch (err) {
+    return res.status(500).send("Error revalidating");
+  }
+}

+ 22 - 3
src/pages/index.jsx

@@ -6,6 +6,8 @@ import dynamic from "next/dynamic";
 import ServicesGroup from "components/services/group";
 import BookmarksGroup from "components/bookmarks/group";
 import Widget from "components/widget";
+import Revalidate from "components/revalidate";
+import { getSettings } from "utils/config";
 import { ColorProvider } from "utils/color-context";
 import { ThemeProvider } from "utils/theme-context";
 
@@ -19,18 +21,34 @@ const ColorToggle = dynamic(() => import("components/color-toggle"), {
 
 const rightAlignedWidgets = ["weatherapi", "openweathermap", "weather", "search"];
 
-export default function Home() {
+export async function getStaticProps() {
+  const settings = await getSettings();
+
+  return {
+    props: {
+      settings,
+    },
+  };
+}
+export default function Home({ settings }) {
   const { data: services } = useSWR("/api/services");
   const { data: bookmarks } = useSWR("/api/bookmarks");
   const { data: widgets } = useSWR("/api/widgets");
 
+  const wrappedStyle = {};
+  if (settings.background) {
+    wrappedStyle.backgroundImage = `url(${settings.background})`;
+    wrappedStyle.backgroundSize = "cover";
+  }
+
   return (
     <ColorProvider>
       <ThemeProvider>
         <Head>
-          <title>Welcome</title>
+          <title>{settings.title || "Homepage"}</title>
         </Head>
-        <div className="w-full container m-auto flex flex-col h-screen justify-between">
+        <div className="fixed w-full h-full m-0 p-0" style={wrappedStyle} />
+        <div className="relative w-full container m-auto flex flex-col h-screen justify-between">
           <div className="flex flex-row flex-wrap space-x-0 sm:space-x-4 m-8 pb-4 mt-10 border-b-2 border-theme-800 dark:border-theme-200 justify-between md:justify-start">
             {widgets && (
               <>
@@ -69,6 +87,7 @@ export default function Home() {
 
           <div className="rounded-full flex p-8 w-full justify-between">
             <ColorToggle />
+            <Revalidate />
             <ThemeToggle />
           </div>
         </div>

+ 13 - 0
src/styles/theme.css

@@ -1,3 +1,16 @@
+.theme-white {
+  --color-50: 255 255 255;
+  --color-100: 255 255 255;
+  --color-200: 255 255 255;
+  --color-300: 255 255 255;
+  --color-400: 255 255 255;
+  --color-500: 60 60 60;
+  --color-600: 255 255 255;
+  --color-700: 40 40 40;
+  --color-800: 255 255 255;
+  --color-900: 255 255 255;
+}
+
 .theme-slate {
   --color-50: 248 250 252;
   --color-100: 241 245 249;