Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
010b0ec
added contacts dropdown for create email
ahmetskilinc Apr 15, 2025
f75473e
Add useContacts hook for managing contacts in mail app
MrgSub Apr 15, 2025
8c5413d
Refactor useContacts to handle missing connectionId
MrgSub Apr 15, 2025
1999c31
Merge branch 'staging' of github.com:Mail-0/Zero into list-users-cont…
ahmetskilinc Apr 15, 2025
12aabef
Merge pull request #677 from Mail-0/list-users-contacts-from-recieved…
MrgSub Apr 15, 2025
a776323
review time plz
nizzyabi Apr 15, 2025
ef3154a
relocate settings routing
kingstondoesit Apr 16, 2025
a6ef4ac
dropdown reccomendation email
nizzyabi Apr 16, 2025
b6dc7b2
use next/Link
kingstondoesit Apr 16, 2025
e7b4d0d
Merge pull request #684 from Mail-0/new-create-email
MrgSub Apr 16, 2025
25940ad
Merge branch 'staging' into setting-btn
MrgSub Apr 16, 2025
c079943
Merge pull request #683 from kingstondoesit/setting-btn
MrgSub Apr 16, 2025
81c6aa0
chore: bring back login button
hiheyhello123 Apr 16, 2025
b5e6b16
Refactor auth.ts for early access validation
MrgSub Apr 16, 2025
8e3eddf
Merge branch 'main' into staging
MrgSub Apr 16, 2025
21b00f2
posthog
nizzyabi Apr 16, 2025
8db5a64
Refactor mail actions and types to improve thread handling and respon…
MrgSub Apr 16, 2025
7dbb565
remove search from drafts
nizzyabi Apr 17, 2025
af8f4f6
Refactor email handling with active driver integration
MrgSub Apr 17, 2025
e861844
Refactor API routes, utils, and actions for consistency
MrgSub Apr 17, 2025
b9ba433
Update provider value assignment in layout.tsx
MrgSub Apr 17, 2025
7981705
Merge branch 'staging' into feat/driver-updates
MrgSub Apr 17, 2025
7afd073
Merge pull request #693 from Mail-0/feat/driver-updates
MrgSub Apr 17, 2025
59f142e
Update user settings schema and default value; add custom prompt in u…
MrgSub Apr 17, 2025
2017781
Fix unreachable code and add missing mutation to thread display<commi…
MrgSub Apr 17, 2025
aef5179
no select
nizzyabi Apr 17, 2025
c158a64
Refactor conditional rendering logic in mail-list component
MrgSub Apr 17, 2025
e10b286
Merge branch 'staging' of https://github.com/nizzyabi/mail into staging
MrgSub Apr 17, 2025
2fc4702
width
nizzyabi Apr 17, 2025
2240342
width
nizzyabi Apr 17, 2025
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
66 changes: 17 additions & 49 deletions apps/mail/actions/connections.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,26 @@
"use server";
'use server';

import { connection, user } from "@zero/db/schema";
import { headers } from "next/headers";
import { and, eq } from "drizzle-orm";
import { type IConnection } from "@/types";
import { auth } from "@/lib/auth";
import { db } from "@zero/db";

export async function getConnections() {
try {
const headersList = await headers();
const session = await auth.api.getSession({ headers: headersList });

if (!session) {
throw new Error("Unauthorized, reconnect");
}

const userId = session?.user?.id;

if (!userId) {
throw new Error("Unauthorized, reconnect");
}

const connections = (await db
.select({
id: connection.id,
email: connection.email,
name: connection.name,
picture: connection.picture,
createdAt: connection.createdAt,
})
.from(connection)
.where(eq(connection.userId, userId))) as IConnection[];

return connections;
} catch (error) {
console.error("Failed to fetch connections:", error);
throw new Error("Failed to fetch connections");
}
}
import { getAuthenticatedUserId } from '@/app/api/utils';
import { connection, user } from '@zero/db/schema';
import { type IConnection } from '@/types';
import { headers } from 'next/headers';
import { and, eq } from 'drizzle-orm';
import { auth } from '@/lib/auth';
import { db } from '@zero/db';

export async function deleteConnection(connectionId: string) {
try {
const headersList = await headers();
const session = await auth.api.getSession({ headers: headersList });

if (!session) {
throw new Error("Unauthorized, reconnect");
throw new Error('Unauthorized, reconnect');
}

const userId = session?.user?.id;

if (!userId) {
throw new Error("Unauthorized, reconnect");
throw new Error('Unauthorized, reconnect');
}

await db
Expand All @@ -67,8 +35,8 @@ export async function deleteConnection(connectionId: string) {

return { success: true };
} catch (error) {
console.error("Failed to delete connection:", error);
throw new Error("Failed to delete connection");
console.error('Failed to delete connection:', error);
throw new Error('Failed to delete connection');
}
}

Expand All @@ -78,13 +46,13 @@ export async function putConnection(connectionId: string) {
const session = await auth.api.getSession({ headers: headersList });

if (!session) {
throw new Error("Unauthorized, reconnect");
throw new Error('Unauthorized, reconnect');
}

const userId = session?.user?.id;

if (!userId) {
throw new Error("Unauthorized, reconnect");
throw new Error('Unauthorized, reconnect');
}

const [foundConnection] = await db
Expand All @@ -94,7 +62,7 @@ export async function putConnection(connectionId: string) {
.limit(1);

if (!foundConnection) {
throw new Error("Connection not found");
throw new Error('Connection not found');
}

await db
Expand All @@ -106,7 +74,7 @@ export async function putConnection(connectionId: string) {

return { success: true };
} catch (error) {
console.error("Failed to update connection:", error);
throw new Error("Failed to update connection");
console.error('Failed to update connection:', error);
throw new Error('Failed to update connection');
}
}
13 changes: 7 additions & 6 deletions apps/mail/actions/mail.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use server';
import { deleteActiveConnection, FatalErrors, getActiveDriver } from './utils';
import { IGetThreadResponse } from '@/app/api/driver/types';
import { ParsedMessage } from '@/types';

export const getMails = async ({
Expand Down Expand Up @@ -29,7 +30,7 @@ export const getMails = async ({
}
};

export const getMail = async ({ id }: { id: string }): Promise<ParsedMessage[]> => {
export const getMail = async ({ id }: { id: string }): Promise<IGetThreadResponse> => {
if (!id) {
throw new Error('Missing required fields');
}
Expand Down Expand Up @@ -128,17 +129,17 @@ export const toggleStar = async ({ ids }: { ids: string[] }) => {
return { success: false, error: 'No thread IDs provided' };
}

const threadResults = await Promise.allSettled(
threadIds.map(id => driver.get(id))
);
const threadResults = await Promise.allSettled(threadIds.map((id) => driver.get(id)));

let anyStarred = false;
let processedThreads = 0;

for (const result of threadResults) {
if (result.status === 'fulfilled' && result.value && result.value.length > 0) {
if (result.status === 'fulfilled' && result.value && result.value.messages.length > 0) {
processedThreads++;
const isThreadStarred = result.value.some((message: ParsedMessage) => message.tags?.includes('STARRED'));
const isThreadStarred = result.value.messages.some((message: ParsedMessage) =>
message.tags?.includes('STARRED'),
);
if (isThreadStarred) {
anyStarred = true;
break;
Expand Down
24 changes: 13 additions & 11 deletions apps/mail/actions/notes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use server';

import { notes } from '@/app/api/notes';
import type { Note } from '@/app/api/notes/types';
import { notes } from '@/app/api/notes';

export type ActionResult<T> = {
success: boolean;
Expand All @@ -17,7 +17,7 @@ export async function fetchThreadNotes(threadId: string): Promise<ActionResult<N
console.error('Error fetching thread notes:', error);
return {
success: false,
error: error.message || 'Failed to fetch thread notes'
error: error.message || 'Failed to fetch thread notes',
};
}
}
Expand All @@ -26,7 +26,7 @@ export async function createNote({
threadId,
content,
color = 'default',
isPinned = false
isPinned = false,
}: {
threadId: string;
content: string;
Expand All @@ -40,14 +40,14 @@ export async function createNote({
console.error('Error creating note:', error);
return {
success: false,
error: error.message || 'Failed to create note'
error: error.message || 'Failed to create note',
};
}
}

export async function updateNote(
noteId: string,
data: Partial<Omit<Note, 'id' | 'userId' | 'threadId' | 'createdAt' | 'updatedAt'>>
data: Partial<Omit<Note, 'id' | 'userId' | 'threadId' | 'createdAt' | 'updatedAt'>>,
): Promise<ActionResult<Note>> {
try {
const result = await notes.updateNote(noteId, data);
Expand All @@ -56,7 +56,7 @@ export async function updateNote(
console.error('Error updating note:', error);
return {
success: false,
error: error.message || 'Failed to update note'
error: error.message || 'Failed to update note',
};
}
}
Expand All @@ -69,30 +69,32 @@ export async function deleteNote(noteId: string): Promise<ActionResult<boolean>>
console.error('Error deleting note:', error);
return {
success: false,
error: error.message || 'Failed to delete note'
error: error.message || 'Failed to delete note',
};
}
}

export async function reorderNotes(
notesArray: { id: string; order: number; isPinned?: boolean | null }[]
notesArray: { id: string; order: number; isPinned?: boolean | null }[],
): Promise<ActionResult<boolean>> {
try {
if (!notesArray || notesArray.length === 0) {
console.warn('Attempted to reorder an empty array of notes');
return { success: true, data: true };
}

console.log(`Reordering ${notesArray.length} notes:`,
notesArray.map(({id, order, isPinned}) => ({id, order, isPinned})));
console.log(
`Reordering ${notesArray.length} notes:`,
notesArray.map(({ id, order, isPinned }) => ({ id, order, isPinned })),
);

const result = await notes.reorderNotes(notesArray);
return { success: true, data: result };
} catch (error: any) {
console.error('Error reordering notes:', error);
return {
success: false,
error: error.message || 'Failed to reorder notes'
error: error.message || 'Failed to reorder notes',
};
}
}
Loading