feat: show sender avatar in mail view and user avatar in people section

This commit is contained in:
zelfroster 2023-03-25 18:58:05 +05:30
parent e2603ea2b6
commit fd6e96cdd4
8 changed files with 175 additions and 114 deletions

BIN
data/user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

6
data/user.svg Normal file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-user-circle" width="48" height="48" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<circle cx="12" cy="12" r="9" />
<circle cx="12" cy="10" r="3" />
<path d="M6.168 18.849a4 4 0 0 1 3.832 -2.849h4a4 4 0 0 1 3.834 2.855" />
</svg>

After

Width:  |  Height:  |  Size: 435 B

View File

@ -67,7 +67,7 @@ input.star-check:checked + label.star-check {
}
.truncate {
display: flex;
width: 70vw;
width: 65vw;
height: 1rem;
flex-wrap: wrap;
gap: 4px;
@ -115,3 +115,12 @@ iframe.msg {
margin-left: 200px;
animation: fadein 0.5s;
}
.msgHeader {
display: flex;
}
.msgHeaderDetails {
display: flex;
flex-direction: column;
}

View File

@ -1,6 +1,7 @@
const m = require('mithril');
const rs = require('rswebui');
const widget = require('widgets');
const peopleUtil = require('people/people_util');
// rsmsgs.h
const RS_MSG_BOXMASK = 0x000f;
@ -151,6 +152,15 @@ const MessageView = () => {
}
});
}
rs.rsJsonApiRequest(
'/rsIdentity/getIdDetails',
{
id: details.from._addr_string,
},
(data) => {
details = { ...details, avatar: data.details.mAvatar };
}
);
},
view: (v) =>
m(
@ -170,46 +180,52 @@ const MessageView = () => {
m('i.fas.fa-arrow-left')
),
m('h3', details.title),
details.from &&
m('from', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'From: '),
rs.userList.userMap[details.from._addr_string],
]),
toList &&
Object.keys(toList).length > 0 &&
// TODO: optimize javascript for show-more and show-less working
m('to', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'To: '),
m('div.truncate[id=truncate]',
Object.keys(toList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
),
m('button[id=show-more]', {
style: { display: Object.keys(toList).length > 10 ? 'block' : 'none' },
onclick: () => {
document.querySelector('#show-more').style.display = 'none';
document.querySelector('#truncate').style.height = 'max-content';
document.querySelector('#show-less').style.display = 'block';
}
}, 'Show More'),
m('button[id=show-less][style="display: none;"]', {
onclick: () => {
document.querySelector('#show-more').style.display = 'block';
document.querySelector('#truncate').style.height = '1rem';
document.querySelector('#show-less').style.display = 'none';
}
}, 'Show Less'),
]),
ccList &&
Object.keys(ccList).length > 0 &&
m('cc', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'CC: '),
Object.keys(ccList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
]),
bccList &&
Object.keys(bccList).length > 0 &&
m('bcc', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'BCC: '),
Object.keys(bccList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
m('.msgHeader', [
details.from &&
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() : '' }),
m('.msgHeaderDetails', [
details.from &&
m('from', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'From: '),
rs.userList.userMap[details.from._addr_string],
]),
toList &&
Object.keys(toList).length > 0 &&
// TODO: optimize javascript for show-more and show-less working
m('to', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'To: '),
m('div.truncate[id=truncate]',
Object.keys(toList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
),
m('button[id=show-more]', {
style: { display: Object.keys(toList).length > 10 ? 'block' : 'none' },
onclick: () => {
document.querySelector('#show-more').style.display = 'none';
document.querySelector('#truncate').style.height = 'max-content';
document.querySelector('#show-less').style.display = 'block';
}
}, 'Show More'),
m('button[id=show-less][style="display: none;"]', {
onclick: () => {
document.querySelector('#show-more').style.display = 'block';
document.querySelector('#truncate').style.height = '1rem';
document.querySelector('#show-less').style.display = 'none';
}
}, 'Show Less'),
]),
ccList &&
Object.keys(ccList).length > 0 &&
m('cc', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'CC: '),
Object.keys(ccList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
]),
bccList &&
Object.keys(bccList).length > 0 &&
m('bcc', { style: { display: 'block ruby' } }, [
m('p', { style: { fontWeight: 'bold' } }, 'BCC: '),
Object.keys(bccList).map((key, index) => m('p', rs.userList.userMap[key] + ', ')),
]),
])
]),
m('button', 'Reply'),
m('button', 'Reply All'),

View File

@ -17,10 +17,26 @@
font-size: 0.9em;
}
.defaultAvatar {
width: 50px;
height: max-content;
aspect-ratio: 1;
background: lightsteelblue;
border-radius: 50%;
display: grid;
place-items: center;
}
.defaultAvatar p {
font-weight: 900;
color: #666F7F;
transform: translateY(1px);
}
img.avatar {
float: left;
height: 100px;
display: block;
width: 50px;
aspect-ratio: 1;
margin-right: 0.3em;
border-radius: 50%;
}
.identity .details {

View File

@ -29,26 +29,26 @@ const SignedIdentiy = () => {
owns.ids.length > 0
? rs.rsJsonApiRequest(
'/rsIdentity/createIdentity',
{
id: owns.ids[0],
name: v.attrs.name,
pseudonimous: false,
pgpPassword: passphase,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
console.log(message);
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
)
'/rsIdentity/createIdentity',
{
id: owns.ids[0],
name: v.attrs.name,
pseudonimous: false,
pgpPassword: passphase,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
console.log(message);
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
)
: widget.popupMessage([
m('h3', 'Create new Identity'),
m('hr'),
'An error occured while creating identity.',
]);
m('h3', 'Create new Identity'),
m('hr'),
'An error occured while creating identity.',
]);
});
},
},
@ -99,10 +99,10 @@ const CreateIdentity = () => {
m(
'p',
'You can have one or more identities. ' +
'They are used when you chat in lobbies, ' +
'forums and channel comments. ' +
'They act as the destination for distant chat and ' +
'the Retroshare distant mail system.'
'They are used when you chat in lobbies, ' +
'forums and channel comments. ' +
'They act as the destination for distant chat and ' +
'the Retroshare distant mail system.'
),
m(
'button',
@ -111,18 +111,18 @@ const CreateIdentity = () => {
!pseudonimous
? widget.popupMessage(m(SignedIdentiy, { name }))
: rs.rsJsonApiRequest(
'/rsIdentity/createIdentity',
{
name,
pseudonimous,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
);
'/rsIdentity/createIdentity',
{
name,
pseudonimous,
},
(data) => {
const message = data.retval
? 'Successfully created identity.'
: 'An error occured while creating identity.';
widget.popupMessage([m('h3', 'Create new Identity'), m('hr'), message]);
}
);
},
},
'Create'
@ -192,28 +192,28 @@ const EditIdentity = () => {
onclick: () => {
!peopleUtil.checksudo(v.attrs.details.mPgpId)
? widget.popupMessage([
m(SignedEditIdentity, {
name,
details: v.attrs.details,
}),
])
m(SignedEditIdentity, {
name,
details: v.attrs.details,
}),
])
: rs.rsJsonApiRequest(
'/rsIdentity/updateIdentity',
{
id: v.attrs.details.mId,
'/rsIdentity/updateIdentity',
{
id: v.attrs.details.mId,
name,
name,
// avatar: v.attrs.details.mAvatar.mData.base64,
pseudonimous: true,
},
(data) => {
const message = data.retval
? 'Successfully Updated identity.'
: 'An error occured while updating identity.';
widget.popupMessage([m('h3', 'Update Identity'), m('hr'), message]);
}
);
// avatar: v.attrs.details.mAvatar.mData.base64,
pseudonimous: true,
},
(data) => {
const message = data.retval
? 'Successfully Updated identity.'
: 'An error occured while updating identity.';
widget.popupMessage([m('h3', 'Update Identity'), m('hr'), message]);
}
);
},
},
'Save'
@ -276,7 +276,8 @@ const Identity = () => {
},
[
m('h4', details.mNickname),
m(peopleUtil.UserAvatar, { avatar: details.mAvatar }),
details.mNickname &&
m(peopleUtil.UserAvatar, { avatar: details.mAvatar, firstLetter: details.mNickname.slice(0, 1).toUpperCase() }),
m('.details', [
m('p', 'ID:'),
m('p', details.mId),

View File

@ -10,10 +10,15 @@ const UserAvatar = () => ({
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('img.avatar', {
src: 'data:image/png;base64,' + imageURI.mData.base64,
});
src: 'data:image/png;base64,' + imageURI.mData.base64,
});
},
});
@ -55,7 +60,7 @@ 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));
@ -113,7 +118,8 @@ const regularcontactInfo = () => {
},
[
m('h4', details.mNickname),
m(UserAvatar, { avatar: details.mAvatar }),
details.mNickname &&
m(UserAvatar, { avatar: details.mAvatar, firstLetter: details.mNickname.slice(0, 1).toUpperCase() }),
m('.details', [
m('p', 'ID:'),
m('p', details.mId),

View File

@ -2,6 +2,12 @@
General site-wide rules
******************************/
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Main base div for tabs used by m.route */
.content {
height: 100%;
@ -156,19 +162,20 @@ hr {
font-size: 0.8rem;
border-radius: 5px;
display: flex;
justify-content: start;
justify-content: center;
align-items: center;
gap: 0.5rem;
color: black;
border-radius: 5px;
border: 1px solid black;
padding: 0px 10px;
padding: 10px 14px;
cursor: pointer;
}
.webhelp > i {
margin-right: 1.2px;
font-size: 1.2rem;
}
.webhelp > p {
margin-bottom: -4px;
font-weight: 600;
}
.retroshareID {
@ -360,7 +367,7 @@ Target specific sections
/* Navbar */
.nav-logo {
width: 9rem;
width: 130px;
padding: 1.2rem 0;
display: flex;
gap: 0.3rem;
@ -383,22 +390,22 @@ nav.tab-menu {
flex-direction: column;
align-items: center;
height: 100%;
padding: 0.5rem 0.4rem;
padding: 8px 6px;
margin-right: 0rem;
}
.tab-menu-item {
width: 10rem;
border-radius: 8px;
border-radius: 6px;
display: flex;
align-items: center;
}
a.tab-menu-item {
margin: 0.2rem;
padding: 0.7rem 0.4rem;
margin: 4px;
padding: 10px;
text-align: center;
text-decoration: none;
color: #ccc;
font-size: 1em;
font-size: 0.875em;
/* CSS capitalization is magical! */
text-transform: capitalize;
transition: all 300ms;
@ -411,8 +418,8 @@ a.tab-menu-item {
}
.tab-menu-item.selected-tab-item {
color: white;
background-color: #FFFFFF20;
color: #99DEFF;
background-color: #89BEFA20;
font-weight: medium;
}
.sidebar {