factor out tintable SVGs into their own component, and use plain DOM onload rather than react synthetic events

This commit is contained in:
Matthew Hodgson 2016-01-06 02:11:07 +00:00
parent 9e8daba8d7
commit 509ea7c4f3
8 changed files with 82 additions and 20 deletions

View file

@ -102,7 +102,7 @@ function calcCssFixups() {
} }
function calcSvgFixups(nodes) { function calcSvgFixups(nodes) {
var svgs = nodes || document.getElementsByClassName("mx_Svg"); var svgs = nodes || document.getElementsByClassName("mx_TintableSvg");
var fixups = []; var fixups = [];
for (var i = 0; i < svgs.length; i++) { for (var i = 0; i < svgs.length; i++) {

View file

@ -23,14 +23,14 @@ limitations under the License.
module.exports.components = {}; module.exports.components = {};
module.exports.components['structures.CreateRoom'] = require('./components/structures/CreateRoom'); 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.MatrixChat'] = require('./components/structures/MatrixChat');
module.exports.components['structures.RoomView'] = require('./components/structures/RoomView'); module.exports.components['structures.RoomView'] = require('./components/structures/RoomView');
module.exports.components['structures.ScrollPanel'] = require('./components/structures/ScrollPanel'); module.exports.components['structures.ScrollPanel'] = require('./components/structures/ScrollPanel');
module.exports.components['structures.UploadBar'] = require('./components/structures/UploadBar'); module.exports.components['structures.UploadBar'] = require('./components/structures/UploadBar');
module.exports.components['structures.UserSettings'] = require('./components/structures/UserSettings'); 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.MemberAvatar'] = require('./components/views/avatars/MemberAvatar');
module.exports.components['views.avatars.RoomAvatar'] = require('./components/views/avatars/RoomAvatar'); module.exports.components['views.avatars.RoomAvatar'] = require('./components/views/avatars/RoomAvatar');
module.exports.components['views.create_room.CreateRoomButton'] = require('./components/views/create_room/CreateRoomButton'); 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.dialogs.QuestionDialog'] = require('./components/views/dialogs/QuestionDialog');
module.exports.components['views.elements.EditableText'] = require('./components/views/elements/EditableText'); 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.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.elements.UserSelector'] = require('./components/views/elements/UserSelector');
module.exports.components['views.login.CaptchaForm'] = require('./components/views/login/CaptchaForm'); module.exports.components['views.login.CaptchaForm'] = require('./components/views/login/CaptchaForm');
module.exports.components['views.login.CasLogin'] = require('./components/views/login/CasLogin'); 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.PasswordLogin'] = require('./components/views/login/PasswordLogin');
module.exports.components['views.login.RegistrationForm'] = require('./components/views/login/RegistrationForm'); 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.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.MFileBody'] = require('./components/views/messages/MFileBody');
module.exports.components['views.messages.MImageBody'] = require('./components/views/messages/MImageBody'); 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.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.TextualBody'] = require('./components/views/messages/TextualBody');
module.exports.components['views.messages.TextualEvent'] = require('./components/views/messages/TextualEvent'); module.exports.components['views.messages.TextualEvent'] = require('./components/views/messages/TextualEvent');
module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody'); module.exports.components['views.messages.UnknownBody'] = require('./components/views/messages/UnknownBody');

View file

@ -1104,6 +1104,7 @@ module.exports = React.createClass({
var RoomSettings = sdk.getComponent("rooms.RoomSettings"); var RoomSettings = sdk.getComponent("rooms.RoomSettings");
var SearchBar = sdk.getComponent("rooms.SearchBar"); var SearchBar = sdk.getComponent("rooms.SearchBar");
var ScrollPanel = sdk.getComponent("structures.ScrollPanel"); var ScrollPanel = sdk.getComponent("structures.ScrollPanel");
var TintableSvg = sdk.getComponent("elements.TintableSvg");
if (!this.state.room) { if (!this.state.room) {
if (this.props.roomId) { if (this.props.roomId) {
@ -1198,7 +1199,7 @@ module.exports = React.createClass({
<div className="mx_RoomView_tabCompleteWrapper"> <div className="mx_RoomView_tabCompleteWrapper">
<TabCompleteBar entries={this.tabComplete.peek(6)} /> <TabCompleteBar entries={this.tabComplete.peek(6)} />
<div className="mx_RoomView_tabCompleteEol" title="->|"> <div className="mx_RoomView_tabCompleteEol" title="->|">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/eol.svg" width="22" height="16"/> <TintableSvg src="img/eol.svg" width="22" height="16"/>
Auto-complete Auto-complete
</div> </div>
</div> </div>
@ -1272,7 +1273,7 @@ module.exports = React.createClass({
if (this.state.draggingFile) { if (this.state.draggingFile) {
fileDropTarget = <div className="mx_RoomView_fileDropTarget"> fileDropTarget = <div className="mx_RoomView_fileDropTarget">
<div className="mx_RoomView_fileDropTargetLabel" title="Drop File Here"> <div className="mx_RoomView_fileDropTargetLabel" title="Drop File Here">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/upload-big.svg" width="45" height="59"/><br/> <TintableSvg src="img/upload-big.svg" width="45" height="59"/><br/>
Drop File Here Drop File Here
</div> </div>
</div>; </div>;
@ -1310,7 +1311,7 @@ module.exports = React.createClass({
if (call.type === "video") { if (call.type === "video") {
zoomButton = ( zoomButton = (
<div className="mx_RoomView_voipButton" onClick={this.onFullscreenClick} title="Fill screen"> <div className="mx_RoomView_voipButton" onClick={this.onFullscreenClick} title="Fill screen">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/fullscreen.svg" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }}/> <TintableSvg src="img/fullscreen.svg" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }}/>
</div> </div>
); );
@ -1342,7 +1343,7 @@ module.exports = React.createClass({
{ videoMuteButton } { videoMuteButton }
{ zoomButton } { zoomButton }
{ statusBar } { statusBar }
<object onLoad={ this.onSvgLoad } type="image/svg+xml" className="mx_RoomView_voipChevron mx_Svg" data="img/voip-chevron.svg" width="22" height="17"/> <TintableSvg className="mx_RoomView_voipChevron" src="img/voip-chevron.svg" width="22" height="17"/>
</div> </div>
} }

View file

@ -0,0 +1,56 @@
/*
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");
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,
},
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);
},
onLoad: function(event) {
dis.dispatch({ action: "svg_onload", svg: event.target });
},
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 }/>
);
}
});

View file

@ -19,6 +19,7 @@ limitations under the License.
var React = require('react'); var React = require('react');
var filesize = require('filesize'); var filesize = require('filesize');
var MatrixClientPeg = require('../../../MatrixClientPeg'); var MatrixClientPeg = require('../../../MatrixClientPeg');
var sdk = require('../../../index');
var dis = require("../../../dispatcher"); var dis = require("../../../dispatcher");
module.exports = React.createClass({ module.exports = React.createClass({
@ -57,12 +58,14 @@ module.exports = React.createClass({
var httpUrl = cli.mxcUrlToHttp(content.url); var httpUrl = cli.mxcUrlToHttp(content.url);
var text = this.presentableTextForFile(content); var text = this.presentableTextForFile(content);
var TintableSvg = sdk.getComponent("elements.TintableSvg");
if (httpUrl) { if (httpUrl) {
return ( return (
<span className="mx_MFileBody"> <span className="mx_MFileBody">
<div className="mx_MImageBody_download"> <div className="mx_MImageBody_download">
<a href={cli.mxcUrlToHttp(content.url)} target="_blank"> <a href={cli.mxcUrlToHttp(content.url)} target="_blank">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/download.svg" width="12" height="14"/> <TintableSvg src="img/download.svg" width="12" height="14"/>
Download {text} Download {text}
</a> </a>
</div> </div>

View file

@ -102,6 +102,7 @@ module.exports = React.createClass({
}, },
render: function() { render: function() {
var TintableSvg = sdk.getComponent("elements.TintableSvg");
var content = this.props.mxEvent.getContent(); var content = this.props.mxEvent.getContent();
var cli = MatrixClientPeg.get(); var cli = MatrixClientPeg.get();
@ -123,7 +124,7 @@ module.exports = React.createClass({
</a> </a>
<div className="mx_MImageBody_download"> <div className="mx_MImageBody_download">
<a href={cli.mxcUrlToHttp(content.url)} target="_blank"> <a href={cli.mxcUrlToHttp(content.url)} target="_blank">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/download.svg" width="12" height="14"/> <TintableSvg src="img/download.svg" width="12" height="14"/>
Download {content.body} ({ content.info && content.info.size ? filesize(content.info.size) : "Unknown size" }) Download {content.body} ({ content.info && content.info.size ? filesize(content.info.size) : "Unknown size" })
</a> </a>
</div> </div>

View file

@ -465,6 +465,7 @@ module.exports = React.createClass({
var me = this.props.room.getMember(MatrixClientPeg.get().credentials.userId); var me = this.props.room.getMember(MatrixClientPeg.get().credentials.userId);
var uploadInputStyle = {display: 'none'}; var uploadInputStyle = {display: 'none'};
var MemberAvatar = sdk.getComponent('avatars.MemberAvatar'); var MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
var TintableSvg = sdk.getComponent("elements.TintableSvg");
var callButton, videoCallButton, hangupButton; var callButton, videoCallButton, hangupButton;
var call = CallHandler.getCallForRoom(this.props.room.roomId); var call = CallHandler.getCallForRoom(this.props.room.roomId);
@ -478,11 +479,11 @@ module.exports = React.createClass({
else { else {
callButton = callButton =
<div className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title="Voice call"> <div className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title="Voice call">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/voice.svg" width="16" height="26"/> <TintableSvg src="img/voice.svg" width="16" height="26"/>
</div> </div>
videoCallButton = videoCallButton =
<div className="mx_MessageComposer_videocall" onClick={this.onCallClick} title="Video call"> <div className="mx_MessageComposer_videocall" onClick={this.onCallClick} title="Video call">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/call.svg" width="30" height="22"/> <TintableSvg src="img/call.svg" width="30" height="22"/>
</div> </div>
} }
@ -497,7 +498,7 @@ module.exports = React.createClass({
<textarea ref="textarea" rows="1" onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} placeholder="Type a message..." /> <textarea ref="textarea" rows="1" onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} placeholder="Type a message..." />
</div> </div>
<div className="mx_MessageComposer_upload" onClick={this.onUploadClick} title="Upload file"> <div className="mx_MessageComposer_upload" onClick={this.onUploadClick} title="Upload file">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/upload.svg" width="19" height="24"/> <TintableSvg src="img/upload.svg" width="19" height="24"/>
<input type="file" style={uploadInputStyle} ref="uploadInput" onChange={this.onUploadFileSelected} /> <input type="file" style={uploadInputStyle} ref="uploadInput" onChange={this.onUploadFileSelected} />
</div> </div>
{ hangupButton } { hangupButton }

View file

@ -74,6 +74,7 @@ module.exports = React.createClass({
render: function() { render: function() {
var EditableText = sdk.getComponent("elements.EditableText"); var EditableText = sdk.getComponent("elements.EditableText");
var RoomAvatar = sdk.getComponent('avatars.RoomAvatar'); var RoomAvatar = sdk.getComponent('avatars.RoomAvatar');
var TintableSvg = sdk.getComponent("elements.TintableSvg");
var header; var header;
if (this.props.simpleHeader) { if (this.props.simpleHeader) {
@ -123,7 +124,7 @@ module.exports = React.createClass({
<div className="mx_RoomHeader_nametext" title={ this.props.room.name }>{ this.props.room.name }</div> <div className="mx_RoomHeader_nametext" title={ this.props.room.name }>{ this.props.room.name }</div>
{ searchStatus } { searchStatus }
<div className="mx_RoomHeader_settingsButton" title="Settings"> <div className="mx_RoomHeader_settingsButton" title="Settings">
<object className="mx_Svg" type="image/svg+xml" data="img/settings.svg" width="12" height="12"/> <TintableSvg src="img/settings.svg" width="12" height="12"/>
</div> </div>
</div> </div>
if (topic) topic_el = <div className="mx_RoomHeader_topic" title={topic.getContent().topic}>{ topic.getContent().topic }</div>; if (topic) topic_el = <div className="mx_RoomHeader_topic" title={topic.getContent().topic}>{ topic.getContent().topic }</div>;
@ -140,8 +141,7 @@ module.exports = React.createClass({
if (this.props.onLeaveClick) { if (this.props.onLeaveClick) {
leave_button = leave_button =
<div className="mx_RoomHeader_button mx_RoomHeader_leaveButton" onClick={this.props.onLeaveClick} title="Leave room"> <div className="mx_RoomHeader_button mx_RoomHeader_leaveButton" onClick={this.props.onLeaveClick} title="Leave room">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/leave.svg" <TintableSvg src="img/leave.svg" width="26" height="20"/>
width="26" height="20"/>
</div>; </div>;
} }
@ -149,8 +149,7 @@ module.exports = React.createClass({
if (this.props.onForgetClick) { if (this.props.onForgetClick) {
forget_button = forget_button =
<div className="mx_RoomHeader_button mx_RoomHeader_leaveButton" onClick={this.props.onForgetClick} title="Forget room"> <div className="mx_RoomHeader_button mx_RoomHeader_leaveButton" onClick={this.props.onForgetClick} title="Forget room">
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/leave.svg" <TintableSvg src="img/leave.svg" width="26" height="20"/>
width="26" height="20"/>
</div>; </div>;
} }
@ -171,7 +170,7 @@ module.exports = React.createClass({
{ forget_button } { forget_button }
{ leave_button } { leave_button }
<div className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search"> <div className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
<object className="mx_Svg" type="image/svg+xml" data="img/search.svg" width="21" height="19"/> <TintableSvg src="img/search.svg" width="21" height="19"/>
</div> </div>
</div> </div>
</div> </div>