diff --git a/app/(home)/bot/pronouns/layout.tsx b/app/(home)/bot/pronouns/layout.tsx index 2f26b060..8004d975 100644 --- a/app/(home)/bot/pronouns/layout.tsx +++ b/app/(home)/bot/pronouns/layout.tsx @@ -2,12 +2,11 @@ import type { Metadata } from "next"; import { Montserrat, Patrick_Hand } from "next/font/google"; import Image from "next/image"; import Link from "next/link"; -import { BsDiscord } from "react-icons/bs"; import { HiHome, HiUserAdd } from "react-icons/hi"; -import { ClientButton } from "@/components/client"; import Comment from "@/components/comment"; import ImageGrid from "@/components/image-grid"; +import { Button } from "@/components/ui/button"; import { defaultFetchOptions } from "@/lib/api"; import ArrowPic from "@/public/icons/arroww.webp"; import type { ApiV1TopguildsGetResponse } from "@/typings"; @@ -57,19 +56,17 @@ export default async function RootLayout({ .then((res) => res.json()) .catch(() => null) as ApiV1TopguildsGetResponse[] | null; - return ( -
- -
-

- Pronouns - {" in "} - discord -

-
- - { - topGuilds && + return (<> +
+

+ Pronouns + {" in "} + discord +

+
+ + { + topGuilds && b.memberCount - a.memberCount) .map((guild) => ({ @@ -78,83 +75,109 @@ export default async function RootLayout({ link: getCanonicalUrl("leaderboard", guild.id) }))} /> - } + } -
-
- +
+ + + +
+ + +
-
+
-
- } - className="button-primary w-1/2 lg:w-fit !text-xl !font-medium" +
+ +
- + Join Support + + +
- - arrow up - Get started here in seconds - -
+ + arrow up + Get started here in seconds +
+
-
- {children} -
- +
+ {children} +
+ + -
- ); + ); } \ No newline at end of file diff --git a/app/(home)/bot/pronouns/page.tsx b/app/(home)/bot/pronouns/page.tsx index 417bee47..1192c9e2 100644 --- a/app/(home)/bot/pronouns/page.tsx +++ b/app/(home)/bot/pronouns/page.tsx @@ -1,12 +1,13 @@ -import { Chip } from "@nextui-org/react"; import { Montserrat } from "next/font/google"; import Image from "next/image"; import Link from "next/link"; -import { HiCash, HiPlus } from "react-icons/hi"; +import { BsPlus } from "react-icons/bs"; +import { HiCash } from "react-icons/hi"; import Box from "@/components/box"; -import { ClientButton } from "@/components/client"; import DiscordMessage from "@/components/discord/message"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; import { cn } from "@/utils/cn"; const montserrat = Montserrat({ subsets: ["latin"] }); @@ -45,14 +46,14 @@ export default function Home() {
- } + radius="rounded" > - Everything for free - + + Everything for free +

Sexualities, Genders & Pronouns

@@ -62,14 +63,16 @@ export default function Home() {
- } - href="/support" - > - Request additional - +
diff --git a/app/(home)/commands.component.tsx b/app/(home)/commands.component.tsx index 8e466bcf..83b4245c 100644 --- a/app/(home)/commands.component.tsx +++ b/app/(home)/commands.component.tsx @@ -1,7 +1,7 @@ import { HiFire, HiInformationCircle } from "react-icons/hi"; import Box from "@/components/box"; -import { ClientChip } from "@/components/client"; +import { Badge } from "@/components/ui/badge"; import { defaultFetchOptions } from "@/lib/api"; import { intl } from "@/utils/numbers"; @@ -26,21 +26,21 @@ export async function Commands({ className="p-5 pb-3 dark:bg-wamellow bg-wamellow-100 rounded-lg my-4 w-full" >
- } + radius="rounded" > - Popular Slash Commands - + + Popular Slash Commands + +
- Since 7th December + Since September 2024
- {commands && Array.isArray(commands) ? + {commands && Array.isArray(commands) && commands.length ?
{commands .sort((a, b) => b.uses - a.uses) diff --git a/app/(home)/debug/page.tsx b/app/(home)/debug/page.tsx index bbc93d4d..d5f3dde4 100644 --- a/app/(home)/debug/page.tsx +++ b/app/(home)/debug/page.tsx @@ -1,26 +1,27 @@ import type { Metadata } from "next"; import { cookies, headers } from "next/headers"; -import Link from "next/link"; import { HiTrash } from "react-icons/hi"; import Box from "@/components/box"; -import { ClientButton } from "@/components/client"; import { Shiggy } from "@/components/shiggy"; +import { Button } from "@/components/ui/button"; import { getBaseUrl, getCanonicalUrl } from "@/utils/urls"; import Panel from "./panel.component"; export const generateMetadata = (): Metadata => { const title = "Shiggy"; - const description = ""; + const description = "Uhhhh debug page???"; const url = getCanonicalUrl("debug"); return { title, description, + alternates: { canonical: url }, + openGraph: { title, description, @@ -31,6 +32,7 @@ export const generateMetadata = (): Metadata => { type: "image/gif" } }, + twitter: { card: "summary", title, @@ -39,7 +41,9 @@ export const generateMetadata = (): Metadata => { url: `${getBaseUrl()}/shiggy.gif`, alt: title } - } + }, + + robots: "noindex, follow" }; }; @@ -101,31 +105,19 @@ export default async function Home() { items={(await cookies()).getAll()} action={(cookie) => (
- + )} >
- + - - Logout -
diff --git a/app/(home)/page.tsx b/app/(home)/page.tsx index 7458b0be..09d264ab 100644 --- a/app/(home)/page.tsx +++ b/app/(home)/page.tsx @@ -3,12 +3,10 @@ import { Montserrat, Patrick_Hand } from "next/font/google"; import Image from "next/image"; import Link from "next/link"; import { Suspense } from "react"; -import { BsDiscord, BsYoutube } from "react-icons/bs"; +import { BsYoutube } from "react-icons/bs"; import { HiArrowNarrowRight, HiArrowRight, HiCash, HiCheck, HiFire, HiLockOpen, HiUserAdd } from "react-icons/hi"; -import { Avatar } from "@/components/avatar"; import Box from "@/components/box"; -import { ClientAvatarGroup, ClientButton, ClientChip } from "@/components/client"; import Comment from "@/components/comment"; import DiscordAppBadge from "@/components/discord/app-badge"; import DiscordChannel from "@/components/discord/channel"; @@ -18,6 +16,9 @@ import DiscordMessage from "@/components/discord/message"; import DiscordMessageEmbed from "@/components/discord/message-embed"; import DiscordUser from "@/components/discord/user"; import ImageReduceMotion from "@/components/image-reduce-motion"; +import { AvatarGroup, UserAvatar } from "@/components/ui/avatar"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { defaultFetchOptions } from "@/lib/api"; import AiPic from "@/public/ai.webp"; @@ -79,7 +80,7 @@ export default async function Home() { return (
-
+
}> @@ -103,54 +104,55 @@ export default async function Home() { Stay updated with dailyposts and receive social notifications! - + {toFixedArrayLength(topGuilds || [], 8) ?.map((guild) => ( - )) } - +
Go to Dashboard -
- } +
+ +
@@ -178,7 +180,7 @@ export default async function Home() {
-
-
-
-
- Scroll down... +
+
- } + radius="rounded" > - 100% free forever - + + 100% free forever +

40 Voices in 8 Languages

@@ -231,10 +229,7 @@ export default async function Home() { Great for people with aphonia, dysphonia, or other speech impairments.
- + {["us", "de", "es", "fr", "jp", "kr", "br", "id"].map((lang) => { const name = Object .entries(actor) @@ -242,29 +237,28 @@ export default async function Home() { ?.[1][0] || lang; return ( - ); })} - Change Text-to-Speech language and voice - +
- } - href="https://youtu.be/NS5fZ1ltovE?si=I3nViYb4sx3n3Uvo" - target="_blank" - > - Watch YouTube Video - +
@@ -305,16 +299,17 @@ export default async function Home() {
- } + radius="rounded" > - Free styling, 30 Channels - + + Free styling — 30 channels + +

YouTube, Twitch, Bluesky & Reddit

+
Set up notifications with free custom messages and embeds for up to 30 channels and get notified in less than a minute. @@ -334,23 +329,26 @@ export default async function Home() {
- } - href="https://youtu.be/xizs-hrwK4I?si=6pIYALygtNhUwpph" - target="_blank" - > - Watch Tutorial - - } - href="/dashboard?to=notifications&utm_source=wamellow.com&utm_medium=home" - > - Setup - + +
@@ -380,44 +378,45 @@ export default async function Home() {
- } + radius="rounded" > - 100% no money loss - + + No premium required + +

Free /image command

+
Summon the enchantment of AI-generated images to your Discord server with our versatile /image command, featuring over 40 distinct custom models. Customize the rating, quality, aesthetics, image width and height, upscaled, generation steps and the CFG scale all for free.
-
- + } + radius="rounded" > - NSFW Supported - + + Supports NSFW +
Generate spicy images and more in nsfw marked channels.
- } - href="/ai-gallery?utm_source=wamellow.com&utm_medium=home" - > - View Images - +
@@ -443,31 +442,31 @@ export default async function Home() {
- } + radius="rounded" > - 100% sexy forever - + + 100% sexy for free + +

/anime command

+
Unleash the magic of anime right within your Discord server with Wamellow{"'"}s 25+ categories. Dive into a world of adorable nekos, charming waifus, and much more, all at your fingertips. Whether it{"'"}s sharing the cutest characters or discovering stunning artwork, bring the joy of anime directly to your community, making your server a hub for all things anime-related.
-
- + } + radius="rounded" > - NSFW Supported - + + Supports NSFW +
Find spicy nekos, waifus, and more in nsfw marked channels.
@@ -498,30 +497,32 @@ export default async function Home() {
- } + radius="rounded" > - 100% free forever - + + Free custom backgrounds + +

/leaderboard & /rank

+
- Enhance your server{"’"}s engagement with our text-, voice- and invite based leaderboards, tailored to track and reward your most active members. + Enhance your server{"’"}s engagement with text-, voice- and invite based leaderboards, tailored to track and reward your most active members. By motivating your members to communicate, you{"’"}ll cultivate a more active server community.
- } - href="/leaderboard/828676951023550495?utm_source=wamellow.com&utm_medium=home" - > - View Leaderboard - +
@@ -545,30 +546,32 @@ export default async function Home() {
- } + radius="rounded" > - My lawyer said that title below - + + My lawyer said that title below + +

POGBOARD DEEZ NUTS

+
With Starboards, you have the power to highlight remarkable messages in your server. When you come across a message that is either funny or hilarious, simply react with a star, and if enough people star the message, it will be posted to the set starboard channel.
- } - href="/dashboard?to=starboard&utm_source=wamellow.com&utm_medium=home" - > - Setup - +
@@ -603,30 +606,31 @@ export default async function Home() {
- } + radius="rounded" > - w/ free image card backgrounds - + + w/ free image card backgrounds + +

Greetings

+
- Give a warm welcome to new members, introducing them to rules, topics, and ongoing events. - Whether gaming, joining a guild, or casual chat, every member should sense a strong community bond. + Give a warm welcome to new members, introducing them to rules, and topics with a fully customized message.
- } - href="/dashboard?to=greeting&utm_source=wamellow.com&utm_medium=home" - > - Setup - +
@@ -651,38 +655,41 @@ export default async function Home() {
- } + radius="rounded" > - Of course it{"'"}s free - + + Free and Secure + +

Captcha verification

+
Protect your server from unwanted attacks, such as bot-raids, with our captcha verification system. Ensure that only human members can access your channels, safeguarding your server from raider attacks and ensuring a safe and secure environment for all your members.
- } - href="/passport/1125063180801036329?utm_source=wamellow.com&utm_medium=home" - > - Try it out - - } - href="/dashboard?to=greeting&utm_source=wamellow.com&utm_medium=home" - > - Setup - + +
@@ -705,16 +712,17 @@ export default async function Home() {
- } + radius="rounded" > - 30 tags free - + + 30 tags free + +

Wamellow tags

+
Easily handle frequently asked questions, common queries, and repetitive tasks in a snap. Empower your server with quick access to custom commands. @@ -722,14 +730,15 @@ export default async function Home() {
- } - href="/dashboard?to=custom-commands&utm_source=wamellow.com&utm_medium=home" - > - Setup - +
@@ -785,15 +794,18 @@ export default async function Home() { function Invite() { return ( - } + ); } \ No newline at end of file diff --git a/app/(home)/pro/page.tsx b/app/(home)/pro/page.tsx index fec6d75e..ceb23bde 100644 --- a/app/(home)/pro/page.tsx +++ b/app/(home)/pro/page.tsx @@ -1,4 +1,3 @@ -import { Button, Chip } from "@nextui-org/react"; import type { Metadata } from "next"; import { Montserrat } from "next/font/google"; import Link from "next/link"; @@ -8,16 +7,36 @@ import { IoMdInfinite } from "react-icons/io"; import Comment from "@/components/comment"; import ImageGrid from "@/components/image-grid"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { defaultFetchOptions } from "@/lib/api"; import type { ApiV1TopguildsGetResponse } from "@/typings"; import { cn } from "@/utils/cn"; import { getBaseUrl, getCanonicalUrl } from "@/utils/urls"; -const maybe = null; const montserrat = Montserrat({ subsets: ["latin"] }); +const maybe = null; -export const revalidate = 3600; +const items = [ + { title: "Price", free: "$0 /month", pro: "$3.99 /month" }, + { title: "Custom commands", free: 30, pro: Infinity }, + { title: "Social notifications", free: 30, pro: Infinity }, + { title: "Dailyposts", free: 30, pro: Infinity }, + // { title: "Stickymessages", free: 10, pro: 50 }, + // { title: "Custom footers", free: false, pro: true }, + { title: "Welcome roles", free: 5, pro: 10 }, + { title: "Welcome pings", free: 5, pro: 15 }, + // { title: "Level roles", free: 15, pro: 25 }, + { title: "Spotify control", free: maybe, pro: true, url: "/profile/spotify" }, + { title: "Custom /rank sub-text", free: false, pro: true }, + // { title: "Display user as webhook", free: false, pro: true }, + { title: "Passport bypass", free: false, pro: true }, + // { title: "Custom page color", free: false, pro: true }, + // { title: "Statistics & Analytics", free: false, pro: true }, + { title: "Crosspost social notifications", free: false, pro: true } +]; -const fetchOptions = { headers: { Authorization: process.env.API_SECRET as string }, next: { revalidate: 60 * 60 } }; +export const revalidate = 3600; export const generateMetadata = (): Metadata => { @@ -49,39 +68,7 @@ export const generateMetadata = (): Metadata => { }; export default async function Home() { - const topGuilds = await fetch(`${process.env.NEXT_PUBLIC_API}/top-guilds`, fetchOptions).then((res) => res.json()) as ApiV1TopguildsGetResponse[]; - - const buttons = (<> - - - ); - - const displayState = (is: string | number | boolean | null) => { - if (typeof is === "boolean" || is === null) { - if (is === true) return ; - if (is === false) return ; - if (is === null) return ; - } - - if (is === Infinity) return ; - return is; - }; + const topGuilds = await fetch(`${process.env.NEXT_PUBLIC_API}/top-guilds`, defaultFetchOptions).then((res) => res.json()) as ApiV1TopguildsGetResponse[]; return (
@@ -93,14 +80,14 @@ export default async function Home() { Professional - - Not available - + Not available +
{topGuilds && @@ -126,24 +113,7 @@ export default async function Home() { Pro+ ULTRA HD
- {[ - { title: "Price", free: "$0 /month", pro: "$3.99 /month" }, - { title: "Custom commands", free: 30, pro: Infinity }, - { title: "Social notifications", free: 30, pro: Infinity }, - { title: "Dailyposts", free: 30, pro: Infinity }, - // { title: "Stickymessages", free: 10, pro: 50 }, - // { title: "Custom footers", free: false, pro: true }, - { title: "Welcome roles", free: 5, pro: 10 }, - { title: "Welcome pings", free: 5, pro: 15 }, - // { title: "Level roles", free: 15, pro: 25 }, - { title: "Spotify control", free: maybe, pro: true, url: "/profile/spotify" }, - { title: "Custom /rank sub-text", free: false, pro: true }, - // { title: "Display user as webhook", free: false, pro: true }, - { title: "Passport bypass", free: false, pro: true }, - // { title: "Custom page color", free: false, pro: true }, - // { title: "Statistics & Analytics", free: false, pro: true }, - { title: "Crosspost social notifications", free: false, pro: true } - ].map((item) => ( + {items.map((item) => (
{item.title} @@ -159,7 +129,7 @@ export default async function Home() {
- {buttons} +
@@ -187,12 +157,12 @@ export default async function Home() {
Upgrade your guilds further! - - Not available - + Not available +
); +} + +function displayState(is: string | number | boolean | null) { + if (typeof is === "boolean" || is === null) { + if (is === true) return ; + if (is === false) return ; + if (is === null) return ; + } + + if (is === Infinity) return ; + return is; +} + +function Subscribe() { + return (<> + + + ); } \ No newline at end of file diff --git a/app/(home)/status/cluster.component.tsx b/app/(home)/status/cluster.component.tsx index 5735a7d6..179588b8 100644 --- a/app/(home)/status/cluster.component.tsx +++ b/app/(home)/status/cluster.component.tsx @@ -1,8 +1,7 @@ -import { Chip } from "@nextui-org/react"; import Image from "next/image"; -import { FaCrown } from "react-icons/fa6"; import { HiLightningBolt } from "react-icons/hi"; +import { Badge } from "@/components/ui/badge"; import { cn } from "@/utils/cn"; import { intl } from "@/utils/numbers"; @@ -46,24 +45,14 @@ export function Cluster(cluster: ApiCluster) {
- {cluster.id === 0 - ? } - color="warning" - variant="flat" - > - {cluster.ping}ms - - : 0 && "text-neutral-400 bg-wamellow w-1/6")} - startContent={} - variant="flat" - color={cluster.ping < 0 ? "danger" : "default"} - > - {cluster.ping}ms - - } + 0 && "text-neutral-400 bg-wamellow max-w-1/6")} + variant={cluster.ping < 0 ? "destructive" : "default"} + radius="rounded" + > + + {cluster.ping}ms +
); } diff --git a/app/(home)/status/node.component.tsx b/app/(home)/status/node.component.tsx index 503d38d9..96c39966 100644 --- a/app/(home)/status/node.component.tsx +++ b/app/(home)/status/node.component.tsx @@ -1,7 +1,5 @@ -import { Chip } from "@nextui-org/react"; import Image from "next/image"; import type { ReactNode } from "react"; -import { FaCrown } from "react-icons/fa"; import type { ApiNode } from "./api"; @@ -20,17 +18,6 @@ export function Node({ index, node }: { index: number; node: ApiNode; }) { #{index} - - {node.id.endsWith("-lun-1") && - } - color="warning" - variant="flat" - > - master - - }
diff --git a/app/(home)/team/repository.component.tsx b/app/(home)/team/repository.component.tsx index 373d1223..65514cc5 100644 --- a/app/(home)/team/repository.component.tsx +++ b/app/(home)/team/repository.component.tsx @@ -1,7 +1,7 @@ import Link from "next/link"; import { HiBeaker, HiExternalLink, HiStar } from "react-icons/hi"; -import { ClientChip } from "@/components/client"; +import { Badge } from "@/components/ui/badge"; import { getRepository } from "@/lib/github"; import { cn } from "@/utils/cn"; @@ -28,20 +28,20 @@ export async function Repository({ {repo.full_name} - } + + {repo.stargazers_count} - - } - size="sm" + + + {repo.language} - +
{repo.description}
diff --git a/app/ai-gallery/(home)/filter.component.tsx b/app/ai-gallery/(home)/filter.component.tsx index ba4dd1c2..d574c575 100644 --- a/app/ai-gallery/(home)/filter.component.tsx +++ b/app/ai-gallery/(home)/filter.component.tsx @@ -1,13 +1,13 @@ "use client"; -import { Badge, Button, Popover, PopoverContent, PopoverTrigger } from "@nextui-org/react"; import { useRouter } from "next/navigation"; -import { useCookies } from "next-client-cookies"; import { useEffect, useState } from "react"; import Switch from "@/components/inputs/switch"; +import { Button } from "@/components/ui/button"; +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; -export default function SearchFilter( +export function SearchFilter( { searchParams }: { @@ -19,7 +19,6 @@ export default function SearchFilter( } ) { const router = useRouter(); - const cookies = useCookies(); const [isEmbedded, setEmbedded] = useState(false); @@ -31,58 +30,33 @@ export default function SearchFilter( return ( - - - - - - + + + - {(titleProps) => ( -
-

- Search options -

-
- { - const params = new URLSearchParams(searchParams); - params.delete("nsfw"); +

Search Options

+
+ { + const params = new URLSearchParams(searchParams); + params.delete("nsfw"); - if (!checked) params.append("nsfw", "true"); + if (!checked) params.append("nsfw", "true"); - router.replace(`?${params.toString()}`); - }} - /> -
-
- )} + router.replace(`?${params.toString()}`); + }} + /> +
diff --git a/app/ai-gallery/(home)/layout.tsx b/app/ai-gallery/(home)/layout.tsx index 51bccbad..9aaf4a19 100644 --- a/app/ai-gallery/(home)/layout.tsx +++ b/app/ai-gallery/(home)/layout.tsx @@ -2,11 +2,10 @@ import type { Metadata } from "next"; import { Montserrat } from "next/font/google"; import Image from "next/image"; import Link from "next/link"; -import { BsDiscord } from "react-icons/bs"; import { HiUserAdd } from "react-icons/hi"; -import { ClientButton } from "@/components/client"; import { Footer } from "@/components/footer"; +import { Button } from "@/components/ui/button"; import CommandPic from "@/public/image-command.webp"; import { cn } from "@/utils/cn"; import { getBaseUrl, getCanonicalUrl } from "@/utils/urls"; @@ -55,9 +54,7 @@ export default function RootLayout({ return (<> -

+

/image Ai {" generated in "} Discord @@ -70,9 +67,8 @@ export default function RootLayout({ prefetch={false} target="_blank" > - /image command usage -
- } +
+ +
diff --git a/app/ai-gallery/(home)/page.tsx b/app/ai-gallery/(home)/page.tsx index 54f5ec33..1d0b3062 100644 --- a/app/ai-gallery/(home)/page.tsx +++ b/app/ai-gallery/(home)/page.tsx @@ -1,13 +1,13 @@ -import { Chip } from "@nextui-org/react"; import Image from "next/image"; import Link from "next/link"; import Notice from "@/components/notice"; import { HomeButton, ScreenMessage, SupportButton } from "@/components/screen-message"; +import { Badge } from "@/components/ui/badge"; import SadWumpusPic from "@/public/sad-wumpus.gif"; import { getUploads } from "../api"; -import SearchFilter from "./filter.component"; +import { SearchFilter } from "./filter.component"; import Pagination from "./pagination.component"; interface Props { @@ -46,11 +46,7 @@ export default async function Home({ searchParams }: Props) { } if (!uploads.results.length) { - return ( - - ); + return ; } return (<> @@ -82,14 +78,13 @@ export default async function Home({ searchParams }: Props) { width={300} /> - {upload.model} - +

diff --git a/app/ai-gallery/[uploadId]/layout.tsx b/app/ai-gallery/[uploadId]/layout.tsx index c7416a18..b9beb36c 100644 --- a/app/ai-gallery/[uploadId]/layout.tsx +++ b/app/ai-gallery/[uploadId]/layout.tsx @@ -1,13 +1,12 @@ -import { Button } from "@nextui-org/react"; import type { Metadata } from "next"; -import NextImage from "next/image"; +import Image from "next/image"; import Link from "next/link"; -import { HiArrowLeft, HiHome, HiPlus } from "react-icons/hi"; +import { HiArrowLeft, HiPlus } from "react-icons/hi"; -import { ClientButton } from "@/components/client"; import { Footer } from "@/components/footer"; import Notice from "@/components/notice"; -import { ScreenMessage, SupportButton } from "@/components/screen-message"; +import { ScreenMessage } from "@/components/screen-message"; +import { Button } from "@/components/ui/button"; import { getPageAnalytics } from "@/lib/analytics"; import { getGuild } from "@/lib/api"; import SadWumpusPic from "@/public/sad-wumpus.gif"; @@ -84,18 +83,8 @@ export default async function RootLayout({ params, children }: Props) { top="4rem" title="Something went wrong!" description={upload.message} - buttons={<> - } - > - Go back to Home - - - } > - + }

@@ -125,7 +114,7 @@ export default async function RootLayout({ params, children }: Props) { className="h-24 w-24" href={`/ai-gallery/${upload.id}`} > -
diff --git a/app/ai-gallery/[uploadId]/page.tsx b/app/ai-gallery/[uploadId]/page.tsx index 6c283892..9bd4b73c 100644 --- a/app/ai-gallery/[uploadId]/page.tsx +++ b/app/ai-gallery/[uploadId]/page.tsx @@ -1,8 +1,9 @@ -import { Chip, Image } from "@nextui-org/react"; -import NextImage from "next/image"; +import Image from "next/image"; import Link from "next/link"; import { HiExternalLink } from "react-icons/hi"; +import { Badge } from "@/components/ui/badge"; + import { getUpload } from "../api"; export interface Props { @@ -19,47 +20,40 @@ export default async function Home({ params }: Props) { const src = `https://r2.wamellow.com/ai-image/${upload.id}.webp`; - return ( -
- -
- {upload.prompt} - -
-
- - {upload.model} - -
{upload.prompt}
-
{upload.negativePrompt}
-
+ return (<> +
+ {upload.prompt} + +
+
+ + {upload.model} + +
{upload.prompt}
+
{upload.negativePrompt}
+
- - Open original file - - + + Open original file + + -
- ); + ); } \ No newline at end of file diff --git a/app/ai-gallery/[uploadId]/side.component.tsx b/app/ai-gallery/[uploadId]/side.component.tsx index 0de8ea94..f046c87a 100644 --- a/app/ai-gallery/[uploadId]/side.component.tsx +++ b/app/ai-gallery/[uploadId]/side.component.tsx @@ -1,18 +1,17 @@ "use client"; -import { Accordion, AccordionItem, Button, Chip, Tooltip } from "@nextui-org/react"; +import { Accordion, AccordionItem } from "@nextui-org/react"; import Link from "next/link"; import { useCookies } from "next-client-cookies"; -import { FaReddit, FaTwitter } from "react-icons/fa"; -import { HiCheck, HiHand, HiShare, HiUserGroup } from "react-icons/hi"; +import { HiHand, HiUserGroup } from "react-icons/hi"; import Ad from "@/components/ad"; -import { CopyToClipboardButton } from "@/components/copy-to-clipboard"; import ImageReduceMotion from "@/components/image-reduce-motion"; +import { Share } from "@/components/share"; import { formatDate } from "@/components/time"; +import { Badge } from "@/components/ui/badge"; import type { AnalyticsError, AnalyticsResponse } from "@/lib/analytics"; import type { ApiError, ApiV1GuildsGetResponse, ApiV1UploadGetResponse } from "@/typings"; -import { truncate } from "@/utils/truncate"; import { getCanonicalUrl } from "@/utils/urls"; export default function Side({ @@ -26,42 +25,14 @@ export default function Side({ }) { const cookies = useCookies(); - const prompt = "prompt" in upload - ? truncate(upload.prompt.split(" ").map((str) => str.replace(/^\w/, (char) => char.toUpperCase())).join(" "), 32) - : null; - return (
- - {"id" in upload && -
- } - /> - - - - - - -
+ {"prompt" in upload && + } Created - + {"createdAt" in upload ? formatDate(upload.createdAt as string, "en-US") : "unknown" } - +
{analytics && "results" in analytics &&
- Views - + Views + {Array.isArray(analytics.results) && analytics.results.length ? (analytics.results[0].pageviews) : @@ -111,58 +76,49 @@ export default function Side({ } {" "} views - +
} {"author" in upload &&
- Author - - } - > + Author + + + {upload.author.username} {upload.author.bot && - } + - APP - + BOT + } - +
}
- Rating - - {"nsfw" in upload && upload.nsfw - ? - : - } - - } + variant={"nsfw" in upload && upload.nsfw ? "destructive" : "default"} > + {"nsfw" in upload && upload.nsfw + ? + : + } {"nsfw" in upload && upload.nsfw ? "Mature" : "Everyone"} - +
@@ -203,7 +159,7 @@ export default function Side({ />
-
{guild.name}
+
{guild.name}
View leaderboard
@@ -213,8 +169,7 @@ export default function Side({ The image has been generated by artificial intelligence (AI) and not by a human creator. Wamellow and its developers disclaim any responsibility for the content of the images and reserve all rights to the media.
- -
+
); } \ No newline at end of file diff --git a/app/ai-gallery/generate/layout.tsx b/app/ai-gallery/generate/layout.tsx deleted file mode 100644 index 87b62444..00000000 --- a/app/ai-gallery/generate/layout.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { Button } from "@nextui-org/react"; -import type { Metadata } from "next"; -import Link from "next/link"; -import { HiArrowLeft } from "react-icons/hi"; - -import { Footer } from "@/components/footer"; -import { getBaseUrl, getCanonicalUrl } from "@/utils/urls"; - -export interface Props { - params: Promise<{ uploadId: string; }>; - children: React.ReactNode; -} - -export const revalidate = 3600; - -export const generateMetadata = async ({ params }: Props): Promise => { - const { uploadId } = await params; - - const title = "Generate images with your Intel® Arc™ A-Series GPU"; - const description = "Generate AI images using your Intel® Arc™ A-Series GPU with Luna-devv/intel-arc-ai installed and running locally on your machine or network."; - const images = `${getBaseUrl()}/waya-v3.webp?v=2`; - const url = getCanonicalUrl("ai-gallery", uploadId); - - return { - title, - description, - alternates: { - canonical: url - }, - openGraph: { - title, - description, - type: "website", - url, - images - }, - twitter: { - card: "summary", - site: "wamellow.com", - title, - description, - images - } - }; -}; - -export default function RootLayout({ - children -}: Props) { - - return ( -
- - {children} - - - -
- -
- ); -} \ No newline at end of file diff --git a/app/ai-gallery/generate/page.tsx b/app/ai-gallery/generate/page.tsx deleted file mode 100644 index 3015c982..00000000 --- a/app/ai-gallery/generate/page.tsx +++ /dev/null @@ -1,164 +0,0 @@ -"use client"; - -import { Button, Image, Spinner } from "@nextui-org/react"; -import NextImage from "next/image"; -import { useRouter, useSearchParams } from "next/navigation"; -import { useCookies } from "next-client-cookies"; -import { useEffect, useState } from "react"; -import { HiPrinter } from "react-icons/hi"; - -import DumbTextInput from "@/components/inputs/dumb-text-input"; -import LinkTag from "@/components/link-tag"; -import Notice from "@/components/notice"; -import { cn } from "@/utils/cn"; - -import Time from "./time.component"; -import UploadButton from "./upload.component"; - -enum State { - Idle = 0, - Loading = 1 -} - -export default function Home() { - const cookies = useCookies(); - const search = useSearchParams(); - const router = useRouter(); - - const imageUrl = search.get("image_url"); - - const [state, setState] = useState(State.Idle); - const [error, setError] = useState(null); - - const [gpu, setGpu] = useState(null); - - const [baseUrl, setBaseUrl] = useState("https://ai.local.wamellow.com"); - const [model, setModel] = useState("animagine-xl-v3"); - const [prompt, setPrompt] = useState(""); - - useEffect(() => { - fetch(baseUrl) - .then((res) => res.json() as Promise<{ gpu: string; }>) - .then((res) => { - setError(null); - setGpu(res.gpu || null); - }) - .catch((err) => { - setError(`Could not fetch local GPU instance (${err.toString()})`); - }); - }, [baseUrl]); - - async function generate() { - setState(State.Loading); - - let params = new URLSearchParams(); - params.delete("image_url"); - router.push(`?${params.toString()}`, { scroll: false }); - - const reqparams = new URLSearchParams({ - prompt: prompt - }); - - const res = await fetch(`${baseUrl}/generate/image/${model}?${reqparams.toString()}`) - .then((res) => res.json()) as { url: string; duration: number; }; - - params = new URLSearchParams(); - params.delete("image_url"); - params.append("image_url", res.url); - - router.push(`?${params.toString()}`, { scroll: false }); - - setState(State.Idle); - } - - return ( -
- - {error && - - } - -
- -
- {imageUrl && state !== State.Loading ? - { - const params = new URLSearchParams(); - params.delete("image_url"); - router.push(`?${params.toString()}`, { scroll: false }); - }} - /> - : -
- {state === State.Loading - ? -
- -
- : - - No image generated yet - - } -
- } -
- -
- - - - - - -
- - {gpu || "unknown gpu"} - - - - ( -
- - - -
- Generate AI images using your own Intel® Arc™ A-Series GPU (16gb vram minimum). - Make sure you have Luna-devv/intel-arc-ai installed and running locally on your machine or local network. -
- -
-
-
- ); -} \ No newline at end of file diff --git a/app/ai-gallery/generate/time.component.tsx b/app/ai-gallery/generate/time.component.tsx deleted file mode 100644 index 870ec013..00000000 --- a/app/ai-gallery/generate/time.component.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { useEffect, useRef, useState } from "react"; - -export default function Time({ - loading -}: { - loading: boolean; -}) { - const intervalRef = useRef(null); - - const [previousLoading, setPreviousLoading] = useState(false); - const [estimatedTime, setEstimatedTime] = useState(0); - - useEffect(() => { - if (loading === previousLoading) return; - - if (!previousLoading && loading) setEstimatedTime(0); - setPreviousLoading(loading); - - if (!loading) { - if (intervalRef.current) clearInterval(intervalRef.current); - return; - } - - intervalRef.current = setInterval(() => { - setEstimatedTime((prev) => prev + 100); - }, 100); - }, [loading]); - - return ( - - {(estimatedTime / 1000).toFixed(1)}s - - ); -} \ No newline at end of file diff --git a/app/ai-gallery/generate/upload.component.tsx b/app/ai-gallery/generate/upload.component.tsx deleted file mode 100644 index 47e95f60..00000000 --- a/app/ai-gallery/generate/upload.component.tsx +++ /dev/null @@ -1,117 +0,0 @@ -"use client"; - -import { Button, Checkbox } from "@nextui-org/react"; -import { useSearchParams } from "next/navigation"; -import { useCookies } from "next-client-cookies"; -import { useEffect, useState } from "react"; -import { HiCloudUpload } from "react-icons/hi"; - -import type { ApiV1UploadGetResponse } from "@/typings"; -import { cn } from "@/utils/cn"; - -enum State { - Idle = 0, - Loading = 1, - Success = 2 -} - -export default function UploadButton({ - model, - prompt -}: { - model: string; - prompt: string; -}) { - const search = useSearchParams(); - const cookies = useCookies(); - - const imageUrl = search.get("image_url"); - - const [state, setState] = useState(State.Idle); - const [error, setError] = useState(null); - - const [nsfw, setNsfw] = useState(false); - - const isDisabled = !cookies.get("session") || !imageUrl; - - useEffect(() => { - setState(State.Idle); - }, [imageUrl]); - - async function upload() { - setState(State.Loading); - - const res = await fetch(`${process.env.NEXT_PUBLIC_API}/ai`, { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - url: imageUrl, - model: model, - prompt: prompt, - nsfw: nsfw - }) - }) - .then((res) => res.json()) as ApiV1UploadGetResponse; - - if ("message" in res) { - setError(res.message as string); - return; - } - - setState(State.Success); - } - - return ( -
- -
- setNsfw(now)} - color="secondary" - isDisabled={isDisabled} - /> - Is NSFW content? -
- - - - {error && - - {error} - - } - -
- ); - -} \ No newline at end of file diff --git a/app/dashboard/[guildId]/layout.tsx b/app/dashboard/[guildId]/layout.tsx index 65529aca..3d602223 100644 --- a/app/dashboard/[guildId]/layout.tsx +++ b/app/dashboard/[guildId]/layout.tsx @@ -3,15 +3,14 @@ import { Button, Skeleton } from "@nextui-org/react"; import Image from "next/image"; import Link from "next/link"; -import { redirect, useParams, usePathname } from "next/navigation"; +import { redirect, useParams } from "next/navigation"; import { useCookies } from "next-client-cookies"; import { Suspense, useEffect, useMemo, useState } from "react"; -import { HiArrowNarrowLeft, HiBell, HiChartBar, HiCode, HiCursorClick, HiEye, HiHome, HiPaperAirplane, HiShare, HiStar, HiUserAdd, HiUsers, HiViewGridAdd } from "react-icons/hi"; +import { HiArrowNarrowLeft, HiBell, HiChartBar, HiCode, HiEye, HiHome, HiPaperAirplane, HiStar, HiUserAdd, HiUsers, HiViewGridAdd } from "react-icons/hi"; import { useQuery } from "react-query"; import { guildStore } from "@/common/guilds"; import { ClientButton } from "@/components/client"; -import { CopyToClipboardButton } from "@/components/copy-to-clipboard"; import ImageReduceMotion from "@/components/image-reduce-motion"; import { ListTab } from "@/components/list"; import { ScreenMessage, SupportButton } from "@/components/screen-message"; @@ -19,7 +18,6 @@ import { cacheOptions, getData } from "@/lib/api"; import SadWumpusPic from "@/public/sad-wumpus.gif"; import type { ApiV1GuildsChannelsGetResponse, ApiV1GuildsEmojisGetResponse, ApiV1GuildsGetResponse, ApiV1GuildsRolesGetResponse } from "@/typings"; import { intl } from "@/utils/numbers"; -import { getCanonicalUrl } from "@/utils/urls"; function useGuildData( url: string, @@ -46,7 +44,6 @@ export default function RootLayout({ }) { const cookies = useCookies(); const params = useParams(); - const path = usePathname(); const [error, setError] = useState(); const [loaded, setLoaded] = useState([]); @@ -54,7 +51,6 @@ export default function RootLayout({ const guild = guildStore((g) => g); const session = useMemo(() => cookies.get("session"), [cookies]); - const isDevMode = useMemo(() => cookies.get("devTools") === "true", [cookies]); if (!session) redirect(`/login?callback=/dashboard/${params.guildId}`); @@ -108,26 +104,14 @@ export default function RootLayout({ {`${guild?.name}'s Dashboard`}
-
- - {isDevMode && - , name: "Copy page url", description: "Creates a link to this specific page", text: getCanonicalUrl(...path.split("/").slice(1)) }, - { icon: , name: "Copy dash-to url", description: "Creates a dash-to link to the current tab", text: getCanonicalUrl(`dashboard?to=${path.split("/dashboard/")[1].split("/")[1] || "/"}`) } - ]} - icon={} - /> - } -
+
@@ -228,6 +212,6 @@ export default function RootLayout({ (guild && loaded.length === 3) ? children : <> } -
+
); } \ No newline at end of file diff --git a/app/globals.css b/app/globals.css index bd3f6b21..4ed9de3d 100644 --- a/app/globals.css +++ b/app/globals.css @@ -4,6 +4,11 @@ @layer base { .dark { + --background-rgb: rgb(3, 2, 6); + + --wamellow: #ffffff0d; + --wamellow-100: #ffffff1a; + --wamellow-200: #ffffff33; --font-outfit: 'Outfit', sans-serif; --font-noto-sans-jp: 'Noto Sans JP', sans-serif; @@ -11,20 +16,31 @@ --wamellow-rgb: rgba(255, 255, 255, 0.16); --foreground: 210 20% 98%; + --card: 224 71.4% 4.1%; --card-foreground: 210 20% 98%; + --popover: 260 3% 4.1%; --popover-foreground: 210 20% 98%; + --primary: 0 0% 100%; --primary-foreground: 220.9 39.3% 89%; + --secondary: 258 89% 66%; --secondary-foreground: 210 20% 98%; + + --flat: var(--secondary); + --flat-foreground: 270 59% 85%; + --muted: 260 3% 16%; - --muted-foreground: 217.9 10.6% 64.9%; + --muted-foreground: 217 10% 65%; + --accent: 258 89% 66%; --accent-foreground: 210 20% 98%; - --destructive: 0 62.8% 30.6%; + + --destructive: 0 62.8% 40.6; --destructive-foreground: 210 20% 98%; + --border: 260 3% 16%; --input: 258 89% 66%; --ring: 258 89% 66%; @@ -38,16 +54,21 @@ } @layer base { - * { - @apply border-border; + * { + @apply border-border; + } + svg { + @apply shrink-0; + } + button { + @apply cursor-pointer + } + html { + font-family: var(--font-outfit), var(--font-noto-sans-jp), sans-serif; + scroll-behavior: smooth; + min-height: 100svh; + background: var(--background-rgb); } -} - -html { - font-family: var(--font-outfit), var(--font-noto-sans-jp), sans-serif; - - min-height: 100svh!important; - scroll-behavior: smooth; } div[id="bg"] { @@ -202,7 +223,7 @@ a[role="button"]:not(.w-unit-10):not(.default):not(.bg-secondary):not(.button-pr } .button { - @apply flex dark:text-neutral-300 text-neutral-700 dark:bg-wamellow bg-wamellow-100 dark:hover:bg-wamellow-light hover:bg-wamellow-100-light py-2 px-4 duration-200 justify-center gap-2 items-center text-medium + @apply flex text-white bg-wamellow-100 hover:bg-wamellow-200 py-2 px-4 duration-200 justify-center gap-2 items-center text-medium } .button-primary { diff --git a/app/layout.tsx b/app/layout.tsx index 1690557a..d9627ac5 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -11,9 +11,8 @@ import { CookiesProvider } from "next-client-cookies/server"; import { HiBookOpen } from "react-icons/hi"; import { SiKofi } from "react-icons/si"; -import Header from "@/components/header"; -import LoginButton from "@/components/login-button"; -import Notice, { NoticeType } from "@/components/notice"; +import { Header } from "@/components/header"; +import { LoginButton } from "@/components/login-button"; import { cn } from "@/utils/cn"; import { getBaseUrl } from "@/utils/urls"; @@ -64,73 +63,6 @@ export const generateMetadata = (): Metadata => { }, description, - keywords: [ - "discord", - "bot", - "app", - "intefration", - "discord bot", - "discord app", - "discord application", - "app list", - "waya", - "waya bot", - "waya.one", - "mwya", - "mellow", - "wamellow", - "mwlica", - "lunish", - "Luna-devv", - "mee6 alternative", - "arcane alternative", - "dyno alternative", - "starboard", - "ranks", - "leaderboard", - "lb", - "leaderboards", - "text to speech", - "captcha", - "passport", - "verification", - "verify", - "captcha.bot", - "security", - "tts", - "text to speech", - "free", - "customizable", - "next-gen", - "next generation", - "ai", - "ai images", - "nsfw detection", - "moderation", - "anime", - "nekos", - "waifus", - "chat to speech", - "accessibility", - "aphonia", - "dysphonia", - "mute", - "liapew", - "wumpus", - "wumpus store", - "wumpus bots", - "youtube notifications", - "youtube notifis", - "youtube to discord", - "twitch notifications", - "twitch notifis", - "twitch to discord", - "bluesky notifications", - "bluesky notifis", - "bluesky to discord", - "bluesky", - "bsky" - ], alternates: { canonical: getBaseUrl() @@ -195,7 +127,6 @@ export default function RootLayout({
-