Update to new design for avatars: individual/group icons/colors
And two initials.
This commit is contained in:
parent
cf16ced91c
commit
8f3e3b7aaf
21 changed files with 1210 additions and 1017 deletions
22
images/profile-group.svg
Normal file
22
images/profile-group.svg
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="28px" height="28px" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 51.3 (57544) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Group/group-28</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<path d="M18.7272727,13.2857143 C20.6890909,13.2857143 22.2609091,11.6585714 22.2609091,9.64285714 C22.2609091,7.62714286 20.6890909,6 18.7272727,6 C16.7654545,6 15.1818182,7.62714286 15.1818182,9.64285714 C15.1818182,11.6585714 16.7654545,13.2857143 18.7272727,13.2857143 Z M9.27272727,13.2857143 C11.2345455,13.2857143 12.8063636,11.6585714 12.8063636,9.64285714 C12.8063636,7.62714286 11.2345455,6 9.27272727,6 C7.31090909,6 5.72727273,7.62714286 5.72727273,9.64285714 C5.72727273,11.6585714 7.31090909,13.2857143 9.27272727,13.2857143 Z M9.27272727,15.7142857 C6.51909091,15.7142857 1,17.135 1,19.9642857 L1,23 L17.5454545,23 L17.5454545,19.9642857 C17.5454545,17.135 12.0263636,15.7142857 9.27272727,15.7142857 Z M18.7272727,15.7142857 C18.3845455,15.7142857 17.9945455,15.7385714 17.5809091,15.775 C18.9518182,16.795 19.9090909,18.1671429 19.9090909,19.9642857 L19.9090909,23 L27,23 L27,19.9642857 C27,17.135 21.4809091,15.7142857 18.7272727,15.7142857 Z" id="path-1"></path>
|
||||||
|
<rect id="path-3" x="0" y="0" width="28" height="28"></rect>
|
||||||
|
</defs>
|
||||||
|
<g id="Group/group-28" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<mask id="mask-2" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="Shape" fill="#000000" fill-rule="nonzero" xlink:href="#path-1"></use>
|
||||||
|
<g id="Color/UI/Black" mask="url(#mask-2)">
|
||||||
|
<mask id="mask-4" fill="white">
|
||||||
|
<use xlink:href="#path-3"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="fill" fill="#000000" fill-rule="evenodd" xlink:href="#path-3"></use>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
22
images/profile-individual.svg
Normal file
22
images/profile-individual.svg
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="28px" height="28px" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 51.3 (57544) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Profile/profile-28</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<path d="M14,14 C16.7625,14 19,11.7625 19,9 C19,6.2375 16.7625,4 14,4 C11.2375,4 9,6.2375 9,9 C9,11.7625 11.2375,14 14,14 Z M14,16.5 C10.6625,16.5 4,18.175 4,21.5 L4,24 L24,24 L24,21.5 C24,18.175 17.3375,16.5 14,16.5 Z" id="path-1"></path>
|
||||||
|
<rect id="path-3" x="0" y="0" width="28" height="28"></rect>
|
||||||
|
</defs>
|
||||||
|
<g id="Profile/profile-28" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<mask id="mask-2" fill="white">
|
||||||
|
<use xlink:href="#path-1"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="Shape" fill="#000000" fill-rule="nonzero" xlink:href="#path-1"></use>
|
||||||
|
<g id="Color/UI/Black" mask="url(#mask-2)">
|
||||||
|
<mask id="mask-4" fill="white">
|
||||||
|
<use xlink:href="#path-3"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="fill" fill="#000000" fill-rule="evenodd" xlink:href="#path-3"></use>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -174,8 +174,6 @@
|
||||||
format() {
|
format() {
|
||||||
const { format } = PhoneNumber;
|
const { format } = PhoneNumber;
|
||||||
const regionCode = storage.get('regionCode');
|
const regionCode = storage.get('regionCode');
|
||||||
|
|
||||||
const avatar = this.getAvatar();
|
|
||||||
const color = this.getColor();
|
const color = this.getColor();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -183,7 +181,7 @@
|
||||||
ourRegionCode: regionCode,
|
ourRegionCode: regionCode,
|
||||||
}),
|
}),
|
||||||
color,
|
color,
|
||||||
avatarPath: avatar ? avatar.url : null,
|
avatarPath: this.getAvatarPath(),
|
||||||
name: this.getName(),
|
name: this.getName(),
|
||||||
profileName: this.getProfileName(),
|
profileName: this.getProfileName(),
|
||||||
title: this.getTitle(),
|
title: this.getTitle(),
|
||||||
|
@ -192,6 +190,7 @@
|
||||||
getPropsForListItem() {
|
getPropsForListItem() {
|
||||||
const result = {
|
const result = {
|
||||||
...this.format(),
|
...this.format(),
|
||||||
|
conversationType: this.isPrivate() ? 'direct' : 'group',
|
||||||
|
|
||||||
lastUpdated: this.get('timestamp'),
|
lastUpdated: this.get('timestamp'),
|
||||||
unreadCount: this.get('unreadCount') || 0,
|
unreadCount: this.get('unreadCount') || 0,
|
||||||
|
@ -1369,6 +1368,15 @@
|
||||||
const { migrateColor } = Util;
|
const { migrateColor } = Util;
|
||||||
return migrateColor(this.get('color'));
|
return migrateColor(this.get('color'));
|
||||||
},
|
},
|
||||||
|
getAvatarPath() {
|
||||||
|
const avatar = this.get('avatar') || this.get('profileAvatar');
|
||||||
|
|
||||||
|
if (avatar && avatar.path) {
|
||||||
|
return getAbsoluteAttachmentPath(avatar.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
getAvatar() {
|
getAvatar() {
|
||||||
const title = this.get('name');
|
const title = this.get('name');
|
||||||
const color = this.getColor();
|
const color = this.getColor();
|
||||||
|
|
|
@ -300,7 +300,6 @@
|
||||||
const regionCode = storage.get('regionCode');
|
const regionCode = storage.get('regionCode');
|
||||||
|
|
||||||
const contactModel = this.findContact(phoneNumber);
|
const contactModel = this.findContact(phoneNumber);
|
||||||
const avatar = contactModel ? contactModel.getAvatar() : null;
|
|
||||||
const color = contactModel ? contactModel.getColor() : null;
|
const color = contactModel ? contactModel.getColor() : null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -308,7 +307,7 @@
|
||||||
ourRegionCode: regionCode,
|
ourRegionCode: regionCode,
|
||||||
}),
|
}),
|
||||||
color,
|
color,
|
||||||
avatarPath: avatar ? avatar.url : null,
|
avatarPath: contactModel ? contactModel.getAvatarPath() : null,
|
||||||
name: contactModel ? contactModel.getName() : null,
|
name: contactModel ? contactModel.getName() : null,
|
||||||
profileName: contactModel ? contactModel.getProfileName() : null,
|
profileName: contactModel ? contactModel.getProfileName() : null,
|
||||||
title: contactModel ? contactModel.getTitle() : null,
|
title: contactModel ? contactModel.getTitle() : null,
|
||||||
|
@ -394,8 +393,9 @@
|
||||||
const contact = this.findAndFormatContact(phoneNumber);
|
const contact = this.findAndFormatContact(phoneNumber);
|
||||||
const contactModel = this.findContact(phoneNumber);
|
const contactModel = this.findContact(phoneNumber);
|
||||||
|
|
||||||
const authorAvatar = contactModel ? contactModel.getAvatar() : null;
|
const authorAvatarPath = contactModel
|
||||||
const authorAvatarPath = authorAvatar ? authorAvatar.url : null;
|
? contactModel.getAvatarPath()
|
||||||
|
: null;
|
||||||
|
|
||||||
const expirationLength = this.get('expireTimer') * 1000;
|
const expirationLength = this.get('expireTimer') * 1000;
|
||||||
const expireTimerStart = this.get('expirationStartTimestamp');
|
const expireTimerStart = this.get('expirationStartTimestamp');
|
||||||
|
@ -530,10 +530,16 @@
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { format } = PhoneNumber;
|
||||||
|
const regionCode = storage.get('regionCode');
|
||||||
|
|
||||||
|
const conversation = this.getConversation();
|
||||||
const { author, id, referencedMessageNotFound } = quote;
|
const { author, id, referencedMessageNotFound } = quote;
|
||||||
const contact = author && ConversationController.get(author);
|
const contact = author && ConversationController.get(author);
|
||||||
|
|
||||||
const authorPhoneNumber = author;
|
const authorPhoneNumber = format(author, {
|
||||||
|
ourRegionCode: regionCode,
|
||||||
|
});
|
||||||
const authorProfileName = contact ? contact.getProfileName() : null;
|
const authorProfileName = contact ? contact.getProfileName() : null;
|
||||||
const authorName = contact ? contact.getName() : null;
|
const authorName = contact ? contact.getName() : null;
|
||||||
const isFromMe = contact ? contact.id === this.OUR_NUMBER : false;
|
const isFromMe = contact ? contact.id === this.OUR_NUMBER : false;
|
||||||
|
@ -556,6 +562,7 @@
|
||||||
authorPhoneNumber,
|
authorPhoneNumber,
|
||||||
authorProfileName,
|
authorProfileName,
|
||||||
authorName,
|
authorName,
|
||||||
|
conversationColor: conversation && conversation.getColor(),
|
||||||
onClick,
|
onClick,
|
||||||
referencedMessageNotFound,
|
referencedMessageNotFound,
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
this.contactView = null;
|
this.contactView = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const avatar = this.model.getAvatar();
|
|
||||||
const avatarPath = avatar && avatar.url;
|
|
||||||
const color = avatar && avatar.color;
|
|
||||||
const isMe = this.ourNumber === this.model.id;
|
const isMe = this.ourNumber === this.model.id;
|
||||||
|
|
||||||
this.contactView = new Whisper.ReactWrapperView({
|
this.contactView = new Whisper.ReactWrapperView({
|
||||||
|
@ -35,8 +32,8 @@
|
||||||
Component: window.Signal.Components.ContactListItem,
|
Component: window.Signal.Components.ContactListItem,
|
||||||
props: {
|
props: {
|
||||||
isMe,
|
isMe,
|
||||||
color,
|
color: this.model.getColor(),
|
||||||
avatarPath,
|
avatarPath: this.model.getAvatarPath(),
|
||||||
phoneNumber: this.model.getNumber(),
|
phoneNumber: this.model.getNumber(),
|
||||||
name: this.model.getName(),
|
name: this.model.getName(),
|
||||||
profileName: this.model.getProfileName(),
|
profileName: this.model.getProfileName(),
|
||||||
|
|
|
@ -145,8 +145,6 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
const getHeaderProps = () => {
|
const getHeaderProps = () => {
|
||||||
const avatar = this.model.getAvatar();
|
|
||||||
const avatarPath = avatar ? avatar.url : null;
|
|
||||||
const expireTimer = this.model.get('expireTimer');
|
const expireTimer = this.model.get('expireTimer');
|
||||||
const expirationSettingName = expireTimer
|
const expirationSettingName = expireTimer
|
||||||
? Whisper.ExpirationTimerOptions.getName(expireTimer || 0)
|
? Whisper.ExpirationTimerOptions.getName(expireTimer || 0)
|
||||||
|
@ -158,7 +156,7 @@
|
||||||
phoneNumber: this.model.getNumber(),
|
phoneNumber: this.model.getNumber(),
|
||||||
profileName: this.model.getProfileName(),
|
profileName: this.model.getProfileName(),
|
||||||
color: this.model.getColor(),
|
color: this.model.getColor(),
|
||||||
avatarPath,
|
avatarPath: this.model.getAvatarPath(),
|
||||||
isVerified: this.model.isVerified(),
|
isVerified: this.model.isVerified(),
|
||||||
isMe: this.model.isMe(),
|
isMe: this.model.isMe(),
|
||||||
isGroup: !this.model.isPrivate(),
|
isGroup: !this.model.isPrivate(),
|
||||||
|
@ -1401,6 +1399,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = new Whisper.Message({
|
const message = new Whisper.Message({
|
||||||
|
conversationId: this.model.id,
|
||||||
quote: this.quote,
|
quote: this.quote,
|
||||||
});
|
});
|
||||||
message.quotedMessage = this.quotedMessage;
|
message.quotedMessage = this.quotedMessage;
|
||||||
|
|
|
@ -560,74 +560,6 @@
|
||||||
// This accounts for the weird extra 3px we get at the bottom of messages
|
// This accounts for the weird extra 3px we get at the bottom of messages
|
||||||
bottom: -3px;
|
bottom: -3px;
|
||||||
right: calc(100% + 4px);
|
right: calc(100% + 4px);
|
||||||
|
|
||||||
img {
|
|
||||||
height: 36px;
|
|
||||||
width: 36px;
|
|
||||||
border-radius: 18px;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message__author-default-avatar {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0px;
|
|
||||||
right: calc(100% + 4px);
|
|
||||||
|
|
||||||
height: 36px;
|
|
||||||
width: 36px;
|
|
||||||
border-radius: 18px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
// Default, in case we have no color
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message__author-default-avatar--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message__author-default-avatar__label {
|
|
||||||
width: 100%;
|
|
||||||
font-size: 18px;
|
|
||||||
color: $color-white;
|
|
||||||
|
|
||||||
// Because it just doesn't look properly centered
|
|
||||||
padding-right: 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module: Expire Timer
|
// Module: Expire Timer
|
||||||
|
@ -1025,37 +957,6 @@
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-embedded-contact__image-container {
|
|
||||||
flex: initial;
|
|
||||||
min-width: 50px;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
object-fit: cover;
|
|
||||||
|
|
||||||
img {
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-embedded-contact__image-container__default-avatar {
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
color: $color-white;
|
|
||||||
font-size: 25px;
|
|
||||||
line-height: 52px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-embedded-contact__text-container {
|
.module-embedded-contact__text-container {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
|
@ -1106,31 +1007,8 @@
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-contact-detail__image-container {
|
.module-contact-detail__avatar {
|
||||||
height: 80px;
|
|
||||||
width: 80px;
|
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
display: inline-block;
|
|
||||||
object-fit: cover;
|
|
||||||
|
|
||||||
img {
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-detail__image-container__default-avatar {
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
color: $color-white;
|
|
||||||
font-size: 50px;
|
|
||||||
line-height: 82px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-contact-detail__contact-name {
|
.module-contact-detail__contact-name {
|
||||||
|
@ -1366,69 +1244,6 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-contact-list-item__avatar {
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 44px;
|
|
||||||
width: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-list-item__avatar-default {
|
|
||||||
height: 44px;
|
|
||||||
width: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-list-item__avatar-default--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-list-item__avatar-default__label {
|
|
||||||
width: 100%;
|
|
||||||
color: $color-white;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-list-item__text {
|
.module-contact-list-item__text {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
@ -1506,54 +1321,8 @@
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-header___avatar {
|
.module-conversation-header__avatar {
|
||||||
height: 32px;
|
min-width: 28px;
|
||||||
width: 32px;
|
|
||||||
min-width: 32px;
|
|
||||||
border-radius: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-conversation-header___default-avatar {
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
|
|
||||||
line-height: 32px;
|
|
||||||
font-size: 16px;
|
|
||||||
color: $color-white;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-conversation-header___default-avatar--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-header__title {
|
.module-conversation-header__title {
|
||||||
|
@ -1565,8 +1334,8 @@
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
color: $color-light-90;
|
color: $color-light-90;
|
||||||
|
|
||||||
// width of avatar and our 8px left margin
|
// width of avatar (28px) and our 8px left margin
|
||||||
max-width: calc(100% - 40px);
|
max-width: calc(100% - 36px);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -1674,56 +1443,6 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-message-detail__contact__avatar {
|
|
||||||
height: 44px;
|
|
||||||
width: 44px;
|
|
||||||
min-width: 44px;
|
|
||||||
border-radius: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message-detail__contact__default-avatar {
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
|
|
||||||
line-height: 44px;
|
|
||||||
font-size: 20px;
|
|
||||||
color: $color-white;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message-detail__contact__default-avatar--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message-detail__contact__text {
|
.module-message-detail__contact__text {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
@ -2013,58 +1732,8 @@
|
||||||
|
|
||||||
.module-conversation-list-item__avatar-container {
|
.module-conversation-list-item__avatar-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
|
||||||
.module-conversation-list-item__avatar {
|
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
height: 48px;
|
|
||||||
width: 48px;
|
|
||||||
border-radius: 24px;
|
|
||||||
min-width: 48px;
|
|
||||||
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar {
|
|
||||||
color: white;
|
|
||||||
font-size: 26px;
|
|
||||||
line-height: 48px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-conversation-list-item__default-avatar--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__unread-count {
|
.module-conversation-list-item__unread-count {
|
||||||
|
@ -2073,8 +1742,8 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
padding-top: 1px;
|
padding-top: 1px;
|
||||||
padding-left: 2px;
|
padding-left: 3px;
|
||||||
padding-right: 2px;
|
padding-right: 3px;
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -6px;
|
right: -6px;
|
||||||
|
@ -2089,7 +1758,7 @@
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
||||||
box-shadow: 0px 0px 1px 2px $color-white-05;
|
box-shadow: 0px 0px 0px 1px $color-gray-02;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__content {
|
.module-conversation-list-item__content {
|
||||||
|
@ -2118,6 +1787,9 @@
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
font-weight: 300;
|
||||||
|
color: $color-gray-90;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__header__name--with-unread {
|
.module-conversation-list-item__header__name--with-unread {
|
||||||
|
@ -2137,10 +1809,13 @@
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
color: $color-gray-60;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__header__date--has-unread {
|
.module-conversation-list-item__header__date--has-unread {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
color: $color-gray-90;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__message {
|
.module-conversation-list-item__message {
|
||||||
|
@ -2168,6 +1843,7 @@
|
||||||
|
|
||||||
.module-conversation-list-item__message__text--has-unread {
|
.module-conversation-list-item__message__text--has-unread {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
color: $color-gray-90;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__message__status-icon {
|
.module-conversation-list-item__message__status-icon {
|
||||||
|
@ -2208,6 +1884,167 @@
|
||||||
@include color-svg('../images/error.svg', $color-core-red);
|
@include color-svg('../images/error.svg', $color-core-red);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module: Avatar
|
||||||
|
|
||||||
|
.module-avatar {
|
||||||
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__label {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 300;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: $color-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--group {
|
||||||
|
@include color-svg('../images/profile-group.svg', $color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--direct {
|
||||||
|
@include color-svg('../images/profile-individual.svg', $color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--28 {
|
||||||
|
height: 28px;
|
||||||
|
width: 28px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 28px;
|
||||||
|
width: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__label--28 {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--28 {
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--36 {
|
||||||
|
height: 36px;
|
||||||
|
width: 36px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 36px;
|
||||||
|
width: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__label--36 {
|
||||||
|
margin-top: 1px;
|
||||||
|
width: 36px;
|
||||||
|
font-size: 16px;
|
||||||
|
letter-spacing: 0.19px;
|
||||||
|
line-height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--36 {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--48 {
|
||||||
|
height: 48px;
|
||||||
|
width: 48px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 48px;
|
||||||
|
width: 48px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__label--48 {
|
||||||
|
width: 48px;
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 0.19px;
|
||||||
|
line-height: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--48 {
|
||||||
|
height: 26px;
|
||||||
|
width: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--80 {
|
||||||
|
height: 80px;
|
||||||
|
width: 80px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 80px;
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__label--80 {
|
||||||
|
width: 80px;
|
||||||
|
font-size: 40px;
|
||||||
|
line-height: 82px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--80 {
|
||||||
|
height: 42px;
|
||||||
|
width: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--no-image {
|
||||||
|
background-color: $color-conversation-grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--red {
|
||||||
|
background-color: $color-conversation-red;
|
||||||
|
}
|
||||||
|
.module-avatar--deep_orange {
|
||||||
|
background-color: $color-conversation-deep_orange;
|
||||||
|
}
|
||||||
|
.module-avatar--brown {
|
||||||
|
background-color: $color-conversation-brown;
|
||||||
|
}
|
||||||
|
.module-avatar--pink {
|
||||||
|
background-color: $color-conversation-pink;
|
||||||
|
}
|
||||||
|
.module-avatar--purple {
|
||||||
|
background-color: $color-conversation-purple;
|
||||||
|
}
|
||||||
|
.module-avatar--indigo {
|
||||||
|
background-color: $color-conversation-indigo;
|
||||||
|
}
|
||||||
|
.module-avatar--blue {
|
||||||
|
background-color: $color-conversation-blue;
|
||||||
|
}
|
||||||
|
.module-avatar--teal {
|
||||||
|
background-color: $color-conversation-teal;
|
||||||
|
}
|
||||||
|
.module-avatar--green {
|
||||||
|
background-color: $color-conversation-green;
|
||||||
|
}
|
||||||
|
.module-avatar--light_green {
|
||||||
|
background-color: $color-conversation-light_green;
|
||||||
|
}
|
||||||
|
.module-avatar--blue_grey {
|
||||||
|
background-color: $color-conversation-blue_grey;
|
||||||
|
}
|
||||||
|
|
||||||
// Third-party module: react-contextmenu
|
// Third-party module: react-contextmenu
|
||||||
|
|
||||||
.react-contextmenu {
|
.react-contextmenu {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
body.dark-theme {
|
body.dark-theme {
|
||||||
background-color: $color-black;
|
background-color: $color-black;
|
||||||
color: $color-gray-95;
|
color: $color-gray-05;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-theme {
|
.dark-theme {
|
||||||
|
@ -797,44 +797,6 @@ body.dark-theme {
|
||||||
border: 1px solid $color-dark-60;
|
border: 1px solid $color-dark-60;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-message__author-default-avatar--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-message__author-default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message__author-default-avatar__label {
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Module: Expire Timer
|
// Module: Expire Timer
|
||||||
|
|
||||||
.module-expire-timer {
|
.module-expire-timer {
|
||||||
|
@ -1076,11 +1038,6 @@ body.dark-theme {
|
||||||
|
|
||||||
// Module: Embedded Contact
|
// Module: Embedded Contact
|
||||||
|
|
||||||
.module-embedded-contact__image-container__default-avatar {
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-embedded-contact__contact-name {
|
.module-embedded-contact__contact-name {
|
||||||
color: $color-dark-05;
|
color: $color-dark-05;
|
||||||
}
|
}
|
||||||
|
@ -1099,11 +1056,6 @@ body.dark-theme {
|
||||||
|
|
||||||
// Module: Contact Detail
|
// Module: Contact Detail
|
||||||
|
|
||||||
.module-contact-detail__image-container__default-avatar {
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-detail__send-message {
|
.module-contact-detail__send-message {
|
||||||
background-color: $blue;
|
background-color: $blue;
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
|
@ -1145,7 +1097,7 @@ body.dark-theme {
|
||||||
|
|
||||||
.module-verification-notification__button {
|
.module-verification-notification__button {
|
||||||
color: $color-signal-blue;
|
color: $color-signal-blue;
|
||||||
background-color: $color-light-02;
|
background-color: $color-gray-75;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module: Verification Notification
|
// Module: Verification Notification
|
||||||
|
@ -1182,48 +1134,6 @@ body.dark-theme {
|
||||||
color: $color-dark-30;
|
color: $color-dark-30;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-contact-list-item__avatar-default {
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-list-item__avatar-default--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-contact-list-item__avatar-default--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-list-item__avatar-default__label {
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-contact-list-item__text__verified-icon {
|
.module-contact-list-item__text__verified-icon {
|
||||||
@include color-svg('../images/verified-check.svg', $color-dark-30);
|
@include color-svg('../images/verified-check.svg', $color-dark-30);
|
||||||
}
|
}
|
||||||
|
@ -1240,45 +1150,6 @@ body.dark-theme {
|
||||||
@include color-svg('../images/back.svg', $color-dark-05);
|
@include color-svg('../images/back.svg', $color-dark-05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-header___default-avatar {
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-conversation-header___default-avatar--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-conversation-header___default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-conversation-header__title {
|
.module-conversation-header__title {
|
||||||
color: $color-dark-05;
|
color: $color-dark-05;
|
||||||
}
|
}
|
||||||
|
@ -1308,45 +1179,6 @@ body.dark-theme {
|
||||||
border: solid 1px $color-light-35;
|
border: solid 1px $color-light-35;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-message-detail__contact__default-avatar {
|
|
||||||
background-color: $color-conversation-grey;
|
|
||||||
color: $color-white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message-detail__contact__default-avatar--red {
|
|
||||||
background-color: $color-conversation-red;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-message-detail__contact__default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-message-detail__contact__error {
|
.module-message-detail__contact__error {
|
||||||
color: $color-core-red;
|
color: $color-core-red;
|
||||||
}
|
}
|
||||||
|
@ -1437,43 +1269,30 @@ body.dark-theme {
|
||||||
background-color: $color-dark-70;
|
background-color: $color-dark-70;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__default-avatar {
|
.module-conversation-list-item__unread-count {
|
||||||
color: white;
|
color: $color-white;
|
||||||
background-color: $color-conversation-grey;
|
background-color: $color-signal-blue;
|
||||||
|
box-shadow: 0px 0px 0px 1px $color-dark-85;
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__default-avatar--red {
|
.module-conversation-list-item__header__name {
|
||||||
background-color: $color-conversation-red;
|
color: $color-gray-05;
|
||||||
}
|
}
|
||||||
.module-conversation-list-item__default-avatar--deep_orange {
|
|
||||||
background-color: $color-conversation-deep_orange;
|
.module-conversation-list-item__header__timestamp {
|
||||||
|
color: $color-gray-25;
|
||||||
}
|
}
|
||||||
.module-conversation-list-item__default-avatar--brown {
|
|
||||||
background-color: $color-conversation-brown;
|
.module-conversation-list-item__header__date--has-unread {
|
||||||
|
color: $color-gray-05;
|
||||||
}
|
}
|
||||||
.module-conversation-list-item__default-avatar--pink {
|
|
||||||
background-color: $color-conversation-pink;
|
.module-conversation-list-item__message__text {
|
||||||
|
color: $color-gray-25;
|
||||||
}
|
}
|
||||||
.module-conversation-list-item__default-avatar--purple {
|
|
||||||
background-color: $color-conversation-purple;
|
.module-conversation-list-item__message__text--has-unread {
|
||||||
}
|
color: $color-gray-05;
|
||||||
.module-conversation-list-item__default-avatar--indigo {
|
|
||||||
background-color: $color-conversation-indigo;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--blue {
|
|
||||||
background-color: $color-conversation-blue;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--teal {
|
|
||||||
background-color: $color-conversation-teal;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--green {
|
|
||||||
background-color: $color-conversation-green;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--light_green {
|
|
||||||
background-color: $color-conversation-light_green;
|
|
||||||
}
|
|
||||||
.module-conversation-list-item__default-avatar--blue_grey {
|
|
||||||
background-color: $color-conversation-blue_grey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-conversation-list-item__message__status-icon--sending {
|
.module-conversation-list-item__message__status-icon--sending {
|
||||||
|
@ -1492,6 +1311,58 @@ body.dark-theme {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module: Avatar
|
||||||
|
|
||||||
|
.module-avatar__label {
|
||||||
|
color: $color-gray-05;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--group {
|
||||||
|
@include color-svg('../images/profile-group.svg', $color-gray-05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar__icon--direct {
|
||||||
|
@include color-svg('../images/profile-individual.svg', $color-gray-05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--no-image {
|
||||||
|
background-color: $color-conversation-grey-shade;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-avatar--red {
|
||||||
|
background-color: $color-conversation-red-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--deep_orange {
|
||||||
|
background-color: $color-conversation-deep_orange-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--brown {
|
||||||
|
background-color: $color-conversation-brown-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--pink {
|
||||||
|
background-color: $color-conversation-pink-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--purple {
|
||||||
|
background-color: $color-conversation-purple-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--indigo {
|
||||||
|
background-color: $color-conversation-indigo-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--blue {
|
||||||
|
background-color: $color-conversation-blue-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--teal {
|
||||||
|
background-color: $color-conversation-teal-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--green {
|
||||||
|
background-color: $color-conversation-green-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--light_green {
|
||||||
|
background-color: $color-conversation-light_green-shade;
|
||||||
|
}
|
||||||
|
.module-avatar--blue_grey {
|
||||||
|
background-color: $color-conversation-blue_grey-shade;
|
||||||
|
}
|
||||||
|
|
||||||
// Third-party module: react-contextmenu
|
// Third-party module: react-contextmenu
|
||||||
|
|
||||||
.react-contextmenu {
|
.react-contextmenu {
|
||||||
|
|
299
ts/components/Avatar.md
Normal file
299
ts/components/Avatar.md
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
### With avatar
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="pink"
|
||||||
|
name="John Smith"
|
||||||
|
avatarPath={util.gifObjectUrl}
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="pink"
|
||||||
|
name="Puppies"
|
||||||
|
avatarPath={util.gifObjectUrl}
|
||||||
|
conversationType="group"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### With only name
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="blue"
|
||||||
|
name="John"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="green"
|
||||||
|
name="John Smith"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="red"
|
||||||
|
name="Puppies"
|
||||||
|
conversationType="group"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Just phone number
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="pink"
|
||||||
|
phoneNumber="(555) 353-3433"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### All colors
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="red"
|
||||||
|
name="Red"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="deep_orange"
|
||||||
|
name="Deep Orange"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="brown"
|
||||||
|
name="Broen"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="pink"
|
||||||
|
name="Pink"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="purple"
|
||||||
|
name="Purple"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="indigo"
|
||||||
|
name="Indigo"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="blue"
|
||||||
|
name="Blue"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="teal"
|
||||||
|
name="Teal"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="green"
|
||||||
|
name="Green"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="light_green"
|
||||||
|
name="Light Green"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="blue_grey"
|
||||||
|
name="Blue Grey"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 36px
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={36}
|
||||||
|
color="teal"
|
||||||
|
name="John Smith"
|
||||||
|
avatarPath={util.gifObjectUrl}
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={36}
|
||||||
|
color="teal"
|
||||||
|
name="John"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={36}
|
||||||
|
color="teal"
|
||||||
|
name="John Smith"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={36}
|
||||||
|
color="teal"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={36}
|
||||||
|
color="teal"
|
||||||
|
name="Pupplies"
|
||||||
|
conversationType="group"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 48px
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={48}
|
||||||
|
color="teal"
|
||||||
|
name="John Smith"
|
||||||
|
avatarPath={util.gifObjectUrl}
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={48}
|
||||||
|
color="teal"
|
||||||
|
name="John"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={48}
|
||||||
|
color="teal"
|
||||||
|
name="John Smith"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={48}
|
||||||
|
color="teal"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={48}
|
||||||
|
color="teal"
|
||||||
|
name="Pupplies"
|
||||||
|
conversationType="group"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 80px
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={80}
|
||||||
|
color="teal"
|
||||||
|
name="John Smith"
|
||||||
|
avatarPath={util.gifObjectUrl}
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={80}
|
||||||
|
color="teal"
|
||||||
|
name="John"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={80}
|
||||||
|
color="teal"
|
||||||
|
name="John Smith"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={80}
|
||||||
|
color="teal"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<Avatar
|
||||||
|
size={80}
|
||||||
|
color="teal"
|
||||||
|
name="Pupplies"
|
||||||
|
conversationType="group"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Broken color
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="fake"
|
||||||
|
name="F"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Broken image
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
color="pink"
|
||||||
|
name="John Smith"
|
||||||
|
avatarPath="nonexistent"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Broken image for group
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<Avatar
|
||||||
|
size={28}
|
||||||
|
avatarPath="nonexistent"
|
||||||
|
color="pink"
|
||||||
|
name="Puppies"
|
||||||
|
avatarPath="nonexistent"
|
||||||
|
conversationType="group"
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
```
|
118
ts/components/Avatar.tsx
Normal file
118
ts/components/Avatar.tsx
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { getInitials } from '../util/getInitials';
|
||||||
|
import { Localizer } from '../types/Util';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
avatarPath?: string;
|
||||||
|
color?: string;
|
||||||
|
conversationType: 'group' | 'direct';
|
||||||
|
i18n: Localizer;
|
||||||
|
name?: string;
|
||||||
|
phoneNumber?: string;
|
||||||
|
profileName?: string;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
imageBroken: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Avatar extends React.Component<Props, State> {
|
||||||
|
public handleImageErrorBound: () => void;
|
||||||
|
|
||||||
|
public constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleImageErrorBound = this.handleImageError.bind(this);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
imageBroken: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public handleImageError() {
|
||||||
|
// tslint:disable-next-line no-console
|
||||||
|
console.log('Avatar: Image failed to load; failing over to placeholder');
|
||||||
|
this.setState({
|
||||||
|
imageBroken: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderImage() {
|
||||||
|
const { avatarPath, i18n, name, phoneNumber, profileName } = this.props;
|
||||||
|
const { imageBroken } = this.state;
|
||||||
|
const hasImage = avatarPath && !imageBroken;
|
||||||
|
|
||||||
|
if (!hasImage) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = `${name || phoneNumber}${
|
||||||
|
!name && profileName ? ` ~${profileName}` : ''
|
||||||
|
}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
onError={this.handleImageErrorBound}
|
||||||
|
alt={i18n('contactAvatarAlt', [title])}
|
||||||
|
src={avatarPath}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderNoImage() {
|
||||||
|
const { conversationType, name, size } = this.props;
|
||||||
|
|
||||||
|
const initials = getInitials(name);
|
||||||
|
const isGroup = conversationType === 'group';
|
||||||
|
|
||||||
|
if (!isGroup && initials) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'module-avatar__label',
|
||||||
|
`module-avatar__label--${size}`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{initials}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'module-avatar__icon',
|
||||||
|
`module-avatar__icon--${conversationType}`,
|
||||||
|
`module-avatar__icon--${size}`
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { avatarPath, color, size } = this.props;
|
||||||
|
const { imageBroken } = this.state;
|
||||||
|
|
||||||
|
const hasImage = avatarPath && !imageBroken;
|
||||||
|
|
||||||
|
if (size !== 28 && size !== 36 && size !== 48 && size !== 80) {
|
||||||
|
throw new Error(`Size ${size} is not supported!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'module-avatar',
|
||||||
|
`module-avatar--${size}`,
|
||||||
|
hasImage ? 'module-avatar--with-image' : 'module-avatar--no-image',
|
||||||
|
!hasImage ? `module-avatar--${color}` : null
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{hasImage ? this.renderImage() : this.renderNoImage()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { Avatar } from './Avatar';
|
||||||
import { Emojify } from './conversation/Emojify';
|
import { Emojify } from './conversation/Emojify';
|
||||||
|
|
||||||
import { Localizer } from '../types/Util';
|
import { Localizer } from '../types/Util';
|
||||||
|
@ -17,35 +18,28 @@ interface Props {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitial(name: string): string {
|
|
||||||
return name.trim()[0] || '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ContactListItem extends React.Component<Props> {
|
export class ContactListItem extends React.Component<Props> {
|
||||||
public renderAvatar({ displayName }: { displayName: string }) {
|
public renderAvatar() {
|
||||||
const { avatarPath, i18n, color, name } = this.props;
|
const {
|
||||||
|
avatarPath,
|
||||||
if (avatarPath) {
|
i18n,
|
||||||
return (
|
color,
|
||||||
<div className="module-contact-list-item__avatar">
|
name,
|
||||||
<img alt={i18n('contactAvatarAlt', [displayName])} src={avatarPath} />
|
phoneNumber,
|
||||||
</div>
|
profileName,
|
||||||
);
|
} = this.props;
|
||||||
}
|
|
||||||
|
|
||||||
const title = name ? getInitial(name) : '#';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Avatar
|
||||||
className={classNames(
|
avatarPath={avatarPath}
|
||||||
'module-contact-list-item__avatar-default',
|
color={color}
|
||||||
`module-contact-list-item__avatar-default--${color}`
|
conversationType="direct"
|
||||||
)}
|
i18n={i18n}
|
||||||
>
|
name={name}
|
||||||
<div className="module-contact-list-item__avatar-default__label">
|
phoneNumber={phoneNumber}
|
||||||
{title}
|
profileName={profileName}
|
||||||
</div>
|
size={48}
|
||||||
</div>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +76,7 @@ export class ContactListItem extends React.Component<Props> {
|
||||||
onClick ? 'module-contact-list-item--with-click-handler' : null
|
onClick ? 'module-contact-list-item--with-click-handler' : null
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{this.renderAvatar({ displayName })}
|
{this.renderAvatar()}
|
||||||
<div className="module-contact-list-item__text">
|
<div className="module-contact-list-item__text">
|
||||||
<div className="module-contact-list-item__text__name">
|
<div className="module-contact-list-item__text__name">
|
||||||
<Emojify text={displayName} i18n={i18n} /> {profileElement}
|
<Emojify text={displayName} i18n={i18n} /> {profileElement}
|
||||||
|
|
|
@ -1,154 +1,175 @@
|
||||||
#### With name and profile
|
#### With name and profile
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<ConversationListItem
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
name="Someone 🔥 Somewhere"
|
|
||||||
phoneNumber="(202) 555-0011"
|
|
||||||
avatarPath={util.gifObjectUrl}
|
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
|
||||||
lastMessage={{
|
|
||||||
text: "What's going on?",
|
|
||||||
status: 'sent',
|
|
||||||
}}
|
|
||||||
onClick={() => console.log('onClick')}
|
|
||||||
i18n={util.i18n}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Profile, with name, no avatar
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
<ConversationListItem
|
|
||||||
phoneNumber="(202) 555-0011"
|
|
||||||
name="Mr. Fire🔥"
|
|
||||||
color="green"
|
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
|
||||||
lastMessage={{
|
|
||||||
text: 'Just a second',
|
|
||||||
status: 'read',
|
|
||||||
}}
|
|
||||||
onClick={() => console.log('onClick')}
|
|
||||||
i18n={util.i18n}
|
|
||||||
/>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### All types of status
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
<div>
|
|
||||||
<ConversationListItem
|
<ConversationListItem
|
||||||
|
name="Someone 🔥 Somewhere"
|
||||||
|
conversationType={'direct'}
|
||||||
phoneNumber="(202) 555-0011"
|
phoneNumber="(202) 555-0011"
|
||||||
name="Mr. Fire🔥"
|
avatarPath={util.gifObjectUrl}
|
||||||
color="green"
|
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
lastMessage={{
|
lastMessage={{
|
||||||
text: 'Sending',
|
text: "What's going on?",
|
||||||
status: 'sending',
|
|
||||||
}}
|
|
||||||
onClick={() => console.log('onClick')}
|
|
||||||
i18n={util.i18n}
|
|
||||||
/>
|
|
||||||
<ConversationListItem
|
|
||||||
phoneNumber="(202) 555-0011"
|
|
||||||
name="Mr. Fire🔥"
|
|
||||||
color="green"
|
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
|
||||||
lastMessage={{
|
|
||||||
text: 'Sent',
|
|
||||||
status: 'sent',
|
status: 'sent',
|
||||||
}}
|
}}
|
||||||
onClick={() => console.log('onClick')}
|
onClick={() => console.log('onClick')}
|
||||||
i18n={util.i18n}
|
i18n={util.i18n}
|
||||||
/>
|
/>
|
||||||
|
</util.LeftPaneContext>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Profile, with name, no avatar
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
<ConversationListItem
|
<ConversationListItem
|
||||||
phoneNumber="(202) 555-0011"
|
phoneNumber="(202) 555-0011"
|
||||||
|
conversationType={'direct'}
|
||||||
name="Mr. Fire🔥"
|
name="Mr. Fire🔥"
|
||||||
color="green"
|
color="green"
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
lastMessage={{
|
lastMessage={{
|
||||||
text: 'Delivered',
|
text: 'Just a second',
|
||||||
status: 'delivered',
|
|
||||||
}}
|
|
||||||
onClick={() => console.log('onClick')}
|
|
||||||
i18n={util.i18n}
|
|
||||||
/>
|
|
||||||
<ConversationListItem
|
|
||||||
phoneNumber="(202) 555-0011"
|
|
||||||
name="Mr. Fire🔥"
|
|
||||||
color="green"
|
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
|
||||||
lastMessage={{
|
|
||||||
text: 'Read',
|
|
||||||
status: 'read',
|
status: 'read',
|
||||||
}}
|
}}
|
||||||
onClick={() => console.log('onClick')}
|
onClick={() => console.log('onClick')}
|
||||||
i18n={util.i18n}
|
i18n={util.i18n}
|
||||||
/>
|
/>
|
||||||
<ConversationListItem
|
</util.LeftPaneContext>
|
||||||
phoneNumber="(202) 555-0011"
|
```
|
||||||
name="Mr. Fire🔥"
|
|
||||||
color="green"
|
#### All types of status
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
|
||||||
lastMessage={{
|
```jsx
|
||||||
text: 'Error',
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
status: 'error',
|
<div>
|
||||||
}}
|
<ConversationListItem
|
||||||
onClick={() => console.log('onClick')}
|
phoneNumber="(202) 555-0011"
|
||||||
i18n={util.i18n}
|
conversationType={'direct'}
|
||||||
/>
|
name="Mr. Fire🔥"
|
||||||
</div>
|
color="green"
|
||||||
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
|
lastMessage={{
|
||||||
|
text: 'Sending',
|
||||||
|
status: 'sending',
|
||||||
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<ConversationListItem
|
||||||
|
phoneNumber="(202) 555-0011"
|
||||||
|
conversationType={'direct'}
|
||||||
|
name="Mr. Fire🔥"
|
||||||
|
color="green"
|
||||||
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
|
lastMessage={{
|
||||||
|
text: 'Sent',
|
||||||
|
status: 'sent',
|
||||||
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<ConversationListItem
|
||||||
|
phoneNumber="(202) 555-0011"
|
||||||
|
conversationType={'direct'}
|
||||||
|
name="Mr. Fire🔥"
|
||||||
|
color="green"
|
||||||
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
|
lastMessage={{
|
||||||
|
text: 'Delivered',
|
||||||
|
status: 'delivered',
|
||||||
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<ConversationListItem
|
||||||
|
phoneNumber="(202) 555-0011"
|
||||||
|
conversationType={'direct'}
|
||||||
|
name="Mr. Fire🔥"
|
||||||
|
color="green"
|
||||||
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
|
lastMessage={{
|
||||||
|
text: 'Read',
|
||||||
|
status: 'read',
|
||||||
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
<ConversationListItem
|
||||||
|
phoneNumber="(202) 555-0011"
|
||||||
|
conversationType={'direct'}
|
||||||
|
name="Mr. Fire🔥"
|
||||||
|
color="green"
|
||||||
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
|
lastMessage={{
|
||||||
|
text: 'Error',
|
||||||
|
status: 'error',
|
||||||
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### With unread
|
#### With unread
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<div>
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
<ConversationListItem
|
<div>
|
||||||
phoneNumber="(202) 555-0011"
|
<ConversationListItem
|
||||||
unreadCount={4}
|
phoneNumber="(202) 555-0011"
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
conversationType={'direct'}
|
||||||
lastMessage={{
|
unreadCount={4}
|
||||||
text: 'Hey there!',
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text: 'Hey there!',
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
<ConversationListItem
|
i18n={util.i18n}
|
||||||
phoneNumber="(202) 555-0011"
|
/>
|
||||||
unreadCount={10}
|
<ConversationListItem
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
phoneNumber="(202) 555-0011"
|
||||||
lastMessage={{
|
conversationType={'direct'}
|
||||||
text: 'Hey there!',
|
unreadCount={10}
|
||||||
}}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
onClick={() => console.log('onClick')}
|
lastMessage={{
|
||||||
i18n={util.i18n}
|
text: 'Hey there!',
|
||||||
/>
|
}}
|
||||||
<ConversationListItem
|
onClick={() => console.log('onClick')}
|
||||||
phoneNumber="(202) 555-0011"
|
i18n={util.i18n}
|
||||||
unreadCount={250}
|
/>
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
<ConversationListItem
|
||||||
lastMessage={{
|
phoneNumber="(202) 555-0011"
|
||||||
text: 'Hey there!',
|
conversationType={'direct'}
|
||||||
}}
|
unreadCount={250}
|
||||||
onClick={() => console.log('onClick')}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
i18n={util.i18n}
|
lastMessage={{
|
||||||
/>
|
text: 'Hey there!',
|
||||||
</div>
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Selected
|
#### Selected
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<ConversationListItem
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
phoneNumber="(202) 555-0011"
|
<ConversationListItem
|
||||||
isSelected={true}
|
phoneNumber="(202) 555-0011"
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
conversationType={'direct'}
|
||||||
lastMessage={{
|
isSelected={true}
|
||||||
text: 'Hey there!',
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text: 'Hey there!',
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### With emoji/links in message, no status
|
#### With emoji/links in message, no status
|
||||||
|
@ -156,26 +177,30 @@
|
||||||
We don't want Jumbomoji or links.
|
We don't want Jumbomoji or links.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<div>
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
<ConversationListItem
|
<div>
|
||||||
phoneNumber="(202) 555-0011"
|
<ConversationListItem
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
phoneNumber="(202) 555-0011"
|
||||||
lastMessage={{
|
conversationType={'direct'}
|
||||||
text: 'Download at http://signal.org',
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text: 'Download at http://signal.org',
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
<ConversationListItem
|
i18n={util.i18n}
|
||||||
phoneNumber="(202) 555-0011"
|
/>
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
<ConversationListItem
|
||||||
lastMessage={{
|
phoneNumber="(202) 555-0011"
|
||||||
text: '🔥',
|
conversationType={'direct'}
|
||||||
}}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
onClick={() => console.log('onClick')}
|
lastMessage={{
|
||||||
i18n={util.i18n}
|
text: '🔥',
|
||||||
/>
|
}}
|
||||||
</div>
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Long content
|
#### Long content
|
||||||
|
@ -183,72 +208,80 @@ We don't want Jumbomoji or links.
|
||||||
We only show one line.
|
We only show one line.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<div>
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
<ConversationListItem
|
<div>
|
||||||
phoneNumber="(202) 555-0011"
|
<ConversationListItem
|
||||||
name="Long contact name. Esquire. The third. And stuff. And more! And more!"
|
phoneNumber="(202) 555-0011"
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
conversationType={'direct'}
|
||||||
lastMessage={{
|
name="Long contact name. Esquire. The third. And stuff. And more! And more!"
|
||||||
text: 'Normal message',
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text: 'Normal message',
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
<ConversationListItem
|
i18n={util.i18n}
|
||||||
phoneNumber="(202) 555-0011"
|
/>
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
<ConversationListItem
|
||||||
lastMessage={{
|
phoneNumber="(202) 555-0011"
|
||||||
text:
|
conversationType={'direct'}
|
||||||
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text:
|
||||||
i18n={util.i18n}
|
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
||||||
/>
|
}}
|
||||||
<ConversationListItem
|
onClick={() => console.log('onClick')}
|
||||||
phoneNumber="(202) 555-0011"
|
i18n={util.i18n}
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
/>
|
||||||
lastMessage={{
|
<ConversationListItem
|
||||||
text:
|
phoneNumber="(202) 555-0011"
|
||||||
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
conversationType={'direct'}
|
||||||
status: 'read',
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text:
|
||||||
i18n={util.i18n}
|
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
||||||
/>
|
status: 'read',
|
||||||
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
|
||||||
<ConversationListItem
|
<ConversationListItem
|
||||||
phoneNumber="(202) 555-0011"
|
phoneNumber="(202) 555-0011"
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
conversationType={'direct'}
|
||||||
unreadCount={8}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
lastMessage={{
|
unreadCount={8}
|
||||||
text:
|
lastMessage={{
|
||||||
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
text:
|
||||||
}}
|
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
||||||
onClick={() => console.log('onClick')}
|
}}
|
||||||
i18n={util.i18n}
|
onClick={() => console.log('onClick')}
|
||||||
/>
|
i18n={util.i18n}
|
||||||
<ConversationListItem
|
/>
|
||||||
phoneNumber="(202) 555-0011"
|
<ConversationListItem
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
phoneNumber="(202) 555-0011"
|
||||||
lastMessage={{
|
conversationType={'direct'}
|
||||||
text:
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
"Many lines. This is a many-line message.\nLine 2 is really exciting but it shouldn't be seen.\nLine three is even better.\nLine 4, well.",
|
lastMessage={{
|
||||||
}}
|
text:
|
||||||
onClick={() => console.log('onClick')}
|
"Many lines. This is a many-line message.\nLine 2 is really exciting but it shouldn't be seen.\nLine three is even better.\nLine 4, well.",
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
<ConversationListItem
|
i18n={util.i18n}
|
||||||
phoneNumber="(202) 555-0011"
|
/>
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
<ConversationListItem
|
||||||
lastMessage={{
|
phoneNumber="(202) 555-0011"
|
||||||
text:
|
conversationType={'direct'}
|
||||||
"Many lines. This is a many-line message.\nLine 2 is really exciting but it shouldn't be seen.\nLine three is even better.\nLine 4, well.",
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
status: 'delivered',
|
lastMessage={{
|
||||||
}}
|
text:
|
||||||
onClick={() => console.log('onClick')}
|
"Many lines. This is a many-line message.\nLine 2 is really exciting but it shouldn't be seen.\nLine three is even better.\nLine 4, well.",
|
||||||
i18n={util.i18n}
|
status: 'delivered',
|
||||||
/>
|
}}
|
||||||
</div>
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### More narrow
|
#### More narrow
|
||||||
|
@ -256,104 +289,119 @@ We only show one line.
|
||||||
On platforms that show scrollbars all the time, this is true all the time.
|
On platforms that show scrollbars all the time, this is true all the time.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<div style={{ width: '280px' }}>
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
<ConversationListItem
|
<div style={{ width: '280px' }}>
|
||||||
phoneNumber="(202) 555-0011"
|
<ConversationListItem
|
||||||
name="Long contact name. Esquire. The third. And stuff. And more! And more!"
|
phoneNumber="(202) 555-0011"
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
conversationType={'direct'}
|
||||||
lastMessage={{
|
name="Long contact name. Esquire. The third. And stuff. And more! And more!"
|
||||||
text: 'Normal message',
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text: 'Normal message',
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
<ConversationListItem
|
i18n={util.i18n}
|
||||||
phoneNumber="(202) 555-0011"
|
/>
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
<ConversationListItem
|
||||||
lastMessage={{
|
phoneNumber="(202) 555-0011"
|
||||||
text:
|
conversationType={'direct'}
|
||||||
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text:
|
||||||
i18n={util.i18n}
|
"Long line. This is a really really really long line. Really really long. Because that's just how it is",
|
||||||
/>
|
}}
|
||||||
</div>
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### With various ages
|
#### With various ages
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<div>
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
<ConversationListItem
|
<div>
|
||||||
phoneNumber="(202) 555-0011"
|
<ConversationListItem
|
||||||
lastUpdated={Date.now() - 5 * 60 * 60 * 1000}
|
phoneNumber="(202) 555-0011"
|
||||||
lastMessage={{
|
conversationType={'direct'}
|
||||||
text: 'Five hours ago',
|
lastUpdated={Date.now() - 5 * 60 * 60 * 1000}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text: 'Five hours ago',
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
<ConversationListItem
|
i18n={util.i18n}
|
||||||
phoneNumber="(202) 555-0011"
|
/>
|
||||||
lastUpdated={Date.now() - 24 * 60 * 60 * 1000}
|
<ConversationListItem
|
||||||
lastMessage={{
|
phoneNumber="(202) 555-0011"
|
||||||
text: 'One day ago',
|
conversationType={'direct'}
|
||||||
}}
|
lastUpdated={Date.now() - 24 * 60 * 60 * 1000}
|
||||||
onClick={() => console.log('onClick')}
|
lastMessage={{
|
||||||
i18n={util.i18n}
|
text: 'One day ago',
|
||||||
/>
|
}}
|
||||||
<ConversationListItem
|
onClick={() => console.log('onClick')}
|
||||||
phoneNumber="(202) 555-0011"
|
i18n={util.i18n}
|
||||||
lastUpdated={Date.now() - 7 * 24 * 60 * 60 * 1000}
|
/>
|
||||||
lastMessage={{
|
<ConversationListItem
|
||||||
text: 'One week ago',
|
phoneNumber="(202) 555-0011"
|
||||||
}}
|
conversationType={'direct'}
|
||||||
onClick={() => console.log('onClick')}
|
lastUpdated={Date.now() - 7 * 24 * 60 * 60 * 1000}
|
||||||
i18n={util.i18n}
|
lastMessage={{
|
||||||
/>
|
text: 'One week ago',
|
||||||
<ConversationListItem
|
}}
|
||||||
phoneNumber="(202) 555-0011"
|
onClick={() => console.log('onClick')}
|
||||||
lastUpdated={Date.now() - 365 * 24 * 60 * 60 * 1000}
|
i18n={util.i18n}
|
||||||
lastMessage={{
|
/>
|
||||||
text: 'One year ago',
|
<ConversationListItem
|
||||||
}}
|
phoneNumber="(202) 555-0011"
|
||||||
onClick={() => console.log('onClick')}
|
conversationType={'direct'}
|
||||||
i18n={util.i18n}
|
lastUpdated={Date.now() - 365 * 24 * 60 * 60 * 1000}
|
||||||
/>
|
lastMessage={{
|
||||||
</div>
|
text: 'One year ago',
|
||||||
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Missing data
|
#### Missing data
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
<div>
|
<util.LeftPaneContext theme={util.theme}>
|
||||||
<ConversationListItem
|
<div>
|
||||||
name="John"
|
<ConversationListItem
|
||||||
lastUpdated={null}
|
name="John"
|
||||||
lastMessage={{
|
conversationType={'direct'}
|
||||||
text: 'Missing last updated',
|
lastUpdated={null}
|
||||||
}}
|
lastMessage={{
|
||||||
onClick={() => console.log('onClick')}
|
text: 'Missing last updated',
|
||||||
i18n={util.i18n}
|
}}
|
||||||
/>
|
onClick={() => console.log('onClick')}
|
||||||
<ConversationListItem
|
i18n={util.i18n}
|
||||||
name="Missing message"
|
/>
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
<ConversationListItem
|
||||||
lastMessage={{
|
name="Missing message"
|
||||||
text: null,
|
conversationType={'direct'}
|
||||||
}}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
onClick={() => console.log('onClick')}
|
lastMessage={{
|
||||||
i18n={util.i18n}
|
text: null,
|
||||||
/>
|
}}
|
||||||
<ConversationListItem
|
onClick={() => console.log('onClick')}
|
||||||
phoneNumber="(202) 555-0011"
|
i18n={util.i18n}
|
||||||
lastUpdated={Date.now() - 5 * 60 * 1000}
|
/>
|
||||||
lastMessage={{
|
<ConversationListItem
|
||||||
text: null,
|
phoneNumber="(202) 555-0011"
|
||||||
status: 'sent',
|
conversationType={'direct'}
|
||||||
}}
|
lastUpdated={Date.now() - 5 * 60 * 1000}
|
||||||
onClick={() => console.log('onClick')}
|
lastMessage={{
|
||||||
i18n={util.i18n}
|
text: null,
|
||||||
/>
|
status: 'sent',
|
||||||
</div>
|
}}
|
||||||
|
onClick={() => console.log('onClick')}
|
||||||
|
i18n={util.i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</util.LeftPaneContext>
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { Avatar } from './Avatar';
|
||||||
import { MessageBody } from './conversation/MessageBody';
|
import { MessageBody } from './conversation/MessageBody';
|
||||||
import { Timestamp } from './conversation/Timestamp';
|
import { Timestamp } from './conversation/Timestamp';
|
||||||
import { ContactName } from './conversation/ContactName';
|
import { ContactName } from './conversation/ContactName';
|
||||||
|
@ -11,6 +12,7 @@ interface Props {
|
||||||
profileName?: string;
|
profileName?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
|
conversationType: 'group' | 'direct';
|
||||||
avatarPath?: string;
|
avatarPath?: string;
|
||||||
|
|
||||||
lastUpdated: number;
|
lastUpdated: number;
|
||||||
|
@ -26,50 +28,29 @@ interface Props {
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitial(name: string): string {
|
|
||||||
return name.trim()[0] || '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ConversationListItem extends React.Component<Props> {
|
export class ConversationListItem extends React.Component<Props> {
|
||||||
public renderAvatar() {
|
public renderAvatar() {
|
||||||
const {
|
const {
|
||||||
avatarPath,
|
avatarPath,
|
||||||
color,
|
color,
|
||||||
|
conversationType,
|
||||||
i18n,
|
i18n,
|
||||||
name,
|
name,
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
profileName,
|
profileName,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!avatarPath) {
|
|
||||||
const initial = getInitial(name || '');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="module-conversation-list-item__avatar-container">
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
'module-conversation-list-item__avatar',
|
|
||||||
'module-conversation-list-item__default-avatar',
|
|
||||||
`module-conversation-list-item__default-avatar--${color}`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{initial}
|
|
||||||
</div>
|
|
||||||
{this.renderUnread()}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const title = `${name || phoneNumber}${
|
|
||||||
!name && profileName ? ` ~${profileName}` : ''
|
|
||||||
}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-conversation-list-item__avatar-container">
|
<div className="module-conversation-list-item__avatar-container">
|
||||||
<img
|
<Avatar
|
||||||
className="module-conversation-list-item__avatar"
|
avatarPath={avatarPath}
|
||||||
alt={i18n('contactAvatarAlt', [title])}
|
color={color}
|
||||||
src={avatarPath}
|
conversationType={conversationType}
|
||||||
|
i18n={i18n}
|
||||||
|
name={name}
|
||||||
|
phoneNumber={phoneNumber}
|
||||||
|
profileName={profileName}
|
||||||
|
size={48}
|
||||||
/>
|
/>
|
||||||
{this.renderUnread()}
|
{this.renderUnread()}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -207,7 +207,9 @@ export class ContactDetail extends React.Component<Props> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-contact-detail">
|
<div className="module-contact-detail">
|
||||||
{renderAvatar({ contact, i18n, module })}
|
<div className="module-contact-detail__avatar">
|
||||||
|
{renderAvatar({ contact, i18n, size: 80 })}
|
||||||
|
</div>
|
||||||
{renderName({ contact, isIncoming, module })}
|
{renderName({ contact, isIncoming, module })}
|
||||||
{renderContactShorthand({ contact, isIncoming, module })}
|
{renderContactShorthand({ contact, isIncoming, module })}
|
||||||
{this.renderSendMessage({ hasSignalAccount, i18n, onSendMessage })}
|
{this.renderSendMessage({ hasSignalAccount, i18n, onSendMessage })}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import { Emojify } from './Emojify';
|
import { Emojify } from './Emojify';
|
||||||
|
import { Avatar } from '../Avatar';
|
||||||
import { Localizer } from '../../types/Util';
|
import { Localizer } from '../../types/Util';
|
||||||
import {
|
import {
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
|
@ -45,10 +45,6 @@ interface Props {
|
||||||
onGoBack: () => void;
|
onGoBack: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitial(name: string): string {
|
|
||||||
return name.trim()[0] || '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ConversationHeader extends React.Component<Props> {
|
export class ConversationHeader extends React.Component<Props> {
|
||||||
public captureMenuTriggerBound: (trigger: any) => void;
|
public captureMenuTriggerBound: (trigger: any) => void;
|
||||||
public showMenuBound: (event: React.MouseEvent<HTMLDivElement>) => void;
|
public showMenuBound: (event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
|
@ -116,37 +112,25 @@ export class ConversationHeader extends React.Component<Props> {
|
||||||
avatarPath,
|
avatarPath,
|
||||||
color,
|
color,
|
||||||
i18n,
|
i18n,
|
||||||
|
isGroup,
|
||||||
name,
|
name,
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
profileName,
|
profileName,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!avatarPath) {
|
|
||||||
const initial = getInitial(name || '');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
'module-conversation-header___avatar',
|
|
||||||
'module-conversation-header___default-avatar',
|
|
||||||
`module-conversation-header___default-avatar--${color}`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{initial}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const title = `${name || phoneNumber}${
|
|
||||||
!name && profileName ? ` ~${profileName}` : ''
|
|
||||||
}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<span className="module-conversation-header__avatar">
|
||||||
className="module-conversation-header___avatar"
|
<Avatar
|
||||||
alt={i18n('contactAvatarAlt', [title])}
|
avatarPath={avatarPath}
|
||||||
src={avatarPath}
|
color={color}
|
||||||
/>
|
conversationType={isGroup ? 'group' : 'direct'}
|
||||||
|
i18n={i18n}
|
||||||
|
name={name}
|
||||||
|
phoneNumber={phoneNumber}
|
||||||
|
profileName={profileName}
|
||||||
|
size={28}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { Avatar } from '../Avatar';
|
||||||
import { Contact, getName } from '../../types/Contact';
|
import { Contact, getName } from '../../types/Contact';
|
||||||
|
|
||||||
import { Localizer } from '../../types/Util';
|
import { Localizer } from '../../types/Util';
|
||||||
|
@ -41,7 +42,7 @@ export class EmbeddedContact extends React.Component<Props> {
|
||||||
role="button"
|
role="button"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
{renderAvatar({ contact, i18n, module })}
|
{renderAvatar({ contact, i18n, size: 48 })}
|
||||||
<div className="module-embedded-contact__text-container">
|
<div className="module-embedded-contact__text-container">
|
||||||
{renderName({ contact, isIncoming, module })}
|
{renderName({ contact, isIncoming, module })}
|
||||||
{renderContactShorthand({ contact, isIncoming, module })}
|
{renderContactShorthand({ contact, isIncoming, module })}
|
||||||
|
@ -53,40 +54,29 @@ export class EmbeddedContact extends React.Component<Props> {
|
||||||
|
|
||||||
// Note: putting these below the main component so style guide picks up EmbeddedContact
|
// Note: putting these below the main component so style guide picks up EmbeddedContact
|
||||||
|
|
||||||
function getInitial(name: string): string {
|
|
||||||
return name.trim()[0] || '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderAvatar({
|
export function renderAvatar({
|
||||||
contact,
|
contact,
|
||||||
i18n,
|
i18n,
|
||||||
module,
|
size,
|
||||||
}: {
|
}: {
|
||||||
contact: Contact;
|
contact: Contact;
|
||||||
i18n: Localizer;
|
i18n: Localizer;
|
||||||
module: string;
|
size: number;
|
||||||
}) {
|
}) {
|
||||||
const { avatar } = contact;
|
const { avatar } = contact;
|
||||||
|
|
||||||
const path = avatar && avatar.avatar && avatar.avatar.path;
|
const avatarPath = avatar && avatar.avatar && avatar.avatar.path;
|
||||||
const name = getName(contact) || '';
|
const name = getName(contact) || '';
|
||||||
|
|
||||||
if (!path) {
|
|
||||||
const initials = getInitial(name);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`module-${module}__image-container`}>
|
|
||||||
<div className={`module-${module}__image-container__default-avatar`}>
|
|
||||||
{initials}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`module-${module}__image-container`}>
|
<Avatar
|
||||||
<img src={path} alt={i18n('contactAvatarAlt', [name])} />
|
avatarPath={avatarPath}
|
||||||
</div>
|
color="grey"
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={i18n}
|
||||||
|
name={name}
|
||||||
|
size={size}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
isVideoTypeSupported,
|
isVideoTypeSupported,
|
||||||
} from '../../util/GoogleChrome';
|
} from '../../util/GoogleChrome';
|
||||||
|
|
||||||
|
import { Avatar } from '../Avatar';
|
||||||
import { MessageBody } from './MessageBody';
|
import { MessageBody } from './MessageBody';
|
||||||
import { ExpireTimer, getIncrement } from './ExpireTimer';
|
import { ExpireTimer, getIncrement } from './ExpireTimer';
|
||||||
import { Timestamp } from './Timestamp';
|
import { Timestamp } from './Timestamp';
|
||||||
|
@ -133,10 +134,6 @@ function canDisplayImage(attachment?: Attachment) {
|
||||||
return height > 0 && height <= 4096 && width > 0 && width <= 4096;
|
return height > 0 && height <= 4096 && width > 0 && width <= 4096;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitial(name: string): string {
|
|
||||||
return name.trim()[0] || '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getExtension({
|
function getExtension({
|
||||||
fileName,
|
fileName,
|
||||||
contentType,
|
contentType,
|
||||||
|
@ -633,21 +630,17 @@ export class Message extends React.Component<Props, State> {
|
||||||
|
|
||||||
public renderAvatar() {
|
public renderAvatar() {
|
||||||
const {
|
const {
|
||||||
|
authorAvatarPath,
|
||||||
authorName,
|
authorName,
|
||||||
authorPhoneNumber,
|
authorPhoneNumber,
|
||||||
authorProfileName,
|
authorProfileName,
|
||||||
authorAvatarPath,
|
|
||||||
conversationColor,
|
|
||||||
collapseMetadata,
|
collapseMetadata,
|
||||||
|
conversationColor,
|
||||||
conversationType,
|
conversationType,
|
||||||
direction,
|
direction,
|
||||||
i18n,
|
i18n,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const title = `${authorName || authorPhoneNumber}${
|
|
||||||
!authorName && authorProfileName ? ` ~${authorProfileName}` : ''
|
|
||||||
}`;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
collapseMetadata ||
|
collapseMetadata ||
|
||||||
conversationType !== 'group' ||
|
conversationType !== 'group' ||
|
||||||
|
@ -656,26 +649,18 @@ export class Message extends React.Component<Props, State> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!authorAvatarPath) {
|
|
||||||
const label = authorName ? getInitial(authorName) : '#';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
'module-message__author-default-avatar',
|
|
||||||
`module-message__author-default-avatar--${conversationColor}`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="module-message__author-default-avatar__label">
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-message__author-avatar">
|
<div className="module-message__author-avatar">
|
||||||
<img alt={i18n('contactAvatarAlt', [title])} src={authorAvatarPath} />
|
<Avatar
|
||||||
|
avatarPath={authorAvatarPath}
|
||||||
|
color={conversationColor}
|
||||||
|
conversationType="direct"
|
||||||
|
i18n={i18n}
|
||||||
|
name={authorName}
|
||||||
|
phoneNumber={authorPhoneNumber}
|
||||||
|
profileName={authorProfileName}
|
||||||
|
size={36}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import { Avatar } from '../Avatar';
|
||||||
import { ContactName } from './ContactName';
|
import { ContactName } from './ContactName';
|
||||||
import { Message, Props as MessageProps } from './Message';
|
import { Message, Props as MessageProps } from './Message';
|
||||||
import { Localizer } from '../../types/Util';
|
import { Localizer } from '../../types/Util';
|
||||||
|
@ -31,40 +32,21 @@ interface Props {
|
||||||
i18n: Localizer;
|
i18n: Localizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInitial(name: string): string {
|
|
||||||
return name.trim()[0] || '#';
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MessageDetail extends React.Component<Props> {
|
export class MessageDetail extends React.Component<Props> {
|
||||||
public renderAvatar(contact: Contact) {
|
public renderAvatar(contact: Contact) {
|
||||||
const { i18n } = this.props;
|
const { i18n } = this.props;
|
||||||
const { avatarPath, color, phoneNumber, name, profileName } = contact;
|
const { avatarPath, color, phoneNumber, name, profileName } = contact;
|
||||||
|
|
||||||
if (!avatarPath) {
|
|
||||||
const initial = getInitial(name || '');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
'module-message-detail__contact__avatar',
|
|
||||||
'module-message-detail__contact__default-avatar',
|
|
||||||
`module-message-detail__contact__default-avatar--${color}`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{initial}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const title = `${name || phoneNumber}${
|
|
||||||
!name && profileName ? ` ~${profileName}` : ''
|
|
||||||
}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<Avatar
|
||||||
className="module-message-detail__contact__avatar"
|
avatarPath={avatarPath}
|
||||||
alt={i18n('contactAvatarAlt', [title])}
|
color={color}
|
||||||
src={avatarPath}
|
conversationType="direct"
|
||||||
|
i18n={i18n}
|
||||||
|
name={name}
|
||||||
|
phoneNumber={phoneNumber}
|
||||||
|
profileName={profileName}
|
||||||
|
size={48}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
25
ts/styleguide/LeftPaneContext.tsx
Normal file
25
ts/styleguide/LeftPaneContext.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/**
|
||||||
|
* Corresponds to the theme setting in the app, and the class added to the root element.
|
||||||
|
*/
|
||||||
|
theme: 'light-theme' | 'dark-theme';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the parent elements necessary to allow the main Signal Desktop stylesheet to
|
||||||
|
* apply (with no changes) to messages in the Style Guide.
|
||||||
|
*/
|
||||||
|
export class LeftPaneContext extends React.Component<Props> {
|
||||||
|
public render() {
|
||||||
|
const { theme } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames(theme || 'light-theme')}>
|
||||||
|
<div className="gutter">{this.props.children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import classNames from 'classnames';
|
||||||
|
|
||||||
import { default as _ } from 'lodash';
|
import { default as _ } from 'lodash';
|
||||||
export { ConversationContext } from './ConversationContext';
|
export { ConversationContext } from './ConversationContext';
|
||||||
|
export { LeftPaneContext } from './LeftPaneContext';
|
||||||
|
|
||||||
export { _, classNames };
|
export { _, classNames };
|
||||||
|
|
||||||
|
|
21
ts/util/getInitials.ts
Normal file
21
ts/util/getInitials.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
const BAD_CHARACTERS = /[^A-Za-z\s]+/g;
|
||||||
|
const WHITESPACE = /\s+/g;
|
||||||
|
|
||||||
|
function removeNonInitials(name: string) {
|
||||||
|
return name.replace(BAD_CHARACTERS, '').replace(WHITESPACE, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInitials(name?: string): string | null {
|
||||||
|
if (!name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleaned = removeNonInitials(name);
|
||||||
|
const parts = cleaned.split(' ');
|
||||||
|
const initials = parts.map(part => part.trim()[0]);
|
||||||
|
if (!initials.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return initials.slice(0, 2).join('');
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue