Compare commits

...

5 Commits

Author SHA1 Message Date
dependabot[bot]
47b2866131
Merge 93ba83433951d8f2b13cdabdd6c0ce0cf9e242fc into 2bcda5fd3b341485846a4acc22d73683f0cabd83 2025-01-31 19:47:12 -06:00
dvelo
2bcda5fd3b
feat: migrate accounts 2025-01-29 21:12:42 -06:00
dvelo
21c0f75e4c fix: type issue 2025-01-29 21:10:43 -06:00
dvelo
532ead4bdf feat: migrate accounts from development to production 2025-01-29 21:03:20 -06:00
dependabot[bot]
93ba834339
build(deps-dev): bump postcss from 8.4.39 to 8.5.1
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.39 to 8.5.1.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.39...8.5.1)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 05:54:22 +00:00
9 changed files with 200 additions and 176 deletions

@ -39,81 +39,99 @@ import { DialogContent, DialogTrigger } from "@/components/ui/dialog";
import CodeDialog from "@/components/misc/LinkDialog";
export default function Settings() {
const clerk = useClerk();
const clerk = useClerk();
const { user, isSignedIn } = useUser();
const [linked, setLinked] = useState(false);
useEffect(() => {
setLinked(user?.publicMetadata.player != undefined);
}, [user, isSignedIn]);
const { user, isSignedIn } = useUser();
const [linked, setLinked] = useState(false);
useEffect(() => {
setLinked(user?.publicMetadata.player != undefined);
}, [user, isSignedIn]);
return (
<main className="p-4">
<strong className="text-3xl">Linking</strong>
<br />
<br />
<strong className="font-bold">Link Account</strong>
<div className="flex items-center">
<p>
Link a Minecraft account to customize a server you own.
<br />{" "}
{user?.publicMetadata.player != undefined && linked && (
<>Currently linked to {user?.publicMetadata.player as string}</>
)}
</p>
const forceUnlink = async () => {
if (!linked) await toast.promise(unlinkMCAccount(), {
success: "Unlinked account!",
loading: "Unlinking...",
error: "Error while unlinking account.",
});
else
await toast.warning("Please use the normal unlink option before using the force unlink one.")
};
<Dialog>
<DialogTrigger>
{!linked && <Button className="h-[30px] ml-2">Link Account</Button>}
</DialogTrigger>
<DialogContent>
<CodeDialog
linked={linked}
setLinked={(c) => {
setLinked(c);
}}
/>
</DialogContent>
</Dialog>
return (
<main className="p-4">
<strong className="text-3xl">Linking</strong>
<br />
<br />
<strong className="font-bold">Link Account</strong>
<div className="flex items-center">
<p>
Link a Minecraft account to customize a server you own.
<br />{" "}
{user?.publicMetadata.player != undefined && linked && (
<>Currently linked to {user?.publicMetadata.player as string}</>
)}
</p>
{linked && (
<Button className="h-[30px] ml-2" disabled>
Already linked
</Button>
)}
</div>
<br />
<strong className="font-bold">Unlink Account</strong>
<div className="flex items-center">
<p>Unlink your Minecraft account if you have already linked one.</p>
<Dialog>
<DialogTrigger>
{!linked && <Button className="h-[30px] ml-2">Link Account</Button>}
</DialogTrigger>
<DialogContent>
<CodeDialog
linked={linked}
setLinked={(c) => {
setLinked(c);
}}
/>
</DialogContent>
</Dialog>
{!linked && (
<Button className="h-[30px] ml-2" disabled>
No linked account
</Button>
)}
{linked && (
<Button className="h-[30px] ml-2" disabled>
Already linked
</Button>
)}
</div>
<br />
<strong className="font-bold">Unlink Account</strong>
<div className="flex items-center">
<p>Unlink your Minecraft account if you have already linked one.</p>
{linked && (
<Button
className="h-[30px] ml-2"
variant="destructive"
onClick={async () => {
await toast.promise(unlinkMCAccount(), {
success: "Unlinked account!",
loading: "Unlinking...",
error: "Error while unlinking account.",
});
setLinked(false);
}}
>
Unlink account
</Button>
)}
</div>
<small className="mt-0">
All of your customizations stay the same, and can be changed if another
account links your Minecraft account.
</small>
</main>
);
{!linked && (
<Button className="h-[30px] ml-2" disabled>
No linked account
</Button>
)}
{linked && (
<Button
className="h-[30px] ml-2"
variant="destructive"
onClick={async () => {
await toast.promise(unlinkMCAccount(), {
success: "Unlinked account!",
loading: "Unlinking...",
error: "Error while unlinking account.",
});
setLinked(false);
}}
>
Unlink account
</Button>
)}
</div>
<small className="mt-0">
All of your customizations stay the same, and can be changed if another
account links your Minecraft account.{" "}
<div
className="cursor-pointer text-blue-600"
onClick={forceUnlink}
onKeyDown={forceUnlink}
onKeyUp={forceUnlink}
>
Still linked in-game? Force unlink your account.
</div>
</small>
</main>
);
}

@ -37,13 +37,13 @@ import { ThemeProvider } from "@/components/ThemeProvider";
import { ClerkThemeProvider } from "@/components/clerk/ClerkThemeProvider";
import NewDomainDialog from "@/components/misc/NewDomainDialog";
import ThemedToaster from "@/components/misc/ThemedToaster";
import UnofficalDialog from "@/components/misc/UnofficalDialog";
import { TooltipProvider } from "@/components/ui/tooltip";
import type { Metadata, Viewport } from "next";
import { Inter as interFont } from "next/font/google";
import LayoutPart from "@/components/feat/LayoutPart";
import AllBanners from "@/components/feat/AllBanners";
import Footer from "@/components/misc/Footer";
import { SwitchEnvPopup } from "@/components/misc/SwitchEnvPopup";
export const extraMetadata = {
twitter: {
@ -84,7 +84,7 @@ export default async function RootLayout({
<SpeedInsights />
<Analytics />
<NewDomainDialog />
<UnofficalDialog />
<SwitchEnvPopup />
<Footer />
</TooltipProvider>
</ThemeProvider>

@ -368,7 +368,7 @@ export default function ServerList() {
"dark:border-gray-50/[.1] dark:bg-gray-50/[.10] dark:hover:bg-gray-50/[.15]"
)}
onClick={() =>
router.push(pageFind(`Server:${server.name}`))
router.push(pageFind(`Server:${server.name}`) as string)
}
>
<div className="items-center gap-2 p-4">

@ -35,8 +35,9 @@ import {
PopoverTrigger,
} from "@/components/ui/popover";
import { Button } from "../ui/button";
import { AtSign, LogIn } from "lucide-react";
import { AtSign, LogIn, Ship } from "lucide-react";
import { useClerk } from "@clerk/nextjs";
import { useRouter } from "@/lib/useRouter";
export default function SignInPopoverButton({
className,
@ -67,11 +68,14 @@ export default function SignInPopoverButton({
export function SignInPopover() {
const clerk = useClerk();
const router = useRouter();
return (
<div className=" grid w-[200px]">
<strong className="text-center">Login</strong>
<small className="text-center pb-6">
Customize your own servers and favorite other servers. Secured by Clerk
<small className="text-center pb-2">
Customize your own servers and favorite other servers. Secured by Clerk
<br className="py-2"/>
If you created your account before Jan. 29, 2025, use the legacy migration button.
</small>
<br />
<Button variant={"ghost"} onClick={() => clerk.openSignIn()}>
@ -82,6 +86,9 @@ export function SignInPopover() {
<AtSign size={18} className="mr-2" />
Sign-up
</Button>
<Button variant="ghost" onClick={() => router.push(process.env.NEXT_PUBLIC_CLERK_SWITCH_DOMAIN as string)}>
<Ship size={18} className="mr-2"/>Legacy Migration
</Button>
</div>
);
}

@ -41,8 +41,8 @@ export default function A({
}) {
return (
<NextLink
href={pageFind(children || "")}
className="no-underline transition duration-300 hover:underline "
href={pageFind(children || "") || "#"}
className="transition duration-300 underline"
title={children}
>
{(children || "").startsWith("Docs:") && (
@ -68,7 +68,7 @@ export function ALegacy({
}) {
return (
<NextLink
href={pageFind(href || "")}
href={pageFind(href || "") || "#"}
className="no-underline transition duration-300 hover:underline "
title={href}
>
@ -95,6 +95,7 @@ export const pageFind = (text: string) => {
if (text === "Special:AccountOptions") return "/account/settings/options";
if (text.startsWith("Server:") && text.endsWith("/Customization"))
return "/server/" + text.substring(7, text.length - 14) + "/customization";
if (text === "Special:ClerkConvertionPage") return process.env.NEXT_PUBLIC_CLERK_SWITCH_DOMAIN;
if (text.startsWith("Server:")) return "/server/" + text.substring(7);
if (text.startsWith("Wiki:"))
return "https://minehut.wiki.gg/wiki/" + text.substring(5);

@ -0,0 +1,58 @@
"use client";
import { useEffect, useState } from "react";
import {
Dialog,
DialogContent,
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
import { OctagonAlert } from "lucide-react";
import A from "./Link";
import { Button } from "../ui/button";
import { useRouter } from "@/lib/useRouter";
export function SwitchEnvPopup() {
const [open, setOpen] = useState(false);
const router = useRouter();
useEffect(() => {
if (localStorage.getItem("mhsf--switch-env-alert") !== "true") {
setOpen(true);
}
}, [])
const setDialogTrigger = (v: boolean) => {
setOpen(v)
if (!v) {
localStorage.setItem("mhsf--switch-env-alert", "true")
}
}
return (
<Dialog open={open} onOpenChange={setDialogTrigger}>
<DialogContent>
<OctagonAlert className="text-orange-300" />
<DialogTitle className="text-3xl">
Wait! Did you have an old account?
</DialogTitle>
<p className="inline">
<strong>If you had an account before Jan. 28th, 2025</strong>, you
have a legacy account that <i>needs to be converted.</i>
</p>
<p className="inline">
Legacy accounts can be converted by going to{" "}
<A alt="this page">Special:ClerkConvertionPage</A> and logging in with
your old account & creating a new account. Your old account settings &
content will automatically be transferred to your new account.{" "}
</p>
<div className="flex items-center">
<Button onClick={() => { router.push(process.env.NEXT_PUBLIC_CLERK_SWITCH_DOMAIN || "#") }}>Convert account</Button>{" "}
<DialogTrigger>
<Button className="ml-2" variant="outline">Close</Button>
</DialogTrigger>
</div>
</DialogContent>
</Dialog>
);
}

@ -1,77 +0,0 @@
/*
* MHSF, Minehut Server List
* All external content is rather licensed under the ECA Agreement
* located here: https://list.mlnehut.com/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 { useEffect, useState } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "../ui/dialog";
export default function UnofficalDialog() {
const [isOpen, setOpen] = useState(false);
useEffect(() => {
const dialog = localStorage.getItem("unoffical-dialog-open");
if (dialog == null) {
setOpen(true);
}
}, []);
const onChangeVal = (state: boolean) => {
if (state == false) {
setOpen(false);
localStorage.setItem("unoffical-dialog-open", "true");
} else setOpen(state);
};
return (
<Dialog open={isOpen} onOpenChange={onChangeVal}>
<DialogContent>
<DialogHeader>
<DialogTitle>Welcome to the Minehut Server List (MHSF)</DialogTitle>
</DialogHeader>
<DialogDescription>
MHSF is a Minehut server-list using the Minehut API to serve you
servers with filters, sorts and other helpful information when picking
a server to play.{" "}
<span className="font-bold">
Keep in mind that MHSF is not endorsed by Minehut or GamerSafer in
any way, as MHSF is a open-source unofficial project.
</span>
</DialogDescription>
</DialogContent>
</Dialog>
);
}

@ -67,8 +67,25 @@ const FeatureList = ({
);
};
export const version = "1.7.0";
export const version = "1.7.5";
export const changelog: { name: string; id: string; changelog: ReactNode }[] = [
{
id: "tj4ijg09aern9eargjjuauerr",
name: "v1.7.5",
changelog: (
<FeatureList
github="https://github.com/DeveloLongScript/MHSF/releases/tag/1.7.5"
features={[
"Migrated accounts from development to production"
]}
title={
<strong className="flex items-center">
Version 1.7.5 (January 29th 2025)
</strong>
}
/>
),
},
{
id: "38ufajf8efajwj3njdaisef",
name: "v1.7",

@ -6422,10 +6422,10 @@ mz@^2.7.0:
object-assign "^4.0.1"
thenify-all "^1.0.0"
nanoid@^3.3.6, nanoid@^3.3.7:
version "3.3.7"
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
nanoid@^3.3.6, nanoid@^3.3.8:
version "3.3.8"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
natural-compare@^1.4.0:
version "1.4.0"
@ -6788,10 +6788,10 @@ periscopic@^3.0.0:
estree-walker "^3.0.0"
is-reference "^3.0.0"
picocolors@^1.0.0, picocolors@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz"
integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
picocolors@^1.0.0, picocolors@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
version "2.3.1"
@ -6906,13 +6906,13 @@ postcss@8.4.31:
source-map-js "^1.0.2"
postcss@^8, postcss@^8.4.23, postcss@^8.4.38, postcss@^8.4.39:
version "8.4.39"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.39.tgz#aa3c94998b61d3a9c259efa51db4b392e1bde0e3"
integrity sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==
version "8.5.1"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.1.tgz#e2272a1f8a807fafa413218245630b5db10a3214"
integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.1"
source-map-js "^1.2.0"
nanoid "^3.3.8"
picocolors "^1.1.1"
source-map-js "^1.2.1"
prelude-ls@^1.2.1:
version "1.2.1"
@ -7553,10 +7553,10 @@ sonner@^1.7.0:
resolved "https://registry.yarnpkg.com/sonner/-/sonner-1.7.0.tgz#f59a2a70e049a179b6fbd1bb1bf2619d5ced07c0"
integrity sha512-W6dH7m5MujEPyug3lpI2l3TC3Pp1+LTgK0Efg+IHDrBbtEjyCmCHHo6yfNBOsf1tFZ6zf+jceWwB38baC8yO9g==
source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz"
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
source-map-resolve@^0.5.2:
version "0.5.3"