@@ -450,6 +470,7 @@ export default function AfterServerView({ server }: { server: string }) {
ownership, they may or may not available at that certain
moment either.
+ {serverObject?.purchased_icons.length == 0 && }
{serverObject?.purchased_icons.map((icon) => (
-
-
-
-
-
-
-
-
- Favorite the server?
-
- By favoriting the server, you can see it later.{" "}
-
- You need to sign in to favorite a server.
-
-
-
-
-
-
-
-
- {
- setLoadingFavorite(true);
- favoriteServer(single.grabOffline()?.name as string).then(
- () => {
- setFavorited(!favorited);
- setLoadingFavorite(false);
- }
- );
- }}
- >
- {favorited && (
-
-
-
- )}
- {!favorited && (
-
-
-
- )}
- {favorited && "Unf"}
- {!favorited && "F"}avorite Server
-
-
-
-
-
- This is unlike voting. The{" "}
- amount of people who favorited are public, but the server
- doesn{"'"}t know who favorited, as Favorites are completely
- anonymous.
-
-
-
+
>
diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx
index c8ee787..96026f2 100644
--- a/src/components/ThemeProvider.tsx
+++ b/src/components/ThemeProvider.tsx
@@ -31,7 +31,7 @@
"use client";
import * as React from "react";
-import { ThemeProvider as NextThemesProvider } from "next-themes";
+import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes";
import { type ThemeProviderProps } from "next-themes/dist/types";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
@@ -45,3 +45,57 @@ export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return {children};
}
+
+interface UseThemeTransitionResult {
+ theme: string | undefined;
+ changeTheme: (changeTheme: string) => () => void;
+ mounted: boolean;
+}
+
+export function useThemeTransition(): UseThemeTransitionResult {
+ const { theme, setTheme, systemTheme } = useTheme();
+ const [mounted, setMounted] = React.useState(false);
+
+ React.useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ const changeTheme = (changeTheme: string) => {
+ if (!mounted) return;
+
+ const resolvedTheme = theme === "system" ? systemTheme : changeTheme;
+
+ if (document.startViewTransition) {
+ document.startViewTransition(() => {
+ const root = document.documentElement;
+ root.style.setProperty(
+ "--current-background",
+ `var(--${resolvedTheme}-background)`
+ );
+ root.style.setProperty(
+ "--current-foreground",
+ `var(--${resolvedTheme}-foreground)`
+ );
+ setTheme(changeTheme);
+ });
+ } else {
+ setTheme(changeTheme);
+ }
+ };
+
+ React.useEffect(() => {
+ if (mounted && theme) {
+ const root = document.documentElement;
+ root.style.setProperty(
+ "--current-background",
+ `var(--${theme}-background)`
+ );
+ root.style.setProperty(
+ "--current-foreground",
+ `var(--${theme}-foreground)`
+ );
+ }
+ }, [mounted, theme]);
+
+ return { theme, changeTheme, mounted };
+}
diff --git a/src/components/ThemeSwitcher.tsx b/src/components/ThemeSwitcher.tsx
index ea06c01..e2758ed 100644
--- a/src/components/ThemeSwitcher.tsx
+++ b/src/components/ThemeSwitcher.tsx
@@ -29,10 +29,7 @@
*/
"use client";
-
-import * as React from "react";
import { Moon, Sun } from "lucide-react";
-import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
import {
@@ -41,27 +38,28 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
+import { useThemeTransition } from "./ThemeProvider";
export function ModeToggle() {
- const { setTheme } = useTheme();
+ const { changeTheme } = useThemeTransition();
return (
-
- setTheme("light")}>
+ changeTheme("light")}>
Light
- setTheme("dark")}>
+ changeTheme("dark")}>
Dark
- setTheme("system")}>
+ changeTheme("system")}>
System
diff --git a/src/components/feat/AchievementList.tsx b/src/components/feat/AchievementList.tsx
index 6f80fa1..77c5d0d 100644
--- a/src/components/feat/AchievementList.tsx
+++ b/src/components/feat/AchievementList.tsx
@@ -36,6 +36,7 @@ import { Card, CardContent } from "../ui/card";
import { Skeleton } from "../ui/skeleton";
import A from "../misc/Link";
import { formalNames } from "@/config/achievements";
+import NoItems from "../misc/NoItems";
export default function AchievementList({ server }: { server: string }) {
const [achievements, setAchievements] = useState<
@@ -70,6 +71,7 @@ export default function AchievementList({ server }: { server: string }) {
Achievements are earned automatically when the server is online. See{" "}
Docs:Advanced/Achievements
+ {achievements.length === 0 && }
{achievements
.filter(
(value, index) => listify(achievements).indexOf(value.type) === index
@@ -109,8 +111,6 @@ export default function AchievementList({ server }: { server: string }) {
);
}
-
-
type WithInterval = K & {
interval: number;
};
diff --git a/src/components/feat/QRCodeGen.tsx b/src/components/feat/QRCodeGen.tsx
new file mode 100644
index 0000000..2147520
--- /dev/null
+++ b/src/components/feat/QRCodeGen.tsx
@@ -0,0 +1,57 @@
+/*
+ * MHSF, Minehut Server List
+ * All external content is rather licensed under the ECA Agreement
+ * located here: https://mhsf.app/docs/legal/external-content-agreement
+ *
+ * All code under MHSF is licensed under the MIT License
+ * by open source contributors
+ *
+ * Copyright (c) 2024 dvelo
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+"use client";
+
+import QRCode from "react-qr-code";
+import { DrawerFooter, DrawerTrigger } from "../ui/drawer";
+import { Button } from "../ui/button";
+import { useTheme } from "next-themes";
+
+export default function QRCodeGenerator({ server }: { server: string }) {
+ const { resolvedTheme } = useTheme();
+
+ return (
+
+
+
+
+ Close
+
+
+
+ );
+}
diff --git a/src/components/misc/NoItems.tsx b/src/components/misc/NoItems.tsx
new file mode 100644
index 0000000..4a79d7d
--- /dev/null
+++ b/src/components/misc/NoItems.tsx
@@ -0,0 +1,48 @@
+/*
+ * MHSF, Minehut Server List
+ * All external content is rather licensed under the ECA Agreement
+ * located here: https://mhsf.app/docs/legal/external-content-agreement
+ *
+ * All code under MHSF is licensed under the MIT License
+ * by open source contributors
+ *
+ * Copyright (c) 2024 dvelo
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+"use client";
+
+import { DatabaseZap } from "lucide-react";
+
+export default function NoItems() {
+ return (
+ <>
+
+
+
+ Huh, we tried to find something, but nothing was found.
+
+
+ >
+ );
+}
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx
index 9838605..d3b29c9 100644
--- a/src/components/ui/button.tsx
+++ b/src/components/ui/button.tsx
@@ -50,6 +50,8 @@ const buttonVariants = cva(
ghost:
"hover:bg-accent hover:text-accent-foreground focus:ring-4 focus:ring-neutral-100 focus:ring-offset-current dark:focus:ring-neutral-900 duration-150 ease-in-out transition-all",
link: "text-primary underline-offset-4 hover:underline",
+ favorite:
+ "text-black rounded-lg hover:bg-primary/90 focus:ring-4 focus:ring-yellow-400/60 focus:ring-offset-current dark:focus:ring-yellow-400/60 duration-150 ease-in-out transition-all bg-gradient-to-bl from-yellow-300 via-yellow-500 to-yellow-100",
},
size: {
default: "h-10 px-4 py-2",
diff --git a/src/config/version.tsx b/src/config/version.tsx
index a87dd62..d76dd17 100644
--- a/src/config/version.tsx
+++ b/src/config/version.tsx
@@ -55,8 +55,30 @@ const FeatureList = ({
);
};
-export const version = "1.4.0";
+export const version = "1.6.0";
export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
+ {
+ id: "h9jr2cbxn7qwfvt5uypsdg",
+ name: "v1.6.0",
+ changelog: (
+
+ Version 1.6.0 (November 17th 2024)
+
+ }
+ />
+ ),
+ },
{
id: "r9swempc7kaqd2j84nutv5",
name: "v1.5.0",
diff --git a/src/lib/head.ts b/src/lib/head.ts
new file mode 100644
index 0000000..3165e09
--- /dev/null
+++ b/src/lib/head.ts
@@ -0,0 +1,36 @@
+/*
+ * MHSF, Minehut Server List
+ * All external content is rather licensed under the ECA Agreement
+ * located here: https://mhsf.app/docs/legal/external-content-agreement
+ *
+ * All code under MHSF is licensed under the MIT License
+ * by open source contributors
+ *
+ * Copyright (c) 2024 dvelo
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+export async function getMinecraftHead(username: string) {
+ const uuidRequest = await fetch("https://api.mojang.com/users/profiles/minecraft/" + username);
+ const uuid = (await uuidRequest.json()).id;
+
+ return `https://crafatar.com/avatars/${uuid}`;
+}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 7de6b74..db00a94 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6847,6 +6847,11 @@ punycode@^2.1.0, punycode@^2.3.0:
resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
+qr.js@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
+ integrity sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==
+
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
@@ -6923,6 +6928,14 @@ react-markdown@^9.0.1:
unist-util-visit "^5.0.0"
vfile "^6.0.0"
+react-qr-code@^2.0.15:
+ version "2.0.15"
+ resolved "https://registry.yarnpkg.com/react-qr-code/-/react-qr-code-2.0.15.tgz#fbfc12952c504bcd64275647e9d1ea63251742ce"
+ integrity sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw==
+ dependencies:
+ prop-types "^15.8.1"
+ qr.js "0.0.0"
+
react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.4, react-remove-scroll-bar@^2.3.6:
version "2.3.6"
resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz"