Add 'Add to contacts' feature
Toolbar More menu now saves sender to Contact Manager with green success toast or grey 'Already in contacts' toast for duplicates. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+33
-4
@@ -2896,11 +2896,19 @@ function OnboardingWizard({accountId,onComplete,C}){
|
||||
|
||||
|
||||
// ── Email Toolbar ─────────────────────────────────────────────────────────────
|
||||
function EmailToolbar({email,folder,C,onReply,onReplyAll,onForward,onArchive,onDelete,onJunk,onStar,onUnread,onPrint}){
|
||||
function EmailToolbar({email,folder,C,onReply,onReplyAll,onForward,onArchive,onDelete,onJunk,onStar,onUnread,onPrint,onAddToContacts}){
|
||||
const[moreOpen,setMore]=useState(false);
|
||||
const[addedToast,setAddedToast]=useState(null); // null | "added" | "exists"
|
||||
const isSent=folder==="sent"||folder==="drafts"||folder==="out";
|
||||
|
||||
function handleAddToContacts(){
|
||||
setMore(false);
|
||||
const result=onAddToContacts?.({name:email.from,email:email.from_email,av:email.av,avColor:email.avColor});
|
||||
setAddedToast(result||"added");
|
||||
setTimeout(()=>setAddedToast(null),3000);
|
||||
}
|
||||
return <div style={{display:"flex",alignItems:"center",gap:2,padding:"6px 14px",
|
||||
borderBottom:`1px solid ${C.border}`,background:C.surface,flexShrink:0,flexWrap:"wrap"}}>
|
||||
borderBottom:`1px solid ${C.border}`,background:C.surface,flexShrink:0,flexWrap:"wrap",position:"relative"}}>
|
||||
{!isSent&&<>
|
||||
<IBtn icon="ti-arrow-back-up" title="Reply" C={C} onClick={onReply} label="Reply"/>
|
||||
<IBtn icon="ti-arrows-left" title="Reply All" C={C} onClick={onReplyAll} label="Reply All"/>
|
||||
@@ -2922,7 +2930,7 @@ function EmailToolbar({email,folder,C,onReply,onReplyAll,onForward,onArchive,onD
|
||||
{[["ti-alert-triangle","Mark as junk",()=>{onJunk();setMore(false);}],
|
||||
["ti-copy","Copy to folder",()=>setMore(false)],
|
||||
["ti-code","View source",()=>setMore(false)],
|
||||
["ti-user-plus","Add to contacts",()=>setMore(false)]].map(([ic,lbl,fn])=>(
|
||||
["ti-user-plus","Add to contacts",handleAddToContacts]].map(([ic,lbl,fn])=>(
|
||||
<button key={lbl} onClick={fn} style={{display:"flex",alignItems:"center",gap:9,
|
||||
width:"100%",padding:"9px 14px",background:"transparent",border:"none",
|
||||
cursor:"pointer",fontFamily:FONT,fontSize:13,color:C.text,textAlign:"left"}}
|
||||
@@ -2933,6 +2941,16 @@ function EmailToolbar({email,folder,C,onReply,onReplyAll,onForward,onArchive,onD
|
||||
))}
|
||||
</div>}
|
||||
</div>
|
||||
{addedToast&&<div style={{position:"absolute",top:44,right:14,zIndex:60,
|
||||
display:"flex",alignItems:"center",gap:8,padding:"8px 14px",borderRadius:8,
|
||||
background:addedToast==="added"?"#166534":"#374151",
|
||||
boxShadow:"0 4px 16px rgba(0,0,0,0.25)",animation:"loginIn 0.2s ease both"}}>
|
||||
<i className={`ti ${addedToast==="added"?"ti-user-check":"ti-user-x"}`}
|
||||
style={{fontSize:15,color:addedToast==="added"?"#86efac":"#9ca3af"}} aria-hidden="true"/>
|
||||
<span style={{fontSize:13,color:"#fff",fontFamily:FONT,whiteSpace:"nowrap"}}>
|
||||
{addedToast==="added"?"Contact added successfully":"Already in contacts"}
|
||||
</span>
|
||||
</div>}
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -3694,6 +3712,16 @@ function EmailApp({activeProfile,profiles,setActiveProfile,saveProfile,loginBg,s
|
||||
function doDelete(){if(selEmail){setEmails(p=>p.map(e=>e.id===selEmail.id?{...e,folder:"trash"}:e));setSelEmail(null);}}
|
||||
function doJunk(){if(selEmail){setEmails(p=>p.map(e=>e.id===selEmail.id?{...e,folder:"trash"}:e));setSelEmail(null);}}
|
||||
function doStar(){if(selEmail)setEmails(p=>p.map(e=>e.id===selEmail.id?{...e,starred:!e.starred}:e));}
|
||||
function doAddToContacts(data){
|
||||
if(!data?.email)return"added";
|
||||
const exists=contacts.some(c=>c.email?.toLowerCase()===data.email.toLowerCase());
|
||||
if(!exists){
|
||||
setContacts(p=>[...p,{id:"ct"+uid(),name:data.name||data.email,email:data.email,
|
||||
av:data.av||data.email.slice(0,2).toUpperCase(),avColor:data.avColor||"#0078d4",phone:"",address:""}]);
|
||||
return"added";
|
||||
}
|
||||
return"exists";
|
||||
}
|
||||
function doUnread(){if(selEmail){setEmails(p=>p.map(e=>e.id===selEmail.id?{...e,read:false}:e));setSelEmail(null);}}
|
||||
function openReply(mode){
|
||||
if(!selEmail)return;
|
||||
@@ -4029,7 +4057,8 @@ function EmailApp({activeProfile,profiles,setActiveProfile,saveProfile,loginBg,s
|
||||
<EmailToolbar email={selEmail} folder={selFolder} C={C}
|
||||
onReply={()=>openReply("reply")} onReplyAll={()=>openReply("replyAll")}
|
||||
onForward={()=>openReply("forward")} onArchive={doArchive} onDelete={doDelete}
|
||||
onJunk={doJunk} onStar={doStar} onUnread={doUnread} onPrint={()=>printEmail(selEmail)}/>
|
||||
onJunk={doJunk} onStar={doStar} onUnread={doUnread} onPrint={()=>printEmail(selEmail)}
|
||||
onAddToContacts={doAddToContacts}/>
|
||||
<div style={{padding:"16px 22px 14px",borderBottom:`1px solid ${bgDark?"rgba(255,255,255,0.12)":C.border}`,background:bgDark?"rgba(0,0,0,0.25)":"rgba(255,255,255,0.7)",flexShrink:0,backdropFilter:bgIsImage(bg)?"blur(12px)":"none"}}>
|
||||
<h2 style={{margin:"0 0 12px",fontSize:17,fontWeight:600,color:readingTextColor,lineHeight:1.3}}>
|
||||
{selEmail.subject}
|
||||
|
||||
Reference in New Issue
Block a user