MM-52280: Generate higher contrast for some usernames (#25073)
* MM-52280: Generate higher contrast for some usernames Keep 3 tries but return the best value instead of the last one Signed-off-by: Nicolas Le Cam <niko.lecam@gmail.com> * Try ten times to find the best contrast before giving up --------- Signed-off-by: Nicolas Le Cam <niko.lecam@gmail.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
375404c12e
Коммит
573e45691f
30
webapp/channels/src/components/user_profile/user.test.ts
Обычный файл
30
webapp/channels/src/components/user_profile/user.test.ts
Обычный файл
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import ColorContrastChecker from 'color-contrast-checker';
|
||||
|
||||
import {cachedUserNameColors, generateColor} from './utils';
|
||||
|
||||
const CONSTRAST_CHECKER = new ColorContrastChecker();
|
||||
const BACKGROUND_COLOR = '#ACC8E5';
|
||||
|
||||
describe('components/user_profile/utils', () => {
|
||||
test.each([
|
||||
['Ross_Bednar', '#432dd2', 4.5],
|
||||
['Geovany95', '#2d3086', 4.5],
|
||||
['Madisen25', '#52783a', 2.9],
|
||||
['Gerard17', '#783a54', 4.5],
|
||||
['Alia30', '#392d86', 4.5],
|
||||
['Darien.Prosacco97', '#862d6d', 4.5],
|
||||
['Alf48', '#4053bf', 3.7],
|
||||
['Darron_Orn-Walsh49', '#742d86', 4.5],
|
||||
])('should generate best color contrast', (userName, expected, ratio) => {
|
||||
cachedUserNameColors.clear();
|
||||
|
||||
const actual = generateColor(userName, BACKGROUND_COLOR);
|
||||
expect(actual).toBe(expected);
|
||||
expect(
|
||||
CONSTRAST_CHECKER.isLevelCustom(actual, BACKGROUND_COLOR, ratio),
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -4,27 +4,44 @@
|
||||
import ColorContrastChecker from 'color-contrast-checker';
|
||||
import ColorHash from 'color-hash';
|
||||
|
||||
const cachedColors = new Map<string, string>();
|
||||
const REQUIRED_COLOR_RATIO = 4.5;
|
||||
|
||||
export const cachedUserNameColors = new Map<string, string>();
|
||||
|
||||
export function generateColor(username: string, background: string): string {
|
||||
const cacheKey = `${username}-${background}`;
|
||||
const cachedColor = cachedColors.get(cacheKey);
|
||||
const cachedColor = cachedUserNameColors.get(cacheKey);
|
||||
if (cachedColor) {
|
||||
return cachedColor;
|
||||
}
|
||||
|
||||
let userColor = background;
|
||||
let contrastRatio = 1;
|
||||
let userAndSalt = username;
|
||||
const checker = new ColorContrastChecker();
|
||||
const colorHash = new ColorHash();
|
||||
|
||||
let tries = 3;
|
||||
while (!checker.isLevelCustom(userColor, background, 4.5) && tries > 0) {
|
||||
userColor = colorHash.hex(userAndSalt);
|
||||
const backgroundLuminance = checker.hexToLuminance(background);
|
||||
for (let tries = 10; tries > 0; tries--) {
|
||||
const textColor = colorHash.hex(userAndSalt);
|
||||
|
||||
const cr = checker.getContrastRatio(
|
||||
checker.hexToLuminance(textColor),
|
||||
backgroundLuminance,
|
||||
);
|
||||
|
||||
if (cr > contrastRatio) {
|
||||
userColor = textColor;
|
||||
contrastRatio = cr;
|
||||
}
|
||||
|
||||
if (cr >= REQUIRED_COLOR_RATIO) {
|
||||
break;
|
||||
}
|
||||
|
||||
userAndSalt += 'salt';
|
||||
tries--;
|
||||
}
|
||||
|
||||
cachedColors.set(cacheKey, userColor);
|
||||
cachedUserNameColors.set(cacheKey, userColor);
|
||||
return userColor;
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user