improved mail view on phones

Fixed css issues
This commit is contained in:
defnax 2026-07-26 23:06:56 +02:00
parent 8157f6dd16
commit f144a85a73
8 changed files with 1775 additions and 1276 deletions

View File

@ -117,6 +117,53 @@ function scrollChatToBottom() {
}, 50);
}
function renderUserTooltip(gxsId, name) {
const details = ChatHubState.gxsDetails[gxsId];
if (!details) return null;
const avatar = getSafeAvatar(details);
const firstLetter = (name || '?').slice(0, 1).toUpperCase();
const votes = details.mReputation
? (details.mReputation.mFriendsPositiveVotes - details.mReputation.mFriendsNegativeVotes)
: 0;
const rect = ChatHubState.hoveredUser ? ChatHubState.hoveredUser.rect : null;
const tooltipWidth = 280;
let left = rect ? rect.left - tooltipWidth - 10 : window.innerWidth - 300;
if (left < 10 && rect) left = rect.right + 10;
let top = rect ? rect.top : 100;
if (top + 160 > window.innerHeight) top = window.innerHeight - 170;
if (top < 10) top = 10;
return m('.user-tooltip', {
style: {
position: 'fixed',
top: `${top}px`,
left: `${left}px`,
zIndex: 10000,
}
}, [
m('.tooltip-avatar', m(peopleUtil.UserAvatar, { avatar, firstLetter, identityId: gxsId, size: 56, isSquare: true })),
m('.tooltip-details', [
m('.tooltip-row', [m('span.tooltip-label', 'Identity name: '), m('span.tooltip-value', name)]),
m('.tooltip-row', [m('span.tooltip-label', 'Identity Id: '), m('span.tooltip-value.tooltip-id', gxsId)]),
details.mPgpId && details.mPgpId !== '0000000000000000' && m('.tooltip-row', [
m('span.tooltip-label', 'Node: '),
m('span.tooltip-value', `${rs.userList.username(details.mPgpId) || name} [${details.mPgpId}]`)
]),
m('.tooltip-row', [
m('span.tooltip-label', 'Votes: '),
m('span.tooltip-value', {
style: {
color: votes >= 0 ? '#008000' : '#cc0000',
fontWeight: 'bold'
}
}, (votes >= 0 ? '+' : '') + votes)
])
])
]);
}
function pollHashStatus(localpath) {
rs.rsJsonApiRequest('/rsFiles/ExtraFileStatus', { localpath }, (data) => {
if (data && data.retval && data.info && data.info.hash && data.info.hash !== '0000000000000000000000000000000000000000') {
@ -641,12 +688,7 @@ const ChatConversationView = () => {
onmouseenter: (e) => {
if (ChatHubState.activeMenu) return;
const rect = e.currentTarget.getBoundingClientRect();
const rightbar = document.querySelector('.chat-hub-rightbar');
if (rightbar) {
const parentRect = rightbar.getBoundingClientRect();
const top = rect.top - parentRect.top + rect.height / 2;
ChatHubState.hoveredUser = { gxsId, name, top };
}
ChatHubState.hoveredUser = { gxsId, name, rect };
},
onmouseleave: () => {
ChatHubState.hoveredUser = null;
@ -717,46 +759,11 @@ const ChatConversationView = () => {
});
}
return null;
})()
})(),
]);
});
})()),
ChatHubState.hoveredUser && (() => {
const hUser = ChatHubState.hoveredUser;
const details = ChatHubState.gxsDetails[hUser.gxsId];
if (!details) return null;
const avatar = getSafeAvatar(details);
const firstLetter = (hUser.name || '?').slice(0, 1).toUpperCase();
const votes = details.mReputation
? (details.mReputation.mFriendsPositiveVotes - details.mReputation.mFriendsNegativeVotes)
: 0;
return m('.user-tooltip', {
style: {
top: `${hUser.top}px`,
}
}, [
m('.tooltip-avatar', m(peopleUtil.UserAvatar, { avatar, firstLetter, identityId: hUser.gxsId, size: 64 })),
m('.tooltip-details', [
m('.tooltip-row', [m('span.tooltip-label', 'Identity name: '), m('span.tooltip-value', hUser.name)]),
m('.tooltip-row', [m('span.tooltip-label', 'Identity Id: '), m('span.tooltip-value.tooltip-id', hUser.gxsId)]),
details.mPgpId && details.mPgpId !== '0000000000000000' && m('.tooltip-row', [
m('span.tooltip-label', 'Node: '),
m('span.tooltip-value', `${rs.userList.username(details.mPgpId) || hUser.name} [${details.mPgpId}]`)
]),
m('.tooltip-row', [
m('span.tooltip-label', 'Votes: '),
m('span.tooltip-value', {
style: {
color: votes >= 0 ? '#22c55e' : '#ef4444',
fontWeight: 'bold'
}
}, (votes >= 0 ? '+' : '') + votes)
])
])
]);
})(),
ChatHubState.hoveredUser && renderUserTooltip(ChatHubState.hoveredUser.gxsId, ChatHubState.hoveredUser.name),
ChatHubState.activeMenu && (() => {
const menu = ChatHubState.activeMenu;
const isOwn = menu.gxsId === rs.idToHex(ChatLobbyModel.currentLobby.gxs_id || '');

View File

@ -68,12 +68,12 @@ const sections = {
drafts: require('mail/mail_draftbox'),
sent: require('mail/mail_sentbox'),
trash: require('mail/mail_trashbox'),
};
const sectionsquickview = {
starred: require('mail/mail_starred'),
system: require('mail/mail_system'),
spam: require('mail/mail_spam'),
attachment: require('mail/mail_attachment'),
};
const sectionsquickview = {
important: require('mail/mail_important'),
work: require('mail/mail_work'),
todo: require('mail/mail_todo'),
@ -81,8 +81,15 @@ const sectionsquickview = {
personal: require('mail/mail_personal'),
};
const tagselect = {
showval: 'Tags',
opts: ['Tags', 'Important', 'Work', 'Personal'],
opts: [
{ label: '🏷️ Filter by Tag...', val: '' },
{ label: '📎 Attachments', val: 'attachment' },
{ label: '🔴 Important', val: 'important' },
{ label: '🟠 Work', val: 'work' },
{ label: '🟢 Personal', val: 'personal' },
{ label: '🔵 Todo', val: 'todo' },
{ label: '🟣 Later', val: 'later' },
],
};
const Layout = () => {
let showCompose = false;
@ -99,12 +106,12 @@ const Layout = () => {
drafts: (Messages.drafts || []).length,
sent: (Messages.sent || []).length,
trash: (Messages.trash || []).length,
};
const sectionsQuickviewSize = {
starred: (Messages.starred || []).length,
system: (Messages.system || []).length,
spam: (Messages.spam || []).length,
attachment: (Messages.attachment || []).length,
};
const sectionsQuickviewSize = {
important: (Messages.important || []).length,
work: (Messages.work || []).length,
todo: (Messages.todo || []).length,
@ -141,16 +148,29 @@ const Layout = () => {
m(
'select.mail-tag',
{
value: tagselect.showval,
onchange: (e) => (tagselect.showval = tagselect.opts[e.target.selectedIndex]),
value: m.route.param().tab || '',
onchange: (e) => {
const selectedTag = e.target.value;
if (selectedTag) {
m.route.set('/mail/:tab', { tab: selectedTag });
}
},
},
[tagselect.opts.map((opt) => m('option', { value: opt }, opt.toLocaleString()))]
tagselect.opts.map((opt) => m('option', { value: opt.val }, opt.label))
),
m(util.SearchBar, { list: {} }),
]),
vnode.children,
])
),
m(
'button.mobile-fab-compose',
{
title: 'Compose Mail',
onclick: () => setShowCompose(true),
},
m('i.fas.fa-pen')
),
showCompose && m(
'.composePopupOverlay#mailComposerPopup',
m(
@ -173,6 +193,7 @@ const tabConfig = {
starred: { title: 'Starred', category: 'starred' },
system: { title: 'System', category: 'system' },
spam: { title: 'Spam', category: 'spam' },
attachment: { title: 'Attachments', category: 'attachment' },
important: { title: 'Important', category: 'important' },
work: { title: 'Work', category: 'work' },
todo: { title: 'Todo', category: 'todo' },
@ -216,7 +237,7 @@ module.exports = {
if (tab === 'attachment') {
return m(
Layout,
m(sectionsquickview.attachment, {
m(sections.attachment, {
list: util.sortList(Messages[tab]),
})
);

View File

@ -53,19 +53,19 @@ function renderMailUserTooltip() {
? ((details.mReputation.mFriendsPositiveVotes || 0) - (details.mReputation.mFriendsNegativeVotes || 0))
: 0;
const top = hUser.rect.top - 10;
const left = Math.min(Math.max(hUser.rect.left, 140), window.innerWidth - 280);
const rect = hUser.rect;
const top = rect ? Math.max(10, Math.min(rect.bottom + 4, window.innerHeight - 185)) : 100;
const left = rect ? Math.min(Math.max(rect.left, 20), window.innerWidth - 300) : 100;
return m('.user-tooltip', {
style: {
position: 'fixed',
top: `${top}px`,
left: `${left}px`,
transform: 'translateY(-100%)',
zIndex: 10000,
}
}, [
m('.tooltip-avatar', m(peopleUtil.UserAvatar, { avatar, firstLetter, identityId: hUser.gxsId, size: 64 })),
m('.tooltip-avatar', m(peopleUtil.UserAvatar, { avatar, firstLetter, identityId: hUser.gxsId, size: 64, isSquare: true })),
m('.tooltip-details', [
m('.tooltip-row', [m('span.tooltip-label', 'Identity name: '), m('span.tooltip-value', hUser.name)]),
m('.tooltip-row', [m('span.tooltip-label', 'Identity Id: '), m('span.tooltip-value.tooltip-id', hUser.gxsId)]),
@ -77,7 +77,7 @@ function renderMailUserTooltip() {
m('span.tooltip-label', 'Votes: '),
m('span.tooltip-value', {
style: {
color: votes >= 0 ? '#22c55e' : '#ef4444',
color: votes >= 0 ? '#008000' : '#cc0000',
fontWeight: 'bold'
}
}, (votes >= 0 ? '+' : '') + votes)
@ -113,6 +113,22 @@ function loadTagTypes() {
}
loadTagTypes();
function formatMailDate(ts) {
if (!ts) return '';
const date = new Date(ts * 1000);
const now = new Date();
const isToday = date.toDateString() === now.toDateString();
if (isToday) {
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
}
const isThisYear = date.getFullYear() === now.getFullYear();
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
if (isThisYear) {
return `${date.getDate()} ${months[date.getMonth()]}`;
}
return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear().toString().slice(2)}`;
}
// Utility functions
const humanReadableSize = (fileSize) => {
return fileSize / 1024 > 1024
@ -179,7 +195,7 @@ const MessageSummary = () => {
},
[
m(
'td',
'td.cell-star',
m(`input.star-check[type=checkbox][id=msg-${v.attrs.details.msgId}]`, { checked: isStarred }),
// Use label with [for] to manipulate hidden checkbox
m(
@ -191,8 +207,8 @@ const MessageSummary = () => {
m('i.fas.fa-star')
)
),
files && m('td', files.length),
m('td', { style: 'border-bottom: inherit;' }, [
m('td.cell-attachment', files && files.length > 0 ? m('i.fas.fa-paperclip', { title: `${files.length} attachment(s)` }) : null),
m('td.cell-subject', [
m('div', {
style: {
display: 'flex',
@ -213,7 +229,7 @@ const MessageSummary = () => {
])
]),
m(
'td',
'td.cell-from',
m(
'div',
{
@ -257,7 +273,7 @@ const MessageSummary = () => {
]
)
),
m('td', new Date(details.ts * 1000).toLocaleString()),
m('td.cell-date', { title: new Date(details.ts * 1000).toLocaleString() }, formatMailDate(details.ts)),
]
),
};
@ -265,7 +281,8 @@ const MessageSummary = () => {
const AttachmentSection = () => {
function handleAttachmentDownload(item) {
const { fname: fileName, hash, size: xstr64 } = item;
const { fname: fileName, hash, size } = item;
const xstr64 = typeof size === 'object' ? size.xstr64 : String(size);
const flags = util.RS_FILE_REQ_ANONYMOUS_ROUTING;
rs.rsJsonApiRequest(
'/rsFiles/FileRequest',
@ -279,26 +296,22 @@ const AttachmentSection = () => {
}
return {
view: (v) =>
m('table.attachment-container', [
m('tr.attachment-header', [
m('th', 'File Name'),
m('th', 'From'),
m('th', 'Size'),
m('th', 'Date'),
m('th', 'Download'),
]),
m(
'tbody',
v.attrs.files.map((file) =>
m('tr.attachment', [
m('td.attachment__name', [m('i.fas.fa-file'), m('span', file.fname)]),
m('td.attachment__from', rs.userList.userMap[file.from._addr_string] || '[Unknown]'),
m('td.attachment__size', humanReadableSize(file.size.xint64)),
m('td.attachment__date', new Date(file.ts * 1000).toLocaleString()),
m('td', m('button', { onclick: () => handleAttachmentDownload(file) }, 'Download')),
])
)
),
m('.attachments-wrapper', [
v.attrs.files.map((file) => {
const fileSizeNum = file.size ? (typeof file.size === 'object' ? file.size.xint64 || parseInt(file.size.xstr64) || 0 : Number(file.size) || 0) : 0;
return m('.attachment-card', [
m('.attachment-icon', m('i.fas.fa-paperclip')),
m('.attachment-info', [
m('.attachment-name', file.fname),
m('.attachment-size', humanReadableSize(fileSizeNum)),
]),
m(
'button.btn-attachment-download',
{ onclick: () => handleAttachmentDownload(file) },
[m('i.fas.fa-download'), m('span.btn-text', ' Download')]
),
]);
}),
]),
};
};
@ -405,10 +418,10 @@ const MessageView = () => {
m('i.fas.fa-arrow-left')
),
m('.msg-view-nav__action', [
m('button', { onclick: () => { composeType = 'reply'; setShowCompose(true); } }, 'Reply'),
m('button', { onclick: () => { composeType = 'replyAll'; setShowCompose(true); } }, 'Reply All'),
m('button', { onclick: () => { composeType = 'forward'; setShowCompose(true); } }, 'Forward'),
m('button', { onclick: confirmMailDelete }, 'Delete'),
m('button', { onclick: () => { composeType = 'reply'; setShowCompose(true); } }, [m('i.fas.fa-reply'), m('span.btn-text', ' Reply')]),
m('button', { onclick: () => { composeType = 'replyAll'; setShowCompose(true); } }, [m('i.fas.fa-reply-all'), m('span.btn-text', ' Reply All')]),
m('button', { onclick: () => { composeType = 'forward'; setShowCompose(true); } }, [m('i.fas.fa-forward'), m('span.btn-text', ' Forward')]),
m('button.red', { onclick: confirmMailDelete }, [m('i.fas.fa-trash'), m('span.btn-text', ' Delete')]),
]),
]),
m('.msg-view__header', [
@ -741,7 +754,6 @@ const Sidebar = () => {
'.sidebar',
tabs.map((panelName, index) => {
const displayName = panelName.charAt(0).toUpperCase() + panelName.slice(1);
const labelText = size[panelName] > 0 ? `${displayName} (${size[panelName]})` : displayName;
return m(
m.route.Link,
{
@ -755,7 +767,8 @@ const Sidebar = () => {
},
[
sidebarIcons[panelName] || null,
labelText,
m('span.sidebar-link-text', displayName),
size[panelName] > 0 && m('span.sidebar-badge', size[panelName]),
]
);
})
@ -772,7 +785,6 @@ const SidebarQuickView = () => {
m('h6.bold', 'Quick View'),
tabs.map((panelName, index) => {
const displayName = panelName.charAt(0).toUpperCase() + panelName.slice(1);
const labelText = size[panelName] > 0 ? `${displayName} (${size[panelName]})` : displayName;
return m(
m.route.Link,
{
@ -787,7 +799,8 @@ const SidebarQuickView = () => {
},
[
sidebarIcons[panelName] || null,
labelText,
m('span.sidebar-link-text', displayName),
size[panelName] > 0 && m('span.sidebar-badge', size[panelName]),
]
);
})

View File

@ -32,7 +32,12 @@ const UserAvatar = () => ({
style: {
width: sizeStr,
height: sizeStr,
borderRadius: isSquare ? '0' : '',
minWidth: sizeStr,
minHeight: sizeStr,
flexShrink: '0',
aspectRatio: '1',
objectFit: 'cover',
borderRadius: isSquare ? '0' : '50%',
}
});
}
@ -41,9 +46,15 @@ const UserAvatar = () => ({
const svgString = jdenticon.toSvg(identityId, pxSize);
return m('div.jdenticon-avatar', {
style: {
display: 'inline-block',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: sizeStr,
height: sizeStr,
minWidth: sizeStr,
minHeight: sizeStr,
flexShrink: '0',
aspectRatio: '1',
borderRadius: isSquare ? '0' : '50%',
overflow: 'hidden',
verticalAlign: 'middle',
@ -67,8 +78,15 @@ const UserAvatar = () => ({
'div.defaultAvatar',
{
style: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: sizeStr,
height: sizeStr,
minWidth: sizeStr,
minHeight: sizeStr,
flexShrink: '0',
aspectRatio: '1',
borderRadius: isSquare ? '0' : '50%',
backgroundColor: backgroundColor,
}

File diff suppressed because it is too large Load Diff

View File

@ -375,3 +375,353 @@ table.attachment-container {
}
}
}
/* Modern Attachment Card Styling */
.attachments-wrapper {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-top: 0.5rem;
}
.attachment-card {
background: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
padding: 0.75rem 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.02);
.attachment-icon {
width: 40px;
height: 40px;
border-radius: 0.5rem;
background: #eff6ff;
color: #3b82f6;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
flex-shrink: 0;
}
.attachment-info {
flex: 1;
min-width: 0;
.attachment-name {
font-weight: 600;
font-size: 0.9rem;
color: #1e293b;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.attachment-size {
font-size: 0.75rem;
color: #64748b;
}
}
.btn-attachment-download {
padding: 0.4rem 0.75rem;
font-size: 0.8rem;
height: 34px;
}
}
.mobile-fab-compose {
display: none;
}
/* Mobile Responsiveness for Mail UI */
@media (max-width: 768px) {
.side-bar {
width: 100% !important;
flex-direction: row !important;
overflow-x: auto !important;
overflow-y: hidden !important;
white-space: nowrap !important;
border-bottom: 1px solid #cbd5e1 !important;
padding: 0.5rem !important;
flex-shrink: 0 !important;
background: #ffffff !important;
}
.side-bar .mail-compose-btn {
display: none !important;
}
.side-bar .sidebar {
width: auto !important;
flex-direction: row !important;
gap: 0.25rem !important;
}
.side-bar .sidebar a {
padding: 0.5rem 0.75rem !important;
font-size: 0.85rem !important;
border-radius: 0.375rem !important;
border-left: none !important;
border-bottom: none !important;
display: inline-flex !important;
align-items: center !important;
gap: 0.35rem !important;
}
.side-bar .sidebar a .sidebar-link-text {
display: none !important;
}
.side-bar .sidebar a i {
margin-right: 0 !important;
font-size: 1.1rem !important;
}
.side-bar .sidebar a .sidebar-badge {
background: #3b82f6 !important;
color: #ffffff !important;
font-size: 0.7rem !important;
font-weight: 700 !important;
padding: 0.15rem 0.4rem !important;
border-radius: 999px !important;
line-height: 1 !important;
}
.side-bar .sidebar a.selected-sidebar-link {
background-color: #e0f2fe !important;
color: #0369a1 !important;
border-left: none !important;
font-weight: 600 !important;
}
.side-bar .sidebarquickview {
display: none !important; /* Hide quickview tags on mobile bar; filter via colored dropdown */
}
select.mail-tag {
padding: 0.45rem 0.75rem !important;
border-radius: 0.5rem !important;
border: 1px solid #cbd5e1 !important;
font-size: 0.85rem !important;
font-weight: 600 !important;
background-color: #ffffff !important;
color: #1e293b !important;
outline: none !important;
cursor: pointer !important;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05) !important;
}
.node-panel {
width: 100% !important;
flex: 1 !important;
padding: 0.5rem !important;
overflow: auto !important;
}
/* Mail List Table -> Mobile Card List View */
.table-pagination-container table.mails {
display: block !important;
width: 100% !important;
}
.table-pagination-container table.mails tr:first-child {
display: none !important;
}
.table-pagination-container table.mails tbody {
display: flex !important;
flex-direction: column !important;
gap: 0.5rem !important;
}
.table-pagination-container table.mails tr.msgbody {
display: flex !important;
flex-direction: column !important;
padding: 0.85rem !important;
background: #ffffff !important;
border: 1px solid #e2e8f0 !important;
border-radius: 0.65rem !important;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03) !important;
position: relative !important;
margin-bottom: 0.25rem !important;
transition: all 0.2s ease !important;
}
.table-pagination-container table.mails tr.msgbody.unread {
background: #f0f9ff !important;
border-color: #bae6fd !important;
border-left: 4px solid #0284c7 !important;
}
.table-pagination-container table.mails tr.msgbody td {
display: block !important;
padding: 0 !important;
border: none !important;
}
/* Top Row: Sender Info & Date */
.table-pagination-container table.mails tr.msgbody td.cell-from {
order: 1 !important;
margin-bottom: 0.35rem !important;
padding-right: 5rem !important;
}
.table-pagination-container table.mails tr.msgbody td.cell-from div {
display: flex !important;
align-items: center !important;
gap: 0.5rem !important;
width: 100% !important;
}
.table-pagination-container table.mails tr.msgbody td.cell-from div .jdenticon-avatar,
.table-pagination-container table.mails tr.msgbody td.cell-from div .defaultAvatar,
.table-pagination-container table.mails tr.msgbody td.cell-from div img.avatar {
flex-shrink: 0 !important;
width: 28px !important;
height: 28px !important;
min-width: 28px !important;
min-height: 28px !important;
aspect-ratio: 1 / 1 !important;
object-fit: cover !important;
border-radius: 50% !important;
}
.table-pagination-container table.mails tr.msgbody td.cell-from div span {
font-weight: 700 !important;
font-size: 0.95rem !important;
color: #1e293b !important;
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
.table-pagination-container table.mails tr.msgbody td.cell-date {
order: 2 !important;
position: absolute !important;
top: 0.85rem !important;
right: 0.85rem !important;
font-size: 0.75rem !important;
font-weight: 600 !important;
color: #64748b !important;
white-space: nowrap !important;
}
/* Subject Row */
.table-pagination-container table.mails tr.msgbody td.cell-subject {
order: 3 !important;
margin-bottom: 0.25rem !important;
font-size: 0.9rem !important;
color: #334155 !important;
}
.table-pagination-container table.mails tr.msgbody td.cell-subject span {
font-weight: 600 !important;
}
/* Star & Attachments */
.table-pagination-container table.mails tr.msgbody td.cell-star {
order: 4 !important;
position: absolute !important;
bottom: 0.75rem !important;
right: 0.85rem !important;
}
.table-pagination-container table.mails tr.msgbody td.cell-attachment {
order: 5 !important;
position: absolute !important;
bottom: 0.75rem !important;
right: 2.5rem !important;
color: #64748b !important;
}
/* Mail Reader (MessageView) Mobile Layout */
.msg-view {
padding: 0.5rem !important;
gap: 0.75rem !important;
}
.msg-view .msg-view-nav {
background: #ffffff !important;
padding: 0.5rem 0.75rem !important;
border-radius: 0.5rem !important;
border: 1px solid #e2e8f0 !important;
}
.msg-view .msg-view-nav__action button {
padding: 0.45rem 0.65rem !important;
min-width: 38px !important;
height: 38px !important;
justify-content: center !important;
}
.msg-view .msg-view-nav__action button .btn-text {
display: none !important;
}
.msg-view .msg-view-nav__action button i {
margin: 0 !important;
font-size: 1rem !important;
}
.msg-view__header {
background: #ffffff !important;
padding: 1rem !important;
border-radius: 0.5rem !important;
border: 1px solid #e2e8f0 !important;
}
.msg-view__header h3 {
font-size: 1.25rem !important;
font-weight: 800 !important;
color: #0f172a !important;
line-height: 1.3 !important;
}
.msg-view__body {
background: #ffffff !important;
padding: 1rem !important;
border-radius: 0.5rem !important;
border: 1px solid #e2e8f0 !important;
font-size: 0.95rem !important;
line-height: 1.6 !important;
color: #1e293b !important;
}
.msg-view__attachment {
height: auto !important;
}
/* Floating Action Button (Compose Mail) */
.mobile-fab-compose {
position: fixed !important;
bottom: 1.75rem !important;
right: 1.5rem !important;
width: 54px !important;
height: 54px !important;
border-radius: 50% !important;
background: linear-gradient(135deg, #3b82f6, #2563eb) !important;
color: #ffffff !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 1.35rem !important;
box-shadow: 0 4px 14px rgba(37, 99, 235, 0.45) !important;
border: none !important;
z-index: 1000 !important;
cursor: pointer !important;
transition: transform 0.2s ease !important;
}
.mobile-fab-compose:active {
transform: scale(0.92) !important;
}
.composePopupOverlay .composePopup {
width: 95% !important;
height: 95% !important;
}
}

View File

@ -42,6 +42,9 @@ if (Test-Path "$src\app\scss\pages\_network.scss") {
if (Test-Path "$src\app\scss\components\_statusbar.scss") {
$extraCss += (Get-Content "$src\app\scss\components\_statusbar.scss" -Raw -Encoding UTF8) + "`n`n"
}
if (Test-Path "$src\app\scss\pages\_mail.scss") {
$extraCss += (Get-Content "$src\app\scss\pages\_mail.scss" -Raw -Encoding UTF8) + "`n`n"
}
$combinedCss = $cssBase + "`n`n" + $extraCss
[System.IO.File]::WriteAllText("$dest\styles.css", $combinedCss, $utf8NoBom)

View File

@ -33,8 +33,15 @@ if [ "$2" = "" ]||[ "$2" = "index.html" ]; then
fi
if [ "$2" = "" ]||[ "$2" = "styles.css" ]; then
echo copying css file
cp $src/styles.css $publicdest/
echo copying and assembling css file
cat $src/styles.css > $publicdest/styles.css
echo "" >> $publicdest/styles.css
for scssfile in $src/app/scss/pages/_*.scss $src/app/scss/components/_*.scss; do
if [ -f "$scssfile" ]; then
cat "$scssfile" >> $publicdest/styles.css
echo -e "\n\n" >> $publicdest/styles.css
fi
done
fi
if [ "$2" = "" ]||[ "$2" = "app.js" ]; then