Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ Thank you for your interest in contributing to 0.email! We're excited to have yo
- Make sure the app runs without errors
- Test your feature thoroughly

- Please lint using `pnpm dlx oxlint@latest` or by downloading an IDE extension here: https://oxc.rs/docs/guide/usage/linter.html#vscode-extension

5. **Commit Your Changes**

- Use clear, descriptive commit messages
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ jobs:

- name: Install dependencies 📦
run: pnpm install

- name: Lint JS
run: pnpm dlx oxlint@latest --deny-warnings
18 changes: 18 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"plugins": ["react", "unicorn", "typescript", "oxc"],
"rules": {
"no-alert": "error", // Emit an error message when a call to `alert()` is found
"oxc/approx-constant": "warn", // Show a warning when you write a number close to a known constant
"no-plusplus": "off", // Allow using the `++` and `--` operators
"no-useless-call": "error",
"no-accumulating-spread": "error",
"no-array-index-key": "error",
"jsx-no-jsx-as-prop": "error",
"jsx-no-new-array-as-prop": "error",
"jsx-no-new-function-as-prop": "error",
"jsx-no-new-object-as-prop": "error",
"prefer-array-find": "error",
"prefer-set-has": "error",
"exhaustive-deps": "off"
}
}
13 changes: 7 additions & 6 deletions apps/mail/app/(full-width)/contributors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
ChartAreaIcon,
GitPullRequest,
LayoutGrid,
FileCode,
} from 'lucide-react';
import {
Area,
Expand Down Expand Up @@ -52,13 +51,13 @@ interface ActivityData {
pullRequests: number;
}

const excludedUsernames = [
const excludedUsernames = new Set([
'bot1',
'dependabot',
'github-actions',
'zerodotemail',
'autofix-ci[bot]',
];
]);
const coreTeamMembers = [
'nizzyabi',
'ahmetskilinc',
Expand Down Expand Up @@ -142,7 +141,7 @@ export default function OpenPage() {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [allContributors, setAllContributors] = useState<Contributor[]>([]);
const [isRendered, setIsRendered] = useState(false);
const [, setIsRendered] = useState(false);

useEffect(() => setIsRendered(true), []);

Expand Down Expand Up @@ -199,7 +198,7 @@ export default function OpenPage() {
return allContributors
?.filter(
(contributor) =>
!excludedUsernames.includes(contributor.login) &&
!excludedUsernames.has(contributor.login) &&
coreTeamMembers.some(
(member) => member.toLowerCase() === contributor.login.toLowerCase(),
),
Expand All @@ -216,7 +215,7 @@ export default function OpenPage() {
allContributors
?.filter(
(contributor) =>
!excludedUsernames.includes(contributor.login) &&
!excludedUsernames.has(contributor.login) &&
!coreTeamMembers.some(
(member) => member.toLowerCase() === contributor.login.toLowerCase(),
),
Expand Down Expand Up @@ -1011,6 +1010,7 @@ export default function OpenPage() {
<a
href="https://discord.gg/mail0"
target="_blank"
rel="noreferrer"
className="text-neutral-500 transition-colors hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
aria-label="Join our Discord"
>
Expand All @@ -1019,6 +1019,7 @@ export default function OpenPage() {
<a
href="https://x.com/mail0dotcom"
target="_blank"
rel="noreferrer"
className="text-neutral-500 transition-colors hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
aria-label="Follow us on X (Twitter)"
>
Expand Down
4 changes: 2 additions & 2 deletions apps/mail/app/(full-width)/hr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '@/components/ui/select';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { formatInTimeZone, fromZonedTime, toZonedTime } from 'date-fns-tz';
import { getBrowserTimezone } from '@/lib/timezones';

import { Plus, Trash2, Clock } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
Expand Down Expand Up @@ -145,7 +145,7 @@ export default function HRPage() {
},
]);
// Company timezone
const [userTimezone, setUserTimezone] = useState('America/Los_Angeles');
const [userTimezone] = useState('America/Los_Angeles');
const [userWorkingHours, setUserWorkingHours] = useState<WorkingHours>({
startTime: '09:00',
endTime: '17:00',
Expand Down
69 changes: 2 additions & 67 deletions apps/mail/app/(full-width)/pricing.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,12 @@
import {
NavigationMenu,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
NavigationMenuContent,
ListItem,
} from '@/components/ui/navigation-menu';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
import { PixelatedBackground } from '@/components/home/pixelated-bg';
import PricingCard from '@/components/pricing/pricing-card';
import Comparision from '@/components/pricing/comparision';
import { signIn, useSession } from '@/lib/auth-client';
import { Separator } from '@/components/ui/separator';
import { Navigation } from '@/components/navigation';
import { useBilling } from '@/hooks/use-billing';
import { Link, useNavigate } from 'react-router';
import { Button } from '@/components/ui/button';
import Footer from '@/components/home/footer';
import { useState, useMemo } from 'react';
import { Menu } from 'lucide-react';
import { toast } from 'sonner';

const resources = [
{
title: 'GitHub',
href: 'https://github.com/Mail-0/Zero',
description: 'Check out our open-source projects and contributions.',
platform: 'github' as const,
},
{
title: 'Twitter',
href: 'https://x.com/mail0dotcom',
description: 'Follow us for the latest updates and announcements.',
platform: 'twitter' as const,
},
{
title: 'LinkedIn',
href: 'https://www.linkedin.com/company/mail0/',
description: 'Connect with us professionally and stay updated.',
platform: 'linkedin' as const,
},
{
title: 'Discord',
href: 'https://discord.gg/mail0',
description: 'Join our community and chat with the team.',
platform: 'discord' as const,
},
];
import { Navigation } from '@/components/navigation';

const aboutLinks = [
{
title: 'About',
href: '/about',
description: 'Learn more about Zero and our mission.',
},
{
title: 'Privacy',
href: '/privacy',
description: 'Read our privacy policy and data handling practices.',
},
{
title: 'Terms of Service',
href: '/terms',
description: 'Review our terms of service and usage guidelines.',
},
];
import Footer from '@/components/home/footer';

export default function PricingPage() {
const navigate = useNavigate();
const [open, setOpen] = useState(false);
const { data: session } = useSession();

return (
<main className="relative flex min-h-screen flex-1 flex-col overflow-x-hidden bg-[#0F0F0F]">
<PixelatedBackground
Expand Down
6 changes: 3 additions & 3 deletions apps/mail/app/(full-width)/privacy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { Navigation } from '@/components/navigation';
import { Button } from '@/components/ui/button';
import Footer from '@/components/home/footer';
import { createSectionId } from '@/lib/utils';
import { useNavigate } from 'react-router';
import { toast } from 'sonner';


import React from 'react';

const LAST_UPDATED = 'May 16, 2025';

export default function PrivacyPolicy() {
const navigate = useNavigate();

const { copiedValue: copiedSection, copyToClipboard } = useCopyToClipboard();

const handleCopyLink = (sectionId: string) => {
Expand Down
6 changes: 3 additions & 3 deletions apps/mail/app/(full-width)/terms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import { Navigation } from '@/components/navigation';
import { Button } from '@/components/ui/button';
import Footer from '@/components/home/footer';
import { createSectionId } from '@/lib/utils';
import { useNavigate } from 'react-router';
import { toast } from 'sonner';


import React from 'react';

const LAST_UPDATED = 'February 13, 2025';

export default function TermsOfService() {
const { copiedValue: copiedSection, copyToClipboard } = useCopyToClipboard();
const navigate = useNavigate();


const handleCopyLink = (sectionId: string) => {
const url = `${window.location.origin}${window.location.pathname}#${sectionId}`;
Expand Down
2 changes: 1 addition & 1 deletion apps/mail/app/(routes)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HotkeyProviderWrapper } from '@/components/providers/hotkey-provider-wrapper';
import { CommandPaletteProvider } from '@/components/context/command-palette-context';
import { VoiceProvider } from '@/providers/voice-provider';

import { Outlet } from 'react-router';

export default function Layout() {
Expand Down
6 changes: 3 additions & 3 deletions apps/mail/app/(routes)/mail/[folder]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useLoaderData, useNavigate } from 'react-router';
import { useTRPC } from '@/providers/query-provider';

import { MailLayout } from '@/components/mail/mail';
import { useLabels } from '@/hooks/use-labels';
import { authProxy } from '@/lib/auth-proxy';
import { useEffect, useState } from 'react';
import type { Route } from './+types/page';

const ALLOWED_FOLDERS = ['inbox', 'draft', 'sent', 'spam', 'bin', 'archive'];
const ALLOWED_FOLDERS = new Set(['inbox', 'draft', 'sent', 'spam', 'bin', 'archive']);

export async function clientLoader({ params, request }: Route.ClientLoaderArgs) {
if (!params.folder) return Response.redirect(`${import.meta.env.VITE_PUBLIC_APP_URL}/mail/inbox`);
Expand All @@ -24,7 +24,7 @@ export default function MailPage() {
const navigate = useNavigate();
const [isLabelValid, setIsLabelValid] = useState<boolean | null>(true);

const isStandardFolder = ALLOWED_FOLDERS.includes(folder);
const isStandardFolder = ALLOWED_FOLDERS.has(folder);

const { userLabels, isLoading: isLoadingLabels } = useLabels();

Expand Down
6 changes: 3 additions & 3 deletions apps/mail/app/(routes)/mail/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { HotkeyProviderWrapper } from '@/components/providers/hotkey-provider-wrapper';
import { OnboardingWrapper } from '@/components/onboarding';
import { VoiceProvider } from '@/providers/voice-provider';

import { NotificationProvider } from '@/components/party';
import { AppSidebar } from '@/components/ui/app-sidebar';
import { Outlet, useLoaderData } from 'react-router';
import type { Route } from './+types/layout';
import { Outlet, } from 'react-router';


export default function MailLayout() {
return (
Expand Down
2 changes: 1 addition & 1 deletion apps/mail/app/(routes)/settings/appearance/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default function AppearancePage() {
<FormField
control={form.control}
name="colorTheme"
render={({ field }) => (
render={() => (
<FormItem>
<FormLabel>{m['pages.settings.appearance.theme']()}</FormLabel>
<FormControl>
Expand Down
9 changes: 2 additions & 7 deletions apps/mail/app/(routes)/settings/categories/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,11 @@ import { useTRPC } from '@/providers/query-provider';
import { toast } from 'sonner';
import type { CategorySetting } from '@/hooks/use-categories';
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';
import * as Icons from '@/components/icons/icons';

import { Sparkles } from '@/components/icons/icons';
import { Loader, GripVertical } from 'lucide-react';
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
} from '@/components/ui/select';
} from '@/components/ui/select';
import { Badge } from '@/components/ui/badge';
import {
DndContext,
Expand Down
6 changes: 3 additions & 3 deletions apps/mail/app/(routes)/settings/connections/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { SettingsCard } from '@/components/settings/settings-card';
import { AddConnectionDialog } from '@/components/connection/add';
import { PricingDialog } from '@/components/ui/pricing-dialog';

import { useSession, authClient } from '@/lib/auth-client';
import { useConnections } from '@/hooks/use-connections';
import { useTRPC } from '@/providers/query-provider';
Expand Down Expand Up @@ -62,9 +62,9 @@ export default function ConnectionsPage() {
<div className="space-y-6">
{isLoading ? (
<div className="grid gap-4 md:grid-cols-3">
{[...Array(3)].map((_, i) => (
{[...Array(3)].map((n) => (
<div
key={i}
key={n}
className="bg-popover flex items-center justify-between rounded-lg border p-4"
>
<div className="flex min-w-0 items-center gap-4">
Expand Down
4 changes: 2 additions & 2 deletions apps/mail/app/(routes)/settings/danger-zone/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useMutation } from '@tanstack/react-query';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { AlertTriangle } from 'lucide-react';
import { useNavigate } from 'react-router';

import { useForm } from 'react-hook-form';
import { m } from '@/paraglide/messages';
import { clear } from 'idb-keyval';
Expand All @@ -33,7 +33,7 @@ const formSchema = z.object({

function DeleteAccountDialog() {
const [isOpen, setIsOpen] = useState(false);
const navigate = useNavigate();

const trpc = useTRPC();
const { refetch } = useSession();
const { mutateAsync: deleteAccount, isPending } = useMutation(trpc.user.delete.mutationOptions());
Expand Down
5 changes: 3 additions & 2 deletions apps/mail/app/(routes)/settings/general/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover
import { useForm, type ControllerRenderProps } from 'react-hook-form';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { SettingsCard } from '@/components/settings/settings-card';
import { Globe, Clock, XIcon, Mail, InfoIcon } from 'lucide-react';
import { useEmailAliases } from '@/hooks/use-email-aliases';
import { Globe, Clock, Mail, InfoIcon } from 'lucide-react';
import { getLocale, setLocale } from '@/paraglide/runtime';
import { useState, useEffect, useMemo, memo } from 'react';
import { userSettingsSchema } from '@zero/server/schemas';
Expand All @@ -28,7 +28,7 @@ import { ScrollArea } from '@/components/ui/scroll-area';
import { zodResolver } from '@hookform/resolvers/zod';
import { useTRPC } from '@/providers/query-provider';
import { getBrowserTimezone } from '@/lib/timezones';
import { Textarea } from '@/components/ui/textarea';

import { useSettings } from '@/hooks/use-settings';
import { locales as localesData } from '@/locales';
import { Switch } from '@/components/ui/switch';
Expand Down Expand Up @@ -167,6 +167,7 @@ export default function GeneralPage() {

toast.success(m['common.settings.saved']());
} catch (error) {
console.error(error);
toast.error(m['common.settings.failedToSave']());
queryClient.setQueryData(trpc.settings.get.queryKey(), (updater) => {
if (!updater) return;
Expand Down
Loading
Loading