Skip to content

Commit

Permalink
frontend: better contact avatars fallback
Browse files Browse the repository at this point in the history
  • Loading branch information
allgood committed Jul 4, 2024
1 parent d90ee02 commit 7ac98c2
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 4 deletions.
4 changes: 3 additions & 1 deletion frontend/src/components/ContactDrawer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { CardHeader } from "@material-ui/core";
import { ContactForm } from "../ContactForm";
import ContactModal from "../ContactModal";
import { ContactNotes } from "../ContactNotes";
import { generateColor } from "../../helpers/colorGenerator";
import { getInitials } from "../../helpers/getInitials";

const drawerWidth = 320;

Expand Down Expand Up @@ -129,7 +131,7 @@ const ContactDrawer = ({ open, handleDrawerClose, contact, ticket, loading }) =>
style={{ cursor: "pointer", width: '100%' }}
titleTypographyProps={{ noWrap: true }}
subheaderTypographyProps={{ noWrap: true }}
avatar={<Avatar src={contact.profilePicUrl} alt="contact_image" style={{ width: 60, height: 60 }} />}
avatar={<Avatar src={contact.profilePicUrl} alt="contact_image" style={{ width: 60, height: 60, backgroundColor: generateColor(contact?.number), color: "white", fontWeight: "bold" }}>{ getInitials(contact?.name) }</Avatar>}
title={
<>
<Typography onClick={() => setOpenForm(true)}>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/TicketInfo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import React, { useState, useEffect } from "react";
import { Avatar, CardHeader } from "@material-ui/core";

import { i18n } from "../../translate/i18n";
import { getInitials } from "../../helpers/getInitials";
import { generateColor } from "../../helpers/colorGenerator";

const TicketInfo = ({ contact, ticket, onClick }) => {
const { user } = ticket
Expand Down Expand Up @@ -36,7 +38,7 @@ const TicketInfo = ({ contact, ticket, onClick }) => {
style={{ cursor: "pointer" }}
titleTypographyProps={{ noWrap: true }}
subheaderTypographyProps={{ noWrap: true }}
avatar={<Avatar src={contact.profilePicUrl} alt="contact_image" />}
avatar={<Avatar style={{ backgroundColor: generateColor(contact?.number), color: "white", fontWeight: "bold" }} src={contact.profilePicUrl} alt="contact_image">{ getInitials(contact?.name) }</Avatar>}
title={`${contactName} #${ticket.id}`}
subheader={ticket.user && `${userName}`}
/>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/TicketListItemCustom/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import VisibilityIcon from "@material-ui/icons/Visibility";
import TicketMessagesDialog from "../TicketMessagesDialog";
import DoneIcon from '@material-ui/icons/Done';
import ClearOutlinedIcon from '@material-ui/icons/ClearOutlined';
import { generateColor } from "../../helpers/colorGenerator";
import { getInitials } from "../../helpers/getInitials";

const useStyles = makeStyles((theme) => ({
ticket: {
Expand Down Expand Up @@ -490,7 +492,7 @@ const TicketListItemCustom = ({ ticket, setTabOpen }) => {
></span>
</Tooltip>
<ListItemAvatar>
<Avatar src={ticket?.contact?.profilePicUrl} />
<Avatar style={{ backgroundColor: generateColor(ticket?.contact?.number), color: "white", fontWeight: "bold" }} src={ticket?.contact?.profilePicUrl}>{ getInitials(ticket?.contact?.name || "") }</Avatar>
</ListItemAvatar>
<ListItemText
disableTypography
Expand Down
68 changes: 68 additions & 0 deletions frontend/src/helpers/colorGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// colorGenerator.js

// Function to hash a string to a number
function hashStringToNumber(str) {
if (!str) {
return 0x7F7F7F; // 50% of all colors
}

let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash |= 0; // Convert to 32bit integer
}
return hash;
}

// Function to generate a color from a hash
function generateColorFromHash(hash) {
// Normalize the hash value
const normalizedHash = Math.abs(hash) % 16777215; // 16777215 is 0xFFFFFF
const r = (normalizedHash & 0xFF0000) >> 16;
const g = (normalizedHash & 0x00FF00) >> 8;
const b = normalizedHash & 0x0000FF;
return { r, g, b };
}

// Function to get the luminance of a color
function getLuminance(r, g, b) {
return 0.299 * r + 0.587 * g + 0.114 * b;
}

// Function to adjust color for contrast
function adjustColorForContrast(r, g, b) {
const luminance = getLuminance(r, g, b);
const thresholdLow = 50; // Luminance threshold for dark colors
const thresholdHigh = 200; // Luminance threshold for bright colors

if (luminance < thresholdLow) {
// Lighten the color if too dark
r = Math.min(255, r + 50);
g = Math.min(255, g + 50);
b = Math.min(255, b + 50);
} else if (luminance > thresholdHigh) {
// Darken the color if too bright
r = Math.max(0, r - 50);
g = Math.max(0, g - 50);
b = Math.max(0, b - 50);
}
return `rgb(${r}, ${g}, ${b})`;
}

// Main function to generate color from user identifier
function generateColor(identifier) {
const hash = hashStringToNumber(identifier);
const { r, g, b } = generateColorFromHash(hash);
const luminance = getLuminance(r, g, b);
const thresholdLow = 50; // Luminance threshold for dark colors
const thresholdHigh = 200; // Luminance threshold for bright colors

if (luminance < thresholdLow || luminance > thresholdHigh) {
return adjustColorForContrast(r, g, b);
}
return `rgb(${r}, ${g}, ${b})`;
}

// Export the function
export { generateColor };
15 changes: 15 additions & 0 deletions frontend/src/helpers/getInitials.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var getInitials = function(string) {
if (!string) {
return "";
}

var names = string.split(' '),
initials = names[0].substring(0, 1).toUpperCase();

if (names.length > 1) {
initials += names[names.length - 1].substring(0, 1).toUpperCase();
}
return initials;
};

export { getInitials };
4 changes: 3 additions & 1 deletion frontend/src/pages/Contacts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { AuthContext } from "../../context/Auth/AuthContext";
import { Can } from "../../components/Can";
import NewTicketModal from "../../components/NewTicketModal";
import { SocketContext } from "../../context/Socket/SocketContext";
import { generateColor } from "../../helpers/colorGenerator";
import { getInitials } from "../../helpers/getInitials";

const reducer = (state, action) => {
if (action.type === "LOAD_CONTACTS") {
Expand Down Expand Up @@ -324,7 +326,7 @@ const Contacts = () => {
{contacts.map((contact) => (
<TableRow key={contact.id}>
<TableCell style={{ paddingRight: 0 }}>
{<Avatar src={contact.profilePicUrl} />}
{<Avatar style={{ backgroundColor: generateColor(contact?.number), fontWeight: "bold", color: "white" }} src={contact.profilePicUrl}>{getInitials(contact?.name)}</Avatar>}
</TableCell>
<TableCell>{contact.name}</TableCell>
<TableCell align="center">{contact.number}</TableCell>
Expand Down

0 comments on commit 7ac98c2

Please sign in to comment.