Initial release: JMAP Webmail Client

A modern, privacy-focused webmail client built with Next.js and the JMAP protocol.
Designed for Stalwart Mail Server.

Features:
- Full email operations (compose, reply, forward, threading)
- Real-time push notifications
- Dark/light theme support
- Mobile responsive design
- Keyboard shortcuts
- Drag-and-drop organization
- i18n (English/French)
- Security-first (external content blocked, HTML sanitization)
This commit is contained in:
Matthieu MALVACHE
2025-12-10 17:54:22 +01:00
committed by Matthieu MALVACHE
commit cf21a84263
79 changed files with 21821 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
"use client";
import { createContext, useContext, useState, useCallback, ReactNode } from "react";
import { Email } from "@/lib/jmap/types";
interface DragDropState {
isDragging: boolean;
draggedEmails: Email[];
dragCount: number;
sourceMailboxId: string | null;
}
interface DragDropContextValue extends DragDropState {
startDrag: (emails: Email[], sourceMailboxId: string) => void;
endDrag: () => void;
}
const initialState: DragDropState = {
isDragging: false,
draggedEmails: [],
dragCount: 0,
sourceMailboxId: null,
};
const DragDropContext = createContext<DragDropContextValue | null>(null);
export function DragDropProvider({ children }: { children: ReactNode }) {
const [state, setState] = useState<DragDropState>(initialState);
const startDrag = useCallback((emails: Email[], sourceMailboxId: string) => {
setState({
isDragging: true,
draggedEmails: emails,
dragCount: emails.length,
sourceMailboxId,
});
}, []);
const endDrag = useCallback(() => {
setState(initialState);
}, []);
return (
<DragDropContext.Provider value={{ ...state, startDrag, endDrag }}>
{children}
</DragDropContext.Provider>
);
}
export function useDragDropContext() {
const context = useContext(DragDropContext);
if (!context) {
throw new Error("useDragDropContext must be used within DragDropProvider");
}
return context;
}