fix styling
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
import { Email, ThreadGroup } from "@/lib/jmap/types";
|
import { Email, ThreadGroup } from "@/lib/jmap/types";
|
||||||
import { ThreadListItem } from "./thread-list-item";
|
import { ThreadListItem } from "./thread-list-item";
|
||||||
import { EmailContextMenu } from "./email-context-menu";
|
import { EmailContextMenu } from "./email-context-menu";
|
||||||
import { cn, formatDateTime } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Trash2, Mail, MailX, MailOpen, Loader2, SearchX, AlertTriangle, CalendarClock } from "lucide-react";
|
import { Trash2, Mail, MailX, MailOpen, Loader2, SearchX, AlertTriangle, CalendarClock } from "lucide-react";
|
||||||
import { useState, useEffect, useRef, useCallback, useMemo } from "react";
|
import { useState, useEffect, useRef, useCallback, useMemo } from "react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -121,7 +121,6 @@ export function EmailList({
|
|||||||
const density = useSettingsStore((state) => state.density);
|
const density = useSettingsStore((state) => state.density);
|
||||||
const showPreview = useSettingsStore((state) => state.showPreview);
|
const showPreview = useSettingsStore((state) => state.showPreview);
|
||||||
const mailLayout = useSettingsStore((state) => state.mailLayout);
|
const mailLayout = useSettingsStore((state) => state.mailLayout);
|
||||||
const timeFormat = useSettingsStore((state) => state.timeFormat);
|
|
||||||
const isFocusedMailLayout = mailLayout === 'focus';
|
const isFocusedMailLayout = mailLayout === 'focus';
|
||||||
const footerHasMore = hasMore ?? hasMoreEmails;
|
const footerHasMore = hasMore ?? hasMoreEmails;
|
||||||
const footerIsLoadingMore = isLoadingMoreItems ?? isLoadingMore;
|
const footerIsLoadingMore = isLoadingMoreItems ?? isLoadingMore;
|
||||||
@@ -482,14 +481,6 @@ export function EmailList({
|
|||||||
onSetColorTag={onSetColorTag}
|
onSetColorTag={onSetColorTag}
|
||||||
onMarkAsSpam={onMarkAsSpam ? (email) => onMarkAsSpam(email) : undefined}
|
onMarkAsSpam={onMarkAsSpam ? (email) => onMarkAsSpam(email) : undefined}
|
||||||
/>
|
/>
|
||||||
{isScheduledView && thread.latestEmail.isScheduled && (
|
|
||||||
<div className="flex flex-wrap items-center gap-2 border-b border-border bg-muted/10 px-4 py-2 text-xs">
|
|
||||||
<span className="flex items-center gap-1 text-muted-foreground">
|
|
||||||
<CalendarClock className="w-3.5 h-3.5" />
|
|
||||||
{thread.latestEmail.scheduledSendAt ? formatDateTime(thread.latestEmail.scheduledSendAt, timeFormat) : ''}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
import { formatDate, stripInvisibleLeading } from "@/lib/utils";
|
import { formatDate, formatDateTime, stripInvisibleLeading } from "@/lib/utils";
|
||||||
import { Email, ThreadGroup } from "@/lib/jmap/types";
|
import { Email, ThreadGroup } from "@/lib/jmap/types";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Avatar } from "@/components/ui/avatar";
|
import { Avatar } from "@/components/ui/avatar";
|
||||||
import { Paperclip, Star, Circle, ChevronRight, ChevronDown, Loader2, MessageSquare, CheckSquare, Square, Reply, Forward } from "lucide-react";
|
import { Paperclip, Star, Circle, ChevronRight, ChevronDown, Loader2, MessageSquare, CheckSquare, Square, Reply, Forward, CalendarClock } from "lucide-react";
|
||||||
import { useSettingsStore, KEYWORD_PALETTE } from "@/stores/settings-store";
|
import { useSettingsStore, KEYWORD_PALETTE } from "@/stores/settings-store";
|
||||||
import { useUIStore } from "@/stores/ui-store";
|
import { useUIStore } from "@/stores/ui-store";
|
||||||
import { useEmailStore } from "@/stores/email-store";
|
import { useEmailStore } from "@/stores/email-store";
|
||||||
@@ -67,6 +67,7 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
|||||||
const emailKeywords = useSettingsStore((state) => state.emailKeywords);
|
const emailKeywords = useSettingsStore((state) => state.emailKeywords);
|
||||||
const density = useSettingsStore((state) => state.density);
|
const density = useSettingsStore((state) => state.density);
|
||||||
const mailLayout = useSettingsStore((state) => state.mailLayout);
|
const mailLayout = useSettingsStore((state) => state.mailLayout);
|
||||||
|
const timeFormat = useSettingsStore((state) => state.timeFormat);
|
||||||
const showAvatarsInJunk = useSettingsStore((state) => state.showAvatarsInJunk);
|
const showAvatarsInJunk = useSettingsStore((state) => state.showAvatarsInJunk);
|
||||||
const hideJunkAvatarImages = currentMailboxRole === 'junk' && !showAvatarsInJunk;
|
const hideJunkAvatarImages = currentMailboxRole === 'junk' && !showAvatarsInJunk;
|
||||||
const isUnifiedView = useEmailStore((state) => state.isUnifiedView);
|
const isUnifiedView = useEmailStore((state) => state.isUnifiedView);
|
||||||
@@ -76,6 +77,9 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
|||||||
const isFocusedMailLayout = mailLayout === 'focus';
|
const isFocusedMailLayout = mailLayout === 'focus';
|
||||||
const trimmedPreview = stripInvisibleLeading(email.preview ?? '');
|
const trimmedPreview = stripInvisibleLeading(email.preview ?? '');
|
||||||
const inlinePreview = showPreview && trimmedPreview ? ` ${trimmedPreview}` : '';
|
const inlinePreview = showPreview && trimmedPreview ? ` ${trimmedPreview}` : '';
|
||||||
|
const scheduledSendLabel = email.isScheduled && email.scheduledSendAt
|
||||||
|
? formatDateTime(email.scheduledSendAt, timeFormat)
|
||||||
|
: null;
|
||||||
|
|
||||||
// Resolve color tags using keyword definitions; unknown tags fall back to gray
|
// Resolve color tags using keyword definitions; unknown tags fall back to gray
|
||||||
const tagIds = getEmailColorTags(email.keywords);
|
const tagIds = getEmailColorTags(email.keywords);
|
||||||
@@ -241,12 +245,22 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
|||||||
{resolvedKeywordDefs.map((kd) => (
|
{resolvedKeywordDefs.map((kd) => (
|
||||||
<span key={kd.id} className={cn('h-2.5 w-2.5 rounded-full', KEYWORD_PALETTE[kd.color]?.dot || 'bg-gray-400')} />
|
<span key={kd.id} className={cn('h-2.5 w-2.5 rounded-full', KEYWORD_PALETTE[kd.color]?.dot || 'bg-gray-400')} />
|
||||||
))}
|
))}
|
||||||
<span className={cn(
|
{scheduledSendLabel ? (
|
||||||
'text-xs tabular-nums',
|
<span
|
||||||
isUnread ? 'text-foreground font-semibold' : 'text-muted-foreground'
|
className="inline-flex max-w-[11rem] shrink-0 items-center gap-1 truncate rounded-full border border-sky-500/20 bg-sky-500/10 px-2 py-0.5 text-xs font-medium tabular-nums text-sky-700 dark:text-sky-300"
|
||||||
)}>
|
title={scheduledSendLabel}
|
||||||
{formatDate(email.receivedAt)}
|
>
|
||||||
</span>
|
<CalendarClock className="h-3 w-3 shrink-0" />
|
||||||
|
<span className="truncate">{scheduledSendLabel}</span>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className={cn(
|
||||||
|
'text-xs tabular-nums',
|
||||||
|
isUnread ? 'text-foreground font-semibold' : 'text-muted-foreground'
|
||||||
|
)}>
|
||||||
|
{formatDate(email.receivedAt)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -299,14 +313,24 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
|||||||
{kd.label}
|
{kd.label}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
<span className={cn(
|
{scheduledSendLabel ? (
|
||||||
"text-xs tabular-nums",
|
<span
|
||||||
isUnread
|
className="inline-flex max-w-[11rem] shrink-0 items-center gap-1 truncate rounded-full border border-sky-500/20 bg-sky-500/10 px-2 py-0.5 text-[11px] font-medium tabular-nums text-sky-700 dark:text-sky-300"
|
||||||
? "text-foreground font-semibold"
|
title={scheduledSendLabel}
|
||||||
: "text-muted-foreground"
|
>
|
||||||
)}>
|
<CalendarClock className="h-3 w-3 shrink-0" />
|
||||||
{formatDate(email.receivedAt)}
|
<span className="truncate">{scheduledSendLabel}</span>
|
||||||
</span>
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className={cn(
|
||||||
|
"text-xs tabular-nums",
|
||||||
|
isUnread
|
||||||
|
? "text-foreground font-semibold"
|
||||||
|
: "text-muted-foreground"
|
||||||
|
)}>
|
||||||
|
{formatDate(email.receivedAt)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -376,12 +400,16 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
|||||||
const showPreview = useSettingsStore((state) => state.showPreview);
|
const showPreview = useSettingsStore((state) => state.showPreview);
|
||||||
const density = useSettingsStore((state) => state.density);
|
const density = useSettingsStore((state) => state.density);
|
||||||
const mailLayout = useSettingsStore((state) => state.mailLayout);
|
const mailLayout = useSettingsStore((state) => state.mailLayout);
|
||||||
|
const timeFormat = useSettingsStore((state) => state.timeFormat);
|
||||||
const showAvatarsInJunk = useSettingsStore((state) => state.showAvatarsInJunk);
|
const showAvatarsInJunk = useSettingsStore((state) => state.showAvatarsInJunk);
|
||||||
const isMobile = useUIStore((state) => state.isMobile);
|
const isMobile = useUIStore((state) => state.isMobile);
|
||||||
const { latestEmail, participantNames, hasUnread, hasStarred, hasAttachment, hasAnswered, hasForwarded, emailCount } = thread;
|
const { latestEmail, participantNames, hasUnread, hasStarred, hasAttachment, hasAnswered, hasForwarded, emailCount } = thread;
|
||||||
const isFocusedMailLayout = mailLayout === 'focus';
|
const isFocusedMailLayout = mailLayout === 'focus';
|
||||||
const trimmedPreview = stripInvisibleLeading(latestEmail.preview ?? '');
|
const trimmedPreview = stripInvisibleLeading(latestEmail.preview ?? '');
|
||||||
const inlinePreview = showPreview && trimmedPreview ? ` ${trimmedPreview}` : '';
|
const inlinePreview = showPreview && trimmedPreview ? ` ${trimmedPreview}` : '';
|
||||||
|
const scheduledSendLabel = latestEmail.isScheduled && latestEmail.scheduledSendAt
|
||||||
|
? formatDateTime(latestEmail.scheduledSendAt, timeFormat)
|
||||||
|
: null;
|
||||||
|
|
||||||
const { selectedMailbox, mailboxes, selectedEmailIds, toggleEmailSelection, selectRangeEmails, clearSelection, isUnifiedView } = useEmailStore();
|
const { selectedMailbox, mailboxes, selectedEmailIds, toggleEmailSelection, selectRangeEmails, clearSelection, isUnifiedView } = useEmailStore();
|
||||||
const getAccountById = useAccountStore((state) => state.getAccountById);
|
const getAccountById = useAccountStore((state) => state.getAccountById);
|
||||||
@@ -647,12 +675,22 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
|||||||
{keywordDef && (
|
{keywordDef && (
|
||||||
<span className={cn('h-2.5 w-2.5 rounded-full', KEYWORD_PALETTE[keywordDef.color]?.dot || 'bg-gray-400')} />
|
<span className={cn('h-2.5 w-2.5 rounded-full', KEYWORD_PALETTE[keywordDef.color]?.dot || 'bg-gray-400')} />
|
||||||
)}
|
)}
|
||||||
<span className={cn(
|
{scheduledSendLabel ? (
|
||||||
'text-xs tabular-nums',
|
<span
|
||||||
hasUnread ? 'text-foreground font-semibold' : 'text-muted-foreground'
|
className="inline-flex max-w-[11rem] shrink-0 items-center gap-1 truncate rounded-full border border-sky-500/20 bg-sky-500/10 px-2 py-0.5 text-xs font-medium tabular-nums text-sky-700 dark:text-sky-300"
|
||||||
)}>
|
title={scheduledSendLabel}
|
||||||
{formatDate(latestEmail.receivedAt)}
|
>
|
||||||
</span>
|
<CalendarClock className="h-3 w-3 shrink-0" />
|
||||||
|
<span className="truncate">{scheduledSendLabel}</span>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className={cn(
|
||||||
|
'text-xs tabular-nums',
|
||||||
|
hasUnread ? 'text-foreground font-semibold' : 'text-muted-foreground'
|
||||||
|
)}>
|
||||||
|
{formatDate(latestEmail.receivedAt)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -717,14 +755,24 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
|||||||
{keywordDef.label}
|
{keywordDef.label}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<span className={cn(
|
{scheduledSendLabel ? (
|
||||||
"text-xs tabular-nums",
|
<span
|
||||||
hasUnread
|
className="inline-flex max-w-[11rem] shrink-0 items-center gap-1 truncate rounded-full border border-sky-500/20 bg-sky-500/10 px-2 py-0.5 text-[11px] font-medium tabular-nums text-sky-700 dark:text-sky-300"
|
||||||
? "text-foreground font-semibold"
|
title={scheduledSendLabel}
|
||||||
: "text-muted-foreground"
|
>
|
||||||
)}>
|
<CalendarClock className="h-3 w-3 shrink-0" />
|
||||||
{formatDate(latestEmail.receivedAt)}
|
<span className="truncate">{scheduledSendLabel}</span>
|
||||||
</span>
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className={cn(
|
||||||
|
"text-xs tabular-nums",
|
||||||
|
hasUnread
|
||||||
|
? "text-foreground font-semibold"
|
||||||
|
: "text-muted-foreground"
|
||||||
|
)}>
|
||||||
|
{formatDate(latestEmail.receivedAt)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user