Merge branch 'main' into release-page-update
This commit is contained in:
7
src/app/.env/page.tsx
Normal file
7
src/app/.env/page.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function WhyAreYouEvenHere() {
|
||||
redirect("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
|
||||
return null;
|
||||
}
|
||||
39
src/app/about/page.tsx
Normal file
39
src/app/about/page.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
"use client";
|
||||
import Footer from "@/components/footer";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
import { releaseNoteIsAlpha, releaseNotes } from "@/lib/release-notes";
|
||||
import Link from "next/link";
|
||||
import Markdown from 'react-markdown'
|
||||
import '../privacy-policy/markdown.css';
|
||||
|
||||
export default function PrivacyPolicy() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<div id="policy" className="min-h-screen py-42 flex mx-auto my-52 p-10 lg:p-0 w-full lg:w-1/3 flex-col">
|
||||
<Markdown>
|
||||
{`
|
||||
# Main Developer Team
|
||||
|
||||
* [**Mauro Baladés**](https://github.com/mauro-balades): Creator, Main Developer, and a funny guy.
|
||||
* **Oscar Gonzalez**: Site Reliability Engineer (SRE) and code signing.
|
||||
* [**Onno**](https://www.onnno.nl/index.html): logo designer.
|
||||
* [**Jafeth Garro**](https://iamjafeth.com/): Documentation writer.
|
||||
* **Peter Jung**: general contributor and AUR maintainer.
|
||||
* [**Gunir**](https://github.com/gunir): Active contributor.
|
||||
* [**n7itro**](https://github.com/n7itro): Active contributor.
|
||||
* [**Canoa**](https://thatcanoa.org/) Active contributor, and very active in issue handling
|
||||
* [**Jan Heres**](https://janheres.eu/): Active contributor and helps with MacOS builds.
|
||||
|
||||
# Many more contributors
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||

|
||||
`}
|
||||
</Markdown>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -6,8 +6,6 @@ export default function BrandingAssetsPage() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<BrandingAssets />
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ export default function BrandingAssetsPage() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<CreateThemePage />
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ export default function Download() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<DownloadPage />
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 106 KiB |
110
src/app/feed.xml/route.ts
Normal file
110
src/app/feed.xml/route.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { Feed } from "feed";
|
||||
import { releaseNotes } from "@/lib/release-notes";
|
||||
import type { ReleaseNote } from "@/lib/release-notes";
|
||||
|
||||
// Force feed.xml to be cached as static and remain constant for the lifetime of the current site build.
|
||||
// The supplied releaseNotes array is constant per build, so this will always be the latest release notes.
|
||||
export const dynamic = "force-static";
|
||||
|
||||
/** The default number of entries to include in the RSS feed. */
|
||||
const RSS_ENTRY_LIMIT = 20;
|
||||
|
||||
/**
|
||||
* Handles the GET request for the `feed.xml` endpoint.
|
||||
* @returns The RSS feed for the Zen Browser release notes.
|
||||
*/
|
||||
export async function GET() {
|
||||
// Just in case the release notes array is empty for whatever reason.
|
||||
const latestDate = releaseNotes.length > 0
|
||||
? formatRssDate(releaseNotes[0].date)
|
||||
: new Date();
|
||||
|
||||
const feed = new Feed({
|
||||
id: "https://www.zen-browser.app/release-notes",
|
||||
link: "https://www.zen-browser.app/release-notes",
|
||||
title: "Zen Browser Release Notes",
|
||||
description: "Release Notes for the Zen Browser",
|
||||
language: "en",
|
||||
favicon: "https://www.zen-browser.app/favicon.ico",
|
||||
copyright: `Zen Browser © ${new Date().getFullYear()} - Made with ❤️ by the Zen team.`,
|
||||
updated: latestDate,
|
||||
});
|
||||
|
||||
for (const releaseNote of releaseNotes.slice(0, RSS_ENTRY_LIMIT)) {
|
||||
feed.addItem({
|
||||
title: `Release notes for version ${releaseNote.version}`,
|
||||
id: `https://www.zen-browser.app/release-notes/${releaseNote.version}`,
|
||||
link: `https://www.zen-browser.app/release-notes/${releaseNote.version}`,
|
||||
date: formatRssDate(releaseNote.date),
|
||||
description: releaseNote.extra,
|
||||
content: formatReleaseNote(releaseNote),
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(feed.rss2(), {
|
||||
headers: {
|
||||
'Content-Type': 'application/xml; charset=utf-8',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a date string in the format day/month/year.
|
||||
*
|
||||
* Note: If release notes change to ISO format, this will need to be updated.
|
||||
* @param dateStr The date string to format.
|
||||
* @returns The passed in date string as a Date object.
|
||||
*/
|
||||
function formatRssDate(dateStr: string) {
|
||||
const splitDate = dateStr.split("/");
|
||||
if (splitDate.length !== 3) {
|
||||
throw new Error("Invalid date format");
|
||||
}
|
||||
|
||||
const day = Number(splitDate[0]);
|
||||
const month = Number(splitDate[1]) - 1;
|
||||
const year = Number(splitDate[2]);
|
||||
return new Date(year, month, day);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the release note entry for use as the content of the RSS feed.
|
||||
* @param releaseNote The release note to format.
|
||||
* @returns The formatted release note as a HTML string.
|
||||
*/
|
||||
function formatReleaseNote(releaseNote: ReleaseNote) {
|
||||
let content = "<p>If you encounter any issues, please report them on <a href=\"https://github.com/zen-browser/desktop/issues/\">the issues page</a>. Thanks everyone for your feedback! ❤️</p>";
|
||||
|
||||
if (releaseNote.extra) {
|
||||
content += `<p>${releaseNote.extra.replace(/(\n)/g, "<br />")}</p>`
|
||||
}
|
||||
|
||||
if (releaseNote.breakingChanges) {
|
||||
content += `<h2>⚠️ Breaking changes</h2>`
|
||||
content += `<ul>`
|
||||
for (const breakingChange of releaseNote.breakingChanges) {
|
||||
content += `<li>${breakingChange}</li>`
|
||||
}
|
||||
content += `</ul>`
|
||||
}
|
||||
|
||||
if (releaseNote.features) {
|
||||
content += `<h2>⭐ Features</h2>`
|
||||
content += `<ul>`
|
||||
for (const feature of releaseNote.features) {
|
||||
content += `<li>${feature}</li>`
|
||||
}
|
||||
content += `</ul>`
|
||||
}
|
||||
|
||||
if (releaseNote.fixes) {
|
||||
content += `<h2>✓ Fixes</h2>`
|
||||
content += `<ul>`
|
||||
for (const fix of releaseNote.fixes) {
|
||||
content += `<li>${fix.description}</li>`
|
||||
}
|
||||
content += `</ul>`
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -41,6 +41,8 @@
|
||||
--color-two: #fe8bbb;
|
||||
--color-three: #9e7aff;
|
||||
|
||||
--surface: rgb(245, 245, 245);
|
||||
|
||||
/*
|
||||
--color-one: #37ecba;
|
||||
--color-two: #72afd3;
|
||||
@@ -48,10 +50,12 @@
|
||||
*/
|
||||
}
|
||||
|
||||
.dark {
|
||||
[data-theme='dark'], .dark {
|
||||
--background: 0 0% 0%;
|
||||
--foreground: 0 0% 98%;
|
||||
|
||||
--surface: rgb(23, 23, 23);
|
||||
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
|
||||
@@ -81,10 +85,13 @@
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
@apply scroll-smooth;
|
||||
}
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Inter } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import { ThemeProvider } from "@/components/theme-provider"
|
||||
import { ThemeProvider } from "@/components/theme-provider";
|
||||
import StyledComponentsRegistry from "@/lib/styled-components-registry";
|
||||
import Footer from "@/components/footer";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
@@ -11,21 +14,32 @@ export const metadata: Metadata = {
|
||||
keywords: ["Zen", "Browser", "Zen Browser", "Web", "Internet", "Fast"],
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<html suppressHydrationWarning>
|
||||
<head>
|
||||
<link rel="me" href="https://fosstodon.org/@zenbrowser"></link>
|
||||
<script defer data-domain="zen-browser.app" src="https://plausible.io/js/script.js"></script>
|
||||
<link rel="alternate" type="application/rss+xml" title="Zen Browser Release Notes" href="https://www.zen-browser.app/feed.xml" />
|
||||
</head>
|
||||
<body className={inter.className}>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="dark"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
{children}
|
||||
<StyledComponentsRegistry>
|
||||
<div>
|
||||
{children}
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</div>
|
||||
</StyledComponentsRegistry>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
8
src/app/not-found.tsx
Normal file
8
src/app/not-found.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
export default function NotFoundPage() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<h1>404</h1>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -10,8 +10,6 @@ export default function Home() {
|
||||
<main className="flex min-h-screen overflow-x-hidden flex-col items-center justify-start">
|
||||
<Header />
|
||||
<Features />
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
"use client";
|
||||
import Footer from "@/components/footer";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
import { releaseNoteIsAlpha, releaseNotes } from "@/lib/release-notes";
|
||||
@@ -52,7 +53,7 @@ Zen Browser offers a "Sync" feature, this is implemented using Mozilla Firefox's
|
||||
# 4. Data Security
|
||||
Although Zen Browser does not collect your data, we are committed to protecting the information that is stored locally on your device and, if you use the Sync feature, the encrypted data stored on Mozilla's servers. We recommend that you use secure passwords, enable device encryption, and regularly update your software to ensure your data remains safe.
|
||||
|
||||
* Note that most of the security measures are taken care by mozilla firefox.
|
||||
* Note that most of the security measures are taken care by Mozilla Firefox.
|
||||
|
||||
# 5. Your Control
|
||||
## 5.1. Data Deletion
|
||||
@@ -82,7 +83,7 @@ You can also optionally enable telemetry data collection and other Mozilla Resea
|
||||
# 9. Contact Us
|
||||
If you have any questions or concerns about this Privacy Policy or Zen Browser, please contact us at:
|
||||
|
||||
* Discord: [Zen Browser's Discord](https://discord.gg/nnShMQzR4b)
|
||||
* Discord: [Zen Browser's Discord](https://discord.com/servers/mauro-s-little-sweatshop-1088172780480114748)
|
||||
* GitHub: [Organization](https://github.com/zen-browser)
|
||||
|
||||
---
|
||||
@@ -90,8 +91,6 @@ If you have any questions or concerns about this Privacy Policy or Zen Browser,
|
||||
By using Zen Browser, you agree to this Privacy Policy. Remember, with Zen, your privacy is in your hands.`}
|
||||
</Markdown>
|
||||
</div>
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import Footer from "@/components/footer";
|
||||
@@ -53,8 +52,11 @@ const VersionList = React.memo(({ currentVersion }: { currentVersion: string })
|
||||
|
||||
VersionList.displayName = 'VersionList';
|
||||
|
||||
export default function ReleaseNotePage() {
|
||||
const params = useParams<{ version: string }>();
|
||||
export async function generateStaticParams() {
|
||||
return [{version: "latest"}, ...releaseNotes.map((note) => ({ version: note.version }))];
|
||||
}
|
||||
|
||||
export default function ReleaseNotePage({ params }: { params: { version: string } }) {
|
||||
const { version } = params;
|
||||
|
||||
if (version === "latest") {
|
||||
@@ -69,14 +71,12 @@ export default function ReleaseNotePage() {
|
||||
<main className="flex min-h-screen flex-col 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>
|
||||
<Link href="/release-notes">
|
||||
<a href="/release-notes">
|
||||
<Button className="mt-4 items-center justify-center">
|
||||
Back to release notes
|
||||
</Button>
|
||||
</Link>
|
||||
</a>
|
||||
</div>
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import Footer from "@/components/footer";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
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>
|
||||
<div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3 mt-10">
|
||||
{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">
|
||||
{releaseNote.version}
|
||||
</div>
|
||||
@@ -22,12 +24,10 @@ export default function ReleaseNotes() {
|
||||
Alpha Release
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,24 +1,54 @@
|
||||
"use client";
|
||||
|
||||
import Footer from "@/components/footer";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
import ThemePage from "@/components/theme-page";
|
||||
import { getThemeFromId } from "@/lib/themes";
|
||||
import { useParams } from "next/navigation";
|
||||
import { getAllThemes, getThemeFromId } from "@/lib/themes";
|
||||
import { Metadata, ResolvingMetadata } from "next";
|
||||
|
||||
export default async function ThemeInfoPage() {
|
||||
const params = useParams<{ theme: string }>();
|
||||
const { theme: themeID } = params;
|
||||
|
||||
const theme = await getThemeFromId(themeID);
|
||||
if (!theme) {
|
||||
return <div>Theme not found</div>;
|
||||
export async function generateMetadata(
|
||||
{ params, searchParams }: any,
|
||||
parent: ResolvingMetadata
|
||||
): Promise<Metadata> {
|
||||
const theme = params.theme
|
||||
const themeData = await getThemeFromId(theme);
|
||||
if (!themeData) {
|
||||
return {
|
||||
title: "Theme not found",
|
||||
description: "Theme not found",
|
||||
};
|
||||
}
|
||||
return {
|
||||
title: themeData.name,
|
||||
description: themeData.description,
|
||||
keywords: [themeData.name, themeData.description],
|
||||
openGraph: {
|
||||
title: themeData.name,
|
||||
description: themeData.description,
|
||||
images: [
|
||||
{
|
||||
url: themeData.image,
|
||||
width: 500,
|
||||
height: 500,
|
||||
alt: themeData.name,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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 (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<ThemePage theme={theme} />
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
<ThemePage themeID={theme} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
import Footer from "@/components/footer";
|
||||
import MarketplacePage from "@/components/marketplace";
|
||||
import { Navigation } from "@/components/navigation";
|
||||
import { getAllThemes, ZenTheme } from "@/lib/themes";
|
||||
import { GetStaticProps } from "next";
|
||||
|
||||
export default function ThemesMarketplace() {
|
||||
export default async function ThemesMarketplace() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<MarketplacePage />
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
<MarketplacePage themes={await getAllThemes()} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ export default function Download() {
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-start">
|
||||
<WelcomePage />
|
||||
<Footer />
|
||||
<Navigation /> {/* At the bottom of the page */}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user