Refactor next.config.js and form.tsx

This commit is contained in:
mr. M 2024-10-14 22:52:01 +02:00
parent 00c7ce4c56
commit 5ec0fcbb56
No known key found for this signature in database
GPG key ID: CBD57A2AEDBDA1FB
31 changed files with 388 additions and 336 deletions

View file

@ -88,9 +88,18 @@ function formatReleaseNote(releaseNote: ReleaseNote) {
content += `<p>${releaseNote.extra.replace(/(\n)/g, "<br />")}</p>`; content += `<p>${releaseNote.extra.replace(/(\n)/g, "<br />")}</p>`;
} }
content += addReleaseNoteSection("⚠️ Breaking changes", releaseNote.breakingChanges); content += addReleaseNoteSection(
content += addReleaseNoteSection("✓ Fixes", releaseNote.fixes?.map(fixToReleaseNote)); "⚠️ Breaking changes",
content += addReleaseNoteSection("🖌 Theme Changes", releaseNote.themeChanges) releaseNote.breakingChanges,
);
content += addReleaseNoteSection(
"✓ Fixes",
releaseNote.fixes?.map(fixToReleaseNote),
);
content += addReleaseNoteSection(
"🖌 Theme Changes",
releaseNote.themeChanges,
);
content += addReleaseNoteSection("⭐ Features", releaseNote.features); content += addReleaseNoteSection("⭐ Features", releaseNote.features);
return content; return content;
@ -112,7 +121,9 @@ function addReleaseNoteSection(title: string, items?: string[]): string {
return content; return content;
} }
function fixToReleaseNote(fix?: Exclude<ReleaseNote['fixes'], undefined>[number]) { function fixToReleaseNote(
fix?: Exclude<ReleaseNote["fixes"], undefined>[number],
) {
if (!fix || !fix.description || fix.description.length === 0) { if (!fix || !fix.description || fix.description.length === 0) {
return ""; return "";
} }

View file

@ -57,7 +57,7 @@
} }
code { code {
font-size: .8em; font-size: 0.8em;
background-color: var(--surface); background-color: var(--surface);
padding: 0.2em 0.4em; padding: 0.2em 0.4em;
border: 1px solid light-dark(rgba(0, 0, 0, 0.5), rgba(255, 255, 255, 0.2)); border: 1px solid light-dark(rgba(0, 0, 0, 0.5), rgba(255, 255, 255, 0.2));

View file

@ -1,13 +1,13 @@
'use client'; "use client";
import { useEffect } from 'react'; import { useEffect } from "react";
import { useRouter } from 'next/navigation'; import { useRouter } from "next/navigation";
export default function ThemesPage() { export default function ThemesPage() {
const router = useRouter(); const router = useRouter();
useEffect(() => { useEffect(() => {
router.replace('/mods'); router.replace("/mods");
}, [router]); }, [router]);
return null; return null;

View file

@ -2,7 +2,6 @@
import Image from "next/image"; import Image from "next/image";
const inDev = process.env.NODE_ENV === "development"; const inDev = process.env.NODE_ENV === "development";
function imageLoader({ src }: { src: string }) { function imageLoader({ src }: { src: string }) {
// Load locally if we are in development // Load locally if we are in development

View file

@ -31,7 +31,7 @@ export const AlertModal = ({
</div> </div>
</AlertDialog.Title> </AlertDialog.Title>
<AlertDialog.Description asChild> <AlertDialog.Description asChild>
<p className="text-center text-sm text-muted-foreground mb-6"> <p className="mb-6 text-center text-sm text-muted-foreground">
Please select other formats if you want to install the Optimized Please select other formats if you want to install the Optimized
version. version.
</p> </p>

View file

@ -75,7 +75,12 @@ export function BrandingAssets() {
CC BY-SA 4.0 CC BY-SA 4.0
</a> </a>
. Thanks to{" "} . Thanks to{" "}
<a href="https://www.onnno.nl/" rel="noopener noreferrer" target="_blank" className="text-blue-500"> <a
href="https://www.onnno.nl/"
rel="noopener noreferrer"
target="_blank"
className="text-blue-500"
>
Donno (mr. Logos) Donno (mr. Logos)
</a>{" "} </a>{" "}
for the assets. for the assets.

View file

@ -8,18 +8,27 @@ import React from "react";
export default function BrowserComplexityExample() { export default function BrowserComplexityExample() {
const [selectedImage, setSelectedImage] = React.useState([1]); const [selectedImage, setSelectedImage] = React.useState([1]);
return ( return (
<div className="flex h-screen items-center flex-col mx-auto mb-32 xl:mb-64 w-full md:w-5/6 lg:w-3/4"> <div className="mx-auto mb-32 flex h-screen w-full flex-col items-center md:w-5/6 lg:w-3/4 xl:mb-64">
<h1 className="text-4xl md:text-5xl font-bold text-center">How much browser do you want?</h1> <h1 className="text-center text-4xl font-bold md:text-5xl">
<p className="mt-4 text-center text-md mx-auto w-2/3 text-muted-foreground"> How much browser do you want?
Zen is designed to be simple and easy to use. We believe that the best software is </h1>
the one that you don't notice. However, we can assure you that if you want customization, we have you covered <p className="text-md mx-auto mt-4 w-2/3 text-center text-muted-foreground">
Zen is designed to be simple and easy to use. We believe that the best
software is the one that you don't notice. However, we can assure you
that if you want customization, we have you covered
</p> </p>
<div className="w-64 mb-6 mt-12 flex gap-4"> <div className="mb-6 mt-12 flex w-64 gap-4">
<span className="opacity-90">🌱</span> <span className="opacity-90">🌱</span>
<Slider step={1} max={3} showSteps="half" value={selectedImage} onValueChange={setSelectedImage} /> <Slider
step={1}
max={3}
showSteps="half"
value={selectedImage}
onValueChange={setSelectedImage}
/>
<span className="opacity-90">🌳</span> <span className="opacity-90">🌳</span>
</div> </div>
<div className="mx-auto md:mb-36 flex justify-center"> <div className="mx-auto flex justify-center md:mb-36">
{[...Array(4)].map((_, i) => ( {[...Array(4)].map((_, i) => (
<CachedImage <CachedImage
width={1620} width={1620}
@ -28,12 +37,15 @@ export default function BrowserComplexityExample() {
key={i} key={i}
src={`www/public/browsers/image${i + 1}.png`} src={`www/public/browsers/image${i + 1}.png`}
alt="Zen Browser" alt="Zen Browser"
className={ny("rounded-md object-cover shadow object-right mx-12 w-full", selectedImage[0] === i className={ny(
"mx-12 w-full rounded-md object-cover object-right shadow",
selectedImage[0] === i
? "" //"animate-fade-up duration-500 !opacity-100" ? "" //"animate-fade-up duration-500 !opacity-100"
: "hidden")} : "hidden",
)}
/> />
))} ))}
</div> </div>
</div> </div>
) );
} }

View file

@ -1,14 +1,12 @@
import s from './styles.module.css' import s from "./styles.module.css";
export default function CoolHeaderText() { export default function CoolHeaderText() {
return ( return (
<> <>
<div className="relative mb-3 mt-5 -translate-y-4 animate-fade-in text-balance bg-gradient-to-br from-30% to-black/40 bg-clip-text py-6 text-5xl font-semibold leading-none tracking-tighter text-transparent opacity-0 [--animation-delay:200ms] dark:from-white dark:to-white/40 sm:text-6xl md:text-7xl lg:text-8xl"> <div className="relative mb-3 mt-5 -translate-y-4 animate-fade-in text-balance bg-gradient-to-br from-30% to-black/40 bg-clip-text py-6 text-5xl font-semibold leading-none tracking-tighter text-transparent opacity-0 [--animation-delay:200ms] dark:from-white dark:to-white/40 sm:text-6xl md:text-7xl lg:text-8xl">
<h1 className={s.title}> <h1 className={s.title}>Stay focused, browse faster with Zen</h1>
Stay focused, browse faster with Zen
</h1>
</div> </div>
<div className="pointer-events-none absolute right-20 top-[-5px] mt-12 hidden h-fit w-fit !rotate-[15deg] transform animate-fade-in rounded-full bg-surface border-2 px-3 py-1 opacity-0 shadow [--animation-delay:400ms] md:block"> <div className="pointer-events-none absolute right-20 top-[-5px] mt-12 hidden h-fit w-fit !rotate-[15deg] transform animate-fade-in rounded-full border-2 bg-surface px-3 py-1 opacity-0 shadow [--animation-delay:400ms] md:block">
Alpha Version Alpha Version
</div> </div>
</> </>

View file

@ -21,4 +21,3 @@
user-select: none; user-select: none;
cursor: default; cursor: default;
} }

View file

@ -5,7 +5,6 @@ import { Button } from "./ui/button";
import React from "react"; import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import { import {
Sheet, Sheet,
SheetContent, SheetContent,

View file

@ -1,4 +1,4 @@
'use client'; "use client";
import { Architecture } from "@/components/download/types"; import { Architecture } from "@/components/download/types";
import { ny } from "@/lib/utils"; import { ny } from "@/lib/utils";

View file

@ -46,9 +46,7 @@ export const MacArchitectureCard = ({
> >
<h1 className="my-2 text-5xl opacity-40 dark:opacity-20">{icon}</h1> <h1 className="my-2 text-5xl opacity-40 dark:opacity-20">{icon}</h1>
<h1 className="my-2 text-2xl font-semibold">{label}</h1> <h1 className="my-2 text-2xl font-semibold">{label}</h1>
<p className="mx-auto text-center text-muted-foreground"> <p className="mx-auto text-center text-muted-foreground">{description}</p>
{description}
</p>
</div> </div>
); );
}; };

View file

@ -1,4 +1,4 @@
'use client'; "use client";
import { Platforms } from "@/components/download/types"; import { Platforms } from "@/components/download/types";
import { ny } from "@/lib/utils"; import { ny } from "@/lib/utils";
@ -10,7 +10,7 @@ interface PlatformCardProps {
} }
const PLATFORMS_DATA: Record< const PLATFORMS_DATA: Record<
Exclude<Platforms, 'Unsupported'>, Exclude<Platforms, "Unsupported">,
{ label: string; icon: string; borderColor: string } { label: string; icon: string; borderColor: string }
> = { > = {
Windows: { Windows: {

View file

@ -1,9 +1,19 @@
'use client' "use client";
import CachedImage from "@/components/CachedImage"; import CachedImage from "@/components/CachedImage";
import Logo from "@/components/logo"; import Logo from "@/components/logo";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"; import {
import { ExternalLinkIcon, EyeClosedIcon, LockClosedIcon, QuestionMarkCircledIcon } from "@radix-ui/react-icons"; Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import {
ExternalLinkIcon,
EyeClosedIcon,
LockClosedIcon,
QuestionMarkCircledIcon,
} from "@radix-ui/react-icons";
import { ShieldCheck, ShieldAlertIcon } from "lucide-react"; import { ShieldCheck, ShieldAlertIcon } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { useState } from "react"; import { useState } from "react";

View file

@ -48,8 +48,8 @@ export default function Features() {
<PaintBucket className="inline h-10 w-10"></PaintBucket> <PaintBucket className="inline h-10 w-10"></PaintBucket>
</h3> </h3>
<p className="mt-4 text-lg text-gray-600 dark:text-gray-300"> <p className="mt-4 text-lg text-gray-600 dark:text-gray-300">
With Zen Mods, you can customize your browsing experience With Zen Mods, you can customize your browsing experience to
to reflect your unique style and preferences. Choose from a wide reflect your unique style and preferences. Choose from a wide
array of Mods, colors, and layouts to make Zen truly your own, array of Mods, colors, and layouts to make Zen truly your own,
transforming your browser into a personalized digital space. transforming your browser into a personalized digital space.
</p> </p>

View file

@ -14,7 +14,9 @@ export function ModeToggle() {
if (savedTheme) { if (savedTheme) {
setTheme(savedTheme); setTheme(savedTheme);
} else { } else {
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
setTheme(prefersDark ? "dark" : "light"); setTheme(prefersDark ? "dark" : "light");
} }
}, [setTheme]); }, [setTheme]);

View file

@ -122,9 +122,9 @@ export function Navigation() {
<div className="border-grey fixed left-0 top-0 z-40 flex w-full items-center justify-center border-b bg-background p-2"> <div className="border-grey fixed left-0 top-0 z-40 flex w-full items-center justify-center border-b bg-background p-2">
<MobileNav /> <MobileNav />
<NavigationMenu> <NavigationMenu>
<NavigationMenuList className="hidden w-full py-3 sm:flex items-center justify-between gap-32"> <NavigationMenuList className="hidden w-full items-center justify-between gap-32 py-3 sm:flex">
<div> <div>
<NavigationMenuItem className="cursor-pointer flex items-center"> <NavigationMenuItem className="flex cursor-pointer items-center">
<NavigationMenuLink href="/"> <NavigationMenuLink href="/">
<Logo withText /> <Logo withText />
</NavigationMenuLink> </NavigationMenuLink>
@ -186,8 +186,8 @@ export function Navigation() {
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
Ko-fi is a way to support us with a one-time donation and help Ko-fi is a way to support us with a one-time donation and
us keep the project alive. help us keep the project alive.
</ListItem2> </ListItem2>
</ul> </ul>
</NavigationMenuContent> </NavigationMenuContent>
@ -215,7 +215,10 @@ export function Navigation() {
<ModeToggle /> <ModeToggle />
</div> </div>
<div> <div>
<NavigationMenuLink href={`/release-notes/${latestRelease.version}`} className="text-[10px] bg-surface py-1 px-2 font-semibold rounded h-fit w-fit flex items-center hover:bg-accent hover:text-accent-foreground transition-colors"> <NavigationMenuLink
href={`/release-notes/${latestRelease.version}`}
className="flex h-fit w-fit items-center rounded bg-surface px-2 py-1 text-[10px] font-semibold transition-colors hover:bg-accent hover:text-accent-foreground"
>
v{latestRelease.version} v{latestRelease.version}
</NavigationMenuLink> </NavigationMenuLink>
</div> </div>

View file

@ -3,8 +3,13 @@ import { getThemeAuthorLink, ZenTheme } from "@/lib/mods";
import { TagIcon } from "lucide-react"; import { TagIcon } from "lucide-react";
import { Badge } from "./ui/badge"; import { Badge } from "./ui/badge";
import Link from "next/link"; import {
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "./ui/card"; Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from "./ui/card";
export default function ThemeCard({ export default function ThemeCard({
theme, theme,
@ -18,7 +23,8 @@ export default function ThemeCard({
const authorLink = getThemeAuthorLink(theme); const authorLink = getThemeAuthorLink(theme);
return ( return (
<Card className="select-none h-full flex-col justify-between rounded-xl border-2 border-[transparent] bg-surface transition-all duration-200 hover:border-[rgba(0,0,0,.5)] hover:shadow-lg dark:bg-[#121212] dark:hover:border-[#333]" <Card
className="h-full select-none flex-col justify-between rounded-xl border-2 border-[transparent] bg-surface transition-all duration-200 hover:border-[rgba(0,0,0,.5)] hover:shadow-lg dark:bg-[#121212] dark:hover:border-[#333]"
onMouseDown={(e) => { onMouseDown={(e) => {
// IMPORTANT NOTE: We do NOT use a Link component here because of how zen manages site injection. // IMPORTANT NOTE: We do NOT use a Link component here because of how zen manages site injection.
// please for the love of god, dont change this to a Link component. Please. // please for the love of god, dont change this to a Link component. Please.
@ -28,7 +34,8 @@ export default function ThemeCard({
if (e.button !== 0 && e.button !== 1) return; if (e.button !== 0 && e.button !== 1) return;
if (e.target instanceof HTMLAnchorElement) return; if (e.target instanceof HTMLAnchorElement) return;
window.open(`/mods/${theme.id}`, e.button === 1 ? "_blank" : "_self"); window.open(`/mods/${theme.id}`, e.button === 1 ? "_blank" : "_self");
}}> }}
>
<div className="relative m-2 mb-0 hidden aspect-[1.85/1] h-48 overflow-hidden rounded-xl border-2 border-[rgba(0,0,0,.5)] object-cover shadow dark:border-[#333] lg:block lg:h-auto"> <div className="relative m-2 mb-0 hidden aspect-[1.85/1] h-48 overflow-hidden rounded-xl border-2 border-[rgba(0,0,0,.5)] object-cover shadow dark:border-[#333] lg:block lg:h-auto">
<img <img
src={theme.image} src={theme.image}

View file

@ -19,7 +19,7 @@ export default async function ThemePage({ themeID }: { themeID: string }) {
return ( return (
<div className="relative mx-auto mt-24 flex flex-col items-start lg:mt-56 lg:flex-row"> <div className="relative mx-auto mt-24 flex flex-col items-start lg:mt-56 lg:flex-row">
<div className="w-md relative mx-auto mr-5 flex h-full w-full flex-col rounded-lg border bg-surface p-5 shadow md:mx-0 md:max-w-sm lg:sticky lg:top-0"> <div className="w-md relative mx-auto mr-5 flex h-full w-full flex-col rounded-lg border bg-surface p-5 shadow md:mx-0 md:max-w-sm lg:sticky lg:top-0">
<div className="flex justify-between w-full items-center mb-2"> <div className="mb-2 flex w-full items-center justify-between">
<a <a
className="flex cursor-pointer items-center opacity-70" className="flex cursor-pointer items-center opacity-70"
href="/mods" href="/mods"
@ -67,11 +67,9 @@ export default async function ThemePage({ themeID }: { themeID: string }) {
</a> </a>
</p> </p>
<hr className="my-4" /> <hr className="my-4" />
<div className="text-sm text-muted-foreground flex justify-between"> <div className="flex justify-between text-sm text-muted-foreground">
<div> <div>
<span className="opacity-70"> <span className="opacity-70">Theme by </span>
Theme by{" "}
</span>
<a <a
href={getThemeAuthorLink(theme)} href={getThemeAuthorLink(theme)}
className="text-md mt-4 text-blue-500" className="text-md mt-4 text-blue-500"
@ -81,9 +79,7 @@ export default async function ThemePage({ themeID }: { themeID: string }) {
{theme.author} {theme.author}
</a> </a>
</div> </div>
<div className="opacity-70"> <div className="opacity-70">v{theme.version}</div>
v{theme.version}
</div>
</div> </div>
</div> </div>
<div className="flex w-full max-w-xl flex-col px-5 lg:min-h-[calc(100vh/2-2rem)] lg:min-w-96 lg:pl-10"> <div className="flex w-full max-w-xl flex-col px-5 lg:min-h-[calc(100vh/2-2rem)] lg:min-w-96 lg:pl-10">
@ -92,7 +88,7 @@ export default async function ThemePage({ themeID }: { themeID: string }) {
alt={theme.name} alt={theme.name}
className="w-full rounded-2xl border-2 object-cover shadow" className="w-full rounded-2xl border-2 object-cover shadow"
/> />
<div id="policy" className="w-full !mt-0"> <div id="policy" className="!mt-0 w-full">
{readme === null ? ( {readme === null ? (
<LoaderCircleIcon className="mx-auto h-12 w-12 animate-spin" /> <LoaderCircleIcon className="mx-auto h-12 w-12 animate-spin" />
) : ( ) : (

View file

@ -1,6 +1,6 @@
import * as React from "react" import * as React from "react";
import { ny } from "@/lib/utils" import { ny } from "@/lib/utils";
const Card = React.forwardRef< const Card = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@ -10,12 +10,12 @@ const Card = React.forwardRef<
ref={ref} ref={ref}
className={ny( className={ny(
"rounded-xl border bg-card text-card-foreground shadow", "rounded-xl border bg-card text-card-foreground shadow",
className className,
)} )}
{...props} {...props}
/> />
)) ));
Card.displayName = "Card" Card.displayName = "Card";
const CardHeader = React.forwardRef< const CardHeader = React.forwardRef<
HTMLDivElement, HTMLDivElement,
@ -26,8 +26,8 @@ const CardHeader = React.forwardRef<
className={ny("flex flex-col space-y-1.5", className)} className={ny("flex flex-col space-y-1.5", className)}
{...props} {...props}
/> />
)) ));
CardHeader.displayName = "CardHeader" CardHeader.displayName = "CardHeader";
const CardTitle = React.forwardRef< const CardTitle = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
@ -38,8 +38,8 @@ const CardTitle = React.forwardRef<
className={ny("font-semibold leading-none tracking-tight", className)} className={ny("font-semibold leading-none tracking-tight", className)}
{...props} {...props}
/> />
)) ));
CardTitle.displayName = "CardTitle" CardTitle.displayName = "CardTitle";
const CardDescription = React.forwardRef< const CardDescription = React.forwardRef<
HTMLParagraphElement, HTMLParagraphElement,
@ -50,27 +50,30 @@ const CardDescription = React.forwardRef<
className={ny("text-sm text-muted-foreground", className)} className={ny("text-sm text-muted-foreground", className)}
{...props} {...props}
/> />
)) ));
CardDescription.displayName = "CardDescription" CardDescription.displayName = "CardDescription";
const CardContent = React.forwardRef< const CardContent = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div ref={ref} className={ny("", className)} {...props} /> <div ref={ref} className={ny("", className)} {...props} />
)) ));
CardContent.displayName = "CardContent" CardContent.displayName = "CardContent";
const CardFooter = React.forwardRef< const CardFooter = React.forwardRef<
HTMLDivElement, HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<div <div ref={ref} className={ny("flex items-center", className)} {...props} />
ref={ref} ));
className={ny("flex items-center", className)} CardFooter.displayName = "CardFooter";
{...props}
/>
))
CardFooter.displayName = "CardFooter"
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardDescription,
CardContent,
};

View file

@ -1,6 +1,6 @@
import React from 'react' import React from "react";
import { ny } from '@/lib/utils' import { ny } from "@/lib/utils";
interface RainbowButtonProps interface RainbowButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {} extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
@ -9,20 +9,20 @@ export function RainbowButton({ children, ...props }: RainbowButtonProps) {
return ( return (
<button <button
className={ny( className={ny(
'focus-visible:ring-ring animate-rainbow text-primary-foreground group relative inline-flex h-11 cursor-pointer items-center justify-center rounded-xl border-0 bg-[length:200%] px-4 py-2 font-medium transition-colors [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.08*1rem)_solid_transparent] focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50', "group relative inline-flex h-11 animate-rainbow cursor-pointer items-center justify-center rounded-xl border-0 bg-[length:200%] px-4 py-2 font-medium text-primary-foreground transition-colors [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.08*1rem)_solid_transparent] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
// before styles // before styles
'before:animate-rainbow before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:bg-[linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))] before:bg-[length:200%] before:[filter:blur(calc(0.8*1rem))]', "before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))] before:bg-[length:200%] before:[filter:blur(calc(0.8*1rem))]",
// light mode colors // light mode colors
'bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]', "bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]",
// dark mode colors // dark mode colors
' dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]', "dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]",
)} )}
{...props} {...props}
> >
{children} {children}
</button> </button>
) );
} }

View file

@ -16,9 +16,10 @@ export default function WelcomePage() {
Start using it by clicking on the sidebar icon or trying out the split Start using it by clicking on the sidebar icon or trying out the split
view feature! view feature!
</p> </p>
<p className="text-md w-2/5 mx-auto mt-12 opacity-70"> <p className="text-md mx-auto mt-12 w-2/5 opacity-70">
<InfoCircledIcon className="inline-block mr-4 size-5 text-yellow-500" /> <InfoCircledIcon className="mr-4 inline-block size-5 text-yellow-500" />
Zen Browser is still in development and may have bugs. This welcome page is under construction. Zen Browser is still in development and may have bugs. This welcome page
is under construction.
</p> </p>
</div> </div>
); );

View file

@ -38,7 +38,10 @@ function isValidDate(date: any): date is Date {
* @param assignFutureDate - Whether to assign a future date if parsing fails. * @param assignFutureDate - Whether to assign a future date if parsing fails.
* @returns A valid Date object. * @returns A valid Date object.
*/ */
function parseDate(dateString: string | undefined, assignFutureDate: boolean = false): Date { function parseDate(
dateString: string | undefined,
assignFutureDate: boolean = false,
): Date {
const date = new Date(dateString || ""); const date = new Date(dateString || "");
if (isValidDate(date)) { if (isValidDate(date)) {
return date; return date;
@ -83,7 +86,10 @@ export async function getAllThemes(): Promise<ZenTheme[]> {
homepage: theme.homepage, homepage: theme.homepage,
readme: theme.readme, readme: theme.readme,
preferences: theme.preferences, preferences: theme.preferences,
isColorTheme: typeof theme.isColorTheme === 'boolean' ? theme.isColorTheme : false, isColorTheme:
typeof theme.isColorTheme === "boolean"
? theme.isColorTheme
: false,
author: theme.author, author: theme.author,
version: theme.version, version: theme.version,
tags: uniqueTags, tags: uniqueTags,
@ -125,7 +131,7 @@ export function getThemesFromSearch(
query: string, query: string,
tags: string[], tags: string[],
sortBy: string, sortBy: string,
createdBefore?: Date createdBefore?: Date,
): ZenTheme[] { ): ZenTheme[] {
const normalizedQuery = query.toLowerCase(); const normalizedQuery = query.toLowerCase();
@ -166,7 +172,9 @@ export function getThemesFromSearch(
* @param id - The ID of the theme to retrieve. * @param id - The ID of the theme to retrieve.
* @returns A promise that resolves to the ZenTheme object or undefined if not found. * @returns A promise that resolves to the ZenTheme object or undefined if not found.
*/ */
export async function getThemeFromId(id: string): Promise<ZenTheme | undefined> { export async function getThemeFromId(
id: string,
): Promise<ZenTheme | undefined> {
const allThemes = await getAllThemes(); const allThemes = await getAllThemes();
return allThemes.find((theme) => theme.id === id); return allThemes.find((theme) => theme.id === id);
} }

View file

@ -285,8 +285,7 @@ export const releaseNotes: ReleaseNote[] = [
issue: 76, issue: 76,
}, },
{ {
description: description: "Added more contrast to web context menus on light mods.",
"Added more contrast to web context menus on light mods.",
issue: 88, issue: 88,
}, },
{ {
@ -745,8 +744,7 @@ export const releaseNotes: ReleaseNote[] = [
issue: 1168, issue: 1168,
}, },
{ {
description: description: "Theme Store settings page doesn't display installed mods",
"Theme Store settings page doesn't display installed mods",
issue: 1125, issue: 1125,
}, },
{ {
@ -1109,7 +1107,8 @@ export const releaseNotes: ReleaseNote[] = [
date: "10/10/2024", date: "10/10/2024",
image: true, image: true,
workflowId: 11279059812, workflowId: 11279059812,
extra: "This release brings Zen to Firefox v131.0.2, which patches a significant security vulnerability.\n\nThis update improves the split view and pinned tabs features.\nWe have also released Zen Twilight; automated unstable builds where you can test out the latest features!", extra:
"This release brings Zen to Firefox v131.0.2, which patches a significant security vulnerability.\n\nThis update improves the split view and pinned tabs features.\nWe have also released Zen Twilight; automated unstable builds where you can test out the latest features!",
features: [ features: [
"Updated to the latest stable version of Firefox (131.0.2)", "Updated to the latest stable version of Firefox (131.0.2)",
"Added floating compact mode", "Added floating compact mode",
@ -1126,29 +1125,31 @@ export const releaseNotes: ReleaseNote[] = [
description: "Fixed performance issue when scrolling", description: "Fixed performance issue when scrolling",
}, },
{ {
description: "Fixed buffering issues on YouTube" description: "Fixed buffering issues on YouTube",
}, },
{ {
description: "Fixed Zen Mod settings page crashing when a mod ceases to exist" description:
"Fixed Zen Mod settings page crashing when a mod ceases to exist",
}, },
{ {
description: "Fixed extension menu breaking compact mode when held open", description:
issue: 1925 "Fixed extension menu breaking compact mode when held open",
issue: 1925,
}, },
{ {
description: "Fixed internal keyboard shortcuts for macOS", description: "Fixed internal keyboard shortcuts for macOS",
issue: 1629 issue: 1629,
}, },
{ {
description: "Fixed display issues with certain keyboard layouts", description: "Fixed display issues with certain keyboard layouts",
issue: 1930 issue: 1930,
}, },
{ {
description: "Applied patches to fix CVE-2024-9680", description: "Applied patches to fix CVE-2024-9680",
issue: 1993 issue: 1993,
},
],
}, },
]
}
].reverse(); ].reverse();
export function releaseNoteIsAlpha(note: ReleaseNote) { export function releaseNoteIsAlpha(note: ReleaseNote) {