-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* recent * recent contacts * recent everything * FileUploadAPIClient.mimeToType() to get the filetype + document to FileUploadAPIClient.mimeToType() removed unnecessary comments images recreated as svg and moved out of code Co-authored-by: Romaric Mourgues <rmourgues@linagora.com>
- Loading branch information
1 parent
f60f2fc
commit 009257b
Showing
36 changed files
with
1,384 additions
and
588 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions
76
twake/frontend/src/app/components/channel-avatar/channel-avatar.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
|
||
|
||
.component-channel-avatar { | ||
|
||
display: inline-flex; | ||
flex-direction: column; | ||
|
||
|
||
|
||
.channel-icon-container{ | ||
display: flex; | ||
flex-direction: row; | ||
|
||
} | ||
|
||
$iconWidth: 64px; | ||
|
||
.channel-icon-wrapper { | ||
height: $iconWidth; | ||
width: $iconWidth; | ||
border-radius: 50%; | ||
box-shadow: 1px 1px 3px #ccc; | ||
margin-bottom:2px; | ||
align-items: center; | ||
text-align: center; | ||
display: flex; | ||
|
||
.channel-icon-text { | ||
line-height: 64px; | ||
width:100%; | ||
font-size: 24px; | ||
color:white; | ||
font-weight: 700; | ||
} | ||
|
||
.channel-icon-img { | ||
width:$iconWidth; | ||
height:$iconWidth; | ||
object-fit: cover; | ||
object-position: 50% 15%; | ||
border-radius: 50%; | ||
|
||
} | ||
} | ||
|
||
.channel-icon-wrapper:not(:first-child){ | ||
margin-left:calc($iconWidth*2/5*-1); | ||
} | ||
|
||
|
||
.channel-label { | ||
text-align: center; | ||
font-size:10px; | ||
line-height: 1.2em; | ||
padding-top:4px; | ||
padding-bottom:4px; | ||
width:$iconWidth; | ||
} | ||
|
||
.channel-icon-wrapper.style0{ | ||
background: var(--messagebubblelight); | ||
} | ||
|
||
.channel-icon-wrapper.style1 {background: linear-gradient(129.62deg, #9F2EF4 15.98%, #F97D64 50.17%, #F6C533 82.97%);} | ||
.channel-icon-wrapper.style2 {background: linear-gradient(124.19deg, #0099C0 12.87%, #0099C0 49.65%, #3DD5A8 84.94%);} | ||
.channel-icon-wrapper.style3 {background: linear-gradient(137.24deg, #D3A6FF 15.1%, #B966B5 50.52%, #7E72C6 85.13%);} | ||
.channel-icon-wrapper.style4 {background: linear-gradient(124.08deg, #E2EF54 14.56%, #FF5C66 47.57%, #6248D5 83.84%);} | ||
.channel-icon-wrapper.style5 {background: linear-gradient(120.32deg, #FF5CF1 14.48%, #B38ADE 51.66%, #56CDDF 84.61%);} | ||
.channel-icon-wrapper.style6 {background: linear-gradient(120.32deg, #75C192 14.48%, #70BDA0 51.66%, #21B59C 84.61%);} | ||
.channel-icon-wrapper.style7 {background: linear-gradient(136.93deg, #FFA6AF 14.87%, #E62E40 50.07%, #AA0909 84.36%);} | ||
.channel-icon-wrapper.style8 {background: linear-gradient(136.93deg, #335F50 14.87%, #47888C 50.07%, #08C992 84.36%);} | ||
.channel-icon-wrapper.style9 {background: linear-gradient(135.32deg, #6CD97E 15.23%, #12B312 56.97%, #117600 84.49%);} | ||
.channel-icon-wrapper.style10 {background: linear-gradient(135deg, #7DF1FA 14.84%, #2BB4D6 49.93%, #008AA2 82.63%);} | ||
.channel-icon-wrapper.style11 {background: linear-gradient(136.26deg, #FFBF80 13.66%, #E66B2E 51.13%, #A64300 84.79%);} | ||
} | ||
|
105 changes: 105 additions & 0 deletions
105
twake/frontend/src/app/components/channel-avatar/channel-avatar.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { ChannelType } from 'features/channels/types/channel'; | ||
import React from 'react'; | ||
import './channel-avatar.scss'; | ||
import UsersService from 'features/users/services/current-user-service'; | ||
import UserService from 'features/users/services/current-user-service'; | ||
import { UserType } from 'features/users/types/user'; | ||
import { getUser } from 'features/users/hooks/use-user-list'; | ||
import { addApiUrlIfNeeded } from 'features/global/utils/URLUtils'; | ||
|
||
const emoji = require('emoji-name-map'); | ||
|
||
type PropsType = { | ||
channel: ChannelType; | ||
showLabel: boolean; | ||
}; | ||
|
||
export default ({ channel, showLabel }: PropsType): JSX.Element => { | ||
if (channel.visibility === 'direct') { | ||
let channelMembers = (channel.members || []).filter(e => e !== UsersService.getCurrentUserId()); | ||
channelMembers = channelMembers.filter((e, i) => channelMembers.indexOf(e) === i); | ||
|
||
let channelName: string[] = []; | ||
|
||
let users: UserType[] = []; | ||
|
||
channelMembers.forEach(userId => users.push(getUser(userId))); | ||
|
||
const icons = [] as JSX.Element[]; | ||
|
||
users.forEach(member => { | ||
channelName.push(UserService.getFullName(member)); | ||
icons.push(getThumbnail(member)); | ||
}); | ||
|
||
let width = 64; | ||
|
||
if (channelMembers.length > 1) { | ||
const shift = 64 - (64 * 2) / 5; | ||
width = 64 + (channelMembers.length - 1) * shift; | ||
} | ||
|
||
return ( | ||
<div className="component-channel-avatar"> | ||
<div className="channel-icon-container">{icons.map(icon => icon)}</div> | ||
{showLabel && ( | ||
<div className="channel-label" style={{ width: width }}> | ||
{channelName.join(', ')} | ||
</div> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
let thumbnail; | ||
let label = channel?.name; | ||
|
||
if (channel.icon) { | ||
thumbnail = emoji.get(channel.icon); | ||
} | ||
|
||
if (!thumbnail && channel.name) { | ||
thumbnail = ''; | ||
const channelName = | ||
channel.name.indexOf(' ') < 0 ? channel.name.replace('_', ' ') : channel.name; | ||
const split = channelName.toUpperCase().split(' '); | ||
thumbnail += (split?.[0]?.[0] || '') + (split?.[1]?.[0] || ''); | ||
} | ||
|
||
const style = getStyle(channel.id); | ||
|
||
return ( | ||
<div className="component-channel-avatar"> | ||
<div className={'channel-icon-wrapper' + style}> | ||
<div className="channel-icon-text">{thumbnail}</div> | ||
</div> | ||
{showLabel && <div className="channel-label">{label}</div>} | ||
</div> | ||
); | ||
}; | ||
|
||
const getStyle = (id?: string) => { | ||
if (!id) return ''; | ||
let output = 0; | ||
for (let i = 0; i < id.length; i++) { | ||
output += id[i].charCodeAt(0); | ||
} | ||
const i = (output % 10) + 1; | ||
return ` style${i}`; | ||
}; | ||
|
||
const getThumbnail = (user: UserType) => { | ||
let inner; | ||
let style = ''; | ||
if (user && (user.thumbnail || user.picture)) { | ||
const thumbnail = addApiUrlIfNeeded(user.picture || user.thumbnail || ''); | ||
inner = <img alt={user.first_name} className="channel-icon-img" src={thumbnail} />; | ||
} else { | ||
const fullName = UserService.getFullName(user).toUpperCase().split(' '); | ||
let letters = (fullName?.[0]?.[0] || '?') + (fullName?.[1]?.[0] || ''); | ||
inner = <div className="channel-icon-text">{letters}</div>; | ||
style = getStyle(user.id); | ||
} | ||
|
||
return <div className={`channel-icon-wrapper${style}`}>{inner}</div>; | ||
}; |
Oops, something went wrong.