···11import { getUser } from "@/lib/discord/user";
2233-export const revalidate = 691200; // 8 days
33+export const revalidate = 691_200; // 8 days
4455export async function GET() {
66 const user = await getUser(process.env.NEXT_PUBLIC_CLIENT_ID as string);
+1-2
app/(home)/commands.component.tsx
···11-import { HiFire, HiInformationCircle } from "react-icons/hi";
22-31import Box from "@/components/box";
42import { Badge } from "@/components/ui/badge";
53import { defaultFetchOptions } from "@/lib/api";
64import { intl } from "@/utils/numbers";
55+import { HiFire, HiInformationCircle } from "react-icons/hi";
7687interface Commands {
98 name: string;
+3-4
app/(home)/debug/page.tsx
···11+import { Shiggy } from "@/components/shiggy";
22+import { Button } from "@/components/ui/button";
33+import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
14import type { Metadata } from "next";
25import { cookies, headers } from "next/headers";
36import { HiTrash } from "react-icons/hi";
44-55-import { Shiggy } from "@/components/shiggy";
66-import { Button } from "@/components/ui/button";
77-import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
8798import Panel from "./panel.component";
109
+2-3
app/(home)/faq.component.tsx
···11"use client";
2233+import LinkTag from "@/components/link-tag";
44+import { Section } from "@/components/section";
35import { Accordion, AccordionItem, Code } from "@nextui-org/react";
46import { useCookies } from "next-client-cookies";
57import { HiBell, HiCash, HiChat, HiLockClosed, HiUserAdd } from "react-icons/hi";
66-77-import LinkTag from "@/components/link-tag";
88-import { Section } from "@/components/section";
98109const data = [
1110 {
+3-4
app/(home)/impressum/page.tsx
···11-import type { Metadata } from "next";
22-import Link from "next/link";
33-import { HiExternalLink } from "react-icons/hi";
44-51import { Section } from "@/components/section";
62import { Separator } from "@/components/ui/separator";
73import { cn } from "@/utils/cn";
84import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
55+import type { Metadata } from "next";
66+import Link from "next/link";
77+import { HiExternalLink } from "react-icons/hi";
98109export const revalidate = false;
1110
+2-3
app/(home)/layout.tsx
···11+import { Footer } from "@/components/footer";
12import { Suspense } from "react";
2333-import { Footer } from "@/components/footer";
44-55-export const revalidate = 43200;
44+export const revalidate = 43_200;
6576export default function RootLayout({
87 children
+17-18
app/(home)/page.tsx
···11-import { Code } from "@nextui-org/react";
22-import { Montserrat, Patrick_Hand } from "next/font/google";
33-import { headers } from "next/headers";
44-import Image from "next/image";
55-import Link from "next/link";
66-import { Suspense } from "react";
77-import { BsYoutube } from "react-icons/bs";
88-import { HiArrowNarrowRight, HiArrowRight, HiCash, HiCheck, HiFire, HiLockOpen, HiUserAdd } from "react-icons/hi";
99-101import Box from "@/components/box";
112import Comment from "@/components/comment";
123import DiscordAppBadge from "@/components/discord/app-badge";
···3425import { toFixedArrayLength } from "@/utils/fixed-array-length";
3526import { actor } from "@/utils/tts";
3627import { getCanonicalUrl } from "@/utils/urls";
2828+import { Code } from "@nextui-org/react";
2929+import { Montserrat, Patrick_Hand } from "next/font/google";
3030+import { headers } from "next/headers";
3131+import Image from "next/image";
3232+import Link from "next/link";
3333+import { Suspense } from "react";
3434+import { BsYoutube } from "react-icons/bs";
3535+import { HiArrowNarrowRight, HiArrowRight, HiCash, HiCheck, HiFire, HiLockOpen, HiUserAdd } from "react-icons/hi";
37363837import { Commands } from "./commands.component";
3938import { Faq } from "./faq.component";
···4241const montserrat = Montserrat({ subsets: ["latin"] });
4342const handwritten = Patrick_Hand({ subsets: ["latin"], weight: "400" });
44434545-export const revalidate = 43200;
4444+export const revalidate = 43_200;
46454746const styles = {
4847 h2: cn(montserrat.className, "lg:text-5xl text-4xl bg-gradient-to-b bg-clip-text text-transparent from-neutral-200 from-40% to-neutral-300 font-bold mb-4"),
···356355 <DiscordMessageEmbed
357356 mode="DARK"
358357 title="My wife insisted I do this for her"
359359- color={0x8a57ff}
358358+ color={0x8A_57_FF}
360359 >
361360 <Image
362361 alt=""
···467466 <Image
468467 alt="example leaderboard card"
469468 src={LeaderboardPic}
470470- height={1024 / 4}
469469+ height={1_024 / 4}
471470 itemProp="image"
472471 loading="lazy"
473473- width={2048 / 4}
472472+ width={2_048 / 4}
474473 />
475474 </DiscordMessage>
476475 </div>
···515514 <DiscordMessage {...messageProps()}>
516515 <DiscordMessageEmbed
517516 mode={"DARK"}
518518- color={0xbd7fd6}
517517+ color={0xBD_7F_D6}
519518 author={{
520519 text: "@mwlica",
521520 icon_url: "/luna.webp"
···579578 height={(256 + 16) / 2}
580579 itemProp="image"
581580 loading="lazy"
582582- width={1024 / 2}
581581+ width={1_024 / 2}
583582 />
584583 </DiscordMessage>
585584 </div>
···634633 alt="anime captcha verification example"
635634 className="max-w-56"
636635 src={CaptchaPic}
637637- height={1530 / 5}
636636+ height={1_530 / 5}
638637 itemProp="image"
639638 loading="lazy"
640640- width={1070 / 5}
639639+ width={1_070 / 5}
641640 />
642641 </div>
643642 </Box>
···700699 >
701700 <DiscordMessageEmbed
702701 mode={"DARK"}
703703- color={0xbc7ed4}
702702+ color={0xBC_7E_D4}
704703 >
705704 <DiscordMarkdown mode={"DARK"} text="To create a custom command, go to [your server's dashboard](/dashboard?to=custom-commands), click on `Create`, fill in the response **content**, **embed title**, **embed description**, **embed color**, **embed images**, command **permissions** and more. When you're done you can start using the command 🎉" />
706705 </DiscordMessageEmbed>
···11+import { Badge } from "@/components/ui/badge";
22+import { cn } from "@/utils/cn";
33+import { intl } from "@/utils/numbers";
14import Image from "next/image";
25import type { ReactNode } from "react";
36import { HiLightningBolt } from "react-icons/hi";
44-55-import { Badge } from "@/components/ui/badge";
66-import { cn } from "@/utils/cn";
77-import { intl } from "@/utils/numbers";
8798import type { ApiCluster } from "./api";
109···6968 />
7069 );
7170}
7272-73717472function Row({ name, children, className }: { name: string; children: ReactNode; className?: string; }) {
7573 return (
+3-4
app/(home)/status/layout.tsx
···11+import { Section } from "@/components/section";
22+import { cn } from "@/utils/cn";
33+import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
14import type { Metadata } from "next";
25import { Montserrat } from "next/font/google";
36import type { ReactNode } from "react";
44-55-import { Section } from "@/components/section";
66-import { cn } from "@/utils/cn";
77-import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
8798import { Commands } from "../commands.component";
109
+3-4
app/(home)/status/side.component.tsx
···11"use client";
2233+import DumbTextInput from "@/components/inputs/dumb-text-input";
44+import { Badge } from "@/components/ui/badge";
55+import { intl } from "@/utils/numbers";
36import { Accordion, AccordionItem } from "@nextui-org/react";
47import { useCookies } from "next-client-cookies";
58import { type ReactNode, useEffect, useMemo, useState } from "react";
66-77-import DumbTextInput from "@/components/inputs/dumb-text-input";
88-import { Badge } from "@/components/ui/badge";
99-import { intl } from "@/utils/numbers";
1091110import type { ApiV1StatusGetResponse } from "./api";
1211
+3-4
app/(home)/team/discord.component.tsx
···11+import { getGuild } from "@/lib/discord/guild";
22+import { cn } from "@/utils/cn";
33+import { intl } from "@/utils/numbers";
14import Image from "next/image";
25import Link from "next/link";
36import { HiExternalLink } from "react-icons/hi";
44-55-import { getGuild } from "@/lib/discord/guild";
66-import { cn } from "@/utils/cn";
77-import { intl } from "@/utils/numbers";
8798export async function DiscordServer({
109 guildId
+3-4
app/(home)/team/page.tsx
···11+import { filterDuplicates } from "@/utils/filter-duplicates";
22+import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
13import type { Metadata } from "next";
24import { BsDiscord, BsGithub } from "react-icons/bs";
33-44-import { filterDuplicates } from "@/utils/filter-duplicates";
55-import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
6576import { members, repos } from "./constants";
87import { DiscordServer } from "./discord.component";
98import { Person } from "./person.component";
109import { Repository } from "./repository.component";
11101212-export const revalidate = 3600;
1111+export const revalidate = 3_600;
13121413export const generateMetadata = (): Metadata => {
1514 const title = "Team";
+3-4
app/(home)/team/person.component.tsx
···11+import { getUser } from "@/lib/discord/user";
22+import { cn } from "@/utils/cn";
13import Image from "next/image";
24import Link from "next/link";
35import type { AnchorHTMLAttributes, DetailedHTMLProps, HTMLAttributes } from "react";
44-55-import { getUser } from "@/lib/discord/user";
66-import { cn } from "@/utils/cn";
7687type DivProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
98type LinkProps = DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>;
···4645}
47464847function isLinkProps(props: DivProps | LinkProps): props is LinkProps {
4949- return "href" in props && !!props.href;
4848+ return "href" in props && Boolean(props.href);
5049}
51505251function Component(props: DivProps | LinkProps) {
+2-3
app/(home)/team/repository.component.tsx
···11-import Link from "next/link";
22-import { HiBeaker, HiExternalLink, HiStar } from "react-icons/hi";
33-41import { Badge } from "@/components/ui/badge";
52import { getRepository } from "@/lib/github";
63import { cn } from "@/utils/cn";
44+import Link from "next/link";
55+import { HiBeaker, HiExternalLink, HiStar } from "react-icons/hi";
7687export async function Repository({
98 fullname
+2-3
app/(home)/terms/page.tsx
···11+import BeautifyMarkdown from "@/components/markdown";
22+import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
13import { readFile } from "fs/promises";
24import type { Metadata } from "next";
33-44-import BeautifyMarkdown from "@/components/markdown";
55-import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
6576export const revalidate = false;
87
+2-3
app/(home)/terms/payment/page.tsx
···11+import BeautifyMarkdown from "@/components/markdown";
22+import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
13import { readFile } from "fs/promises";
24import type { Metadata } from "next";
33-44-import BeautifyMarkdown from "@/components/markdown";
55-import { getBaseUrl, getCanonicalUrl } from "@/utils/urls";
6576export const revalidate = false;
87
···11"use client";
2233+import { LoginButton } from "@/components/login-button";
34import { Pagination as UiPagination } from "@nextui-org/react";
45import { useRouter } from "next/navigation";
56import { useCookies } from "next-client-cookies";
66-77-import { LoginButton } from "@/components/login-button";
8798interface Props {
109 searchParams: {
···3029 showControls
3130 total={pages}
3231 size="lg"
3333- page={parseInt(searchParams.page || "0")}
3232+ page={Number.parseInt(searchParams.page || "0", 10)}
3433 onChange={(now) => {
3534 const params = new URLSearchParams(searchParams);
3635 params.delete("page");
+11-12
app/leaderboard/[guildId]/side.component.tsx
···11"use client";
2233-import { Accordion, AccordionItem, Code } from "@nextui-org/react";
44-import Link from "next/link";
55-import { useRouter } from "next/navigation";
66-import { useCookies } from "next-client-cookies";
77-import { useState } from "react";
88-import { BsDiscord } from "react-icons/bs";
99-import { HiAnnotation, HiLink, HiTrash, HiViewGridAdd, HiVolumeUp } from "react-icons/hi";
1010-113import Ad from "@/components/ad";
124import Modal from "@/components/modal";
135import Notice, { NoticeType } from "@/components/notice";
···168import type { ApiError, ApiV1GuildsGetResponse, ApiV1GuildsTopmembersPaginationGetResponse } from "@/typings";
179import { intl } from "@/utils/numbers";
1810import { getCanonicalUrl } from "@/utils/urls";
1111+import { Accordion, AccordionItem, Code } from "@nextui-org/react";
1212+import Link from "next/link";
1313+import { useRouter } from "next/navigation";
1414+import { useCookies } from "next-client-cookies";
1515+import { useState } from "react";
1616+import { BsDiscord } from "react-icons/bs";
1717+import { HiAnnotation, HiLink, HiTrash, HiViewGridAdd, HiVolumeUp } from "react-icons/hi";
19182019export default function Side({
2120 guild,
···8382 className="w-full justify-start mt-2"
8483 >
8584 <Link
8686- href={getCanonicalUrl("dashboard", guild.id as string)}
8585+ href={getCanonicalUrl("dashboard", guild.id)}
8786 >
8887 <HiViewGridAdd />
8988 Dashboard
···133132 <br />
134133 <br />
135134 The percentage {
136136- cookies.get("lbc") !== "server"
137137- ? "indicates the gap in messages needed to surpass the next user"
138138- : "reflects the contribution of server activity from that user"
135135+ cookies.get("lbc") === "server"
136136+ ? "reflects the contribution of server activity from that user"
137137+ : "indicates the gap in messages needed to surpass the next user"
139138 }.
140139 </AccordionItem>
141140
+4-5
app/login/[social]/route.ts
···11+import { defaultCookieOptions } from "@/lib/cookies";
12import { cookies } from "next/headers";
23import { redirect } from "next/navigation";
3444-import { defaultCookieOptions } from "@/lib/cookies";
55-65import { connect, disconnect, getAuthorizeUrl } from "./api";
7688-const SOCIALS = ["spotify", "bluesky"];
77+const SOCIALS = new Set(["spotify", "bluesky"]);
98109export async function GET(
1110 request: Request,
···1312) {
1413 const { social } = await params;
15141616- if (!SOCIALS.includes(social)) {
1515+ if (!SOCIALS.has(social)) {
1716 return Response.json({
1817 status: 400,
1918 message: "Invalid social"
···6160 res.verifier,
6261 {
6362 ...defaultCookieOptions,
6464- expires: new Date(Date.now() + 1000 * 600)
6363+ expires: new Date(Date.now() + 1_000 * 600)
6564 }
6665 );
6766 }
+2-3
app/login/open-graph/page.tsx
···11+import { getCanonicalUrl } from "@/utils/urls";
12import type { Metadata } from "next";
23import { headers } from "next/headers";
34import { redirect } from "next/navigation";
44-55-import { getCanonicalUrl } from "@/utils/urls";
6576export const generateMetadata = (): Metadata => {
87 const title = "Login with Discord";
···2221 type: "website",
2322 images: {
2423 url,
2525- width: 1200,
2424+ width: 1_200,
2625 height: 630,
2726 type: "image/png"
2827 }
+2-3
app/login/route.ts
···11+import { defaultCookieOptions } from "@/lib/cookies";
22+import { getCanonicalUrl } from "@/utils/urls";
13import { PermissionFlagsBits } from "discord-api-types/v10";
24import { cookies } from "next/headers";
35import { redirect } from "next/navigation";
44-55-import { defaultCookieOptions } from "@/lib/cookies";
66-import { getCanonicalUrl } from "@/utils/urls";
7687import { createSession } from "./api";
98
+10-11
app/passport/[guildId]/page.tsx
···11-import type { Metadata } from "next";
22-import { cookies } from "next/headers";
33-import Image from "next/image";
44-import Link from "next/link";
55-import { BsDiscord } from "react-icons/bs";
66-import { HiChartBar, HiCheck, HiLightningBolt, HiLockClosed, HiStar, HiUsers, HiX } from "react-icons/hi";
77-81import { ClientButton } from "@/components/client";
92import ImageReduceMotion from "@/components/image-reduce-motion";
103import { ListFeature } from "@/components/list";
···147import paintPic from "@/public/paint.webp";
158import { intl } from "@/utils/numbers";
169import { getCanonicalUrl } from "@/utils/urls";
1010+import type { Metadata } from "next";
1111+import { cookies } from "next/headers";
1212+import Image from "next/image";
1313+import Link from "next/link";
1414+import { BsDiscord } from "react-icons/bs";
1515+import { HiChartBar, HiCheck, HiLightningBolt, HiLockClosed, HiStar, HiUsers, HiX } from "react-icons/hi";
17161817import { getPassport } from "./api";
1918import { Verify } from "./verify.component";
···165164 <div className="mb-4 text-neutral-100 font-semibold text-xl">Modern, Simple, Wamellow 👋</div>
166165 <ListFeature
167166 items={[
168168- { icon: <HiLockClosed />, title: "Secure", description: "Wamellow does not store your IP, Geolocation or similar, nothing is kept, no logs.", color: 0xa84b56 },
169169- { icon: <BsDiscord />, title: "Integration", description: "Unparalleled Discord integration, setting us apart from the rest.", color: 0x4752c4 },
170170- { icon: <HiStar />, title: "Easy", description: "The most user-friendly and visually appealing verification process.", color: 0x7f43d8 },
171171- { icon: <HiLightningBolt />, title: "Fast", description: "Welcome new members easily with the fastest verification method available.", color: 0xff9156 }
167167+ { icon: <HiLockClosed />, title: "Secure", description: "Wamellow does not store your IP, Geolocation or similar, nothing is kept, no logs.", color: 0xA8_4B_56 },
168168+ { icon: <BsDiscord />, title: "Integration", description: "Unparalleled Discord integration, setting us apart from the rest.", color: 0x47_52_C4 },
169169+ { icon: <HiStar />, title: "Easy", description: "The most user-friendly and visually appealing verification process.", color: 0x7F_43_D8 },
170170+ { icon: <HiLightningBolt />, title: "Fast", description: "Welcome new members easily with the fastest verification method available.", color: 0xFF_91_56 }
172171 ]}
173172 />
174173 </div>
+5-6
app/passport/[guildId]/verify.component.tsx
···11"use client";
2233-import Link from "next/link";
44-import { BsDiscord } from "react-icons/bs";
55-import { HiExclamation, HiFingerPrint, HiLockClosed } from "react-icons/hi";
66-import { TailSpin } from "react-loading-icons";
77-83import { userStore } from "@/common/user";
94import ImageReduceMotion from "@/components/image-reduce-motion";
105import { Badge } from "@/components/ui/badge";
···127import type { ApiV1GuildsGetResponse } from "@/typings";
138import { State, useCaptcha } from "@/utils/captcha";
149import { cn } from "@/utils/cn";
1010+import Link from "next/link";
1111+import { BsDiscord } from "react-icons/bs";
1212+import { HiExclamation, HiFingerPrint, HiLockClosed } from "react-icons/hi";
1313+import { TailSpin } from "react-loading-icons";
15141615interface Props {
1716 guild: ApiV1GuildsGetResponse;
···5150 ref={button}
5251 variant={state === State.Success ? "success" : "secondary"}
5352 className={cn(error && "cursor-not-allowed", state === State.Success && "cursor-not-allowed", "font-medium w-full")}
5454- disabled={!!error || state === State.Success}
5353+ disabled={Boolean(error) || state === State.Success}
5554 >
5655 {state === State.Loading
5756 ? <TailSpin stroke="#d4d4d4" strokeWidth={8} className="relative h-3 w-3 overflow-visible" />
+11-13
app/profile/billing/page.tsx
···11"use client";
2233-import { Turnstile, type TurnstileInstance } from "@marsidev/react-turnstile";
44-import Link from "next/link";
55-import { useRef, useState } from "react";
66-import { GrAmex } from "react-icons/gr";
77-import { HiCreditCard, HiLightningBolt } from "react-icons/hi";
88-import { SiDinersclub, SiDiscover, SiJcb, SiMastercard, SiStripe, SiVisa } from "react-icons/si";
99-103import { DonationSelect } from "@/app/(home)/premium/subscribe.component";
114import { userStore } from "@/common/user";
125import Box from "@/components/box";
···2215import { Skeleton } from "@/components/ui/skeleton";
2316import { type ApiEdit, useApi } from "@/lib/api/hook";
2417import type { ApiV1UsersMeBillingGetResponse, ApiV1UsersMeGuildsGetResponse } from "@/typings";
2525-1818+import { Turnstile, type TurnstileInstance } from "@marsidev/react-turnstile";
1919+import Link from "next/link";
2020+import { useRef, useState } from "react";
2121+import { GrAmex } from "react-icons/gr";
2222+import { HiCreditCard, HiLightningBolt } from "react-icons/hi";
2323+import { SiDinersclub, SiDiscover, SiJcb, SiMastercard, SiStripe, SiVisa } from "react-icons/si";
26242725function isActive(status: ApiV1UsersMeBillingGetResponse["status"]): status is "active" | "trialing" | "past_due" {
2826 return status === "active" || status === "trialing" || status === "past_due";
···5856 </>);
5957 }
60586161- const periodEndsInDays = Math.floor((((data?.currentPeriodEnd || 0) - Date.now() / 1000) / (60 * 60 * 24)));
5959+ const periodEndsInDays = Math.floor((((data?.currentPeriodEnd || 0) - Date.now() / 1_000) / (60 * 60 * 24)));
6260 const periodEndsInStr = `${periodEndsInDays > 1 ? "in " : ""}${periodEndsInDays === 0 ? "Today" : periodEndsInDays === 1 ? "Tomorrow" : periodEndsInDays} ${periodEndsInDays > 1 ? "days" : ""}`;
63616462 return (
···102100 ? <Skeleton className="h-12 w-full" />
103101 : (data?.cancelAtPeriodEnd
104102 ? <p>
105105- Your subscription will expire on <span className="font-semibold text-neutral-300">{new Date(data!.currentPeriodEnd * 1000).toLocaleDateString()}</span> and you will not be charged again.
103103+ Your subscription will expire on <span className="font-semibold text-neutral-300">{new Date(data.currentPeriodEnd * 1_000).toLocaleDateString()}</span> and you will not be charged again.
106104 </p>
107105 : <p>
108108- Your subscription will renew on <span className="font-semibold text-neutral-300">{new Date(data!.currentPeriodEnd * 1000).toLocaleDateString()}</span>, for a total of <span className="font-semibold text-neutral-300">EUR {(4 + (data!.donationQuantity || 0)).toFixed(2)}</span>.
106106+ Your subscription will renew on <span className="font-semibold text-neutral-300">{new Date(data!.currentPeriodEnd * 1_000).toLocaleDateString()}</span>, for a total of <span className="font-semibold text-neutral-300">EUR {(4 + (data!.donationQuantity || 0)).toFixed(2)}</span>.
109107110108 You{"'"}re paying <span className="font-semibold text-neutral-300">EUR {(4).toFixed(2)} Premium</span> and <span className="font-semibold text-neutral-300">EUR {(data!.donationQuantity || 0).toFixed(2)} Donation{data!.donationQuantity ? "s" : ""}</span>
111109 {" "}
···233231 name="Premium Guilds"
234232 url="/users/@me/billing/premium-guilds"
235233 dataName="guildIds"
236236- items={data
237237- ?.filter((guild) => guild.bot)
234234+ items={(data || [])
235235+ .filter((guild) => guild.bot)
238236 .map((guild) => ({
239237 icon: (
240238 <ImageReduceMotion
+6-7
app/profile/connections/page.tsx
···11"use client";
2233-import Image from "next/image";
44-import { useRouter } from "next/navigation";
55-import { useState } from "react";
66-import { BsSpotify } from "react-icons/bs";
77-import { HiFingerPrint, HiTrash } from "react-icons/hi";
88-import { SiBluesky } from "react-icons/si";
99-103import DumbTextInput from "@/components/inputs/dumb-text-input";
114import Modal from "@/components/modal";
125import Notice, { NoticeType } from "@/components/notice";
···158import { useApi } from "@/lib/api/hook";
169import { type ApiV1UsersMeConnectionsGetResponse, ConnectionType } from "@/typings";
1710import { cn } from "@/utils/cn";
1111+import Image from "next/image";
1212+import { useRouter } from "next/navigation";
1313+import { useState } from "react";
1414+import { BsSpotify } from "react-icons/bs";
1515+import { HiFingerPrint, HiTrash } from "react-icons/hi";
1616+import { SiBluesky } from "react-icons/si";
18171918const CONNECTION_TYPES = Object
2019 .entries(ConnectionType)
+14-15
app/profile/layout.tsx
···11"use client";
2233-import Link from "next/link";
44-import { redirect } from "next/navigation";
55-import { useCookies } from "next-client-cookies";
66-import { Suspense } from "react";
77-import CountUp from "react-countup";
88-import { HiCreditCard, HiCubeTransparent, HiFire, HiHome, HiPhotograph, HiTranslate } from "react-icons/hi";
99-import { useQuery } from "react-query";
1010-113import { userStore } from "@/common/user";
124import ImageReduceMotion from "@/components/image-reduce-motion";
135import { ListTab } from "@/components/list";
···179import { Skeleton } from "@/components/ui/skeleton";
1810import { cacheOptions, getData } from "@/lib/api";
1911import type { ApiV1UsersMeGetResponse } from "@/typings";
1212+import Link from "next/link";
1313+import { redirect } from "next/navigation";
1414+import { useCookies } from "next-client-cookies";
1515+import { Suspense } from "react";
1616+import CountUp from "react-countup";
1717+import { HiCreditCard, HiCubeTransparent, HiFire, HiHome, HiPhotograph, HiTranslate } from "react-icons/hi";
1818+import { useQuery } from "react-query";
20192120export default function RootLayout({
2221 children
···3635 url,
3736 () => getData<ApiV1UsersMeGetResponse>(url),
3837 {
3939- enabled: !!user?.id,
3838+ enabled: Boolean(user?.id),
4039 onSuccess: (d) => userStore.setState({
4140 ...user,
4241 extended: "status" in d ? {} : d
···7675 />
7776 </Skeleton>
78777979- {!user?.id ?
8080- <div className="flex flex-col mt-2">
8181- <Skeleton className="rounded-xl w-32 h-5 mb-2" />
8282- <Skeleton className="rounded-md w-[90px] h-7" />
8383- </div>
8484- :
7878+ {user?.id ?
8579 <div className="flex flex-col gap-1">
8680 <div className="text-2xl dark:text-neutral-200 text-neutral-800 font-medium">
8781 {user.globalName || user.username}
···9892 {user.extended?.voteCount} VOTE{user.extended?.voteCount === 1 ? "" : "S"}
9993 </Badge>
10094 </Link>
9595+ </div>
9696+ :
9797+ <div className="flex flex-col mt-2">
9898+ <Skeleton className="rounded-xl w-32 h-5 mb-2" />
9999+ <Skeleton className="rounded-md w-[90px] h-7" />
101100 </div>
102101 }
103102 </div>
+7-8
app/profile/page.tsx
···11"use client";
2233-import { motion } from "framer-motion";
44-import Link from "next/link";
55-import { useSearchParams } from "next/navigation";
66-import { useCookies } from "next-client-cookies";
77-import { useMemo, useState } from "react";
88-import { HiChartBar, HiRefresh, HiUserAdd, HiViewGridAdd } from "react-icons/hi";
99-103import ImageReduceMotion from "@/components/image-reduce-motion";
114import DumbTextInput from "@/components/inputs/dumb-text-input";
125import { ScreenMessage } from "@/components/screen-message";
···147import { useApi } from "@/lib/api/hook";
158import type { ApiV1UsersMeGuildsGetResponse } from "@/typings";
169import { cn } from "@/utils/cn";
1010+import { motion } from "framer-motion";
1111+import Link from "next/link";
1212+import { useSearchParams } from "next/navigation";
1313+import { useCookies } from "next-client-cookies";
1414+import { useMemo, useState } from "react";
1515+import { HiChartBar, HiRefresh, HiUserAdd, HiViewGridAdd } from "react-icons/hi";
17161817const MAX_GUILDS = 50 as const;
1918···126125 {isHuge && (
127126 <ScreenMessage
128127 title="There are too many servers.."
129129- description={`To save some performance, use the search to find a guild. Showing ${MAX_GUILDS} out of ~${guilds.length < 1000 ? length : Math.round(length / 1000) * 1000}.`}
128128+ description={`To save some performance, use the search to find a guild. Showing ${MAX_GUILDS} out of ~${guilds.length < 1_000 ? length : Math.round(length / 1_000) * 1_000}.`}
130129 />
131130 )}
132131 </div>);
+6-7
app/profile/rank/card-style.component.tsx
···11-import type { ApiError } from "next/dist/server/api-utils";
22-import Image from "next/image";
33-import { type ChangeEvent, useRef, useState } from "react";
44-import { HiUpload } from "react-icons/hi";
55-61import { type User, userStore } from "@/common/user";
72import Box from "@/components/box";
83import { Shiggy } from "@/components/shiggy";
···116import { cn } from "@/utils/cn";
127import { deepMerge } from "@/utils/deepMerge";
138import sleep from "@/utils/sleep";
99+import type { ApiError } from "next/dist/server/api-utils";
1010+import Image from "next/image";
1111+import { type ChangeEvent, useRef, useState } from "react";
1212+import { HiUpload } from "react-icons/hi";
14131514enum State {
1615 Idle = 0,
···6059 return;
6160 }
62616363- await sleep(1000 * 3);
6262+ await sleep(1_000 * 3);
6463 setState(State.Success);
65646665 userStore.setState({
···145144 </div>
146145147146 <div className="absolute blur-sm gap-4 grid grid-cols-6 left-4 lg:grid-cols-6 md:blur-none md:bottom-4 md:left-0 md:opacity-100 md:relative md:scale-100 md:top-0 md:w-1/2 opacity-45 rotate-1 scale-105 top-6 w-full">
148148- {new Array(18).fill(0).map((_, i) =>
147147+ {Array.from({ length: 18 }).fill(0).map((_, i) =>
149148 <Emoji
150149 key={"emoji-" + i}
151150 index={i}
···11+import type { ApiV1GuildsChannelsGetResponse, ApiV1GuildsEmojisGetResponse, ApiV1GuildsGetResponse, ApiV1GuildsRolesGetResponse } from "@/typings";
12import { create } from "zustand";
22-33-import type { ApiV1GuildsChannelsGetResponse, ApiV1GuildsEmojisGetResponse, ApiV1GuildsGetResponse, ApiV1GuildsRolesGetResponse } from "@/typings";
4354export interface Guild extends ApiV1GuildsGetResponse {
65 channels?: ApiV1GuildsChannelsGetResponse[];
+1-2
common/user.ts
···11+import type { ApiV1UsersMeGetResponse } from "@/typings";
12import { create } from "zustand";
22-33-import type { ApiV1UsersMeGetResponse } from "@/typings";
4354export interface User {
65 HELLO_AND_WELCOME_TO_THE_DEV_TOOLS__PLEASE_GO_AWAY?: true;
+1-2
components/ad.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import { Poppins } from "next/font/google";
45import Link from "next/link";
56import type { FunctionComponent } from "react";
67import { HiArrowNarrowRight } from "react-icons/hi";
77-88-import { cn } from "@/utils/cn";
98109import { Button } from "./ui/button";
1110
+1-2
components/box.tsx
···11+import { cn } from "@/utils/cn";
12import React, { type HTMLProps } from "react";
22-33-import { cn } from "@/utils/cn";
4354type Props = HTMLProps<HTMLDivElement> & {
65 children: React.ReactNode;
···11"use client";
2233+import { guildStore } from "@/common/guilds";
44+import { Button } from "@/components/ui/button";
35import Link from "next/link";
46import { HiArrowLeft, HiExternalLink } from "react-icons/hi";
55-66-import { guildStore } from "@/common/guilds";
77-import { Button } from "@/components/ui/button";
8798interface Props {
109 href: `/${string}`;
+2-3
components/dashboard/lists/selector.tsx
···11"use client";
2233-import Link from "next/link";
44-import { HiExternalLink, HiPencil } from "react-icons/hi";
55-63import { type Guild, guildStore } from "@/common/guilds";
74import { Button } from "@/components/ui/button";
85import { cn } from "@/utils/cn";
66+import Link from "next/link";
77+import { HiExternalLink, HiPencil } from "react-icons/hi";
98109interface TBase {
1110 id: string;
+1-2
components/discord/app-badge.tsx
···11+import { cn } from "@/utils/cn";
12import type { HTMLProps } from "react";
23import { HiCheck } from "react-icons/hi";
33-44-import { cn } from "@/utils/cn";
5465export default function DiscordAppBadge({
76 className,
+1-2
components/discord/channel.tsx
···11+import { cn } from "@/utils/cn";
12import React from "react";
23import { HiHashtag, HiVolumeUp } from "react-icons/hi";
33-44-import { cn } from "@/utils/cn";
5465interface Props {
76 type: "text" | "voice";
+1-3
components/discord/markdown.tsx
···11import "./markdown.css";
22-33-import * as md from "@odiffey/discord-markdown";
44-52import { cn } from "@/utils/cn";
33+import * as md from "@odiffey/discord-markdown";
6475export function DiscordMarkdown({
86 text,
+1-2
components/discord/message-embed.tsx
···11/* eslint-disable @next/next/no-img-element */
22+import { cn } from "@/utils/cn";
23import React from "react";
33-44-import { cn } from "@/utils/cn";
5465import { DiscordMarkdown } from "./markdown";
76
···11+import { toFixedArrayLength } from "@/utils/fixed-array-length";
12import Image from "next/image";
23import Link from "next/link";
33-44-import { toFixedArrayLength } from "@/utils/fixed-array-length";
5465import ImageReduceMotion from "./image-reduce-motion";
76
···11+import type { ApiError } from "@/typings";
22+import { cn } from "@/utils/cn";
13import { useEffect, useState } from "react";
24import { TailSpin } from "react-loading-icons";
33-44-import type { ApiError } from "@/typings";
55-import { cn } from "@/utils/cn";
6576import DumbTextInput from "./dumb-text-input";
87
···11+import { cn } from "@/utils/cn";
12import Link from "next/link";
23import { HiExternalLink } from "react-icons/hi";
33-44-import { cn } from "@/utils/cn";
5465export default function LinkTag({
76 href,
+1-2
components/list.tsx
···11"use client";
2233+import decimalToRgb from "@/utils/decimalToRgb";
34import { Tab, Tabs } from "@nextui-org/react";
45import { usePathname, useRouter, useSearchParams } from "next/navigation";
56import React, { useEffect, useRef, useState } from "react";
67import { HiChevronLeft, HiChevronRight } from "react-icons/hi";
77-88-import decimalToRgb from "@/utils/decimalToRgb";
98109interface ListProps {
1110 tabs: {
+1-2
components/loading-circle.tsx
···11+import { cn } from "@/utils/cn";
12import { LoaderCircleIcon } from "lucide-react";
22-33-import { cn } from "@/utils/cn";
4354export function LoadingCircle({ className = "" }: { className?: string; }) {
65 return (
···77 unix: number;
88 format: string;
99}) {
1010- const date = new Date(unix * 1000);
1010+ const date = new Date(unix * 1_000);
1111 const str = getDateString(date, format);
12121313 return (
+10-5
components/modal.tsx
···11"use client";
2233+import type { ApiError } from "@/typings";
44+import { cn } from "@/utils/cn";
35import Link from "next/link";
46import { useEffect, useState } from "react";
57import { HiFire } from "react-icons/hi";
66-77-import type { ApiError } from "@/typings";
88-import { cn } from "@/utils/cn";
98109import Notice, { NoticeType } from "./notice";
1110import { Badge } from "./ui/badge";
···64636564 async function submit() {
6665 if (state === State.Loading) return;
6767- if (!onSubmit) return onClose();
6666+ if (!onSubmit) {
6767+ onClose();
6868+ return;
6969+ }
68706971 setError(null);
7072 setState(State.Loading);
7173 const data = onSubmit?.();
72747373- if (!data) return onClose();
7575+ if (!data) {
7676+ onClose();
7777+ return;
7878+ }
74797580 if (data instanceof Error) {
7681 setError(data?.message || "something went wrong..");
+2-3
components/screen-message.tsx
···11+import SadWumpusPic from "@/public/sad-wumpus.gif";
22+import { cn } from "@/utils/cn";
13import Image from "next/image";
24import Link from "next/link";
35import { BsDiscord } from "react-icons/bs";
46import { HiHome } from "react-icons/hi";
55-66-import SadWumpusPic from "@/public/sad-wumpus.gif";
77-import { cn } from "@/utils/cn";
8798import { Button } from "./ui/button";
109
···11+import { cn } from "@/utils/cn";
12import { cva, type VariantProps } from "class-variance-authority";
23import * as React from "react";
33-44-import { cn } from "@/utils/cn";
5465const alertVariants = cva(
76 "relative w-full rounded-lg p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-2px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-[17px] [&>svg]:text-foreground",
+1-2
components/ui/avatar.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import * as AvatarPrimitive from "@radix-ui/react-avatar";
45import * as React from "react";
55-66-import { cn } from "@/utils/cn";
7687const Avatar = React.forwardRef<
98 React.ElementRef<typeof AvatarPrimitive.Root>,
+1-2
components/ui/badge.tsx
···11+import { cn } from "@/utils/cn";
12import { cva, type VariantProps } from "class-variance-authority";
23import * as React from "react";
33-44-import { cn } from "@/utils/cn";
5465const badgeVariants = cva(
76 "w-fit inline-flex items-center border font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 [&>svg]:relative [&>svg]:right-1",
+1-2
components/ui/button.tsx
···11+import { cn } from "@/utils/cn";
12import { Slot } from "@radix-ui/react-slot";
23import { cva, type VariantProps } from "class-variance-authority";
34import Link from "next/link";
45import * as React from "react";
55-66-import { cn } from "@/utils/cn";
7687import { LoadingCircle } from "../loading-circle";
98
+1-2
components/ui/checkbox.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
45import { Check } from "lucide-react";
56import * as React from "react";
66-77-import { cn } from "@/utils/cn";
8798const Checkbox = React.forwardRef<
109 React.ElementRef<typeof CheckboxPrimitive.Root>,
+1-2
components/ui/dialog.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import * as DialogPrimitive from "@radix-ui/react-dialog";
45import { X } from "lucide-react";
56import * as React from "react";
66-77-import { cn } from "@/utils/cn";
8798const Dialog = DialogPrimitive.Root;
109
+2-3
components/ui/input-base.tsx
···11"use client";
2233+import { Button } from "@/components/ui/button";
44+import { cn } from "@/utils/cn";
35import { composeEventHandlers } from "@radix-ui/primitive";
46import { useComposedRefs } from "@radix-ui/react-compose-refs";
57import { Primitive } from "@radix-ui/react-primitive";
68import { Slot } from "@radix-ui/react-slot";
79import * as React from "react";
88-99-import { Button } from "@/components/ui/button";
1010-import { cn } from "@/utils/cn";
11101211export type InputBaseContextProps = Pick<
1312 InputBaseProps,
+1-2
components/ui/popover.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import * as PopoverPrimitive from "@radix-ui/react-popover";
45import * as React from "react";
55-66-import { cn } from "@/utils/cn";
7687const Popover = PopoverPrimitive.Root;
98
+1-2
components/ui/separator.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import * as SeparatorPrimitive from "@radix-ui/react-separator";
45import * as React from "react";
55-66-import { cn } from "@/utils/cn";
7687interface SeparatorProps extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> {
98 loading?: boolean;
+1-2
components/ui/switch.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import * as SwitchPrimitives from "@radix-ui/react-switch";
45import * as React from "react";
55-66-import { cn } from "@/utils/cn";
7687const Switch = React.forwardRef<
98 React.ElementRef<typeof SwitchPrimitives.Root>,
+1-2
components/ui/tooltip.tsx
···11"use client";
2233+import { cn } from "@/utils/cn";
34import * as TooltipPrimitive from "@radix-ui/react-tooltip";
45import * as React from "react";
55-66-import { cn } from "@/utils/cn";
7687const TooltipProvider = TooltipPrimitive.Provider;
98
···6969The flags used for string matching are `gi`, only the YouTube and Twitch titles, Bluesky post bodies, and Reddit flairs are checked.
70707171### 🕵️♀️ Styles (whitelabel / webhook)
7272-Notification styles allow you to customise (or whitelabel) the username and avatar of the author (i.e. the sender of the message) separately for each notification. Wamellow will automatically manage the webhooks for you.
7272+Notification styles allow you to customize (or whitelabel) the username and avatar of the author (i.e. the sender of the message) separately for each notification. Wamellow will automatically manage the webhooks for you.
7373<br />
7474<br />
7575
···11-import type React from "react";
22-31import type { User } from "@/common/user";
42import type { ApiError } from "@/typings";
33+import type React from "react";
5465enum State {
76 Idle = 0,