@@ -304,7 +304,6 @@ export default function MailArchiveDashboard() {
- {/* Attachments */}
@@ -459,7 +458,6 @@ export default function MailArchiveDashboard() {
- {/* Footer / Copyright - New Addition */}
diff --git a/web/src/features/mailbox/components/mail-message-view.tsx b/web/src/features/mailbox/components/mail-message-view.tsx
index 3dbc6ad..f825cb3 100644
--- a/web/src/features/mailbox/components/mail-message-view.tsx
+++ b/web/src/features/mailbox/components/mail-message-view.tsx
@@ -19,7 +19,7 @@
import { useEffect, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
-import { Loader, Download, Trash2, MessageSquareMore } from 'lucide-react';
+import { Loader, Download, Trash2, MessageSquareMore, FileText, FileImage, FileAudio, FileVideo, FileSpreadsheet, FileArchive, FileCode, FileIcon } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
@@ -83,6 +83,35 @@ const Multilines: React.FC<{ title: string; lines: string[] }> = ({ title, lines
);
};
+
+const getFileConfig = (mimeType: string) => {
+ const type = mimeType.toLowerCase();
+ if (type.includes('pdf')) {
+ return { icon:
, color: 'text-red-600 bg-red-50 border-red-100' };
+ }
+ if (type.includes('image/')) {
+ return { icon:
, color: 'text-blue-600 bg-blue-50 border-blue-100' };
+ }
+ if (type.includes('audio/')) {
+ return { icon:
, color: 'text-purple-600 bg-purple-50 border-purple-100' };
+ }
+
+ if (type.includes('video/')) {
+ return { icon:
, color: 'text-indigo-600 bg-indigo-50 border-indigo-100' };
+ }
+ if (type.includes('spreadsheet') || type.includes('excel') || type.includes('csv')) {
+ return { icon:
, color: 'text-green-600 bg-green-50 border-green-100' };
+ }
+ if (type.includes('zip') || type.includes('compressed') || type.includes('archive')) {
+ return { icon:
, color: 'text-orange-600 bg-orange-50 border-orange-100' };
+ }
+ if (type.includes('text/') || type.includes('json') || type.includes('javascript')) {
+ return { icon:
, color: 'text-slate-600 bg-slate-50 border-slate-100' };
+ }
+
+ return { icon:
, color: 'text-gray-600 bg-gray-50 border-gray-100' };
+};
+
export function MailMessageView({
envelope,
showActions = true,
@@ -245,11 +274,24 @@ export function MailMessageView({
const nonInline = attachments.filter((a) => !a.inline);
return nonInline.length > 0 ? (
- {nonInline.map((attachment, i) => (
-
-
-
{attachment.filename}
-
[{attachment.file_type}]
+ {nonInline.map((attachment, i) => {
+ const { icon, color } = getFileConfig(attachment.file_type);
+ return
+
+
+ {icon}
+
+
+
+ {attachment.filename}
+
+
+ {attachment.file_type.split('/').pop()?.toUpperCase()}
+
+
@@ -268,7 +310,7 @@ export function MailMessageView({
)}
- ))}
+ })}
) : (
diff --git a/web/src/features/search/mail-message-view.tsx b/web/src/features/search/mail-message-view.tsx
index 7fdbdd2..e115c24 100644
--- a/web/src/features/search/mail-message-view.tsx
+++ b/web/src/features/search/mail-message-view.tsx
@@ -19,7 +19,7 @@
import { useEffect, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
-import { Loader, Download, Trash2, MessageSquareMore } from 'lucide-react';
+import { Loader, Download, Trash2, MessageSquareMore, FileText, FileImage, FileVideo, FileArchive, FileSpreadsheet, FileCode, FileIcon, FileAudio } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Separator } from '@/components/ui/separator';
@@ -84,6 +84,34 @@ const Multilines: React.FC<{ title: string; lines: string[] }> = ({ title, lines
);
};
+const getFileConfig = (mimeType: string) => {
+ const type = mimeType.toLowerCase();
+ if (type.includes('pdf')) {
+ return { icon: , color: 'text-red-600 bg-red-50 border-red-100' };
+ }
+ if (type.includes('image/')) {
+ return { icon: , color: 'text-blue-600 bg-blue-50 border-blue-100' };
+ }
+ if (type.includes('audio/')) {
+ return { icon: , color: 'text-purple-600 bg-purple-50 border-purple-100' };
+ }
+
+ if (type.includes('video/')) {
+ return { icon: , color: 'text-indigo-600 bg-indigo-50 border-indigo-100' };
+ }
+ if (type.includes('spreadsheet') || type.includes('excel') || type.includes('csv')) {
+ return { icon: , color: 'text-green-600 bg-green-50 border-green-100' };
+ }
+ if (type.includes('zip') || type.includes('compressed') || type.includes('archive')) {
+ return { icon: , color: 'text-orange-600 bg-orange-50 border-orange-100' };
+ }
+ if (type.includes('text/') || type.includes('json') || type.includes('javascript')) {
+ return { icon: , color: 'text-slate-600 bg-slate-50 border-slate-100' };
+ }
+
+ return { icon: , color: 'text-gray-600 bg-gray-50 border-gray-100' };
+};
+
export function MailMessageView({
envelope,
showActions = true,
@@ -184,7 +212,6 @@ export function MailMessageView({
return (
- {/* Header Info */}
{showHeader &&
{t('mail.account')}:
@@ -216,7 +243,7 @@ export function MailMessageView({
)}
}
- {/* Action Bar */}
+
{showActions && (
<>
@@ -257,7 +284,6 @@ export function MailMessageView({
>
)}
{showAttachments &&
}
- {/* Attachments */}
{showAttachments && (
{loading ? (
@@ -265,13 +291,27 @@ export function MailMessageView({
) : attachments && attachments.length > 0 ? (
(() => {
const nonInline = attachments.filter((a) => !a.inline);
+
return nonInline.length > 0 ? (
- {nonInline.map((attachment, i) => (
-
-
-
{attachment.filename}
-
[{attachment.file_type}]
+ {nonInline.map((attachment, i) => {
+ const { icon, color } = getFileConfig(attachment.file_type);
+ return
+
+
+ {icon}
+
+
+
+ {attachment.filename}
+
+
+ {attachment.file_type.split('/').pop()?.toUpperCase()}
+
+
@@ -290,7 +330,7 @@ export function MailMessageView({
)}
- ))}
+ })}
) : (
@@ -304,7 +344,6 @@ export function MailMessageView({
)}
{showAttachments &&
}
- {/* Content */}