Merge branch 'main' into runjan/feature

This commit is contained in:
aashirwadRunjan
2024-08-28 13:48:24 +05:30
committed by GitHub
23 changed files with 7311 additions and 214 deletions

View File

@@ -1,12 +1,18 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
output: 'export',
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
protocol: "https", protocol: "https",
hostname: "raw.githubusercontent.com", hostname: "raw.githubusercontent.com",
}, },
{
protocol: "https",
hostname: "cdn.jsdelivr.net",
}
], ],
domains: ['cdn.jsdelivr.net', "raw.githubusercontent.com"], // Allow images from jsDelivr
}, },
experimental: { experimental: {
serverActions: { serverActions: {

7256
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

@@ -0,0 +1,25 @@
import { getAllThemes, getThemeFromId } from '@/lib/themes';
import type { NextApiRequest, NextApiResponse } from 'next';
import { NextRequest, NextResponse } from 'next/server';
// Static NextJS API route. We will have /get-theme?id=theme-id static route
export async function generateStaticParams() {
const themes = await getAllThemes();
return themes.map((theme) => ({
id: theme.id,
}));
}
function removeUneccessaryKeys(theme: any) {
delete theme["isDarkMode"];
delete theme["isColorTheme"];
return theme;
}
export async function GET(request: any, { params }: { params: { id: string } }) {
const themes = await getAllThemes();
const theme = themes.find((theme) => theme.id === params.id);
console.log(theme);
return NextResponse.json(removeUneccessaryKeys(theme));
}

View File

@@ -1,30 +0,0 @@
import { getThemeFromId } from "@/lib/themes";
function getQSParamFromURL(
key: string,
url: string | undefined
): string | null {
if (!url) return "";
const search = new URL(url).search;
const urlParams = new URLSearchParams(search);
return urlParams.get(key);
}
function removeUneccessaryKeys(theme: any) {
delete theme["isDarkMode"];
delete theme["isColorTheme"];
return theme;
}
export async function GET(request: Request, response: Response) {
const id = getQSParamFromURL("id", request.url);
if (!id) {
return Response.json({ error: "id is required" });
}
const theme = await getThemeFromId(id);
if (!theme) {
return Response.json({ error: "theme not found" });
}
return Response.json(removeUneccessaryKeys(theme));
}

View File

@@ -1,3 +1,4 @@
"use client";
import Footer from "@/components/footer"; import Footer from "@/components/footer";
import { Navigation } from "@/components/navigation"; import { Navigation } from "@/components/navigation";
import { releaseNoteIsAlpha, releaseNotes } from "@/lib/release-notes"; import { releaseNoteIsAlpha, releaseNotes } from "@/lib/release-notes";

View File

@@ -1,4 +1,3 @@
"use client";
import Footer from "@/components/footer"; import Footer from "@/components/footer";
import { Navigation } from "@/components/navigation"; import { Navigation } from "@/components/navigation";
@@ -6,10 +5,13 @@ import ReleaseNote from "@/components/release-note";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { releaseNotes } from "@/lib/release-notes"; import { releaseNotes } from "@/lib/release-notes";
import Link from "next/link"; import Link from "next/link";
import { redirect, useParams } from "next/navigation"; import { redirect } from "next/navigation";
export default function ReleaseNotePage() { export async function generateStaticParams() {
const params = useParams<{ version: string }>(); return [{version: "latest"}, ...releaseNotes.map((note) => ({ version: note.version }))];
}
export default function ReleaseNotePage({ params }: { params: { version: string } }) {
const { version } = params; const { version } = params;
if (version === "latest") { if (version === "latest") {
@@ -22,11 +24,11 @@ export default function ReleaseNotePage() {
<main className="flex min-h-screen flex-col items-center justify-center"> <main className="flex min-h-screen flex-col items-center justify-center">
<div className="h-screen flex flex-wrap items-center justify-center"> <div className="h-screen flex flex-wrap items-center justify-center">
<h1 className="text-4xl font-bold mt-12">Release note not found</h1> <h1 className="text-4xl font-bold mt-12">Release note not found</h1>
<Link href="/release-notes"> <a href="/release-notes">
<Button className="mt-4 items-center justify-center"> <Button className="mt-4 items-center justify-center">
Back to release notes Back to release notes
</Button> </Button>
</Link> </a>
</div> </div>
<Footer /> <Footer />
<Navigation /> {/* At the bottom of the page */} <Navigation /> {/* At the bottom of the page */}

View File

@@ -1,3 +1,5 @@
"use client";
import Footer from "@/components/footer"; import Footer from "@/components/footer";
import { Navigation } from "@/components/navigation"; import { Navigation } from "@/components/navigation";
import { releaseNoteIsAlpha, releaseNotes } from "@/lib/release-notes"; import { releaseNoteIsAlpha, releaseNotes } from "@/lib/release-notes";
@@ -10,7 +12,7 @@ export default function ReleaseNotes() {
<h1 className="text-4xl text-center font-bold mt-24">Release Notes</h1> <h1 className="text-4xl text-center font-bold mt-24">Release Notes</h1>
<div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 mt-10"> <div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 mt-10">
{releaseNotes.map((releaseNote) => ( {releaseNotes.map((releaseNote) => (
<Link href={`/release-notes/${releaseNote.version}`} className="bg-background relative max-w-64 overflow-hidden rounded-lg border p-5 hover:border-blue-500 transition-all duration-300 hover:-translate-y-1 hover:-translate-x-1" key={releaseNote.version}> <a href={`/release-notes/${releaseNote.version}`} className="bg-background relative max-w-64 overflow-hidden rounded-lg border p-5 hover:border-blue-500 transition-all duration-300 hover:-translate-y-1 hover:-translate-x-1" key={releaseNote.version}>
<div className="text-md font-medium mb-5"> <div className="text-md font-medium mb-5">
{releaseNote.version} {releaseNote.version}
</div> </div>
@@ -22,7 +24,7 @@ export default function ReleaseNotes() {
Alpha Release Alpha Release
</div> </div>
)} )}
</Link> </a>
))} ))}
</div> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@
import Footer from "@/components/footer"; import Footer from "@/components/footer";
import { Navigation } from "@/components/navigation"; import { Navigation } from "@/components/navigation";
import ThemePage from "@/components/theme-page"; import ThemePage from "@/components/theme-page";
import { getThemeFromId } from "@/lib/themes"; import { getAllThemes, getThemeFromId } from "@/lib/themes";
import { Metadata, ResolvingMetadata } from "next"; import { Metadata, ResolvingMetadata } from "next";
export async function generateMetadata( export async function generateMetadata(
@@ -36,10 +36,19 @@ export async function generateMetadata(
}; };
} }
export default async function ThemeInfoPage() { export async function generateStaticParams() {
const themes = await getAllThemes();
console.log(themes);
return themes.map((theme) => ({
theme: theme.id,
}));
}
export default async function ThemeInfoPage({ params }: { params: { theme: string } }) {
const { theme } = params;
return ( return (
<main className="flex min-h-screen flex-col items-center justify-start"> <main className="flex min-h-screen flex-col items-center justify-start">
<ThemePage /> <ThemePage themeID={theme} />
<Footer /> <Footer />
<Navigation /> {/* At the bottom of the page */} <Navigation /> {/* At the bottom of the page */}
</main> </main>

View File

@@ -16,7 +16,7 @@ export function BrandingAssets() {
<div className="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-10 mt-10 w-full"> <div className="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-10 mt-10 w-full">
{LOGO_COLORS.map((color) => ( {LOGO_COLORS.map((color) => (
<div key={color} className="flex flex-col items-center"> <div key={color} className="flex flex-col items-center">
<img src={`/logos/zen-${color}.svg`} alt={`Zen Browser ${color} logo`} className="w-24 h-24 mt-4" /> <img src={`https://cdn.jsdelivr.net/gh/zen-browser/www/public/logos/zen-${color}.svg`} alt={`Zen Browser ${color} logo`} className="w-24 h-24 mt-4" />
<div className="flex items-center my-2"> <div className="flex items-center my-2">
<a <a
href={`/logos/zen-${color}.svg`} href={`/logos/zen-${color}.svg`}
@@ -38,7 +38,7 @@ export function BrandingAssets() {
<div className="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-10 mt-10 w-full"> <div className="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-10 mt-10 w-full">
{LOGO_COLORS.map((color) => ( {LOGO_COLORS.map((color) => (
<div key={color} className="flex flex-col items-center"> <div key={color} className="flex flex-col items-center">
<img src={`/logos/zen-alpha-${color}.svg`} alt={`Zen Browser ${color} logo`} className="w-24 h-24 mt-4" /> <img src={`https://cdn.jsdelivr.net/gh/zen-browser/www/public/logos/zen-alpha-${color}.svg`} alt={`Zen Browser ${color} logo`} className="w-24 h-24 mt-4" />
<div className="flex items-center my-2"> <div className="flex items-center my-2">
<a <a
href={`/logos/zen-alpha-${color}.svg`} href={`/logos/zen-alpha-${color}.svg`}

View File

@@ -1,5 +1,4 @@
"use client"; "use client";
import { addDownload } from "@/lib/db";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import styled, { keyframes } from "styled-components"; import styled, { keyframes } from "styled-components";
import { ny } from "@/lib/utils"; import { ny } from "@/lib/utils";
@@ -158,7 +157,6 @@ export default function DownloadPage() {
window.location.replace(`${BASE_URL}/${releases[releaseTarget]}`); window.location.replace(`${BASE_URL}/${releases[releaseTarget]}`);
} }
setHasDownloaded(true); setHasDownloaded(true);
addDownload(releaseTarget);
throwConfetti(); throwConfetti();
}; };
@@ -221,16 +219,16 @@ export default function DownloadPage() {
web with Zen! web with Zen!
</p> </p>
<div className="flex font-bold mt-5 items-center justify-between mx-auto"> <div className="flex font-bold mt-5 items-center justify-between mx-auto">
<Link href="https://github.com/zen-browser">Source Code</Link> <a href="https://github.com/zen-browser">Source Code</a>
<Link <a
className="ml-5" className="ml-5"
href="https://patreon.com/zen_browser?utm_medium=unknown&utm_source=join_link&utm_campaign=creatorshare_creator&utm_content=copyLink" href="https://patreon.com/zen_browser?utm_medium=unknown&utm_source=join_link&utm_campaign=creatorshare_creator&utm_content=copyLink"
> >
Donate Donate
</Link> </a>
<Link className="ml-5" href="/release-notes/latest"> <a className="ml-5" href="/release-notes/latest">
Release Notes Release Notes
</Link> </a>
</div> </div>
{selectedPlatform === "MacOS" && ( {selectedPlatform === "MacOS" && (
<div className="mt-12 flex flex-col items-start border justify-between rounded-md bg-background p-5"> <div className="mt-12 flex flex-col items-start border justify-between rounded-md bg-background p-5">
@@ -571,13 +569,13 @@ export default function DownloadPage() {
<InfoCircledIcon className="size-4 mr-2" /> <InfoCircledIcon className="size-4 mr-2" />
<p className="text-muted-foreground"> <p className="text-muted-foreground">
Confused about which build to choose?{" "} Confused about which build to choose?{" "}
<Link <a
href="https://docs.zen-browser.app/guides/generic-optimized" href="https://docs.zen-browser.app/guides/generic-optimized"
target="_blank" target="_blank"
className="text-blue-400" className="text-blue-400"
> >
System requirements System requirements
</Link> </a>
. .
</p> </p>
</div> </div>

View File

@@ -150,11 +150,11 @@ export default function Features() {
</a> </a>
</p> </p>
</div> </div>
<Link href="/download"> <a href="/download">
<Button className="mt-4 rounded-full p-5 ml-auto"> <Button className="mt-4 rounded-full p-5 ml-auto">
Download Zen now! Download Zen now!
</Button> </Button>
</Link> </a>
</div> </div>
<div className="border rounded-lg shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black flex w-fit transform -translate-x-1/3"> <div className="border rounded-lg shadow-md mt-16 mx-auto p-4 bg-white dark:bg-black flex w-fit transform -translate-x-1/3">
{COLORS.map((color) => ( {COLORS.map((color) => (
@@ -190,14 +190,14 @@ export default function Features() {
Killer feature Killer feature
</div> </div>
</div> </div>
<Link href="/download"> <a href="/download">
<Button className="mt-4 rounded-full p-5 ml-4"> <Button className="mt-4 rounded-full p-5 ml-4">
Download Zen now! Download Zen now!
</Button> </Button>
</Link> </a>
</div> </div>
<img <img
src="/compact-mode.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/compact-mode.png"
className="scale-105 hover:scale-110 transform rotate-[-2deg] transition-all duration-100 rounded-md w-full shadow-md dark:shadow-none dark:border-2 mt-16 border-blue-600" className="scale-105 hover:scale-110 transform rotate-[-2deg] transition-all duration-100 rounded-md w-full shadow-md dark:shadow-none dark:border-2 mt-16 border-blue-600"
/> />
</div> </div>
@@ -207,7 +207,7 @@ export default function Features() {
<div className="font-bold text-md"> <div className="font-bold text-md">
What makes Zen Browser different? What makes Zen Browser different?
</div> </div>
<img src="/favicon.ico" className="ml-auto w-7 h-7" /> <img src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/favicon.ico" className="ml-auto w-7 h-7" />
</div> </div>
<div className="h-full w-full flex items-center justify-center"> <div className="h-full w-full flex items-center justify-center">
<Table className="w-full"> <Table className="w-full">
@@ -220,7 +220,7 @@ export default function Features() {
<span className="">How Zen compares to other browsers</span> <span className="">How Zen compares to other browsers</span>
</TableHead> </TableHead>
<TableHead className="py-2 font-bold text-center"> <TableHead className="py-2 font-bold text-center">
<Image <img
height={32} height={32}
width={32} width={32}
src="/favicon.ico" src="/favicon.ico"
@@ -230,20 +230,20 @@ export default function Features() {
Zen Zen
</TableHead> </TableHead>
<TableHead className="py-2 pl-4 lg:pr-0 pr-2 font-bold text-center opacity-60"> <TableHead className="py-2 pl-4 lg:pr-0 pr-2 font-bold text-center opacity-60">
<Image <img
height={32} height={32}
width={32} width={32}
src="/floorp.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/floorp.png"
className="bg-black dark:bg-white rounded-md p-1 mx-auto mb-2 w-7 h-7" className="bg-black dark:bg-white rounded-md p-1 mx-auto mb-2 w-7 h-7"
alt="floorp" alt="floorp"
/> />
Floorp Floorp
</TableHead> </TableHead>
<TableHead className="py-2 pl-0 font-bold text-center opacity-60"> <TableHead className="py-2 pl-0 font-bold text-center opacity-60">
<Image <img
height={32} height={32}
width={32} width={32}
src="/librewolf.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/librewolf.png"
className="bg-black dark:bg-white rounded-md mx-auto p-1 mb-2 w-7 h-7" className="bg-black dark:bg-white rounded-md mx-auto p-1 mb-2 w-7 h-7"
alt="librewolf" alt="librewolf"
/> />
@@ -382,21 +382,21 @@ export default function Features() {
<div className="relative p-16 border-r-2 flex flex-col items-center justify-center row-span-2 col-span-2"> <div className="relative p-16 border-r-2 flex flex-col items-center justify-center row-span-2 col-span-2">
<div className="relative w-full h-full flex items-center justify-center"> <div className="relative w-full h-full flex items-center justify-center">
<img <img
src="/split-view.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/split-view.png"
className={ny( className={ny(
'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300', 'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300',
feature === 0 ? 'translate-x-0' : '-translate-x-1/4 opacity-0' feature === 0 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
)} )}
/> />
<img <img
src="/workspaces.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/workspaces.png"
className={ny( className={ny(
'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300', 'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300',
feature === 1 ? 'translate-x-0' : '-translate-x-1/4 opacity-0' feature === 1 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'
)} )}
/> />
<img <img
src="/sidebar.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/sidebar.png"
className={ny( className={ny(
'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300', 'absolute hover:scale-105 rounded-md w-full shadow-md dark:shadow-none dark:border-2 border-blue-500 transform transition-all duration-300',
feature === 2 ? 'translate-x-0' : '-translate-x-1/4 opacity-0' feature === 2 ? 'translate-x-0' : '-translate-x-1/4 opacity-0'

View File

@@ -6,13 +6,13 @@ export default function Footer() {
return ( return (
<div className="font-medium flex-col md:flex-row px-10 md:px-0 border-t w-full border-grey py-10 mt-10 flex justify-center align-center"> <div className="font-medium flex-col md:flex-row px-10 md:px-0 border-t w-full border-grey py-10 mt-10 flex justify-center align-center">
Zen Browser © {new Date().getFullYear()} - Made with by the Zen team. Zen Browser © {new Date().getFullYear()} - Made with by the Zen team.
<Link <a
href={"https://github.com/zen-browser"} href={"https://github.com/zen-browser"}
target="_blank" target="_blank"
className="mt-5 md:mt-0 md:ml-2 font-bold" className="mt-5 md:mt-0 md:ml-2 font-bold"
> >
Source Code Source Code
</Link> </a>
</div> </div>
); );
} }

View File

@@ -20,7 +20,7 @@ export default function Header() {
id="hero" id="hero"
className="relative mx-auto mt-40 max-w-7xl px-6 text-center md:px-8" className="relative mx-auto mt-40 max-w-7xl px-6 text-center md:px-8"
> >
<Link href="/download"> <a href="/download">
<AnimatedGradientText> <AnimatedGradientText>
🎉 <hr className="mx-2 h-4 w-[1px] shrink-0 bg-gray-300" />{" "} 🎉 <hr className="mx-2 h-4 w-[1px] shrink-0 bg-gray-300" />{" "}
<span <span
@@ -32,7 +32,7 @@ export default function Header() {
</span> </span>
<ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" /> <ChevronRight className="ml-1 size-3 transition-transform duration-300 ease-in-out group-hover:translate-x-0.5" />
</AnimatedGradientText> </AnimatedGradientText>
</Link> </a>
<h1 className="animate-fade-in -translate-y-4 text-balance bg-gradient-to-br from-black 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] sm:text-6xl md:text-7xl lg:text-8xl dark:from-white dark:to-white/40"> <h1 className="animate-fade-in -translate-y-4 text-balance bg-gradient-to-br from-black 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] sm:text-6xl md:text-7xl lg:text-8xl dark:from-white dark:to-white/40">
Zen is the best way Zen is the best way
<br className="hidden md:block" /> to browse the web. <br className="hidden md:block" /> to browse the web.
@@ -42,14 +42,14 @@ export default function Header() {
<br className="hidden md:block" /> We care about your experience, not <br className="hidden md:block" /> We care about your experience, not
your data. your data.
</p> </p>
<Link href="/download"> <a href="/download">
<Button <Button
className="animate-fade-in -translate-y-4 gap-1 rounded-lg text-white opacity-0 ease-in-out [--animation-delay:600ms] dark:text-black" className="animate-fade-in -translate-y-4 gap-1 rounded-lg text-white opacity-0 ease-in-out [--animation-delay:600ms] dark:text-black"
> >
<span>Download Zen Now </span> <span>Download Zen Now </span>
<ArrowRightIcon className="ml-1 size-4 transition-transform duration-300 ease-in-out group-hover:translate-x-1" /> <ArrowRightIcon className="ml-1 size-4 transition-transform duration-300 ease-in-out group-hover:translate-x-1" />
</Button> </Button>
</Link> </a>
<div <div
ref={ref} ref={ref}
className="animate-fade-up relative mt-32 opacity-0 [--animation-delay:400ms] [perspective:2000px] after:absolute after:inset-0 after:z-50 after:[background:linear-gradient(to_top,hsl(var(--background))_10%,transparent)]" className="animate-fade-up relative mt-32 opacity-0 [--animation-delay:400ms] [perspective:2000px] after:absolute after:inset-0 after:z-50 after:[background:linear-gradient(to_top,hsl(var(--background))_10%,transparent)]"
@@ -67,17 +67,17 @@ export default function Header() {
colorTo="var(--color-two)" colorTo="var(--color-two)"
/> />
<Image <img
width={1500} width={1500}
height={700} height={700}
src="/browser-dark.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/browser-dark.png"
alt="browser Image" alt="browser Image"
className="relative hidden rounded-[inherit] border object-contain dark:block" className="relative hidden rounded-[inherit] border object-contain dark:block"
/> />
<Image <img
width={1500} width={1500}
height={700} height={700}
src="/browser-light.png" src="https://cdn.jsdelivr.net/gh/zen-browser/www/public/browser-light.png"
alt="browser Image" alt="browser Image"
className="relative block rounded-[inherit] border object-contain dark:hidden" className="relative block rounded-[inherit] border object-contain dark:hidden"
/> />

View File

@@ -14,7 +14,7 @@ export default function Logo({ withText, ...props }: any) {
}, []); }, []);
return ( return (
<div className="flex items-center m-0" {...props}> <div className="flex items-center m-0" {...props}>
<Image src={`/logos/zen-${randomColor}.svg`} width={40} height={40} alt="Zen Logo" className={ny("transition-all duration-300 hover:scale-110", withText && "mr-2")} /> <img src={`https://cdn.jsdelivr.net/gh/zen-browser/www/public/logos/zen-${randomColor}.svg`} width={40} height={40} alt="Zen Logo" className={ny("transition-all duration-300 hover:scale-110", withText && "mr-2")} />
{withText && <span className="text-2xl font-bold ml-2">zen</span>} {withText && <span className="text-2xl font-bold ml-2">zen</span>}
</div> </div>
); );

View File

@@ -94,8 +94,8 @@ function MobileLink({
}: MobileLinkProps) { }: MobileLinkProps) {
const router = useRouter() const router = useRouter()
return ( return (
<Link <a
href={href} href={href.toString()}
onClick={() => { onClick={() => {
router.push(href.toString()) router.push(href.toString())
onOpenChange?.(false) onOpenChange?.(false)
@@ -104,6 +104,6 @@ function MobileLink({
{...props} {...props}
> >
{children} {children}
</Link> </a>
) )
} }

View File

@@ -64,7 +64,7 @@ export function Navigation() {
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]"> <ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
<li className="row-span-3"> <li className="row-span-3">
<NavigationMenuLink asChild> <NavigationMenuLink asChild>
<Link <a
className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md" className="flex h-full w-full select-none flex-col justify-end rounded-md bg-gradient-to-b from-muted/50 to-muted p-6 no-underline outline-none focus:shadow-md"
href="/" href="/"
> >
@@ -76,7 +76,7 @@ export function Navigation() {
Firefox based browser with a focus on privacy and Firefox based browser with a focus on privacy and
customization. customization.
</p> </p>
</Link> </a>
</NavigationMenuLink> </NavigationMenuLink>
</li> </li>
<ListItem href="/download" title="Download"> <ListItem href="/download" title="Download">

View File

@@ -15,12 +15,12 @@ export default function ReleaseNoteElement({ data }: { data: ReleaseNote }) {
</p> </p>
<p className="text-md mt-4 text-muted-foreground"> <p className="text-md mt-4 text-muted-foreground">
If you encounter any issues, please report them on{" "} If you encounter any issues, please report them on{" "}
<Link <a
href="https://github.com/zen-browser/desktop/issues/" href="https://github.com/zen-browser/desktop/issues/"
className="text-underline text-blue-500" className="text-underline text-blue-500"
> >
the issues page the issues page
</Link> </a>
. Thanks everyone for your feedback! . Thanks everyone for your feedback!
</p> </p>
{data.extra && ( {data.extra && (
@@ -81,13 +81,13 @@ export default function ReleaseNoteElement({ data }: { data: ReleaseNote }) {
<li key={index} className="mt-1 text-muted-foreground"> <li key={index} className="mt-1 text-muted-foreground">
{fix.description} {fix.description}
{fix.issue && ( {fix.issue && (
<Link <a
href={`https://github.com/zen-browser/desktop/issues/${fix.issue}`} href={`https://github.com/zen-browser/desktop/issues/${fix.issue}`}
target="_blank" target="_blank"
className="ml-1 text-blue-500" className="ml-1 text-blue-500"
> >
issue #{fix.issue} issue #{fix.issue}
</Link> </a>
)} )}
</li> </li>
))} ))}
@@ -96,9 +96,9 @@ export default function ReleaseNoteElement({ data }: { data: ReleaseNote }) {
)} )}
</div> </div>
<div className="flex flex-wrap items-center justify-center"> <div className="flex flex-wrap items-center justify-center">
<Link href="/download"> <a href="/download">
<Button className="mt-12 w-fit mx-auto">Download Zen now!</Button> <Button className="mt-12 w-fit mx-auto">Download Zen now!</Button>
</Link> </a>
</div> </div>
</div> </div>
); );

View File

@@ -20,7 +20,7 @@ export default function ThemeCard({
if (event.target instanceof HTMLAnchorElement) return; if (event.target instanceof HTMLAnchorElement) return;
window.open(`/themes/${theme.id}`, "_self"); window.open(`/themes/${theme.id}`, "_self");
}} className="flex flex-col justify-start p-5 rounded-lg shadow-sm bg-muted dark:bg-muted/50 border border-grey-900 dark:border-muted w-full hover:shadow-lg transition duration-300 ease-in-out hover:bg-muted/100 hover:border-blue-500 cursor-pointer select-none "> }} className="flex flex-col justify-start p-5 rounded-lg shadow-sm bg-muted dark:bg-muted/50 border border-grey-900 dark:border-muted w-full hover:shadow-lg transition duration-300 ease-in-out hover:bg-muted/100 hover:border-blue-500 cursor-pointer select-none ">
<Image src={theme.image} alt={theme.name} width={500} height={500} quality={100} <img src={theme.image} alt={theme.name} width={500} height={500}
className="w-full h-32 object-cover rounded-lg border shadow" /> className="w-full h-32 object-cover rounded-lg border shadow" />
<h2 className="text-xl font-bold mt-4 overflow-ellipsis text-start">{theme.name.substring(0, maxNameLen).trim() + (theme.name.length > maxNameLen ? "..." : "")}</h2> <h2 className="text-xl font-bold mt-4 overflow-ellipsis text-start">{theme.name.substring(0, maxNameLen).trim() + (theme.name.length > maxNameLen ? "..." : "")}</h2>
<div className="flex mt-2"> <div className="flex mt-2">

View File

@@ -1,4 +1,4 @@
"use client";
import Image from "next/image"; import Image from "next/image";
import { getThemeAuthorLink, getThemeFromId, getThemeMarkdown, ZenTheme } from "@/lib/themes"; import { getThemeAuthorLink, getThemeFromId, getThemeMarkdown, ZenTheme } from "@/lib/themes";
import { Button } from "./ui/button"; import { Button } from "./ui/button";
@@ -6,11 +6,8 @@ import { useEffect, useState } from "react";
import Markdown from "react-markdown"; import Markdown from "react-markdown";
import '../app/privacy-policy/markdown.css'; import '../app/privacy-policy/markdown.css';
import { ChevronLeft, LoaderCircleIcon } from "lucide-react"; import { ChevronLeft, LoaderCircleIcon } from "lucide-react";
import { useParams } from "next/navigation";
export default async function ThemePage() { export default async function ThemePage({ themeID }: { themeID: string }) {
const params = useParams<{ theme: string }>();
const { theme: themeID } = params;
const theme = await getThemeFromId(themeID); const theme = await getThemeFromId(themeID);
if (!theme) { if (!theme) {
@@ -22,11 +19,11 @@ export default async function ThemePage() {
return ( return (
<div className="mt-24 lg:mt-56 flex-col lg:flex-row flex mx-auto items-start relative"> <div className="mt-24 lg:mt-56 flex-col lg:flex-row flex mx-auto items-start relative">
<div className="flex flex-col relative lg:sticky lg:top-0 w-md h-full p-5 lg:p-0 lg:pr-5 mr-5 w-full md:max-w-sm"> <div className="flex flex-col relative lg:sticky lg:top-0 w-md h-full p-5 lg:p-0 lg:pr-5 mr-5 w-full md:max-w-sm">
<div className="flex mt-2 mb-9 items-center cursor-pointer opacity-70" onClick={() => window.history.back()}> <a className="flex mt-2 mb-9 items-center cursor-pointer opacity-70" href="/themes">
<ChevronLeft className="w-4 h-4 mr-1" /> <ChevronLeft className="w-4 h-4 mr-1" />
<h3 className="text-md">Go back</h3> <h3 className="text-md">Go back</h3>
</div> </a>
<Image src={theme.image} alt={theme.name} width={500} height={500} className="w-full object-cover rounded-lg border-2 shadow" /> <img src={theme.image} alt={theme.name} width={500} height={500} className="w-full object-cover rounded-lg border-2 shadow" />
<h1 className="text-2xl mt-5 font-bold">{theme.name}</h1> <h1 className="text-2xl mt-5 font-bold">{theme.name}</h1>
<p className="text-sm text-muted-foreground mt-2">{theme.description}</p> <p className="text-sm text-muted-foreground mt-2">{theme.description}</p>
{theme.homepage && ( {theme.homepage && (

View File

@@ -1,31 +0,0 @@
"use server";
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'https://dmthyedfjzcysoekmyns.supabase.co'
const supabaseKey = process.env.SUPABASE_KEY as string;
const supabase = createClient(supabaseUrl, supabaseKey);
export async function addDownload(platform: string) {
// Check if the download count for the platform exists
const { data, error } = await supabase
.from('downloads')
.select('count')
.eq('platform', platform)
// If it doesn't exist, create it
console.log(data)
if (data?.length === 0 || data === null) {
const {data, error} = await supabase
.from('downloads')
.insert([{ platform, count: 1 }]);
if (error) {
console.error(error)
}
} else {
// If it exists, increment the count
await supabase
.from('downloads')
.update({ count: data![0].count + 1 })
.eq('platform', platform)
}
}

View File

@@ -628,11 +628,10 @@ export const releaseNotes: ReleaseNote[] = [
}, },
{ {
version: "1.0.0-a.30", version: "1.0.0-a.30",
date: "24/08/2024", date: "26/08/2024",
extra: "This release is the thirtieth alpha release of the 1.0.0-alpha series.", extra: "This release is the thirtieth alpha release of the 1.0.0-alpha series.",
features: [ features: [
"Added support for 24 more languages!", "Added support for 24 more languages!",
"Better wordmark and icons for Private Browsing mode",
"Update installed themes from the browser settings" "Update installed themes from the browser settings"
], ],
fixes: [ fixes: [
@@ -655,11 +654,38 @@ export const releaseNotes: ReleaseNote[] = [
{ {
description: "Can't rename created workspace", description: "Can't rename created workspace",
issue: 604 issue: 604
},
{
description: "JavaScript won't execute in the browser console",
issue: 913
}
]
},
{
version: "1.0.0-a.31",
date: "27/08/2024",
extra: "This release is the thirty-first alpha release of the 1.0.0-alpha series.",
features: [
"Better wordmark and icons for Private Browsing mode",
"Patched security issue with remote debugging",
"Fixed incorrect position of right-side tabs in compact mode",
"Optimized image loading on website",
"Refactored website to be static"
],
fixes: [
{
description: "Horizontal and vertical split don't work with shortcuts",
issue: 915
},
{
description: "Buttons dissapear if there are too many tabs",
issue: 934
} }
] ]
} }
].reverse(); ].reverse();
export function releaseNoteIsAlpha(note: ReleaseNote) { export function releaseNoteIsAlpha(note: ReleaseNote) {
"use client";
return note.version.includes("-a."); return note.version.includes("-a.");
} }

View File

@@ -14,7 +14,9 @@ export interface ZenTheme {
} }
const THEME_API = "https://zen-browser.github.io/theme-store/themes.json"; const THEME_API = "https://zen-browser.github.io/theme-store/themes.json";
const CACHE_OPTIONS = { cache: "no-cache" } as RequestInit; const CACHE_OPTIONS = { next: {
revalidate: 60,
} } as RequestInit;
export async function getAllThemes() { export async function getAllThemes() {
// Fetch from the API // Fetch from the API