mirror of https://github.com/vector-im/riot-web
Merge pull request #4503 from matrix-org/bwindels/customthemechanges
Support setting username and avatar colors in custom themespull/21833/head
commit
3d094ea542
Binary file not shown.
Before Width: | Height: | Size: 169 B |
Binary file not shown.
Before Width: | Height: | Size: 171 B |
Binary file not shown.
Before Width: | Height: | Size: 170 B |
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
//
|
||||
// --accent-color
|
||||
$accent-color: var(--accent-color);
|
||||
$accent-bg-color: var(--accent-color-15pct);
|
||||
$button-bg-color: var(--accent-color);
|
||||
$button-link-fg-color: var(--accent-color);
|
||||
$button-primary-bg-color: var(--accent-color);
|
||||
|
@ -124,3 +125,12 @@ $notice-primary-color: var(--warning-color);
|
|||
$pinned-unread-color: var(--warning-color);
|
||||
$warning-color: var(--warning-color);
|
||||
$button-danger-disabled-bg-color: var(--warning-color-50pct); // still needs alpha at 0.5
|
||||
|
||||
$username-variant1-color: var(--username-colors_1, $username-variant1-color);
|
||||
$username-variant2-color: var(--username-colors_2, $username-variant2-color);
|
||||
$username-variant3-color: var(--username-colors_3, $username-variant3-color);
|
||||
$username-variant4-color: var(--username-colors_4, $username-variant4-color);
|
||||
$username-variant5-color: var(--username-colors_5, $username-variant5-color);
|
||||
$username-variant6-color: var(--username-colors_6, $username-variant6-color);
|
||||
$username-variant7-color: var(--username-colors_7, $username-variant7-color);
|
||||
$username-variant8-color: var(--username-colors_8, $username-variant8-color);
|
||||
|
|
|
@ -53,13 +53,56 @@ export function avatarUrlForUser(user, width, height, resizeMethod) {
|
|||
return url;
|
||||
}
|
||||
|
||||
function isValidHexColor(color) {
|
||||
return typeof color === "string" &&
|
||||
(color.length === 7 || color.lengh === 9) &&
|
||||
color.charAt(0) === "#" &&
|
||||
!color.substr(1).split("").some(c => isNaN(parseInt(c, 16)));
|
||||
}
|
||||
|
||||
function urlForColor(color) {
|
||||
const size = 40;
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
const ctx = canvas.getContext("2d");
|
||||
// bail out when using jsdom in unit tests
|
||||
if (!ctx) {
|
||||
return "";
|
||||
}
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(0, 0, size, size);
|
||||
return canvas.toDataURL();
|
||||
}
|
||||
|
||||
// XXX: Ideally we'd clear this cache when the theme changes
|
||||
// but since this function is at global scope, it's a bit
|
||||
// hard to install a listener here, even if there were a clear event to listen to
|
||||
const colorToDataURLCache = new Map();
|
||||
|
||||
export function defaultAvatarUrlForString(s) {
|
||||
const images = ['03b381', '368bd6', 'ac3ba8'];
|
||||
const defaultColors = ['#03b381', '#368bd6', '#ac3ba8'];
|
||||
let total = 0;
|
||||
for (let i = 0; i < s.length; ++i) {
|
||||
total += s.charCodeAt(i);
|
||||
}
|
||||
return require('../res/img/' + images[total % images.length] + '.png');
|
||||
const colorIndex = total % defaultColors.length;
|
||||
// overwritten color value in custom themes
|
||||
const cssVariable = `--avatar-background-colors_${colorIndex}`;
|
||||
const cssValue = document.body.style.getPropertyValue(cssVariable);
|
||||
const color = cssValue || defaultColors[colorIndex];
|
||||
let dataUrl = colorToDataURLCache.get(color);
|
||||
if (!dataUrl) {
|
||||
// validate color as this can come from account_data
|
||||
// with custom theming
|
||||
if (isValidHexColor(color)) {
|
||||
dataUrl = urlForColor(color);
|
||||
colorToDataURLCache.set(color, dataUrl);
|
||||
} else {
|
||||
dataUrl = "";
|
||||
}
|
||||
}
|
||||
return dataUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
21
src/theme.js
21
src/theme.js
|
@ -141,16 +141,31 @@ export function enumerateThemes() {
|
|||
return Object.assign({}, customThemeNames, BUILTIN_THEMES);
|
||||
}
|
||||
|
||||
|
||||
function setCustomThemeVars(customTheme) {
|
||||
const {style} = document.body;
|
||||
if (customTheme.colors) {
|
||||
for (const [name, hexColor] of Object.entries(customTheme.colors)) {
|
||||
|
||||
function setCSSVariable(name, hexColor, doPct = true) {
|
||||
style.setProperty(`--${name}`, hexColor);
|
||||
// uses #rrggbbaa to define the color with alpha values at 0% and 50%
|
||||
if (doPct) {
|
||||
// uses #rrggbbaa to define the color with alpha values at 0%, 15% and 50%
|
||||
style.setProperty(`--${name}-0pct`, hexColor + "00");
|
||||
style.setProperty(`--${name}-15pct`, hexColor + "26");
|
||||
style.setProperty(`--${name}-50pct`, hexColor + "7F");
|
||||
}
|
||||
}
|
||||
|
||||
if (customTheme.colors) {
|
||||
for (const [name, value] of Object.entries(customTheme.colors)) {
|
||||
if (Array.isArray(value)) {
|
||||
for (let i = 0; i < value.length; i += 1) {
|
||||
setCSSVariable(`${name}_${i}`, value[i], false);
|
||||
}
|
||||
} else {
|
||||
setCSSVariable(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getCustomTheme(themeName) {
|
||||
|
|
Loading…
Reference in New Issue