fix: remove iframe and use a div with contenteditable attribute instead, this commit contains a whole lot of changes

This commit is contained in:
zelfroster 2023-07-15 15:57:47 +05:30
parent 94ed218c61
commit eef7a4c515
11 changed files with 397 additions and 377 deletions

View File

@ -86,7 +86,7 @@ const Layout = () => {
: futil.proxyObj[currentItem.slice(1)].map((item) =>
m('tr', [
m('td.results__name', [m('i.fas.fa-file'), m('span', item.fName)]),
m('td.results__size', futil.makeFriendlyUnit(item.fSize.xstr64)),
m('td.results__size', futil.makeFriendlyUnit(item.fSize.xint64)),
m('td.results__hash', item.fHash),
m(
'td.results__download',

View File

@ -3,9 +3,8 @@ const rs = require('rswebui');
const widget = require('widgets');
const Layout = () => {
const data = {
const Data = {
subject: '',
mailBody: '',
identity: null,
recipients: {
to: {
@ -25,34 +24,82 @@ const Layout = () => {
},
},
};
// async function loadDetails(attrs) {}
return {
oninit: ({ attrs: { ownId, allUsers } }) => {
data.identity = ownId[0];
Object.keys(data.recipients).forEach((item) => {
data.recipients[item].inputList = allUsers;
oninit: async (v) => {
console.log('function loadDetails');
const { ownId, allUsers, msgType } = await v.attrs;
console.log(allUsers, ownId);
console.log('attrs: ', await v.attrs);
if (msgType === 'compose') {
Data.identity = ownId[0];
console.log(ownId);
console.log('id: ', Data.identity);
}
Object.keys(Data.recipients).forEach((item) => {
Data.recipients[item].inputList = allUsers;
});
console.log('Data before reply init: ', Data);
if (msgType === 'reply') {
const { sender, recipients, subject, replyMessage } = await v.attrs;
console.log('id: ', sender);
Data.identity = sender[0];
// console.log('id: ', Data.identity);
Data.recipients.to.sendList = recipients;
const tmb = document.querySelector('#composerMailBody');
tmb.innerHTML = `<br><br><p>-----Original Message-----</p>${replyMessage}`;
Data.subject = subject.substring(0, 4) === 'Re: ' ? subject : `Re: ${subject}`;
if (sender.length > 0) Data.identity = ownId.filter((id) => id === sender[0].mGroupId);
console.log('Data after reply init: ', Data);
}
},
view: ({ attrs: { ownId, allUsers } }) => {
// get recipientType from the function call to handle events for all recipient types
function handleInput(e, recipientType) {
data.recipients[recipientType].inputVal = e.target.value;
data.recipients[recipientType].inputList = allUsers.filter((item) =>
Data.recipients[recipientType].inputVal = e.target.value;
Data.recipients[recipientType].inputList = allUsers.filter((item) =>
item.mGroupName.toLowerCase().includes(e.target.value.toLowerCase())
);
m.redraw();
}
function handleClick(item, recipientType) {
data.recipients[recipientType].sendList.push(item);
// reset values
data.recipients[recipientType].inputVal = '';
data.recipients[recipientType].inputList = allUsers;
m.redraw();
Data.recipients[recipientType].sendList.push(item);
// reset current input values after a sender is selected
Data.recipients[recipientType].inputVal = '';
Data.recipients[recipientType].inputList = allUsers;
}
function removeSelectedItem(recipient, recipientType) {
data.recipients[recipientType].sendList = data.recipients[recipientType].sendList.filter(
Data.recipients[recipientType].sendList = Data.recipients[recipientType].sendList.filter(
(item) => item.mGroupId !== recipient.mGroupId
);
m.redraw();
}
function sendMail() {
const to = Data.recipients.to.sendList.map((toItem) => toItem.mGroupId);
const cc = Data.recipients.cc.sendList.map((ccItem) => ccItem.mGroupId);
const bcc = Data.recipients.bcc.sendList.map((bccItem) => bccItem.mGroupId);
console.log(to, cc, bcc);
const { identity: from, subject } = Data;
console.log(from, subject);
const tmb = document.querySelector('#composerMailBody');
console.log(tmb.innerHTML);
// rs.rsJsonApiRequest('/rsMsgs/sendMail', { from, subject, mailBody, to, cc, bcc }).then(
// (res) => {
// if (res.body.retval) {
// Object.keys(Data.recipients).forEach((recipientType) => {
// Data.recipients[recipientType].sendList = [];
// });
// Data.subject = '';
// Data.mailBody = '';
// m.redraw();
// }
// const success = res.body.retval < 1;
// widget.popupMessage(
// m('.widget', [
// m('.widget__heading', m('h3', success ? 'Success' : 'Error')),
// m('.widget__body', m('p', success ? 'Mail sent successfully' : res.body.errorMsg)),
// ])
// );
// }
// );
}
return m('.widget', [
m('.widget__heading', m('h3', 'Compose a mail')),
@ -62,8 +109,10 @@ const Layout = () => {
m(
'select[id=idtags]',
{
value: data.identity,
onchange: (e) => (data.identity = ownId[e.target.selectedIndex]),
value: Data.identity,
onchange: (e) => {
Data.identity = ownId[e.target.selectedIndex];
},
},
ownId &&
ownId.map((id) =>
@ -78,12 +127,39 @@ const Layout = () => {
),
]),
m('.compose-mail__recipients', [
Object.keys(data.recipients).map((recipientType) =>
m('.compose-mail__recipients__container', [
m('label.bold', 'To: '),
m('.recipients', [
Data.recipients.to.sendList.length > 0 &&
Data.recipients.to.sendList.map((recipient) =>
m('.recipients__selected', [
m('span', recipient.mGroupName),
m('i.fas.fa-times', {
onclick: () => removeSelectedItem(recipient, 'to'),
}),
])
),
m('.recipients__input', [
m('input[type=text].recipients__input-field', {
value: Data.recipients.to.inputVal,
oninput: (e) => handleInput(e, 'to'),
}),
m('ul.recipients__input-list[autocomplete=off]', [
Data.recipients.to.inputList.length > 0
? Data.recipients.to.inputList.map((item) =>
m('li', { onclick: () => handleClick(item, 'to') }, item.mGroupName)
)
: m('li', 'No Item'),
]),
]),
]),
]),
['cc', 'bcc'].map((recipientType) =>
m('.compose-mail__recipients__container', [
m('label.bold', `${recipientType}: `),
m('.recipients', [
data.recipients[recipientType].sendList.length > 0 &&
data.recipients[recipientType].sendList.map((recipient) =>
Data.recipients[recipientType].sendList.length > 0 &&
Data.recipients[recipientType].sendList.map((recipient) =>
m('.recipients__selected', [
m('span', recipient.mGroupName),
m('i.fas.fa-times', {
@ -93,12 +169,12 @@ const Layout = () => {
),
m('.recipients__input', [
m('input[type=text].recipients__input-field', {
value: data.recipients[recipientType].inputVal,
value: Data.recipients[recipientType].inputVal,
oninput: (e) => handleInput(e, recipientType),
}),
m('ul.recipients__input-list[autocomplete=off]', [
data.recipients[recipientType].inputList.length > 0
? data.recipients[recipientType].inputList.map((item) =>
Data.recipients[recipientType].inputList.length > 0
? Data.recipients[recipientType].inputList.map((item) =>
m(
'li',
{ onclick: () => handleClick(item, recipientType) },
@ -113,54 +189,21 @@ const Layout = () => {
),
]),
m('input.compose-mail__subject[type=text][placeholder=Subject]', {
value: data.subject,
oninput: (e) => (data.subject = e.target.value),
}),
m('textarea.compose-mail__message[placeholder=Message]', {
value: data.mailBody,
oninput: (e) => (data.mailBody = e.target.value),
value: Data.subject,
oninput: (e) => (Data.subject = e.target.value),
}),
m('.compose-mail__message', [
m('.compose-mail__message-body[placeholder=Message][contenteditable]#composerMailBody'),
]),
allUsers &&
m(
'button.compose-mail__send-btn',
{
onclick: () => {
const to = data.recipients.to.sendList.map((toItem) => toItem.mGroupId);
const cc = data.recipients.cc.sendList.map((ccItem) => ccItem.mGroupId);
const bcc = data.recipients.bcc.sendList.map((bccItem) => bccItem.mGroupId);
const { identity, subject, mailBody } = data;
rs.rsJsonApiRequest('/rsMsgs/sendMail', {
from: identity,
subject,
mailBody,
to,
cc,
bcc,
}).then((res) => {
if (res.body.retval) {
Object.keys(data.recipients).forEach((item) => {
data.recipients[item].sendList = [];
});
data.subject = '';
data.mailBody = '';
m.redraw();
}
res.body.retval < 1
? widget.popupMessage([m('h3', 'Error'), m('hr'), m('p', res.body.errorMsg)])
: widget.popupMessage([
m('h3', 'Success'),
m('hr'),
m('p', 'Mail Sent successfully'),
]);
});
},
},
[m('span', 'Send Mail'), m('i.fas.fa-paper-plane')]
),
m('button.compose-mail__send-btn', { onclick: sendMail }, [
m('span', 'Send Mail'),
m('i.fas.fa-paper-plane'),
]),
]),
]);
},
};
};
module.exports = Layout();
module.exports = Layout;

View File

@ -5,8 +5,8 @@ const peopleUtil = require('people/people_util');
const compose = require('mail/mail_compose');
const composeData = {
allUsers: undefined,
ownId: undefined,
allUsers: [],
ownId: [],
};
const Messages = {
@ -92,7 +92,6 @@ const Layout = () => {
composeData.ownId.splice(i, 1); // workaround for id '0'
}
}
// identity = ownId[0];
});
composeData.allUsers = await peopleUtil.sortUsers(rs.userList.users);
},
@ -104,7 +103,7 @@ const Layout = () => {
sent: Messages.sent.length,
trash: Messages.trash.length,
};
const sectionsquickviewSize = {
const sectionsQuickviewSize = {
starred: Messages.starred.length,
system: Messages.system.length,
spam: Messages.spam.length,
@ -118,13 +117,7 @@ const Layout = () => {
return [
m('.side-bar', [
m(
'button.mail-compose-btn',
{
onclick: () => (showCompose = true),
},
'Compose'
),
m('button.mail-compose-btn', { onclick: () => (showCompose = true) }, 'Compose'),
m(util.Sidebar, {
tabs: Object.keys(sections),
size: sectionsSize,
@ -132,36 +125,31 @@ const Layout = () => {
}),
m(util.SidebarQuickView, {
tabs: Object.keys(sectionsquickview),
size: sectionsquickviewSize,
size: sectionsQuickviewSize,
baseRoute: '/mail/',
}),
]),
m(
'.node-panel',
m('.widget', [
m('.top-heading', [
m(
'select.mail-tag',
{
value: tagselect.showval,
onchange: (e) => {
tagselect.showval = tagselect.opts[e.target.selectedIndex];
m.route.get().split('/').length < 4 &&
m('.top-heading', [
m(
'select.mail-tag',
{
value: tagselect.showval,
onchange: (e) => (tagselect.showval = tagselect.opts[e.target.selectedIndex]),
},
},
[tagselect.opts.map((o) => m('option', { value: o }, o.toLocaleString()))]
),
m(util.SearchBar, {
list: {},
}),
]),
[tagselect.opts.map((opt) => m('option', { value: opt }, opt.toLocaleString()))]
),
m(util.SearchBar, { list: {} }),
]),
vnode.children,
])
),
m(
'.composePopupOverlay',
{
style: { display: showCompose ? 'block' : 'none' },
},
{ style: { display: showCompose ? 'block' : 'none' } },
m(
'.composePopup',
composeData.allUsers &&
@ -169,14 +157,9 @@ const Layout = () => {
m(compose, {
allUsers: composeData.allUsers,
ownId: composeData.ownId,
msgType: 'compose',
}),
m(
'button.red.close-btn',
{
onclick: () => (showCompose = false),
},
m('i.fas.fa-times')
)
m('button.red.close-btn', { onclick: () => (showCompose = false) }, m('i.fas.fa-times'))
)
),
];
@ -186,23 +169,11 @@ const Layout = () => {
module.exports = {
composeData,
view: (v) => {
const tab = v.attrs.tab;
view: ({ attrs, attrs: { tab, msgId } }) => {
// TODO: utilize multiple routing params
if (Object.prototype.hasOwnProperty.call(v.attrs, 'msgId')) {
return m(
Layout,
m(util.MessageView, {
id: v.attrs.msgId,
})
);
if (Object.prototype.hasOwnProperty.call(attrs, 'msgId')) {
return m(Layout, m(util.MessageView, { msgId }));
}
return m(
Layout,
m(sections[tab] || sectionsquickview[tab], {
list: Messages[tab].reverse(),
})
);
return m(Layout, m(sections[tab] || sectionsquickview[tab], { list: Messages[tab].reverse() }));
},
};

View File

@ -3,6 +3,8 @@ const rs = require('rswebui');
const util = require('files/files_util');
const widget = require('widgets');
const peopleUtil = require('people/people_util');
const compose = require('mail/mail_compose');
const composeData = require('mail/mail_resolver');
// rsmsgs.h
const RS_MSG_BOXMASK = 0x000f;
@ -49,35 +51,36 @@ const MessageSummary = () => {
let isStarred = false;
let msgStatus = '';
let fromUserInfo;
function starMessage(e) {
isStarred = !isStarred;
rs.rsJsonApiRequest('/rsMsgs/MessageStar', { msgId: details.msgId, mark: isStarred });
// Stop event bubbling, both functions for supporting IE & FF
e.stopImmediatePropagation();
e.preventDefault();
}
return {
oninit: async (v) => {
const res = await rs.rsJsonApiRequest('/rsMsgs/getMessage', {
oninit: (v) => {
rs.rsJsonApiRequest('/rsMsgs/getMessage', {
msgId: v.attrs.details.msgId,
});
if (res.body.retval) {
details = res.body.msg;
files = details.files;
isStarred = (details.msgflags & 0xf00) === RS_MSG_STAR;
const flag = details.msgflags & 0xf0;
if (flag === RS_MSG_NEW || flag === RS_MSG_UNREAD_BY_USER) {
msgStatus = 'unread';
} else {
msgStatus = 'read';
}
}
if (details && details.from && details.from._addr_string) {
rs.rsJsonApiRequest(
'/rsIdentity/getIdDetails',
{
id: details.from._addr_string,
},
(data) => {
fromUserInfo = data.details;
})
.then((res) => {
if (res.body.retval) {
details = res.body.msg;
files = details.files;
isStarred = (details.msgflags & 0xf00) === RS_MSG_STAR;
const flag = details.msgflags & 0xf0;
msgStatus = flag === RS_MSG_NEW || flag === RS_MSG_UNREAD_BY_USER ? 'unread' : 'read';
}
);
}
})
.then(() => {
if (details?.from?._addr_string) {
rs.rsJsonApiRequest(
'/rsIdentity/getIdDetails',
{ id: details.from._addr_string },
(data) => (fromUserInfo = data.details)
);
}
});
},
view: (v) =>
m(
@ -86,31 +89,17 @@ const MessageSummary = () => {
key: details.msgId,
class: msgStatus,
onclick: () =>
m.route.set('/mail/:tab/:msgId', {
tab: v.attrs.category,
msgId: details.msgId,
}),
m.route.set('/mail/:tab/:msgId', { tab: v.attrs.category, msgId: details.msgId }),
},
[
m(
'td',
m('input.star-check[type=checkbox][id=msg-' + details.msgId + ']', {
checked: isStarred,
}),
m(`input.star-check[type=checkbox][id=msg-${details.msgId}]`, { checked: isStarred }),
// Use label with [for] to manipulate hidden checkbox
m(
'label.star-check[for=msg-' + details.msgId + ']',
`label.star-check[for=msg-${details.msgId}]`,
{
onclick: (e) => {
isStarred = !isStarred;
rs.rsJsonApiRequest('/rsMsgs/MessageStar', {
msgId: details.msgId,
mark: isStarred,
});
// Stop event bubbling, both functions for supporting IE & FF
e.stopImmediatePropagation();
e.preventDefault();
},
onclick: starMessage,
class: (details.msgflags & 0xf00) === RS_MSG_STAR ? 'starred' : 'unstarred',
},
m('i.fas.fa-star')
@ -129,6 +118,19 @@ const MessageSummary = () => {
};
const AttachmentSection = () => {
function handleAttachmentDownload(item) {
const { fname: fileName, hash, size: xstr64 } = item;
const flags = util.RS_FILE_REQ_ANONYMOUS_ROUTING;
rs.rsJsonApiRequest(
'/rsFiles/FileRequest',
{ fileName, hash, flags, size: { xstr64 } },
(status) =>
widget.popupMessage([
m('i.fas.fa-file-medical'),
m('h3', `File is ${status.retval ? 'being' : 'already'} downloaded!`),
])
).catch((error) => console.log('error: ', error));
}
return {
view: (v) =>
m('table.attachment-container', [
@ -141,54 +143,13 @@ const AttachmentSection = () => {
]),
m(
'tbody',
v.attrs.files.map((item) =>
v.attrs.files.map((file) =>
m('tr.attachment', [
m('td.attachment__name', [m('i.fas.fa-file'), m('span', item.fname)]),
m(
'td.attachment__from',
rs.userList.userMap[item.from._addr_string]
? rs.userList.userMap[item.from._addr_string]
: '[Unknown]'
),
m('td.attachment__size', humanReadableSize(item.size.xint64)),
m('td.attachment__date', new Date(item.ts * 1000).toLocaleString()),
m(
'td',
m(
'button',
{
onclick: () => {
try {
rs.rsJsonApiRequest(
'/rsFiles/FileRequest',
{
fileName: item.fname,
hash: item.hash,
flags: util.RS_FILE_REQ_ANONYMOUS_ROUTING,
size: {
xstr64: item.size.xstr64,
},
},
(status) => {
status.retval
? widget.popupMessage([
m('i.fas.fa-file-medical'),
m('h3', 'File is being downloaded!'),
])
: widget.popupMessage([
m('i.fas.fa-file-medical'),
m('h3', 'File is already downloaded!'),
]);
}
);
} catch (error) {
console.log('error: ', error);
}
},
},
'Download'
)
),
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')),
])
)
),
@ -197,134 +158,144 @@ const AttachmentSection = () => {
};
const MessageView = () => {
let details = {};
let message = '';
const files = [];
const toList = {};
const ccList = {};
const bccList = {};
let showReplyCompose = false;
const replyData = {
sender: [],
recipients: [],
};
const MailData = {
msgId: '',
sender: {},
message: '',
subject: '',
destinations: [],
toList: {},
ccList: {},
bccList: {},
files: [],
};
function handleMailDelete() {
widget.popupMessage([
m('p', 'Are you sure you want to delete this mail?'),
m(
'button',
{
onclick: () => {
rs.rsJsonApiRequest('/rsMsgs/MessageToTrash', { msgId: MailData.msgId, bTrash: true });
rs.rsJsonApiRequest('/rsMsgs/MessageDelete', { msgId: MailData.msgId }).then((res) => {
widget.popupMessage(
m('.widget', [
m('.widget__heading', m('h3', res.body.retval ? 'Success' : 'Error')),
m(
'.widget__body',
m('p', res.body.retval ? 'Mail Deleted.' : 'Error in Deleting.')
),
])
);
m.route.set('/mail/:tab', { tab: m.route.param().tab });
});
},
},
'Delete'
),
]);
}
return {
oninit: async (v) => {
const res = await rs.rsJsonApiRequest('/rsMsgs/getMessage', {
msgId: v.attrs.id,
});
if (res.body.retval) {
details = res.body.msg;
res.body.msg.files.forEach((element) => {
files.push({ ...element, from: res.body.msg.from, ts: res.body.msg.ts });
});
// regex to detect html tags
// better regex? /<[a-z][\s\S]*>/gi
message = /<\/*[a-z][^>]+?>/gi.test(details.msg)
? details.msg
: `<p style="white-space: pre">${details.msg}</p>`;
}
details?.destinations?.map((destDetail) => {
if (destDetail._mode === MSG_ADDRESS_MODE_TO && !toList[destDetail._addr_string]) {
toList[destDetail._addr_string] = destDetail;
} else if (destDetail._mode === MSG_ADDRESS_MODE_CC && !ccList[destDetail._addr_string]) {
ccList[destDetail._addr_string] = destDetail;
} else if (destDetail._mode === MSG_ADDRESS_MODE_BCC && !bccList[destDetail._addr_string]) {
bccList[destDetail._addr_string] = destDetail;
oninit: (v) => {
rs.rsJsonApiRequest('/rsMsgs/getMessage', {
msgId: v.attrs.msgId,
}).then(async (res) => {
if (res.body.retval) {
const msgDetails = res.body.msg;
msgDetails.files.forEach((element) =>
MailData.files.push({ ...element, from: msgDetails.from, ts: msgDetails.ts })
);
// regex to detect html tags, better regex? /<[a-z][\s\S]*>/gi
MailData.message = /<\/*[a-z][^>]+?>/gi.test(msgDetails.msg)
? msgDetails.msg
: `<p style="white-space: pre">${msgDetails.msg}</p>`;
document.querySelector('#msgView').innerHTML = MailData.message;
MailData.sender = msgDetails.from;
console.log('mail sender id: ', MailData.sender._addr_string);
MailData.subject = msgDetails.title;
MailData.destinations = msgDetails.destinations;
}
MailData?.destinations?.map((destDetail) => {
const { _addr_string: addrString, _mode: mode } = destDetail; // destructuring + renaming
if (mode === MSG_ADDRESS_MODE_TO && !MailData.toList[addrString]) {
MailData.toList[addrString] = destDetail;
} else if (mode === MSG_ADDRESS_MODE_CC && !MailData.ccList[addrString]) {
MailData.ccList[addrString] = destDetail;
} else if (mode === MSG_ADDRESS_MODE_BCC && !MailData.bccList[addrString]) {
MailData.bccList[addrString] = destDetail;
}
});
console.log('tolist: ', MailData.toList);
peopleUtil.ownIds(async (data) => {
composeData.ownId = await data;
replyData.recipients = composeData.ownId.filter((id) =>
Object.prototype.hasOwnProperty.call(MailData.toList, id)
);
console.log('recipient: ', replyData.recipients, 'ownIds: ', composeData.ownId);
for (let i = 0; i < composeData.ownId.length; i++) {
if (Number(composeData.ownId[i]) === 0) {
composeData.ownId.splice(i, 1); // workaround for id '0'
}
}
});
composeData.allUsers = peopleUtil.sortUsers(rs.userList.users);
replyData.sender = composeData.allUsers.filter(
(user) => user.mGroupId === MailData.sender._addr_string
);
await rs.rsJsonApiRequest(
'/rsIdentity/getIdDetails',
{ id: MailData?.sender?._addr_string },
(data) => (MailData.avatar = data?.details?.mAvatar)
);
});
await rs.rsJsonApiRequest(
'/rsIdentity/getIdDetails',
{
id: details.from._addr_string,
},
(data) => (details = { ...details, avatar: data.details.mAvatar })
);
},
view: () =>
m(
'.msg-view',
{
key: details.msgId,
},
[
m('.msg-view-nav', [
m(
'a[title=Back]',
{
onclick: () =>
m.route.set('/mail/:tab', {
tab: m.route.param().tab,
}),
},
{ onclick: () => m.route.set('/mail/:tab', { tab: m.route.param().tab }) },
m('i.fas.fa-arrow-left')
),
m('.msg-view-nav__action', [
m('button', 'Reply'),
m('button', { onclick: () => (showReplyCompose = true) }, 'Reply'),
m('button', 'Reply All'),
m('button', 'Forward'),
m(
'button',
{
onclick: () =>
widget.popupMessage([
m('p', 'Are you sure you want to delete this mail?'),
m(
'button',
{
onclick: async () => {
rs.rsJsonApiRequest('/rsMsgs/MessageToTrash', {
msgId: details.msgId,
bTrash: true,
});
const res = await rs.rsJsonApiRequest('/rsMsgs/MessageDelete', {
msgId: details.msgId,
});
res.body.retval
? widget.popupMessage([
m('h3', 'Success'),
m('hr'),
m('p', 'Mail Deleted.'),
])
: widget.popupMessage([
m('h3', 'Error'),
m('hr'),
m('p', res.body.errorMessage),
]);
m.redraw();
m.route.set('/mail/:tab', {
tab: m.route.param().tab,
});
},
},
'Delete'
),
]),
},
'Delete'
),
m('button', { onclick: handleMailDelete }, 'Delete'),
]),
]),
m('.msg-view__header', [
m('h3', details.title),
m('h3', MailData.subject),
m('.msg-details', [
details.from &&
MailData.sender &&
m(peopleUtil.UserAvatar, {
avatar: details.avatar,
firstLetter: rs.userList.userMap[details.from._addr_string]
? rs.userList.userMap[details.from._addr_string].slice(0, 1).toUpperCase()
avatar: MailData.avatar,
firstLetter: rs.userList.userMap[MailData.sender._addr_string]
? rs.userList.userMap[MailData.sender._addr_string].slice(0, 1).toUpperCase()
: '',
}),
m('.msg-details__info', [
details.from &&
MailData.sender &&
m('.msg-details__info-item', [
m('b', 'From: '),
rs.userList.userMap[details.from._addr_string] || 'Unknown',
rs.userList.userMap[MailData.sender._addr_string] || 'Unknown',
]),
toList &&
Object.keys(toList).length > 0 &&
MailData.toList &&
Object.keys(MailData.toList).length > 0 &&
// TODO: optimize javascript for show-more and show-less working
m('.msg-details__info-item', [
m('b', 'To: '),
m(
'#truncate',
Object.keys(toList).map((key, index) =>
Object.keys(MailData.toList).map((key, index) =>
m('span', `${rs.userList.userMap[key]}, `)
)
),
@ -332,7 +303,7 @@ const MessageView = () => {
'button[id=show-more]',
{
style: {
display: Object.keys(toList).length > 10 ? 'block' : 'none',
display: Object.keys(MailData.toList).length > 10 ? 'block' : 'none',
},
onclick: () => {
document.querySelector('#show-more').style.display = 'none';
@ -356,45 +327,55 @@ const MessageView = () => {
'less'
),
]),
ccList &&
Object.keys(ccList).length > 0 &&
MailData.ccList &&
Object.keys(MailData.ccList).length > 0 &&
m('.msg-details__info-item', [
m('b', 'CC: '),
Object.keys(ccList).map((key, index) =>
m('b', 'Cc: '),
Object.keys(MailData.ccList).map((key, index) =>
m('p', `${rs.userList.userMap[key]}, `)
),
]),
bccList &&
Object.keys(bccList).length > 0 &&
MailData.bccList &&
Object.keys(MailData.bccList).length > 0 &&
m('.msg-details__info-item', [
m('b', 'BCC: '),
Object.keys(bccList).map((key, index) =>
m('b', 'Bcc: '),
Object.keys(MailData.bccList).map((key, index) =>
m('p', `${rs.userList.userMap[key]}, `)
),
]),
]),
]),
]),
m(
'.msg-view__body',
m(
'iframe[title=message]',
{
srcdoc: message,
},
message
)
),
files.length > 0 &&
m('.msg-view__body', m('#msgView')),
MailData.files.length > 0 &&
m('.msg-view__attachment', [
m('h3', 'Attachments'),
m('.msg-view__attachment-items', [
m(AttachmentSection, {
files,
}),
]),
m('.msg-view__attachment-items', m(AttachmentSection, { files: MailData.files })),
]),
]
],
m(
'.composePopupOverlay',
{ style: { display: showReplyCompose ? 'block' : 'none' } },
m(
'.composePopup',
composeData.allUsers &&
composeData.ownId &&
m(compose, {
allUsers: composeData.allUsers,
ownId: composeData.ownId,
msgType: 'reply',
sender: replyData.recipients,
recipients: replyData.sender,
subject: MailData.subject,
replyMessage: MailData.message,
}),
m(
'button.red.close-btn',
{ onclick: () => (showReplyCompose = false) },
m('i.fas.fa-times')
)
)
)
),
};
};
@ -418,17 +399,13 @@ const Table = () => {
const SearchBar = () => {
let searchString = '';
return {
view: (v) =>
view: ({ attrs: { list } }) =>
m('input[type=text][placeholder=Search Subject].searchbar', {
value: searchString,
oninput: (e) => {
searchString = e.target.value.toLowerCase();
for (const hash in v.attrs.list) {
if (v.attrs.list[hash].fname.toLowerCase().indexOf(searchString) > -1) {
v.attrs.list[hash].isSearched = true;
} else {
v.attrs.list[hash].isSearched = false;
}
for (const hash in list) {
list[hash].isSearched = list[hash].fname.toLowerCase().indexOf(searchString) > -1;
}
},
}),
@ -442,10 +419,10 @@ const activeSideLink = {
const Sidebar = () => {
return {
view: (v) =>
view: ({ attrs: { tabs, baseRoute, size } }) =>
m(
'.sidebar',
v.attrs.tabs.map((panelName, index) =>
tabs.map((panelName, index) =>
m(
m.route.Link,
{
@ -454,11 +431,9 @@ const Sidebar = () => {
activeSideLink.sideactive = index;
activeSideLink.quicksideactive = -1;
},
href: v.attrs.baseRoute + panelName,
href: baseRoute + panelName,
},
v.attrs.size[panelName] > 0
? panelName + ' (' + v.attrs.size[panelName] + ')'
: panelName
size[panelName] > 0 ? `${panelName} (${size[panelName]})` : panelName
)
)
),
@ -468,11 +443,11 @@ const Sidebar = () => {
const SidebarQuickView = () => {
// for the Mail tab, to be moved later.
return {
view: (v) =>
view: ({ attrs: { tabs, baseRoute, size } }) =>
m(
'.sidebarquickview',
m('h6.bold', 'Quick View'),
v.attrs.tabs.map((panelName, index) =>
tabs.map((panelName, index) =>
m(
m.route.Link,
{
@ -482,11 +457,9 @@ const SidebarQuickView = () => {
activeSideLink.quicksideactive = index;
activeSideLink.sideactive = -1;
},
href: v.attrs.baseRoute + panelName,
href: baseRoute + panelName,
},
v.attrs.size[panelName] > 0
? panelName + ' (' + v.attrs.size[panelName] + ')'
: panelName
size[panelName] > 0 ? `${panelName} (${size[panelName]})` : panelName
)
)
),

View File

@ -26,7 +26,7 @@ const navIcon = {
};
const navbar = () => {
let isCollapsed = false;
let isCollapsed = true;
return {
view: (vnode) =>
m(

View File

@ -8,17 +8,20 @@ function checksudo(id) {
const UserAvatar = () => ({
view: (v) => {
const imageURI = v.attrs.avatar;
console.log(imageURI);
return imageURI === undefined || imageURI.mData.base64 === ''
? m('div.defaultAvatar', {
// image isn't getting loaded
// ? m('img.defaultAvatar', {
// src: '../data/user.png'
// })
}, m('p', v.attrs.firstLetter))
? m(
'div.defaultAvatar',
{
// image isn't getting loaded
// ? m('img.defaultAvatar', {
// src: '../data/user.png'
// })
},
m('p', v.attrs.firstLetter)
)
: m('img.avatar', {
src: 'data:image/png;base64,' + imageURI.mData.base64,
});
src: 'data:image/png;base64,' + imageURI.mData.base64,
});
},
});
@ -60,13 +63,13 @@ function sortIds(list) {
return list;
}
async function ownIds(consumer = (list) => { }, onlySigned = false) {
async function ownIds(consumer = (list) => {}, onlySigned = false) {
await rs.rsJsonApiRequest('/rsIdentity/getOwnSignedIds', {}, (owns) => {
if (onlySigned) {
consumer(sortIds(owns.ids));
} else {
rs.rsJsonApiRequest('/rsIdentity/getOwnPseudonimousIds', {}, (pseudo) =>
consumer(sortIds(pseudo.ids.concat(owns.ids)))
consumer(sortIds(pseudo?.ids.concat(owns.ids)))
);
}
});
@ -119,7 +122,10 @@ const regularcontactInfo = () => {
[
m('h4', details.mNickname),
details.mNickname &&
m(UserAvatar, { avatar: details.mAvatar, firstLetter: details.mNickname.slice(0, 1).toUpperCase() }),
m(UserAvatar, {
avatar: details.mAvatar,
firstLetter: details.mNickname.slice(0, 1).toUpperCase(),
}),
m('.details', [
m('p', 'ID:'),
m('p', details.mId),

View File

@ -58,6 +58,16 @@ input {
a {
cursor: pointer;
&[title='Back'] {
width: max-content;
height: max-content;
padding: 0.475rem 0.75rem;
border-radius: 50%;
transition: 100ms;
&:hover {
background: $light-color;
}
}
}
table {

View File

@ -42,7 +42,7 @@ html:focus-within {
body {
text-rendering: optimizeSpeed;
line-height: 1.5;
font-family: Arial, Helvetica, sans-serif;
font-family: Arial, Helvetica, sans-serif !important;
}
/* A elements that don't have a class get default styles */

View File

@ -13,7 +13,7 @@
position: absolute;
color: #555;
width: 40%;
min-height: 250px;
min-height: 10rem;
height: max-content;
padding: 1.5rem;
inset: 0;
@ -21,8 +21,17 @@
background-color: white;
border-radius: 1rem;
animation: fadein 0.5s;
display: flex;
flex-direction: column;
& button:last-child {
margin-top: auto;
}
& .close-btn {
position: absolute;
right: 1.5rem;
}
// Remove default widget padding
& .widget {
padding: 0;
}
}

View File

@ -80,7 +80,7 @@
}
& li {
list-style: none;
padding: 0.5rem;
padding: 0.25rem 0.5rem;
cursor: pointer;
background: white;
border: 1px solid $light-color;
@ -109,10 +109,22 @@
}
&__message {
padding: 0.5rem 0;
border: none;
height: 100%;
border-radius: 0;
resize: none;
display: flex;
flex-direction: column;
&-body {
padding: 0;
border: none;
border-radius: 0;
resize: none;
height: 100%;
outline: transparent;
}
& .replybox {
border: none;
padding: 0;
height: max-content;
}
}
&__send-btn {
display: flex;
@ -165,11 +177,7 @@
&__body {
height: 100%;
overflow: auto;
iframe {
width: 100%;
height: 98%;
border: none;
}
font-size: 14px !important;
}
&__attachment {
height: 50%;
@ -386,7 +394,7 @@ table.attachment-container {
inset: 0;
margin: auto;
width: 80%;
height: 80%;
height: 90%;
& > .widget {
padding: 2rem;
}

File diff suppressed because one or more lines are too long