feat: mail UI improvements - folder mapping, display name, resize perf, list header

- Add configurable folder mapping (sent/drafts/spam/trash) per account
- Migration 0005_folder_mapping.sql with 4 new columns on mail_accounts
- Backend: send_mail uses account.sent_folder_imap_name if set
- Backend: _build_folder_hierarchy respects folder_mapping for is_standard
- Frontend: MailSettings shows folder mapping editor per account
- Frontend: MailSettings allows editing display_name for existing accounts
- Frontend: MailFolderTree shows display_name || email, removes MailIcon
- Frontend: ResizablePanel isDragging state with contain:strict + pointer-events:none
- Frontend: MailList merges select-all and sort controls into one line
This commit is contained in:
Agent Zero
2026-07-17 23:17:52 +02:00
parent 04c419402b
commit db433e81f1
9 changed files with 295 additions and 71 deletions
+11 -1
View File
@@ -38,6 +38,7 @@ export function ResizablePanel({
...rest
}: ResizablePanelProps) {
const [width, setWidth] = useState(initialWidth);
const [isDragging, setIsDragging] = useState(false);
const isResizing = useRef(false);
const startX = useRef(0);
const startWidth = useRef(0);
@@ -47,6 +48,7 @@ export function ResizablePanel({
e.preventDefault();
e.stopPropagation();
isResizing.current = true;
setIsDragging(true);
startX.current = e.clientX;
startWidth.current = width;
document.body.style.cursor = 'col-resize';
@@ -66,6 +68,7 @@ export function ResizablePanel({
const handleMouseUp = () => {
if (isResizing.current) {
isResizing.current = false;
setIsDragging(false);
document.body.style.cursor = '';
document.body.style.userSelect = '';
}
@@ -90,7 +93,14 @@ export function ResizablePanel({
data-testid={rest['data-testid']}
>
{/* Inner scrollable content area — scrollbar stays inside, never overlaps handle */}
<div className="flex-1 overflow-y-auto overflow-x-hidden min-h-0">
<div
className="flex-1 overflow-y-auto overflow-x-hidden min-h-0"
style={{
contain: 'strict',
pointerEvents: isDragging ? 'none' : 'auto',
willChange: isDragging ? 'width' : undefined,
}}
>
{children}
</div>
{resizable && (