mirror of
https://github.com/element-hq/element-web
synced 2024-11-27 11:47:23 +03:00
Merge pull request #77 from matrix-org/matthew/dynamic-svg
Make SVGs and CSS dynamically recolourable
This commit is contained in:
commit
8170288acb
9 changed files with 320 additions and 35 deletions
|
@ -18,6 +18,7 @@ var MatrixClientPeg = require("./MatrixClientPeg");
|
|||
var MatrixTools = require("./MatrixTools");
|
||||
var dis = require("./dispatcher");
|
||||
var encryption = require("./encryption");
|
||||
var Tinter = require("./Tinter");
|
||||
|
||||
var reject = function(msg) {
|
||||
return {
|
||||
|
@ -42,6 +43,12 @@ var commands = {
|
|||
return reject("Usage: /nick <display_name>");
|
||||
},
|
||||
|
||||
// Takes an #rrggbb colourcode and retints the UI (just for debugging)
|
||||
tint: function(room_id, args) {
|
||||
Tinter.tint(args);
|
||||
return success();
|
||||
},
|
||||
|
||||
encrypt: function(room_id, args) {
|
||||
if (args == "on") {
|
||||
var client = MatrixClientPeg.get();
|
||||
|
|
197
src/Tinter.js
Normal file
197
src/Tinter.js
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
Copyright 2015 OpenMarket 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.
|
||||
*/
|
||||
|
||||
var dis = require("./dispatcher");
|
||||
|
||||
// FIXME: these vars should be bundled up and attached to
|
||||
// module.exports otherwise this will break when included by both
|
||||
// react-sdk and apps layered on top.
|
||||
|
||||
// The colour keys to be replaced as referred to in SVGs
|
||||
var keyRgb = [
|
||||
"rgb(118, 207, 166)", // Vector Green
|
||||
"rgb(234, 245, 240)", // Vector Light Green
|
||||
"rgba(118, 207, 166, 0.2)", // BottomLeftMenu overlay (20% Vector 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
|
||||
var keyHex = [
|
||||
"#76CFA6", // Vector Green
|
||||
"#EAF5F0", // Vector Light Green
|
||||
"#D3EFE1", // BottomLeftMenu overlay (20% Vector Green overlaid on Vector Light Green)
|
||||
];
|
||||
|
||||
// cache of our replacement colours
|
||||
// defaults to our keys.
|
||||
var colors = [
|
||||
keyHex[0],
|
||||
keyHex[1],
|
||||
keyHex[2],
|
||||
];
|
||||
|
||||
var cssFixups = [
|
||||
// {
|
||||
// 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
|
||||
var cssAttrs = [
|
||||
"color",
|
||||
"backgroundColor",
|
||||
"borderColor",
|
||||
];
|
||||
|
||||
var svgAttrs = [
|
||||
"fill",
|
||||
"stroke",
|
||||
];
|
||||
|
||||
var cached = false;
|
||||
|
||||
function calcCssFixups() {
|
||||
for (var i = 0; i < document.styleSheets.length; i++) {
|
||||
var ss = document.styleSheets[i];
|
||||
for (var j = 0; j < ss.cssRules.length; j++) {
|
||||
var rule = ss.cssRules[j];
|
||||
if (!rule.style) continue;
|
||||
for (var k = 0; k < cssAttrs.length; k++) {
|
||||
var attr = cssAttrs[k];
|
||||
for (var l = 0; l < keyRgb.length; l++) {
|
||||
if (rule.style[attr] === keyRgb[l]) {
|
||||
cssFixups.push({
|
||||
style: rule.style,
|
||||
attr: attr,
|
||||
index: l,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyCssFixups() {
|
||||
for (var i = 0; i < cssFixups.length; i++) {
|
||||
var cssFixup = cssFixups[i];
|
||||
cssFixup.style[cssFixup.attr] = colors[cssFixup.index];
|
||||
}
|
||||
}
|
||||
|
||||
function hexToRgb(color) {
|
||||
if (color[0] === '#') color = color.slice(1);
|
||||
if (color.length === 3) {
|
||||
color = color[0] + color[0] +
|
||||
color[1] + color[1] +
|
||||
color[2] + color[2];
|
||||
}
|
||||
var val = parseInt(color, 16);
|
||||
var r = (val >> 16) & 255;
|
||||
var g = (val >> 8) & 255;
|
||||
var b = val & 255;
|
||||
return [r, g, b];
|
||||
}
|
||||
|
||||
function rgbToHex(rgb) {
|
||||
var val = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
|
||||
return '#' + (0x1000000 + val).toString(16).slice(1)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
tint: function(primaryColor, secondaryColor, tertiaryColor) {
|
||||
if (!cached) {
|
||||
calcCssFixups();
|
||||
cached = true;
|
||||
}
|
||||
|
||||
if (!secondaryColor) {
|
||||
var x = 0.16; // average weighting factor calculated from vector green & light green
|
||||
var rgb = hexToRgb(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 = rgbToHex(rgb);
|
||||
}
|
||||
|
||||
if (!tertiaryColor) {
|
||||
var x = 0.19;
|
||||
var rgb1 = hexToRgb(primaryColor);
|
||||
var rgb2 = hexToRgb(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 = rgbToHex(rgb1);
|
||||
}
|
||||
|
||||
colors = [primaryColor, secondaryColor, tertiaryColor];
|
||||
|
||||
// go through manually fixing up the stylesheets.
|
||||
applyCssFixups();
|
||||
|
||||
// tell all the SVGs to go fix themselves up
|
||||
dis.dispatch({ action: 'tint_update' });
|
||||
},
|
||||
|
||||
// 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: function(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.
|
||||
|
||||
var fixups = [];
|
||||
for (var i = 0; i < svgs.length; i++) {
|
||||
var svgDoc = svgs[i].contentDocument;
|
||||
if (!svgDoc) continue;
|
||||
var tags = svgDoc.getElementsByTagName("*");
|
||||
for (var j = 0; j < tags.length; j++) {
|
||||
var tag = tags[j];
|
||||
for (var k = 0; k < svgAttrs.length; k++) {
|
||||
var attr = svgAttrs[k];
|
||||
for (var l = 0; l < keyHex.length; l++) {
|
||||
if (tag.getAttribute(attr) && tag.getAttribute(attr).toUpperCase() === keyHex[l]) {
|
||||
fixups.push({
|
||||
node: tag,
|
||||
attr: attr,
|
||||
index: l,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fixups;
|
||||
},
|
||||
|
||||
applySvgFixups: function(fixups) {
|
||||
for (var i = 0; i < fixups.length; i++) {
|
||||
var svgFixup = fixups[i];
|
||||
svgFixup.node.setAttribute(svgFixup.attr, colors[svgFixup.index]);
|
||||
}
|
||||
},
|
||||
};
|
|
@ -23,14 +23,14 @@ limitations under the License.
|
|||
|
||||
module.exports.components = {};
|
||||
module.exports.components['structures.CreateRoom'] = require('./components/structures/CreateRoom');
|
||||
module.exports.components['structures.login.Login'] = require('./components/structures/login/Login');
|
||||
module.exports.components['structures.login.PostRegistration'] = require('./components/structures/login/PostRegistration');
|
||||
module.exports.components['structures.login.Registration'] = require('./components/structures/login/Registration');
|
||||
module.exports.components['structures.MatrixChat'] = require('./components/structures/MatrixChat');
|
||||
module.exports.components['structures.RoomView'] = require('./components/structures/RoomView');
|
||||
module.exports.components['structures.ScrollPanel'] = require('./components/structures/ScrollPanel');
|
||||
module.exports.components['structures.UploadBar'] = require('./components/structures/UploadBar');
|
||||
module.exports.components['structures.UserSettings'] = require('./components/structures/UserSettings');
|
||||
module.exports.components['structures.login.Login'] = require('./components/structures/login/Login');
|
||||
module.exports.components['structures.login.PostRegistration'] = require('./components/structures/login/PostRegistration');
|
||||
module.exports.components['structures.login.Registration'] = require('./components/structures/login/Registration');
|
||||
module.exports.components['views.avatars.MemberAvatar'] = require('./components/views/avatars/MemberAvatar');
|
||||
module.exports.components['views.avatars.RoomAvatar'] = require('./components/views/avatars/RoomAvatar');
|
||||
module.exports.components['views.create_room.CreateRoomButton'] = require('./components/views/create_room/CreateRoomButton');
|
||||
|
@ -41,6 +41,7 @@ module.exports.components['views.dialogs.LogoutPrompt'] = require('./components/
|
|||
module.exports.components['views.dialogs.QuestionDialog'] = require('./components/views/dialogs/QuestionDialog');
|
||||
module.exports.components['views.elements.EditableText'] = require('./components/views/elements/EditableText');
|
||||
module.exports.components['views.elements.ProgressBar'] = require('./components/views/elements/ProgressBar');
|
||||
module.exports.components['views.elements.TintableSvg'] = require('./components/views/elements/TintableSvg');
|
||||
module.exports.components['views.elements.UserSelector'] = require('./components/views/elements/UserSelector');
|
||||
module.exports.components['views.login.CaptchaForm'] = require('./components/views/login/CaptchaForm');
|
||||
module.exports.components['views.login.CasLogin'] = require('./components/views/login/CasLogin');
|
||||
|
@ -50,10 +51,10 @@ module.exports.components['views.login.LoginHeader'] = require('./components/vie
|
|||
module.exports.components['views.login.PasswordLogin'] = require('./components/views/login/PasswordLogin');
|
||||
module.exports.components['views.login.RegistrationForm'] = require('./components/views/login/RegistrationForm');
|
||||
module.exports.components['views.login.ServerConfig'] = require('./components/views/login/ServerConfig');
|
||||
module.exports.components['views.messages.MessageEvent'] = require('./components/views/messages/MessageEvent');
|
||||
module.exports.components['views.messages.MFileBody'] = require('./components/views/messages/MFileBody');
|
||||
module.exports.components['views.messages.MImageBody'] = require('./components/views/messages/MImageBody');
|
||||
module.exports.components['views.messages.MVideoBody'] = require('./components/views/messages/MVideoBody');
|
||||
module.exports.components['views.messages.MessageEvent'] = require('./components/views/messages/MessageEvent');
|
||||
module.exports.components['views.messages.TextualBody'] = require('./components/views/messages/TextualBody');
|
||||
module.exports.components['views.messages.TextualEvent'] = require('./components/views/messages/TextualEvent');
|
||||
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');
|
||||
|
|
|
@ -1078,6 +1078,7 @@ module.exports = React.createClass({
|
|||
var RoomSettings = sdk.getComponent("rooms.RoomSettings");
|
||||
var SearchBar = sdk.getComponent("rooms.SearchBar");
|
||||
var ScrollPanel = sdk.getComponent("structures.ScrollPanel");
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
if (!this.state.room) {
|
||||
if (this.props.roomId) {
|
||||
|
@ -1152,7 +1153,7 @@ module.exports = React.createClass({
|
|||
if (this.state.syncState === "ERROR") {
|
||||
statusBar = (
|
||||
<div className="mx_RoomView_connectionLostBar">
|
||||
<img src="img/warning.svg" width="24" height="23" alt="/!\ "/>
|
||||
<img src="img/warning.svg" width="24" height="23" title="/!\ " alt="/!\ "/>
|
||||
<div className="mx_RoomView_connectionLostBar_textArea">
|
||||
<div className="mx_RoomView_connectionLostBar_title">
|
||||
Connectivity to the server has been lost.
|
||||
|
@ -1171,8 +1172,8 @@ module.exports = React.createClass({
|
|||
<div className="mx_RoomView_tabCompleteImage">...</div>
|
||||
<div className="mx_RoomView_tabCompleteWrapper">
|
||||
<TabCompleteBar entries={this.tabComplete.peek(6)} />
|
||||
<div className="mx_RoomView_tabCompleteEol">
|
||||
<img src="img/eol.svg" width="22" height="16" alt="->|"/>
|
||||
<div className="mx_RoomView_tabCompleteEol" title="->|">
|
||||
<TintableSvg src="img/eol.svg" width="22" height="16"/>
|
||||
Auto-complete
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1182,7 +1183,7 @@ module.exports = React.createClass({
|
|||
else if (this.state.hasUnsentMessages) {
|
||||
statusBar = (
|
||||
<div className="mx_RoomView_connectionLostBar">
|
||||
<img src="img/warning.svg" width="24" height="23" alt="/!\ "/>
|
||||
<img src="img/warning.svg" width="24" height="23" title="/!\ " alt="/!\ "/>
|
||||
<div className="mx_RoomView_connectionLostBar_textArea">
|
||||
<div className="mx_RoomView_connectionLostBar_title">
|
||||
Some of your messages have not been sent.
|
||||
|
@ -1245,8 +1246,8 @@ module.exports = React.createClass({
|
|||
var fileDropTarget = null;
|
||||
if (this.state.draggingFile) {
|
||||
fileDropTarget = <div className="mx_RoomView_fileDropTarget">
|
||||
<div className="mx_RoomView_fileDropTargetLabel">
|
||||
<img src="img/upload-big.svg" width="45" height="59" alt="Drop File Here"/><br/>
|
||||
<div className="mx_RoomView_fileDropTargetLabel" title="Drop File Here">
|
||||
<TintableSvg src="img/upload-big.svg" width="45" height="59"/><br/>
|
||||
Drop File Here
|
||||
</div>
|
||||
</div>;
|
||||
|
@ -1283,25 +1284,29 @@ module.exports = React.createClass({
|
|||
|
||||
if (call.type === "video") {
|
||||
zoomButton = (
|
||||
<div className="mx_RoomView_voipButton" onClick={this.onFullscreenClick}>
|
||||
<img src="img/fullscreen.svg" title="Fill screen" alt="Fill screen" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }}/>
|
||||
<div className="mx_RoomView_voipButton" onClick={this.onFullscreenClick} title="Fill screen">
|
||||
<TintableSvg src="img/fullscreen.svg" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }}/>
|
||||
</div>
|
||||
);
|
||||
|
||||
videoMuteButton =
|
||||
<div className="mx_RoomView_voipButton" onClick={this.onMuteVideoClick}>
|
||||
<img src={call.isLocalVideoMuted() ? "img/video-unmute.svg" : "img/video-mute.svg"} width="31" height="27"/>
|
||||
<img src={call.isLocalVideoMuted() ? "img/video-unmute.svg" : "img/video-mute.svg"}
|
||||
alt={call.isLocalVideoMuted() ? "Click to unmute video" : "Click to mute video"}
|
||||
width="31" height="27"/>
|
||||
</div>
|
||||
}
|
||||
voiceMuteButton =
|
||||
<div className="mx_RoomView_voipButton" onClick={this.onMuteAudioClick}>
|
||||
<img src={call.isMicrophoneMuted() ? "img/voice-unmute.svg" : "img/voice-mute.svg"} width="21" height="26"/>
|
||||
<img src={call.isMicrophoneMuted() ? "img/voice-unmute.svg" : "img/voice-mute.svg"}
|
||||
alt={call.isMicrophoneMuted() ? "Click to unmute audio" : "Click to mute audio"}
|
||||
width="21" height="26"/>
|
||||
</div>
|
||||
|
||||
if (!statusBar) {
|
||||
statusBar =
|
||||
<div className="mx_RoomView_callBar">
|
||||
<img src="img/sound-indicator.svg" width="23" height="20" alt=""/>
|
||||
<img src="img/sound-indicator.svg" width="23" height="20"/>
|
||||
<b>Active call</b>
|
||||
</div>;
|
||||
}
|
||||
|
@ -1312,7 +1317,7 @@ module.exports = React.createClass({
|
|||
{ videoMuteButton }
|
||||
{ zoomButton }
|
||||
{ statusBar }
|
||||
<img className="mx_RoomView_voipChevron" src="img/voip-chevron.svg" width="22" height="17"/>
|
||||
<TintableSvg className="mx_RoomView_voipChevron" src="img/voip-chevron.svg" width="22" height="17"/>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
69
src/components/views/elements/TintableSvg.js
Normal file
69
src/components/views/elements/TintableSvg.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright 2015 OpenMarket 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.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require("react-dom");
|
||||
var dis = require("../../../dispatcher");
|
||||
var Tinter = require("../../../Tinter");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'TintableSvg',
|
||||
|
||||
propTypes: {
|
||||
src: React.PropTypes.string.isRequired,
|
||||
width: React.PropTypes.string.isRequired,
|
||||
height: React.PropTypes.string.isRequired,
|
||||
className: React.PropTypes.string,
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.fixups = [];
|
||||
this.dispatcherRef = dis.register(this.onAction);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// we can't use onLoad on object due to https://github.com/facebook/react/pull/5781
|
||||
// so handle it with pure DOM instead
|
||||
ReactDOM.findDOMNode(this).addEventListener('load', this.onLoad);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
ReactDOM.findDOMNode(this).removeEventListener('load', this.onLoad);
|
||||
dis.unregister(this.dispatcherRef);
|
||||
},
|
||||
|
||||
onAction: function(payload) {
|
||||
if (payload.action !== 'tint_update') return;
|
||||
Tinter.applySvgFixups(this.fixups);
|
||||
},
|
||||
|
||||
onLoad: function(event) {
|
||||
this.fixups = Tinter.calcSvgFixups([event.target]);
|
||||
Tinter.applySvgFixups(this.fixups);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<object className={ "mx_TintableSvg " + this.props.className }
|
||||
type="image/svg+xml"
|
||||
data={ this.props.src }
|
||||
width={ this.props.width }
|
||||
height={ this.props.height }/>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -19,6 +19,8 @@ limitations under the License.
|
|||
var React = require('react');
|
||||
var filesize = require('filesize');
|
||||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var sdk = require('../../../index');
|
||||
var dis = require("../../../dispatcher");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MFileBody',
|
||||
|
@ -52,12 +54,14 @@ module.exports = React.createClass({
|
|||
var httpUrl = cli.mxcUrlToHttp(content.url);
|
||||
var text = this.presentableTextForFile(content);
|
||||
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
if (httpUrl) {
|
||||
return (
|
||||
<span className="mx_MFileBody">
|
||||
<div className="mx_MImageBody_download">
|
||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
||||
<img src="img/download.png" width="10" height="12"/>
|
||||
<TintableSvg src="img/download.svg" width="12" height="14"/>
|
||||
Download {text}
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -22,6 +22,7 @@ var filesize = require('filesize');
|
|||
var MatrixClientPeg = require('../../../MatrixClientPeg');
|
||||
var Modal = require('../../../Modal');
|
||||
var sdk = require('../../../index');
|
||||
var dis = require("../../../dispatcher");
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MImageBody',
|
||||
|
@ -97,6 +98,7 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
var content = this.props.mxEvent.getContent();
|
||||
var cli = MatrixClientPeg.get();
|
||||
|
||||
|
@ -118,7 +120,7 @@ module.exports = React.createClass({
|
|||
</a>
|
||||
<div className="mx_MImageBody_download">
|
||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank">
|
||||
<img src="img/download.png" width="10" height="12"/>
|
||||
<TintableSvg src="img/download.svg" width="12" height="14"/>
|
||||
Download {content.body} ({ content.info && content.info.size ? filesize(content.info.size) : "Unknown size" })
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -461,6 +461,7 @@ module.exports = React.createClass({
|
|||
var me = this.props.room.getMember(MatrixClientPeg.get().credentials.userId);
|
||||
var uploadInputStyle = {display: 'none'};
|
||||
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
var callButton, videoCallButton, hangupButton;
|
||||
var call = CallHandler.getCallForRoom(this.props.room.roomId);
|
||||
|
@ -473,12 +474,12 @@ module.exports = React.createClass({
|
|||
}
|
||||
else {
|
||||
callButton =
|
||||
<div className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick}>
|
||||
<img src="img/voice.svg" alt="Voice call" title="Voice call" width="16" height="26"/>
|
||||
<div className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title="Voice call">
|
||||
<TintableSvg src="img/voice.svg" width="16" height="26"/>
|
||||
</div>
|
||||
videoCallButton =
|
||||
<div className="mx_MessageComposer_videocall" onClick={this.onCallClick}>
|
||||
<img src="img/call.svg" alt="Video call" title="Video call" width="30" height="22"/>
|
||||
<div className="mx_MessageComposer_videocall" onClick={this.onCallClick} title="Video call">
|
||||
<TintableSvg src="img/call.svg" width="30" height="22"/>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -492,8 +493,8 @@ module.exports = React.createClass({
|
|||
<div className="mx_MessageComposer_input" onClick={ this.onInputClick }>
|
||||
<textarea ref="textarea" rows="1" onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} placeholder="Type a message..." />
|
||||
</div>
|
||||
<div className="mx_MessageComposer_upload" onClick={this.onUploadClick}>
|
||||
<img src="img/upload.svg" alt="Upload file" title="Upload file" width="19" height="24"/>
|
||||
<div className="mx_MessageComposer_upload" onClick={this.onUploadClick} title="Upload file">
|
||||
<TintableSvg src="img/upload.svg" width="19" height="24"/>
|
||||
<input type="file" style={uploadInputStyle} ref="uploadInput" onChange={this.onUploadFileSelected} />
|
||||
</div>
|
||||
{ hangupButton }
|
||||
|
|
|
@ -66,10 +66,11 @@ module.exports = React.createClass({
|
|||
getRoomName: function() {
|
||||
return this.refs.name_edit.value;
|
||||
},
|
||||
|
||||
|
||||
render: function() {
|
||||
var EditableText = sdk.getComponent("elements.EditableText");
|
||||
var RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
|
||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||
|
||||
var header;
|
||||
if (this.props.simpleHeader) {
|
||||
|
@ -118,8 +119,8 @@ module.exports = React.createClass({
|
|||
<div className="mx_RoomHeader_name" onClick={this.props.onSettingsClick}>
|
||||
<div className="mx_RoomHeader_nametext" title={ this.props.room.name }>{ this.props.room.name }</div>
|
||||
{ searchStatus }
|
||||
<div className="mx_RoomHeader_settingsButton">
|
||||
<img src="img/settings.svg" width="12" height="12"/>
|
||||
<div className="mx_RoomHeader_settingsButton" title="Settings">
|
||||
<TintableSvg src="img/settings.svg" width="12" height="12"/>
|
||||
</div>
|
||||
</div>
|
||||
if (topic) topic_el = <div className="mx_RoomHeader_topic" title={topic.getContent().topic}>{ topic.getContent().topic }</div>;
|
||||
|
@ -135,18 +136,16 @@ module.exports = React.createClass({
|
|||
var leave_button;
|
||||
if (this.props.onLeaveClick) {
|
||||
leave_button =
|
||||
<div className="mx_RoomHeader_button mx_RoomHeader_leaveButton">
|
||||
<img src="img/leave.svg" title="Leave room" alt="Leave room"
|
||||
width="26" height="20" onClick={this.props.onLeaveClick}/>
|
||||
<div className="mx_RoomHeader_button mx_RoomHeader_leaveButton" onClick={this.props.onLeaveClick} title="Leave room">
|
||||
<TintableSvg src="img/leave.svg" width="26" height="20"/>
|
||||
</div>;
|
||||
}
|
||||
|
||||
var forget_button;
|
||||
if (this.props.onForgetClick) {
|
||||
forget_button =
|
||||
<div className="mx_RoomHeader_button mx_RoomHeader_leaveButton">
|
||||
<img src="img/leave.svg" title="Forget room" alt="Forget room"
|
||||
width="26" height="20" onClick={this.props.onForgetClick}/>
|
||||
<div className="mx_RoomHeader_button mx_RoomHeader_leaveButton" onClick={this.props.onForgetClick} title="Forget room">
|
||||
<TintableSvg src="img/leave.svg" width="26" height="20"/>
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -166,8 +165,8 @@ module.exports = React.createClass({
|
|||
<div className="mx_RoomHeader_rightRow">
|
||||
{ forget_button }
|
||||
{ leave_button }
|
||||
<div className="mx_RoomHeader_button">
|
||||
<img src="img/search.svg" title="Search" alt="Search" width="21" height="19" onClick={this.props.onSearchClick}/>
|
||||
<div className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
|
||||
<TintableSvg src="img/search.svg" width="21" height="19"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue