support fixing up dynamically loaded SVGs
This commit is contained in:
parent
555abdae30
commit
001dc8612b
7 changed files with 74 additions and 25 deletions
|
@ -45,6 +45,7 @@ var commands = {
|
||||||
|
|
||||||
tint: function(room_id, args) {
|
tint: function(room_id, args) {
|
||||||
Tinter.tint(args);
|
Tinter.tint(args);
|
||||||
|
return success();
|
||||||
},
|
},
|
||||||
|
|
||||||
encrypt: function(room_id, args) {
|
encrypt: function(room_id, args) {
|
||||||
|
|
|
@ -14,6 +14,13 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var dis = require('./dispatcher');
|
||||||
|
|
||||||
|
var registered = false;
|
||||||
|
if (!registered) {
|
||||||
|
dis.register(_onAction);
|
||||||
|
}
|
||||||
|
|
||||||
var keyRgb = [
|
var keyRgb = [
|
||||||
"rgb(118, 207, 166)",
|
"rgb(118, 207, 166)",
|
||||||
"rgb(234, 245, 240)",
|
"rgb(234, 245, 240)",
|
||||||
|
@ -30,6 +37,15 @@ var keyRgb = [
|
||||||
var keyHex = [
|
var keyHex = [
|
||||||
"#76CFA6",
|
"#76CFA6",
|
||||||
"#EAF5F0",
|
"#EAF5F0",
|
||||||
|
"#D3EFE1",
|
||||||
|
];
|
||||||
|
|
||||||
|
// cache of our replacement colours
|
||||||
|
// defaults to our keys.
|
||||||
|
var colors = [
|
||||||
|
keyHex[0],
|
||||||
|
keyHex[1],
|
||||||
|
keyHex[2],
|
||||||
];
|
];
|
||||||
|
|
||||||
var cssFixups = [
|
var cssFixups = [
|
||||||
|
@ -60,6 +76,8 @@ var svgAttrs = [
|
||||||
"stroke",
|
"stroke",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var svgNodes = {};
|
||||||
|
|
||||||
var cached = false;
|
var cached = false;
|
||||||
|
|
||||||
function calcCssFixups() {
|
function calcCssFixups() {
|
||||||
|
@ -83,9 +101,11 @@ function calcCssFixups() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcSvgFixups() {
|
function calcSvgFixups(nodes) {
|
||||||
var svgs = document.getElementsByClassName("mx_Svg");
|
var svgs = nodes || document.getElementsByClassName("mx_Svg");
|
||||||
|
var fixups = [];
|
||||||
for (var i = 0; i < svgs.length; i++) {
|
for (var i = 0; i < svgs.length; i++) {
|
||||||
|
|
||||||
var svgDoc = svgs[i].contentDocument;
|
var svgDoc = svgs[i].contentDocument;
|
||||||
if (!svgDoc) continue;
|
if (!svgDoc) continue;
|
||||||
var tags = svgDoc.getElementsByTagName("*");
|
var tags = svgDoc.getElementsByTagName("*");
|
||||||
|
@ -95,7 +115,7 @@ function calcSvgFixups() {
|
||||||
var attr = svgAttrs[k];
|
var attr = svgAttrs[k];
|
||||||
for (var l = 0; l < keyHex.length; l++) {
|
for (var l = 0; l < keyHex.length; l++) {
|
||||||
if (tag.getAttribute(attr) && tag.getAttribute(attr).toUpperCase() === keyHex[l]) {
|
if (tag.getAttribute(attr) && tag.getAttribute(attr).toUpperCase() === keyHex[l]) {
|
||||||
svgFixups.push({
|
fixups.push({
|
||||||
node: tag,
|
node: tag,
|
||||||
attr: attr,
|
attr: attr,
|
||||||
index: l,
|
index: l,
|
||||||
|
@ -105,26 +125,35 @@ function calcSvgFixups() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fixups;
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyCssFixups(primaryColor, secondaryColor, tertiaryColor) {
|
function applyCssFixups() {
|
||||||
var colors = [primaryColor, secondaryColor, tertiaryColor];
|
|
||||||
|
|
||||||
for (var i = 0; i < cssFixups.length; i++) {
|
for (var i = 0; i < cssFixups.length; i++) {
|
||||||
var cssFixup = cssFixups[i];
|
var cssFixup = cssFixups[i];
|
||||||
cssFixup.style[cssFixup.attr] = colors[cssFixup.index];
|
cssFixup.style[cssFixup.attr] = colors[cssFixup.index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applySvgFixups(primaryColor, secondaryColor, tertiaryColor) {
|
function applySvgFixups(fixups) {
|
||||||
var colors = [primaryColor, secondaryColor, tertiaryColor];
|
for (var i = 0; i < fixups.length; i++) {
|
||||||
|
var svgFixup = fixups[i];
|
||||||
for (var i = 0; i < svgFixups.length; i++) {
|
|
||||||
var svgFixup = svgFixups[i];
|
|
||||||
svgFixup.node.setAttribute(svgFixup.attr, colors[svgFixup.index]);
|
svgFixup.node.setAttribute(svgFixup.attr, colors[svgFixup.index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _onAction(payload) {
|
||||||
|
if (payload.action !== "svg_onload") return;
|
||||||
|
// XXX: we should probably faff around with toggling the visibility of the node to avoid flashing the wrong colour.
|
||||||
|
// (although this would result in an even worse flicker as the element redraws)
|
||||||
|
var fixups = calcSvgFixups([ payload.svg ]);
|
||||||
|
if (fixups.length) {
|
||||||
|
svgFixups = svgFixups.concat(fixups); // XXX: this leaks fixups
|
||||||
|
applySvgFixups(fixups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function hexToRgb(color) {
|
function hexToRgb(color) {
|
||||||
if (color[0] === '#') color = color.slice(1);
|
if (color[0] === '#') color = color.slice(1);
|
||||||
if (color.length === 3) {
|
if (color.length === 3) {
|
||||||
|
@ -148,7 +177,7 @@ module.exports = {
|
||||||
tint: function(primaryColor, secondaryColor, tertiaryColor) {
|
tint: function(primaryColor, secondaryColor, tertiaryColor) {
|
||||||
if (!cached) {
|
if (!cached) {
|
||||||
calcCssFixups();
|
calcCssFixups();
|
||||||
calcSvgFixups();
|
svgFixups = calcSvgFixups();
|
||||||
cached = true;
|
cached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,13 +200,15 @@ module.exports = {
|
||||||
tertiaryColor = rgbToHex(rgb1);
|
tertiaryColor = rgbToHex(rgb1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
colors = [primaryColor, secondaryColor, tertiaryColor];
|
||||||
|
|
||||||
// go through manually fixing up the stylesheets.
|
// go through manually fixing up the stylesheets.
|
||||||
applyCssFixups(primaryColor, secondaryColor, tertiaryColor);
|
applyCssFixups();
|
||||||
|
|
||||||
// go through manually fixing up SVG colours.
|
// go through manually fixing up SVG colours.
|
||||||
// we could do this by stylesheets, but keeping the stylesheets
|
// we could do this by stylesheets, but keeping the stylesheets
|
||||||
// updated would be a PITA, so just brute-force search for the
|
// updated would be a PITA, so just brute-force search for the
|
||||||
// key colour; cache the element and apply.
|
// key colour; cache the element and apply.
|
||||||
applySvgFixups(primaryColor, secondaryColor, tertiaryColor);
|
applySvgFixups(svgFixups);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1093,6 +1093,10 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onSvgLoad: function(event) {
|
||||||
|
dis.dispatch({ action: "svg_onload", svg: event.target });
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var RoomHeader = sdk.getComponent('rooms.RoomHeader');
|
var RoomHeader = sdk.getComponent('rooms.RoomHeader');
|
||||||
var MessageComposer = sdk.getComponent('rooms.MessageComposer');
|
var MessageComposer = sdk.getComponent('rooms.MessageComposer');
|
||||||
|
@ -1194,7 +1198,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 className="mx_Svg" type="image/svg+xml" data="img/eol.svg" width="22" height="16"/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/eol.svg" width="22" height="16"/>
|
||||||
Auto-complete
|
Auto-complete
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1268,7 +1272,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 className="mx_Svg" type="image/svg+xml" data="img/upload-big.svg" width="45" height="59"/><br/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/upload-big.svg" width="45" height="59"/><br/>
|
||||||
Drop File Here
|
Drop File Here
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
@ -1306,7 +1310,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 className="mx_Svg" type="image/svg+xml" data="img/fullscreen.svg" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }}/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/fullscreen.svg" width="29" height="22" style={{ marginTop: 1, marginRight: 4 }}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1338,7 +1342,7 @@ module.exports = React.createClass({
|
||||||
{ videoMuteButton }
|
{ videoMuteButton }
|
||||||
{ zoomButton }
|
{ zoomButton }
|
||||||
{ statusBar }
|
{ statusBar }
|
||||||
<object className="mx_Svg" type="image/svg+xml" className="mx_RoomView_voipChevron" data="img/voip-chevron.svg" width="22" height="17"/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" className="mx_RoomView_voipChevron" data="img/voip-chevron.svg" width="22" height="17"/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 dis = require("../../../dispatcher");
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'MFileBody',
|
displayName: 'MFileBody',
|
||||||
|
@ -45,6 +46,10 @@ module.exports = React.createClass({
|
||||||
return linkText;
|
return linkText;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onSvgLoad: function(event) {
|
||||||
|
dis.dispatch({ action: "svg_onload", svg: event.target });
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
var cli = MatrixClientPeg.get();
|
var cli = MatrixClientPeg.get();
|
||||||
|
@ -57,7 +62,7 @@ module.exports = React.createClass({
|
||||||
<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">
|
||||||
<img src="img/download.png" width="10" height="12"/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/download.svg" width="12" height="14"/>
|
||||||
Download {text}
|
Download {text}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -118,7 +118,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">
|
||||||
<img src="img/download.png" width="10" height="12"/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="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>
|
||||||
|
|
|
@ -457,6 +457,10 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onSvgLoad: function(event) {
|
||||||
|
dis.dispatch({ action: "svg_onload", svg: event.target });
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
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'};
|
||||||
|
@ -474,11 +478,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 className="mx_Svg" type="image/svg+xml" data="img/voice.svg" width="16" height="26"/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="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 className="mx_Svg" type="image/svg+xml" data="img/call.svg" width="30" height="22"/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/call.svg" width="30" height="22"/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +497,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 className="mx_Svg" type="image/svg+xml" data="img/upload.svg" width="19" height="24"/>
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="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 }
|
||||||
|
|
|
@ -66,6 +66,10 @@ module.exports = React.createClass({
|
||||||
getRoomName: function() {
|
getRoomName: function() {
|
||||||
return this.refs.name_edit.value;
|
return this.refs.name_edit.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onSvgLoad: function(event) {
|
||||||
|
dis.dispatch({ action: "svg_onload", svg: event.target });
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var EditableText = sdk.getComponent("elements.EditableText");
|
var EditableText = sdk.getComponent("elements.EditableText");
|
||||||
|
@ -136,7 +140,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 className="mx_Svg" type="image/svg+xml" data="img/leave.svg"
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/leave.svg"
|
||||||
width="26" height="20"/>
|
width="26" height="20"/>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
@ -145,7 +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 className="mx_Svg" type="image/svg+xml" data="img/leave.svg"
|
<object onLoad={ this.onSvgLoad } className="mx_Svg" type="image/svg+xml" data="img/leave.svg"
|
||||||
width="26" height="20"/>
|
width="26" height="20"/>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue