diff --git a/frontend/src/api/mailApi.js b/frontend/src/api/mailApi.js index 1c8903eb..0aaffca6 100644 --- a/frontend/src/api/mailApi.js +++ b/frontend/src/api/mailApi.js @@ -245,7 +245,8 @@ export async function updateMail(mailId, { subject, body, sentTo, - saveAsDraft = true + saveAsDraft = true, + files = [] }) { const url = `${API_BASE}/mails/${mailId}`; const token = localStorage.getItem("token"); @@ -256,7 +257,7 @@ export async function updateMail(mailId, { "Authorization": `Bearer ${token}`, "Content-Type": "application/json" }, - body: JSON.stringify({subject, body, sentTo, saveAsDraft}) + body: JSON.stringify({subject, body, sentTo, saveAsDraft, files}) }); if (!res.ok) throw new Error(`updateMail failed: ${res.status}`); diff --git a/frontend/src/main_page/ComposeEmail/ComposeEmail.css b/frontend/src/main_page/ComposeEmail/ComposeEmail.css index 539a43dc..a86274f0 100644 --- a/frontend/src/main_page/ComposeEmail/ComposeEmail.css +++ b/frontend/src/main_page/ComposeEmail/ComposeEmail.css @@ -1,3 +1,4 @@ +/* ── Base drawer with transitions & overflow hidden ── */ .compose-email { position: fixed; bottom: 2vh; @@ -8,20 +9,31 @@ background: #fff; border: 1px solid #dadce0; border-radius: 8px 8px 0 0; - box-shadow: 0 1px 2px rgba(60,64,67,0.15), - 0 2px 6px rgba(60,64,67,0.15); + box-shadow: + 0 1px 2px rgba(60,64,67,0.15), + 0 2px 6px rgba(60,64,67,0.15); display: flex; flex-direction: column; font-family: 'Roboto', sans-serif; z-index: 1000; - color: #202124; /* default text color */ + color: #202124; + transition: all 0.2s ease; + overflow: hidden; } +/* ── Minimized: only header shows ── */ +.compose-email.minimized { + height: auto; /* shrink to header bar */ + width: 250px; /* Gmail‑style small width */ + max-width: 100%; + bottom: 0; +} .compose-email.minimized .compose-body, .compose-email.minimized .compose-footer { display: none; } +/* ── Maximized: inset overlay with gutters ── */ .compose-email.maximized { top: 10vh !important; bottom: 10vh !important; @@ -29,10 +41,37 @@ right: 10vw !important; width: auto !important; height: auto !important; - max-width: none !important; - max-height: none !important; + max-width: 80vw !important; + max-height: 80vh !important; border-radius: 8px !important; -} + overflow: hidden; + + /* inherit whatever the root .compose-email is set to */ + background: inherit !important; + border-color: inherit !important; +} + +/* ── Responsive auto‑minimize under 600px ── */ +@media (max-width: 600px) { + .compose-email { + left: 0 !important; + right: 0 !important; + width: 100% !important; + max-width: none; + } + /* collapse unless user manually maximized */ + .compose-email:not(.maximized) { + height: auto; + bottom: 0; + } + /* if maximized, fill screen */ + .compose-email.maximized { + height: 100% !important; + width: 100% !important; + } +} + +/* --- existing styles below this line --- */ .compose-header { background: #f1f3f4; @@ -49,11 +88,10 @@ color: #202124; } -/* --- Only this part was added for dark mode title --- */ +/* Dark mode title override */ .compose-email.dark .compose-title { color: #f1f3f4 !important; } -/* ---------------------------------------- */ .compose-controls .control-btn { background: transparent; @@ -193,7 +231,6 @@ border-bottom-color: #1a73e8; } - .attachment-item { display: flex; align-items: center; @@ -232,18 +269,6 @@ color: #d93025; } -/* Optional: dark mode tweaks */ -.compose-email.dark .attachment-item { - color: #e8eaed; -} -.compose-email.dark .remove-btn { - color: #9aa0a6; -} -.compose-email.dark .remove-btn:hover { - color: #f28b82; -} - - .compose-footer { padding: 0.5em 1em; display: flex; diff --git a/frontend/src/main_page/ComposeEmail/ComposeEmail.jsx b/frontend/src/main_page/ComposeEmail/ComposeEmail.jsx index 3580456e..608295d1 100644 --- a/frontend/src/main_page/ComposeEmail/ComposeEmail.jsx +++ b/frontend/src/main_page/ComposeEmail/ComposeEmail.jsx @@ -56,7 +56,7 @@ export default function ComposeEmail({ editorRef.current.innerHTML = initial; } - setAttachments(draftMail.attachments || []); + setAttachments(draftMail.files || []); setToQuery(''); setSuggestions([]); }, [draftMail]); @@ -73,6 +73,14 @@ export default function ComposeEmail({ }, 300); return () => clearTimeout(timer); }, [toQuery]); + // ── auto‑minimize on narrow viewports ── + useEffect(() => { + const mql = window.matchMedia('(max-width: 600px)'); + const handler = e => setView(e.matches ? 'minimized' : 'normal'); + // modern API + mql.addEventListener('change', handler); + return () => mql.removeEventListener('change', handler); + }, []); // Add recipient if not already present const addRecipient = email => { diff --git a/frontend/src/main_page/MainPage.js b/frontend/src/main_page/MainPage.js index d985d103..58e5c80e 100644 --- a/frontend/src/main_page/MainPage.js +++ b/frontend/src/main_page/MainPage.js @@ -145,7 +145,7 @@ const MainPage = () => { {composes.map(c => ( { if (!mail.isDraft) return res.status(400).json({error: 'error only drafts can be updated'}); // Get the input params and edit the mail - const {subject, body, sentTo = [], saveAsDraft = true} = req.body; + const {subject, body, sentTo = [], saveAsDraft = true, files = []} = req.body; const sentToIds = convertMailsToIds(sentTo); // just update the fields in this draft if (saveAsDraft) { - const updated = Mails.updateDraft(mail.id, subject, body, sentToIds); + const updated = Mails.updateDraft(mail.id, subject, body, sentToIds, files); return res.status(200).json(updated); } // turn the draft to a new mail @@ -195,7 +195,7 @@ const editDraft = async (req, res, userId, mail) => { return res.status(403).json({error: 'error mail contains blacklisted URLs'}); // delete the draft and send a new mail Mails.deleteMail(userId, mail.id); - const ownerMail = Mails.sendNewMail(userId, subject, body, sentToIds); + const ownerMail = Mails.sendNewMail(userId, subject, body, sentToIds, files); return res.status(201).location(`/mails/${ownerMail.id}`).json(ownerMail); }