Deprecate Tinter and TintableSVG

This commit is contained in:
Germain Souquet 2021-06-28 16:30:48 +01:00
parent a8f5b7ebae
commit 6607294573
13 changed files with 8 additions and 607 deletions

View File

@ -1,458 +0,0 @@
/*
Copyright 2015 OpenMarket Ltd
Copyright 2017 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const DEBUG = 0;
// utility to turn #rrggbb or rgb(r,g,b) into [red,green,blue]
function colorToRgb(color) {
if (!color) {
return [0, 0, 0];
}
if (color[0] === '#') {
color = color.slice(1);
if (color.length === 3) {
color = color[0] + color[0] +
color[1] + color[1] +
color[2] + color[2];
}
const val = parseInt(color, 16);
const r = (val >> 16) & 255;
const g = (val >> 8) & 255;
const b = val & 255;
return [r, g, b];
} else {
const match = color.match(/rgb\((.*?),(.*?),(.*?)\)/);
if (match) {
return [
parseInt(match[1]),
parseInt(match[2]),
parseInt(match[3]),
];
}
}
return [0, 0, 0];
}
// utility to turn [red,green,blue] into #rrggbb
function rgbToColor(rgb) {
const val = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
return '#' + (0x1000000 + val).toString(16).slice(1);
}
class Tinter {
constructor() {
// The default colour keys to be replaced as referred to in CSS
// (should be overridden by .mx_theme_accentColor and .mx_theme_secondaryAccentColor)
this.keyRgb = [
"rgb(118, 207, 166)", // Vector Green
"rgb(234, 245, 240)", // Vector Light Green
"rgb(211, 239, 225)", // roomsublist-label-bg-color (20% Green overlaid on Light Green)
];
// Some algebra workings for calculating the tint % of Vector Green & Light Green
// x * 118 + (1 - x) * 255 = 234
// x * 118 + 255 - 255 * x = 234
// x * 118 - x * 255 = 234 - 255
// (255 - 118) x = 255 - 234
// x = (255 - 234) / (255 - 118) = 0.16
// The colour keys to be replaced as referred to in SVGs
this.keyHex = [
"#76CFA6", // Vector Green
"#EAF5F0", // Vector Light Green
"#D3EFE1", // roomsublist-label-bg-color (20% Green overlaid on Light Green)
"#FFFFFF", // white highlights of the SVGs (for switching to dark theme)
"#000000", // black lowlights of the SVGs (for switching to dark theme)
];
// track the replacement colours actually being used
// defaults to our keys.
this.colors = [
this.keyHex[0],
this.keyHex[1],
this.keyHex[2],
this.keyHex[3],
this.keyHex[4],
];
// track the most current tint request inputs (which may differ from the
// end result stored in this.colors
this.currentTint = [
undefined,
undefined,
undefined,
undefined,
undefined,
];
this.cssFixups = [
// { theme: {
// style: a style object that should be fixed up taken from a stylesheet
// attr: name of the attribute to be clobbered, e.g. 'color'
// index: ordinal of primary, secondary or tertiary
// },
// }
];
// CSS attributes to be fixed up
this.cssAttrs = [
"color",
"backgroundColor",
"borderColor",
"borderTopColor",
"borderBottomColor",
"borderLeftColor",
];
this.svgAttrs = [
"fill",
"stroke",
];
// List of functions to call when the tint changes.
this.tintables = [];
// the currently loaded theme (if any)
this.theme = undefined;
// whether to force a tint (e.g. after changing theme)
this.forceTint = false;
}
/**
* Register a callback to fire when the tint changes.
* This is used to rewrite the tintable SVGs with the new tint.
*
* It's not possible to unregister a tintable callback. So this can only be
* used to register a static callback. If a set of tintables will change
* over time then the best bet is to register a single callback for the
* entire set.
*
* To ensure the tintable work happens at least once, it is also called as
* part of registration.
*
* @param {Function} tintable Function to call when the tint changes.
*/
registerTintable(tintable) {
this.tintables.push(tintable);
tintable();
}
getKeyRgb() {
return this.keyRgb;
}
tint(primaryColor, secondaryColor, tertiaryColor) {
return;
// eslint-disable-next-line no-unreachable
this.currentTint[0] = primaryColor;
this.currentTint[1] = secondaryColor;
this.currentTint[2] = tertiaryColor;
this.calcCssFixups();
if (DEBUG) {
console.log("Tinter.tint(" + primaryColor + ", " +
secondaryColor + ", " +
tertiaryColor + ")");
}
if (!primaryColor) {
primaryColor = this.keyRgb[0];
secondaryColor = this.keyRgb[1];
tertiaryColor = this.keyRgb[2];
}
if (!secondaryColor) {
const x = 0.16; // average weighting factor calculated from vector green & light green
const rgb = colorToRgb(primaryColor);
rgb[0] = x * rgb[0] + (1 - x) * 255;
rgb[1] = x * rgb[1] + (1 - x) * 255;
rgb[2] = x * rgb[2] + (1 - x) * 255;
secondaryColor = rgbToColor(rgb);
}
if (!tertiaryColor) {
const x = 0.19;
const rgb1 = colorToRgb(primaryColor);
const rgb2 = colorToRgb(secondaryColor);
rgb1[0] = x * rgb1[0] + (1 - x) * rgb2[0];
rgb1[1] = x * rgb1[1] + (1 - x) * rgb2[1];
rgb1[2] = x * rgb1[2] + (1 - x) * rgb2[2];
tertiaryColor = rgbToColor(rgb1);
}
if (this.forceTint == false &&
this.colors[0] === primaryColor &&
this.colors[1] === secondaryColor &&
this.colors[2] === tertiaryColor) {
return;
}
this.forceTint = false;
this.colors[0] = primaryColor;
this.colors[1] = secondaryColor;
this.colors[2] = tertiaryColor;
if (DEBUG) {
console.log("Tinter.tint final: (" + primaryColor + ", " +
secondaryColor + ", " +
tertiaryColor + ")");
}
// go through manually fixing up the stylesheets.
this.applyCssFixups();
// tell all the SVGs to go fix themselves up
// we don't do this as a dispatch otherwise it will visually lag
this.tintables.forEach(function(tintable) {
tintable();
});
}
tintSvgWhite(whiteColor) {
this.currentTint[3] = whiteColor;
if (!whiteColor) {
whiteColor = this.colors[3];
}
if (this.colors[3] === whiteColor) {
return;
}
this.colors[3] = whiteColor;
this.tintables.forEach(function(tintable) {
tintable();
});
}
tintSvgBlack(blackColor) {
this.currentTint[4] = blackColor;
if (!blackColor) {
blackColor = this.colors[4];
}
if (this.colors[4] === blackColor) {
return;
}
this.colors[4] = blackColor;
this.tintables.forEach(function(tintable) {
tintable();
});
}
setTheme(theme) {
this.theme = theme;
// update keyRgb from the current theme CSS itself, if it defines it
if (document.getElementById('mx_theme_accentColor')) {
this.keyRgb[0] = window.getComputedStyle(
document.getElementById('mx_theme_accentColor')).color;
}
if (document.getElementById('mx_theme_secondaryAccentColor')) {
this.keyRgb[1] = window.getComputedStyle(
document.getElementById('mx_theme_secondaryAccentColor')).color;
}
if (document.getElementById('mx_theme_tertiaryAccentColor')) {
this.keyRgb[2] = window.getComputedStyle(
document.getElementById('mx_theme_tertiaryAccentColor')).color;
}
this.calcCssFixups();
this.forceTint = true;
this.tint(this.currentTint[0], this.currentTint[1], this.currentTint[2]);
if (theme === 'dark') {
// abuse the tinter to change all the SVG's #fff to #2d2d2d
// XXX: obviously this shouldn't be hardcoded here.
this.tintSvgWhite('#2d2d2d');
this.tintSvgBlack('#dddddd');
} else {
this.tintSvgWhite('#ffffff');
this.tintSvgBlack('#000000');
}
}
calcCssFixups() {
// cache our fixups
if (this.cssFixups[this.theme]) return;
if (DEBUG) {
console.debug("calcCssFixups start for " + this.theme + " (checking " +
document.styleSheets.length +
" stylesheets)");
}
this.cssFixups[this.theme] = [];
for (let i = 0; i < document.styleSheets.length; i++) {
const ss = document.styleSheets[i];
try {
if (!ss) continue; // well done safari >:(
// Chromium apparently sometimes returns null here; unsure why.
// see $14534907369972FRXBx:matrix.org in HQ
// ...ah, it's because there's a third party extension like
// privacybadger inserting its own stylesheet in there with a
// resource:// URI or something which results in a XSS error.
// See also #vector:matrix.org/$145357669685386ebCfr:matrix.org
// ...except some browsers apparently return stylesheets without
// hrefs, which we have no choice but ignore right now
// XXX seriously? we are hardcoding the name of vector's CSS file in
// here?
//
// Why do we need to limit it to vector's CSS file anyway - if there
// are other CSS files affecting the doc don't we want to apply the
// same transformations to them?
//
// Iterating through the CSS looking for matches to hack on feels
// pretty horrible anyway. And what if the application skin doesn't use
// Vector Green as its primary color?
// --richvdh
// Yes, tinting assumes that you are using the Element skin for now.
// The right solution will be to move the CSS over to react-sdk.
// And yes, the default assets for the base skin might as well use
// Vector Green as any other colour.
// --matthew
// stylesheets we don't have permission to access (eg. ones from extensions) have a null
// href and will throw exceptions if we try to access their rules.
if (!ss.href || !ss.href.match(new RegExp('/theme-' + this.theme + '.css$'))) continue;
if (ss.disabled) continue;
if (!ss.cssRules) continue;
if (DEBUG) console.debug("calcCssFixups checking " + ss.cssRules.length + " rules for " + ss.href);
for (let j = 0; j < ss.cssRules.length; j++) {
const rule = ss.cssRules[j];
if (!rule.style) continue;
if (rule.selectorText && rule.selectorText.match(/#mx_theme/)) continue;
for (let k = 0; k < this.cssAttrs.length; k++) {
const attr = this.cssAttrs[k];
for (let l = 0; l < this.keyRgb.length; l++) {
if (rule.style[attr] === this.keyRgb[l]) {
this.cssFixups[this.theme].push({
style: rule.style,
attr: attr,
index: l,
});
}
}
}
}
} catch (e) {
// Catch any random exceptions that happen here: all sorts of things can go
// wrong with this (nulls, SecurityErrors) and mostly it's for other
// stylesheets that we don't want to proces anyway. We should not propagate an
// exception out since this will cause the app to fail to start.
console.log("Failed to calculate CSS fixups for a stylesheet: " + ss.href, e);
}
}
if (DEBUG) {
console.log("calcCssFixups end (" +
this.cssFixups[this.theme].length +
" fixups)");
}
}
applyCssFixups() {
if (DEBUG) {
console.log("applyCssFixups start (" +
this.cssFixups[this.theme].length +
" fixups)");
}
for (let i = 0; i < this.cssFixups[this.theme].length; i++) {
const cssFixup = this.cssFixups[this.theme][i];
try {
cssFixup.style[cssFixup.attr] = this.colors[cssFixup.index];
} catch (e) {
// Firefox Quantum explodes if you manually edit the CSS in the
// inspector and then try to do a tint, as apparently all the
// fixups are then stale.
console.error("Failed to apply cssFixup in Tinter! ", e.name);
}
}
if (DEBUG) console.log("applyCssFixups end");
}
// XXX: we could just move this all into TintableSvg, but as it's so similar
// to the CSS fixup stuff in Tinter (just that the fixups are stored in TintableSvg)
// keeping it here for now.
calcSvgFixups(svgs) {
// go through manually fixing up SVG colours.
// we could do this by stylesheets, but keeping the stylesheets
// updated would be a PITA, so just brute-force search for the
// key colour; cache the element and apply.
if (DEBUG) console.log("calcSvgFixups start for " + svgs);
const fixups = [];
for (let i = 0; i < svgs.length; i++) {
let svgDoc;
try {
svgDoc = svgs[i].contentDocument;
} catch (e) {
let msg = 'Failed to get svg.contentDocument of ' + svgs[i].toString();
if (e.message) {
msg += e.message;
}
if (e.stack) {
msg += ' | stack: ' + e.stack;
}
console.error(msg);
}
if (!svgDoc) continue;
const tags = svgDoc.getElementsByTagName("*");
for (let j = 0; j < tags.length; j++) {
const tag = tags[j];
for (let k = 0; k < this.svgAttrs.length; k++) {
const attr = this.svgAttrs[k];
for (let l = 0; l < this.keyHex.length; l++) {
if (tag.getAttribute(attr) &&
tag.getAttribute(attr).toUpperCase() === this.keyHex[l]) {
fixups.push({
node: tag,
attr: attr,
index: l,
});
}
}
}
}
}
if (DEBUG) console.log("calcSvgFixups end");
return fixups;
}
applySvgFixups(fixups) {
if (DEBUG) console.log("applySvgFixups start for " + fixups);
for (let i = 0; i < fixups.length; i++) {
const svgFixup = fixups[i];
svgFixup.node.setAttribute(svgFixup.attr, this.colors[svgFixup.index]);
}
if (DEBUG) console.log("applySvgFixups end");
}
}
if (global.singletonTinter === undefined) {
global.singletonTinter = new Tinter();
}
export default global.singletonTinter;

View File

@ -126,12 +126,11 @@ class CategoryRoomList extends React.Component {
}; };
render() { render() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const addButton = this.props.editing ? const addButton = this.props.editing ?
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" (<AccessibleButton className="mx_GroupView_featuredThings_addButton"
onClick={this.onAddRoomsToSummaryClicked} onClick={this.onAddRoomsToSummaryClicked}
> >
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" /> <img src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
<div className="mx_GroupView_featuredThings_addButton_label"> <div className="mx_GroupView_featuredThings_addButton_label">
{ _t('Add a Room') } { _t('Add a Room') }
</div> </div>
@ -300,10 +299,9 @@ class RoleUserList extends React.Component {
}; };
render() { render() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const addButton = this.props.editing ? const addButton = this.props.editing ?
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" onClick={this.onAddUsersClicked}> (<AccessibleButton className="mx_GroupView_featuredThings_addButton" onClick={this.onAddUsersClicked}>
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" /> <img src={require("../../../res/img/icons-create-room.svg")} width="64" height="64" />
<div className="mx_GroupView_featuredThings_addButton_label"> <div className="mx_GroupView_featuredThings_addButton_label">
{ _t('Add a User') } { _t('Add a User') }
</div> </div>
@ -855,7 +853,6 @@ export default class GroupView extends React.Component {
_getRoomsNode() { _getRoomsNode() {
const RoomDetailList = sdk.getComponent('rooms.RoomDetailList'); const RoomDetailList = sdk.getComponent('rooms.RoomDetailList');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const TintableSvg = sdk.getComponent('elements.TintableSvg');
const Spinner = sdk.getComponent('elements.Spinner'); const Spinner = sdk.getComponent('elements.Spinner');
const TooltipButton = sdk.getComponent('elements.TooltipButton'); const TooltipButton = sdk.getComponent('elements.TooltipButton');
@ -871,7 +868,7 @@ export default class GroupView extends React.Component {
onClick={this._onAddRoomsClick} onClick={this._onAddRoomsClick}
> >
<div className="mx_GroupView_rooms_header_addRow_button"> <div className="mx_GroupView_rooms_header_addRow_button">
<TintableSvg src={require("../../../res/img/icons-room-add.svg")} width="24" height="24" /> <img src={require("../../../res/img/icons-room-add.svg")} width="24" height="24" />
</div> </div>
<div className="mx_GroupView_rooms_header_addRow_label"> <div className="mx_GroupView_rooms_header_addRow_label">
{ _t('Add rooms to this community') } { _t('Add rooms to this community') }

View File

@ -34,7 +34,6 @@ import dis from "../../dispatcher/dispatcher";
import Notifier from '../../Notifier'; import Notifier from '../../Notifier';
import Modal from "../../Modal"; import Modal from "../../Modal";
import Tinter from "../../Tinter";
import * as sdk from '../../index'; import * as sdk from '../../index';
import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite'; import { showRoomInviteDialog, showStartChatInviteDialog } from '../../RoomInvite';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
@ -283,11 +282,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.pageChanging = false; this.pageChanging = false;
// check we have the right tint applied for this theme.
// N.B. we don't call the whole of setTheme() here as we may be
// racing with the theme CSS download finishing from index.js
Tinter.tint();
// For PersistentElement // For PersistentElement
this.state.resizeNotifier.on("middlePanelResized", this.dispatchTimelineResize); this.state.resizeNotifier.on("middlePanelResized", this.dispatchTimelineResize);
@ -1573,10 +1567,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
}); });
} }
}); });
// Fire the tinter right on startup to ensure the default theme is applied
// A later sync can/will correct the tint to be the right value for the user
const colorScheme = SettingsStore.getValue("roomColor");
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
} }
/** /**

View File

@ -123,7 +123,7 @@ export default class MyGroups extends React.Component {
</div> </div>
{/*<div className="mx_MyGroups_joinBox mx_MyGroups_headerCard"> {/*<div className="mx_MyGroups_joinBox mx_MyGroups_headerCard">
<AccessibleButton className='mx_MyGroups_headerCard_button' onClick={this._onJoinGroupClick}> <AccessibleButton className='mx_MyGroups_headerCard_button' onClick={this._onJoinGroupClick}>
<TintableSvg src={require("../../../res/img/icons-create-room.svg")} width="50" height="50" /> <img src={require("../../../res/img/icons-create-room.svg")} width="50" height="50" />
</AccessibleButton> </AccessibleButton>
<div className="mx_MyGroups_headerCard_content"> <div className="mx_MyGroups_headerCard_content">
<div className="mx_MyGroups_headerCard_header"> <div className="mx_MyGroups_headerCard_header">

View File

@ -37,7 +37,6 @@ import Modal from '../../Modal';
import * as sdk from '../../index'; import * as sdk from '../../index';
import CallHandler, { PlaceCallType } from '../../CallHandler'; import CallHandler, { PlaceCallType } from '../../CallHandler';
import dis from '../../dispatcher/dispatcher'; import dis from '../../dispatcher/dispatcher';
import Tinter from '../../Tinter';
import rateLimitedFunc from '../../ratelimitedfunc'; import rateLimitedFunc from '../../ratelimitedfunc';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
import eventSearch, { searchPagination } from '../../Searching'; import eventSearch, { searchPagination } from '../../Searching';
@ -677,10 +676,6 @@ export default class RoomView extends React.Component<IProps, IState> {
// cancel any pending calls to the rate_limited_funcs // cancel any pending calls to the rate_limited_funcs
this.updateRoomMembers.cancelPendingCall(); this.updateRoomMembers.cancelPendingCall();
// no need to do this as Dir & Settings are now overlays. It just burnt CPU.
// console.log("Tinter.tint from RoomView.unmount");
// Tinter.tint(); // reset colourscheme
for (const watcher of this.settingWatchers) { for (const watcher of this.settingWatchers) {
SettingsStore.unwatchSetting(watcher); SettingsStore.unwatchSetting(watcher);
} }
@ -1030,10 +1025,6 @@ export default class RoomView extends React.Component<IProps, IState> {
private updateTint() { private updateTint() {
const room = this.state.room; const room = this.state.room;
if (!room) return; if (!room) return;
console.log("Tinter.tint from updateTint");
const colorScheme = SettingsStore.getValue("roomColor", room.roomId);
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
} }
private onAccountData = (event: MatrixEvent) => { private onAccountData = (event: MatrixEvent) => {
@ -1047,12 +1038,7 @@ export default class RoomView extends React.Component<IProps, IState> {
private onRoomAccountData = (event: MatrixEvent, room: Room) => { private onRoomAccountData = (event: MatrixEvent, room: Room) => {
if (room.roomId == this.state.roomId) { if (room.roomId == this.state.roomId) {
const type = event.getType(); const type = event.getType();
if (type === "org.matrix.room.color_scheme") { if (type === "org.matrix.room.preview_urls" || type === "im.vector.web.settings") {
const colorScheme = event.getContent();
// XXX: we should validate the event
console.log("Tinter.tint from onRoomAccountData");
Tinter.tint(colorScheme.primary_color, colorScheme.secondary_color);
} else if (type === "org.matrix.room.preview_urls" || type === "im.vector.web.settings") {
// non-e2ee url previews are stored in legacy event type `org.matrix.room.preview_urls` // non-e2ee url previews are stored in legacy event type `org.matrix.room.preview_urls`
this.updatePreviewUrlVisibility(room); this.updatePreviewUrlVisibility(room);
} }

View File

@ -62,8 +62,6 @@ export default class ActionButton extends React.Component {
}; };
render() { render() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
let tooltip; let tooltip;
if (this.state.showTooltip) { if (this.state.showTooltip) {
const Tooltip = sdk.getComponent("elements.Tooltip"); const Tooltip = sdk.getComponent("elements.Tooltip");
@ -71,7 +69,7 @@ export default class ActionButton extends React.Component {
} }
const icon = this.props.iconPath ? const icon = this.props.iconPath ?
(<TintableSvg src={this.props.iconPath} width={this.props.size} height={this.props.size} />) : (<img src={this.props.iconPath} width={this.props.size} height={this.props.size} />) :
undefined; undefined;
const classNames = ["mx_RoleButton"]; const classNames = ["mx_RoleButton"];

View File

@ -53,7 +53,6 @@ export default class AddressTile extends React.Component {
} }
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const nameClasses = classNames({ const nameClasses = classNames({
"mx_AddressTile_name": true, "mx_AddressTile_name": true,
@ -124,7 +123,7 @@ export default class AddressTile extends React.Component {
if (this.props.canDismiss) { if (this.props.canDismiss) {
dismiss = ( dismiss = (
<div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed} > <div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed} >
<TintableSvg src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" /> <img src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" />
</div> </div>
); );
} }

View File

@ -1,82 +0,0 @@
/*
Copyright 2015 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import PropTypes from 'prop-types';
import Tinter from "../../../Tinter";
import {replaceableComponent} from "../../../utils/replaceableComponent";
@replaceableComponent("views.elements.TintableSvg")
class TintableSvg extends React.Component {
static propTypes = {
src: PropTypes.string.isRequired,
width: PropTypes.string.isRequired,
height: PropTypes.string.isRequired,
className: PropTypes.string,
};
// list of currently mounted TintableSvgs
static mounts = {};
static idSequence = 0;
componentDidMount() {
this.fixups = [];
this.id = TintableSvg.idSequence++;
TintableSvg.mounts[this.id] = this;
}
componentWillUnmount() {
delete TintableSvg.mounts[this.id];
}
tint = () => {
// TODO: only bother running this if the global tint settings have changed
// since we loaded!
Tinter.applySvgFixups(this.fixups);
};
onLoad = event => {
// console.log("TintableSvg.onLoad for " + this.props.src);
this.fixups = Tinter.calcSvgFixups([event.target]);
Tinter.applySvgFixups(this.fixups);
};
render() {
return (
<object className={"mx_TintableSvg " + (this.props.className ? this.props.className : "")}
type="image/svg+xml"
data={this.props.src}
width={this.props.width}
height={this.props.height}
onLoad={this.onLoad}
tabIndex="-1"
/>
);
}
}
// Register with the Tinter so that we will be told if the tint changes
Tinter.registerTintable(function() {
if (TintableSvg.mounts) {
Object.keys(TintableSvg.mounts).forEach((id) => {
TintableSvg.mounts[id].tint();
});
}
});
export default TintableSvg;

View File

@ -16,7 +16,6 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import * as sdk from '../../../index';
import {replaceableComponent} from "../../../utils/replaceableComponent"; import {replaceableComponent} from "../../../utils/replaceableComponent";
/* /*
@ -35,8 +34,7 @@ export default class SimpleRoomHeader extends React.Component {
render() { render() {
let icon; let icon;
if (this.props.icon) { if (this.props.icon) {
const TintableSvg = sdk.getComponent('elements.TintableSvg'); icon = <img
icon = <TintableSvg
className="mx_RoomHeader_icon" src={this.props.icon} className="mx_RoomHeader_icon" src={this.props.icon}
width="25" height="25" width="25" height="25"
/>; />;

View File

@ -857,7 +857,6 @@
"Enable inline URL previews by default": "Enable inline URL previews by default", "Enable inline URL previews by default": "Enable inline URL previews by default",
"Enable URL previews for this room (only affects you)": "Enable URL previews for this room (only affects you)", "Enable URL previews for this room (only affects you)": "Enable URL previews for this room (only affects you)",
"Enable URL previews by default for participants in this room": "Enable URL previews by default for participants in this room", "Enable URL previews by default for participants in this room": "Enable URL previews by default for participants in this room",
"Room Colour": "Room Colour",
"Enable widget screenshots on supported widgets": "Enable widget screenshots on supported widgets", "Enable widget screenshots on supported widgets": "Enable widget screenshots on supported widgets",
"Prompt before sending invites to potentially invalid matrix IDs": "Prompt before sending invites to potentially invalid matrix IDs", "Prompt before sending invites to potentially invalid matrix IDs": "Prompt before sending invites to potentially invalid matrix IDs",
"Show developer tools": "Show developer tools", "Show developer tools": "Show developer tools",

View File

@ -606,14 +606,6 @@ export const SETTINGS: {[setting: string]: ISetting} = {
default: false, default: false,
controller: new UIFeatureController(UIFeature.URLPreviews), controller: new UIFeatureController(UIFeature.URLPreviews),
}, },
"roomColor": {
supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM,
displayName: _td("Room Colour"),
default: {
primary_color: null, // Hex string, eg: #000000
secondary_color: null, // Hex string, eg: #000000
},
},
"notificationsEnabled": { "notificationsEnabled": {
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS, supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
default: false, default: false,

View File

@ -54,8 +54,6 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
} }
this.watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM_ACCOUNT, val); this.watchers.notifyUpdate("urlPreviewsEnabled", roomId, SettingLevel.ROOM_ACCOUNT, val);
} else if (event.getType() === "org.matrix.room.color_scheme") {
this.watchers.notifyUpdate("roomColor", roomId, SettingLevel.ROOM_ACCOUNT, event.getContent());
} else if (event.getType() === "im.vector.web.settings") { } else if (event.getType() === "im.vector.web.settings") {
// Figure out what changed and fire those updates // Figure out what changed and fire those updates
const prevContent = prevEvent ? prevEvent.getContent() : {}; const prevContent = prevEvent ? prevEvent.getContent() : {};
@ -79,14 +77,6 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
return !content['disable']; return !content['disable'];
} }
// Special case room color
if (settingName === "roomColor") {
// The event content should already be in an appropriate format, we just need
// to get the right value.
// don't fallback to {} because thats truthy and would imply there is an event specifying tint
return this.getSettings(roomId, "org.matrix.room.color_scheme");
}
// Special case allowed widgets // Special case allowed widgets
if (settingName === "allowedWidgets") { if (settingName === "allowedWidgets") {
return this.getSettings(roomId, ALLOWED_WIDGETS_EVENT_TYPE); return this.getSettings(roomId, ALLOWED_WIDGETS_EVENT_TYPE);
@ -104,12 +94,6 @@ export default class RoomAccountSettingsHandler extends MatrixClientBackedSettin
return MatrixClientPeg.get().setRoomAccountData(roomId, "org.matrix.room.preview_urls", content); return MatrixClientPeg.get().setRoomAccountData(roomId, "org.matrix.room.preview_urls", content);
} }
// Special case room color
if (settingName === "roomColor") {
// The new value should match our requirements, we just need to store it in the right place.
return MatrixClientPeg.get().setRoomAccountData(roomId, "org.matrix.room.color_scheme", newValue);
}
// Special case allowed widgets // Special case allowed widgets
if (settingName === "allowedWidgets") { if (settingName === "allowedWidgets") {
return MatrixClientPeg.get().setRoomAccountData(roomId, ALLOWED_WIDGETS_EVENT_TYPE, newValue); return MatrixClientPeg.get().setRoomAccountData(roomId, ALLOWED_WIDGETS_EVENT_TYPE, newValue);

View File

@ -18,7 +18,6 @@ limitations under the License.
import {_t} from "./languageHandler"; import {_t} from "./languageHandler";
export const DEFAULT_THEME = "light"; export const DEFAULT_THEME = "light";
import Tinter from "./Tinter";
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import ThemeWatcher from "./settings/watchers/ThemeWatcher"; import ThemeWatcher from "./settings/watchers/ThemeWatcher";
@ -214,7 +213,6 @@ export async function setTheme(theme) {
if (bodyStyles.backgroundColor) { if (bodyStyles.backgroundColor) {
document.querySelector('meta[name="theme-color"]').content = bodyStyles.backgroundColor; document.querySelector('meta[name="theme-color"]').content = bodyStyles.backgroundColor;
} }
Tinter.setTheme(theme);
resolve(); resolve();
}; };