tangled
alpha
login
or
join now
shi.gg
/
mellow-web
4
fork
atom
The weeb for the next gen discord boat - Wamellow
wamellow.com
bot
discord
4
fork
atom
overview
issues
pulls
pipelines
use cookies for devTools & reduceMotions
shi.gg
2 years ago
c25aacfc
dd4a83ef
+84
-94
11 changed files
expand all
collapse all
unified
split
app
(home)
faq.component.tsx
ai-gallery
[uploadId]
side.component.tsx
dashboard
[guildId]
layout.tsx
leaderboards
page.tsx
updating.component.tsx
page.tsx
layout.tsx
leaderboard
[guildId]
side.component.tsx
common
webstore.ts
components
header.tsx
image-reduce-motion.tsx
+3
-3
app/(home)/faq.component.tsx
···
2
3
import { Accordion, AccordionItem, Code } from "@nextui-org/react";
4
import Link from "next/link";
0
5
import { HiCash, HiChat, HiExternalLink, HiLockClosed, HiUserAdd } from "react-icons/hi";
6
7
-
import { webStore } from "@/common/webstore";
8
import cn from "@/utils/cn";
9
10
const data = [
···
98
];
99
100
export default function Faq() {
101
-
const web = webStore((w) => w);
102
103
return (
104
<div className="my-4 w-full">
···
107
className="rounded-lg overflow-hidden"
108
variant="splitted"
109
defaultExpandedKeys={["0"]}
110
-
disableAnimation={web.reduceMotions}
111
>
112
{data.map((item, index) => (
113
<AccordionItem
···
2
3
import { Accordion, AccordionItem, Code } from "@nextui-org/react";
4
import Link from "next/link";
5
+
import { useCookies } from "next-client-cookies";
6
import { HiCash, HiChat, HiExternalLink, HiLockClosed, HiUserAdd } from "react-icons/hi";
7
0
8
import cn from "@/utils/cn";
9
10
const data = [
···
98
];
99
100
export default function Faq() {
101
+
const cookies = useCookies();
102
103
return (
104
<div className="my-4 w-full">
···
107
className="rounded-lg overflow-hidden"
108
variant="splitted"
109
defaultExpandedKeys={["0"]}
110
+
disableAnimation={cookies.get("reduceMotions") === "true"}
111
>
112
{data.map((item, index) => (
113
<AccordionItem
+4
-4
app/ai-gallery/[uploadId]/side.component.tsx
···
2
3
import { Accordion, AccordionItem, Button, Chip, Tooltip } from "@nextui-org/react";
4
import Link from "next/link";
0
5
import { FaReddit, FaTwitter } from "react-icons/fa";
6
import { HiHand, HiShare, HiUserGroup } from "react-icons/hi";
7
8
-
import { webStore } from "@/common/webstore";
9
import Ad from "@/components/ad";
10
import { CopyToClipboardButton } from "@/components/copy-to-clipboard";
11
import ImageReduceMotion from "@/components/image-reduce-motion";
···
26
guild: ApiV1GuildsGetResponse | ApiError | undefined;
27
analytics: { results: AnalyticsResponse[] } | AnalyticsError | undefined;
28
}) {
29
-
const web = webStore((w) => w);
30
31
const prompt = "prompt" in upload
32
? truncate(upload.prompt.split(" ").map((str) => str.replace(/^\w/, (char) => char.toUpperCase())).join(" "), 32)
···
76
className="bg-wamellow"
77
selectionMode="multiple"
78
defaultExpandedKeys={["1"]}
79
-
disableAnimation={web.reduceMotions}
80
>
81
<AccordionItem
82
key="1"
···
159
variant="shadow"
160
className="bg-wamellow"
161
selectionMode="multiple"
162
-
disableAnimation={web.reduceMotions}
163
>
164
<AccordionItem
165
key="1"
···
2
3
import { Accordion, AccordionItem, Button, Chip, Tooltip } from "@nextui-org/react";
4
import Link from "next/link";
5
+
import { useCookies } from "next-client-cookies";
6
import { FaReddit, FaTwitter } from "react-icons/fa";
7
import { HiHand, HiShare, HiUserGroup } from "react-icons/hi";
8
0
9
import Ad from "@/components/ad";
10
import { CopyToClipboardButton } from "@/components/copy-to-clipboard";
11
import ImageReduceMotion from "@/components/image-reduce-motion";
···
26
guild: ApiV1GuildsGetResponse | ApiError | undefined;
27
analytics: { results: AnalyticsResponse[] } | AnalyticsError | undefined;
28
}) {
29
+
const cookies = useCookies();
30
31
const prompt = "prompt" in upload
32
? truncate(upload.prompt.split(" ").map((str) => str.replace(/^\w/, (char) => char.toUpperCase())).join(" "), 32)
···
76
className="bg-wamellow"
77
selectionMode="multiple"
78
defaultExpandedKeys={["1"]}
79
+
disableAnimation={cookies.get("reduceMotions") === "true"}
80
>
81
<AccordionItem
82
key="1"
···
159
variant="shadow"
160
className="bg-wamellow"
161
selectionMode="multiple"
162
+
disableAnimation={cookies.get("reduceMotions") === "true"}
163
>
164
<AccordionItem
165
key="1"
+1
-1
app/dashboard/[guildId]/layout.tsx
···
194
</div>
195
196
<div className="md:ml-auto mt-6 md:mt-0">
197
-
{web.devToolsEnabled &&
198
<CopyToClipboardButton
199
needsWait
200
text={getCanonicalUrl("leaderboard", params.guildId.toString())}
···
194
</div>
195
196
<div className="md:ml-auto mt-6 md:mt-0">
197
+
{cookies.get("devTools") &&
198
<CopyToClipboardButton
199
needsWait
200
text={getCanonicalUrl("leaderboard", params.guildId.toString())}
+1
-5
app/dashboard/[guildId]/leaderboards/page.tsx
···
22
const cookies = useCookies();
23
24
const guild = guildStore((g) => g);
25
-
const web = webStore((w) => w);
26
const params = useParams();
27
28
const url = `/guilds/${params.guildId}/modules/leaderboard` as const;
···
66
icon={<HiChartBar />}
67
/>
68
69
-
{web.devToolsEnabled &&
70
<div className={"flex gap-4 border-2 border-violet-400 p-4 mb-4 rounded-lg"}>
71
72
<div className="lg:w-1/2 flex gap-2 w-full">
···
80
type="color"
81
defaultState={data.textColor ?? 0xe5e5e5}
82
resetState={0xe5e5e5}
83
-
disabled={!web.devToolsEnabled}
84
/>
85
</div>
86
···
93
type="color"
94
defaultState={data.accentColor ?? 0x8b5cf6}
95
resetState={0x8b5cf6}
96
-
disabled={!web.devToolsEnabled}
97
/>
98
</div>
99
···
108
type="color"
109
defaultState={data.backgroundColor ?? 0x0d0f11}
110
resetState={0x0d0f11}
111
-
disabled={!web.devToolsEnabled}
112
/>
113
</div>
114
···
22
const cookies = useCookies();
23
24
const guild = guildStore((g) => g);
0
25
const params = useParams();
26
27
const url = `/guilds/${params.guildId}/modules/leaderboard` as const;
···
65
icon={<HiChartBar />}
66
/>
67
68
+
{cookies.get("devTools") &&
69
<div className={"flex gap-4 border-2 border-violet-400 p-4 mb-4 rounded-lg"}>
70
71
<div className="lg:w-1/2 flex gap-2 w-full">
···
79
type="color"
80
defaultState={data.textColor ?? 0xe5e5e5}
81
resetState={0xe5e5e5}
0
82
/>
83
</div>
84
···
91
type="color"
92
defaultState={data.accentColor ?? 0x8b5cf6}
93
resetState={0x8b5cf6}
0
94
/>
95
</div>
96
···
105
type="color"
106
defaultState={data.backgroundColor ?? 0x0d0f11}
107
resetState={0x0d0f11}
0
108
/>
109
</div>
110
+4
-4
app/dashboard/[guildId]/leaderboards/updating.component.tsx
···
2
import { Tab, Tabs } from "@nextui-org/react";
3
import Image from "next/image";
4
import Link from "next/link";
0
5
import { FunctionComponent, useState } from "react";
6
import { HiExternalLink, HiPencil, HiTrash } from "react-icons/hi";
7
8
import { Guild } from "@/common/guilds";
9
-
import { webStore } from "@/common/webstore";
10
import SelectInput from "@/components/inputs/SelectMenu";
11
import Switch from "@/components/inputs/Switch";
12
import Modal from "@/components/modal";
···
24
}
25
26
const UpdatingLeaderboardCard: FunctionComponent<Props> = ({ guild, lb, type }) => {
27
-
const web = webStore((w) => w);
28
29
const [leaderboard, setLeaderboard] = useState(lb);
30
const [modal, setModal] = useState<ModalType | undefined>(undefined);
···
77
<span className="ml-1">{leaderboard?.channelId ? "Edit" : "Create"} leaderboard</span>
78
</button>
79
80
-
{leaderboard?.channelId && web.devToolsEnabled &&
81
<button
82
onClick={() => setModal(ModalType.Delete)}
83
className="flex dark:text-red-400/60 dark:hover:text-red-400/90 text-red-600/60 hover:text-red-600/90 duration-200"
···
122
styles
123
});
124
}}
125
-
subChildren={leaderboard && web.devToolsEnabled &&
126
<div className="text-xs flex flex-col">
127
{leaderboard.createdAt &&
128
<span>
···
2
import { Tab, Tabs } from "@nextui-org/react";
3
import Image from "next/image";
4
import Link from "next/link";
5
+
import { useCookies } from "next-client-cookies";
6
import { FunctionComponent, useState } from "react";
7
import { HiExternalLink, HiPencil, HiTrash } from "react-icons/hi";
8
9
import { Guild } from "@/common/guilds";
0
10
import SelectInput from "@/components/inputs/SelectMenu";
11
import Switch from "@/components/inputs/Switch";
12
import Modal from "@/components/modal";
···
24
}
25
26
const UpdatingLeaderboardCard: FunctionComponent<Props> = ({ guild, lb, type }) => {
27
+
const cookies = useCookies();
28
29
const [leaderboard, setLeaderboard] = useState(lb);
30
const [modal, setModal] = useState<ModalType | undefined>(undefined);
···
77
<span className="ml-1">{leaderboard?.channelId ? "Edit" : "Create"} leaderboard</span>
78
</button>
79
80
+
{leaderboard?.channelId && cookies.get("devTools") &&
81
<button
82
onClick={() => setModal(ModalType.Delete)}
83
className="flex dark:text-red-400/60 dark:hover:text-red-400/90 text-red-600/60 hover:text-red-600/90 duration-200"
···
122
styles
123
});
124
}}
125
+
subChildren={leaderboard && cookies.get("devTools") &&
126
<div className="text-xs flex flex-col">
127
{leaderboard.createdAt &&
128
<span>
+3
-3
app/dashboard/[guildId]/page.tsx
···
4
import Image from "next/image";
5
import Link from "next/link";
6
import { useParams } from "next/navigation";
0
7
import { useState } from "react";
8
import { HiChartBar, HiMail } from "react-icons/hi";
9
10
import { guildStore } from "@/common/guilds";
11
-
import { webStore } from "@/common/webstore";
12
import SelectMenu from "@/components/inputs/SelectMenu";
13
import Switch from "@/components/inputs/Switch";
14
import Modal from "@/components/modal";
···
16
import OverviewLinkComponent from "../../../components/OverviewLinkComponent";
17
18
export default function Home() {
19
-
const web = webStore((w) => w);
20
const guild = guildStore((g) => g);
21
22
const [modal, setModal] = useState(false);
···
133
<Accordion
134
className="lg:w-1/2"
135
defaultExpandedKeys={["1"]}
136
-
disableAnimation={web.reduceMotions}
137
>
138
<AccordionItem
139
key="1"
···
4
import Image from "next/image";
5
import Link from "next/link";
6
import { useParams } from "next/navigation";
7
+
import { useCookies } from "next-client-cookies";
8
import { useState } from "react";
9
import { HiChartBar, HiMail } from "react-icons/hi";
10
11
import { guildStore } from "@/common/guilds";
0
12
import SelectMenu from "@/components/inputs/SelectMenu";
13
import Switch from "@/components/inputs/Switch";
14
import Modal from "@/components/modal";
···
16
import OverviewLinkComponent from "../../../components/OverviewLinkComponent";
17
18
export default function Home() {
19
+
const cookies = useCookies();
20
const guild = guildStore((g) => g);
21
22
const [modal, setModal] = useState(false);
···
133
<Accordion
134
className="lg:w-1/2"
135
defaultExpandedKeys={["1"]}
136
+
disableAnimation={cookies.get("reduceMotions") === "true"}
137
>
138
<AccordionItem
139
key="1"
+44
-44
app/layout.tsx
···
94
const cookieStore = cookies();
95
96
return (
97
-
<html
98
-
suppressHydrationWarning
99
-
data-theme="dark"
100
-
lang="en"
101
-
className="dark flex justify-center min-h-screen max-w-screen overflow-x-hidden"
102
-
>
103
-
104
-
<Script defer data-domain="wamellow.com" src="https://analytics.wamellow.com/js/script.js" />
105
-
106
-
<body className={cn("w-full max-w-7xl", outfit.className)}>
107
-
<div id="bg" className="absolute top-0 right-0 w-screen h-screen -z-10" />
108
109
-
<nav className="p-4 flex items-center gap-2 text-base font-medium dark:text-neutral-300 text-neutral-700 select-none h-20">
110
-
<Link
111
-
aria-label="Go to Wamellow's homepage"
112
-
className={cn("font-semibold flex items-center mr-2", montserrat.className)}
113
-
href="/?utm_source=wamellow.com&utm_medium=header"
114
-
>
115
-
<Image src="/waya-v3-small.webp" width={64} height={64} alt="" className="rounded-full mr-2 w-8 h-8 shrink-0" />
116
-
<span className="text-xl dark:text-neutral-100 text-neutral-900 hidden sm:block">Wamellow</span>
117
-
</Link>
118
119
-
<Divider
120
-
className="h-10 rotate-6 mx-1"
121
-
orientation="vertical"
122
-
/>
123
124
-
<div className="flex gap-1">
125
<Link
126
-
href="https://lunish.nl/kofi"
127
-
className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 hidden sm:flex items-center gap-2 group"
0
128
>
129
-
<SiKofi className="group-hover:text-[#ff6c6b] duration-200 mt-0.5" />
130
-
Donate
131
-
</Link>
132
-
<Link href="/vote" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 flex items-center gap-2 group">
133
-
<TopggIcon className="group-hover:text-[#ff3366] duration-200 h-5 w-5 mt-0.5" />
134
-
Vote
135
</Link>
136
-
</div>
137
138
-
{cookieStore.get("hasSession")?.value === "true" ?
139
-
<Header className="ml-auto" />
140
-
:
141
-
<LoginButton />
142
-
}
143
-
</nav>
144
145
-
<CookiesProvider>
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
146
<Provider>
147
{children}
148
</Provider>
149
150
<StoreLastPage />
151
-
</CookiesProvider>
152
153
-
</body>
154
-
</html>
0
155
);
156
}
···
94
const cookieStore = cookies();
95
96
return (
97
+
<CookiesProvider>
98
+
<html
99
+
suppressHydrationWarning
100
+
data-theme="dark"
101
+
lang="en"
102
+
className="dark flex justify-center min-h-screen max-w-screen overflow-x-hidden"
103
+
>
0
0
0
0
104
105
+
<Script defer data-domain="wamellow.com" src="https://analytics.wamellow.com/js/script.js" />
0
0
0
0
0
0
0
0
106
107
+
<body className={cn("w-full max-w-7xl", outfit.className)}>
108
+
<div id="bg" className="absolute top-0 right-0 w-screen h-screen -z-10" />
0
0
109
110
+
<nav className="p-4 flex items-center gap-2 text-base font-medium dark:text-neutral-300 text-neutral-700 select-none h-20">
111
<Link
112
+
aria-label="Go to Wamellow's homepage"
113
+
className={cn("font-semibold flex items-center mr-2", montserrat.className)}
114
+
href="/?utm_source=wamellow.com&utm_medium=header"
115
>
116
+
<Image src="/waya-v3-small.webp" width={64} height={64} alt="" className="rounded-full mr-2 w-8 h-8 shrink-0" />
117
+
<span className="text-xl dark:text-neutral-100 text-neutral-900 hidden sm:block">Wamellow</span>
0
0
0
0
118
</Link>
0
119
120
+
<Divider
121
+
className="h-10 rotate-6 mx-1"
122
+
orientation="vertical"
123
+
/>
0
0
124
125
+
<div className="flex gap-1">
126
+
<Link
127
+
href="https://lunish.nl/kofi"
128
+
className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 hidden sm:flex items-center gap-2 group"
129
+
>
130
+
<SiKofi className="group-hover:text-[#ff6c6b] duration-200 mt-0.5" />
131
+
Donate
132
+
</Link>
133
+
<Link href="/vote" className="dark:hover:bg-wamellow-alpha hover:bg-wamellow-100-alpha py-1 px-3 rounded-md duration-200 flex items-center gap-2 group">
134
+
<TopggIcon className="group-hover:text-[#ff3366] duration-200 h-5 w-5 mt-0.5" />
135
+
Vote
136
+
</Link>
137
+
</div>
138
+
139
+
{cookieStore.get("hasSession")?.value === "true" ?
140
+
<Header className="ml-auto" />
141
+
:
142
+
<LoginButton />
143
+
}
144
+
</nav>
145
+
146
<Provider>
147
{children}
148
</Provider>
149
150
<StoreLastPage />
0
151
152
+
</body>
153
+
</html>
154
+
</CookiesProvider>
155
);
156
}
+4
-4
app/leaderboard/[guildId]/side.component.tsx
···
3
import { Accordion, AccordionItem, Button, Code, Tooltip } from "@nextui-org/react";
4
import Link from "next/link";
5
import { useRouter } from "next/navigation";
0
6
import { useState } from "react";
7
import { BsDiscord } from "react-icons/bs";
8
import { FaReddit, FaTwitter } from "react-icons/fa";
9
import { HiAnnotation, HiLink, HiShare, HiTrash, HiViewGridAdd, HiVolumeUp } from "react-icons/hi";
10
11
-
import { webStore } from "@/common/webstore";
12
import Ad from "@/components/ad";
13
import { CopyToClipboardButton } from "@/components/copy-to-clipboard";
14
import Modal from "@/components/modal";
···
28
pagination: ApiV1GuildsTopmembersPaginationGetResponse | ApiError | undefined;
29
currentCircular: "next" | "server" | undefined;
30
}) {
31
-
const web = webStore((w) => w);
32
const router = useRouter();
33
34
const [modal, setModal] = useState(false);
···
86
<Accordion
87
selectionMode="multiple"
88
defaultExpandedKeys={["1", "2", "3"]}
89
-
disableAnimation={web.reduceMotions}
90
>
91
92
-
{guild && "id" in guild && web.devToolsEnabled ?
93
<AccordionItem
94
key="1"
95
aria-label="admin tools"
···
3
import { Accordion, AccordionItem, Button, Code, Tooltip } from "@nextui-org/react";
4
import Link from "next/link";
5
import { useRouter } from "next/navigation";
6
+
import { useCookies } from "next-client-cookies";
7
import { useState } from "react";
8
import { BsDiscord } from "react-icons/bs";
9
import { FaReddit, FaTwitter } from "react-icons/fa";
10
import { HiAnnotation, HiLink, HiShare, HiTrash, HiViewGridAdd, HiVolumeUp } from "react-icons/hi";
11
0
12
import Ad from "@/components/ad";
13
import { CopyToClipboardButton } from "@/components/copy-to-clipboard";
14
import Modal from "@/components/modal";
···
28
pagination: ApiV1GuildsTopmembersPaginationGetResponse | ApiError | undefined;
29
currentCircular: "next" | "server" | undefined;
30
}) {
31
+
const cookies = useCookies();
32
const router = useRouter();
33
34
const [modal, setModal] = useState(false);
···
86
<Accordion
87
selectionMode="multiple"
88
defaultExpandedKeys={["1", "2", "3"]}
89
+
disableAnimation={cookies.get("reduceMotions") === "true"}
90
>
91
92
+
{guild && "id" in guild && cookies.get("devTools") ?
93
<AccordionItem
94
key="1"
95
aria-label="admin tools"
-4
common/webstore.ts
···
1
import { create } from "zustand";
2
3
export interface Web {
4
-
devToolsEnabled: boolean | undefined;
5
-
reduceMotions: boolean;
6
width: number;
7
}
8
9
export const webStore = create<Web>(() => ({
10
-
devToolsEnabled: undefined,
11
-
reduceMotions: false,
12
width: Infinity
13
}));
···
1
import { create } from "zustand";
2
3
export interface Web {
0
0
4
width: number;
5
}
6
7
export const webStore = create<Web>(() => ({
0
0
8
width: Infinity
9
}));
+16
-19
components/header.tsx
···
3
import { Button, Chip, Skeleton, Switch, Tooltip } from "@nextui-org/react";
4
import { AnimatePresence, motion, MotionConfig } from "framer-motion";
5
import Link from "next/link";
0
0
6
import React, { useEffect, useState } from "react";
7
import { HiBadgeCheck, HiBeaker, HiChartPie, HiChevronDown, HiEyeOff, HiIdentification, HiLogout, HiViewGridAdd } from "react-icons/hi";
8
···
15
import ImageReduceMotion from "./image-reduce-motion";
16
17
export default function Header(props: React.ComponentProps<"div">) {
0
0
0
18
19
const [menu, setMenu] = useState(false);
20
const [loginstate, setLoginstate] = useState<"LOADING" | "ERRORED" | undefined>("LOADING");
21
22
const user = userStore((s) => s);
23
-
const web = webStore((w) => w);
24
25
useEffect(() => {
26
···
32
});
33
});
34
35
-
const devToolsEnabled = localStorage.getItem("devToolsEnabled");
36
-
const reduceMotions = localStorage.getItem("reduceMotions");
37
-
38
webStore.setState({
39
-
...web,
40
-
width: window?.innerWidth,
41
-
devToolsEnabled: !!devToolsEnabled,
42
-
reduceMotions: !!reduceMotions
43
});
44
}, []);
45
···
80
{
81
name: "Reduce Motion",
82
icon: <HiEyeOff />,
83
-
value: web.reduceMotions,
84
onChange: () => {
85
-
if (!web.reduceMotions) localStorage.setItem("reduceMotions", "true");
86
-
else localStorage.removeItem("reduceMotions");
87
-
88
-
webStore.setState({ ...web, reduceMotions: !web.reduceMotions });
89
}
90
},
91
...(user?.HELLO_AND_WELCOME_TO_THE_DEV_TOOLS__PLEASE_GO_AWAY ?
···
99
{
100
name: "Lunar Tools",
101
icon: <HiBeaker />,
102
-
value: web.devToolsEnabled,
103
onChange: () => {
104
-
if (!web.devToolsEnabled) localStorage.setItem("devToolsEnabled", "true");
105
-
else localStorage.removeItem("devToolsEnabled");
106
-
107
-
webStore.setState({ ...web, devToolsEnabled: !web.devToolsEnabled });
108
}
109
}
110
]
···
223
}
224
225
<MotionConfig
226
-
transition={web.reduceMotions ?
227
{ duration: 0 }
228
:
229
{ type: "spring", bounce: 0.4, duration: menu ? 0.7 : 0.4 }
···
3
import { Button, Chip, Skeleton, Switch, Tooltip } from "@nextui-org/react";
4
import { AnimatePresence, motion, MotionConfig } from "framer-motion";
5
import Link from "next/link";
6
+
import { useRouter } from "next/navigation";
7
+
import { useCookies } from "next-client-cookies";
8
import React, { useEffect, useState } from "react";
9
import { HiBadgeCheck, HiBeaker, HiChartPie, HiChevronDown, HiEyeOff, HiIdentification, HiLogout, HiViewGridAdd } from "react-icons/hi";
10
···
17
import ImageReduceMotion from "./image-reduce-motion";
18
19
export default function Header(props: React.ComponentProps<"div">) {
20
+
const cookies = useCookies();
21
+
const devTools = cookies.get("devTools") === "true";
22
+
const reduceMotions = cookies.get("reduceMotions") === "true";
23
24
const [menu, setMenu] = useState(false);
25
const [loginstate, setLoginstate] = useState<"LOADING" | "ERRORED" | undefined>("LOADING");
26
27
const user = userStore((s) => s);
28
+
const router = useRouter();
29
30
useEffect(() => {
31
···
37
});
38
});
39
0
0
0
40
webStore.setState({
41
+
width: window?.innerWidth
0
0
0
42
});
43
}, []);
44
···
79
{
80
name: "Reduce Motion",
81
icon: <HiEyeOff />,
82
+
value: reduceMotions,
83
onChange: () => {
84
+
if (!reduceMotions) cookies.set("reduceMotions", "true", { expires: 365 });
85
+
else cookies.remove("reduceMotions");
86
+
router.refresh();
0
87
}
88
},
89
...(user?.HELLO_AND_WELCOME_TO_THE_DEV_TOOLS__PLEASE_GO_AWAY ?
···
97
{
98
name: "Lunar Tools",
99
icon: <HiBeaker />,
100
+
value: devTools,
101
onChange: () => {
102
+
if (!devTools) cookies.set("devTools", "true", { expires: 365 });
103
+
else cookies.remove("devTools");
104
+
router.refresh();
0
105
}
106
}
107
]
···
220
}
221
222
<MotionConfig
223
+
transition={reduceMotions ?
224
{ duration: 0 }
225
:
226
{ type: "spring", bounce: 0.4, duration: menu ? 0.7 : 0.4 }
+4
-3
components/image-reduce-motion.tsx
···
1
"use client";
2
import Image from "next/image";
0
3
4
-
import { webStore } from "@/common/webstore";
5
6
interface Props {
7
url: string | null | undefined;
···
17
className,
18
forceStatic
19
}: Props) {
20
-
const web = webStore((w) => w);
0
21
22
return (
23
<Image
24
itemProp="image"
25
-
src={!url?.includes("null") && !url?.includes("undefined") && url ? `${url}.${url.includes("a_") && !web.reduceMotions && !forceStatic ? "gif" : "webp"}?size=${size}` : "/discord.webp"}
26
width={size}
27
height={size}
28
alt={alt}
···
1
"use client";
2
import Image from "next/image";
3
+
import { useCookies } from "next-client-cookies";
4
0
5
6
interface Props {
7
url: string | null | undefined;
···
17
className,
18
forceStatic
19
}: Props) {
20
+
const cookies = useCookies();
21
+
const reduceMotions = cookies.get("reduceMotions") === "true";
22
23
return (
24
<Image
25
itemProp="image"
26
+
src={!url?.includes("null") && !url?.includes("undefined") && url ? `${url}.${url.includes("a_") && !reduceMotions && !forceStatic ? "gif" : "webp"}?size=${size}` : "/discord.webp"}
27
width={size}
28
height={size}
29
alt={alt}