Convert image URLs in React to require calls

This allows Webpack to insert the proper image URL after builds steps like
adding a hash and so on. The path you supply to `require` is relative to the JS
source file, just like any other would be.
This commit is contained in:
J. Ryan Stinnett 2019-01-10 19:37:28 -06:00
parent 989227d435
commit 20e296b20e
75 changed files with 201 additions and 176 deletions

View file

@ -147,7 +147,7 @@ module.exports = React.createClass({
<div className="mx_RoomView_fileDropTarget">
<div className="mx_RoomView_fileDropTargetLabel"
title={_t("Drop File Here")}>
<TintableSvg src="img/upload-big.svg" width="45" height="59" />
<TintableSvg src={require("../../../../res/img/upload-big.svg")} width="45" height="59" />
<br />
{ _t("Drop file here to upload") }
</div>

View file

@ -160,7 +160,7 @@ const EntityTile = React.createClass({
if (this.props.showInviteButton) {
inviteButton = (
<div className="mx_EntityTile_invite">
<img src="img/plus.svg" width="16" height="16" />
<img src={require("../../../../res/img/plus.svg")} width="16" height="16" />
</div>
);
}
@ -169,8 +169,8 @@ const EntityTile = React.createClass({
const powerStatus = this.props.powerStatus;
if (powerStatus) {
const src = {
[EntityTile.POWER_STATUS_MODERATOR]: "img/mod.svg",
[EntityTile.POWER_STATUS_ADMIN]: "img/admin.svg",
[EntityTile.POWER_STATUS_MODERATOR]: require("../../../../res/img/mod.svg"),
[EntityTile.POWER_STATUS_ADMIN]: require("../../../../res/img/admin.svg"),
}[powerStatus];
const alt = {
[EntityTile.POWER_STATUS_MODERATOR]: _t("Moderator"),

View file

@ -768,23 +768,31 @@ module.exports.haveTileForEvent = function(e) {
function E2ePadlockUndecryptable(props) {
return (
<E2ePadlock alt={_t("Undecryptable")}
src="img/e2e-blocked.svg" width="12" height="12"
src={require("../../../../res/img/e2e-blocked.svg")} width="12" height="12"
style={{ marginLeft: "-1px" }} {...props} />
);
}
function E2ePadlockEncrypting(props) {
return <E2ePadlock alt={_t("Encrypting")} src="img/e2e-encrypting.svg" width="10" height="12" {...props} />;
return (
<E2ePadlock alt={_t("Encrypting")}
src={require("../../../../res/img/e2e-encrypting.svg")} width="10" height="12"
{...props} />
);
}
function E2ePadlockNotSent(props) {
return <E2ePadlock alt={_t("Encrypted, not sent")} src="img/e2e-not_sent.svg" width="10" height="12" {...props} />;
return (
<E2ePadlock alt={_t("Encrypted, not sent")}
src={require("../../../../res/img/e2e-not_sent.svg")} width="10" height="12"
{...props} />
);
}
function E2ePadlockVerified(props) {
return (
<E2ePadlock alt={_t("Encrypted by a verified device")}
src="img/e2e-verified.svg" width="10" height="12"
src={require("../../../../res/img/e2e-verified.svg")} width="10" height="12"
{...props} />
);
}
@ -792,7 +800,7 @@ function E2ePadlockVerified(props) {
function E2ePadlockUnverified(props) {
return (
<E2ePadlock alt={_t("Encrypted by an unverified device")}
src="img/e2e-warning.svg" width="15" height="12"
src={require("../../../../res/img/e2e-warning.svg")} width="15" height="12"
style={{ marginLeft: "-2px" }} {...props} />
);
}
@ -800,7 +808,7 @@ function E2ePadlockUnverified(props) {
function E2ePadlockUnencrypted(props) {
return (
<E2ePadlock alt={_t("Unencrypted message")}
src="img/e2e-unencrypted.svg" width="12" height="12"
src={require("../../../../res/img/e2e-unencrypted.svg")} width="12" height="12"
{...props} />
);
}

View file

@ -135,7 +135,7 @@ module.exports = React.createClass({
</div>
</div>
<img className="mx_LinkPreviewWidget_cancel mx_filterFlipColor"
src="img/cancel.svg" width="18" height="18"
src={require("../../../../res/img/cancel.svg")} width="18" height="18"
onClick={this.props.onCancelClick} />
</div>
);

View file

@ -27,19 +27,19 @@ export default class MemberDeviceInfo extends React.Component {
if (this.props.device.isBlocked()) {
indicator = (
<div className="mx_MemberDeviceInfo_blacklisted">
<img src="img/e2e-blocked.svg" width="12" height="12" style={{ marginLeft: "-1px" }} alt={_t("Blacklisted")} />
<img src={require("../../../../res/img/e2e-blocked.svg")} width="12" height="12" style={{ marginLeft: "-1px" }} alt={_t("Blacklisted")} />
</div>
);
} else if (this.props.device.isVerified()) {
indicator = (
<div className="mx_MemberDeviceInfo_verified">
<img src="img/e2e-verified.svg" width="10" height="12" alt={_t("Verified")} />
<img src={require("../../../../res/img/e2e-verified.svg")} width="10" height="12" alt={_t("Verified")} />
</div>
);
} else {
indicator = (
<div className="mx_MemberDeviceInfo_unverified">
<img src="img/e2e-warning.svg" width="15" height="12" style={{ marginLeft: "-2px" }} alt={_t("Unverified")} />
<img src={require("../../../../res/img/e2e-warning.svg")} width="15" height="12" style={{ marginLeft: "-2px" }} alt={_t("Unverified")} />
</div>
);
}

View file

@ -815,7 +815,7 @@ module.exports = withMatrixClient(React.createClass({
onClick={this.onNewDMClick}
>
<div className="mx_RoomTile_avatar">
<img src="img/create-big.svg" width="26" height="26" />
<img src={require("../../../../res/img/create-big.svg")} width="26" height="26" />
</div>
<div className={labelClasses}><i>{ _t("Start a chat") }</i></div>
</AccessibleButton>;
@ -963,7 +963,7 @@ module.exports = withMatrixClient(React.createClass({
<div className="mx_MemberInfo">
<div className="mx_MemberInfo_name">
<AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}>
<img src="img/minimise.svg" width="10" height="16" className="mx_filterFlipColor" alt={_t('Close')} />
<img src={require("../../../../res/img/minimise.svg")} width="10" height="16" className="mx_filterFlipColor" alt={_t('Close')} />
</AccessibleButton>
<EmojiText element="h2">{ memberName }</EmojiText>
</div>

View file

@ -253,7 +253,7 @@ module.exports = React.createClass({
const text = _t("and %(count)s others...", { count: overflowCount });
return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
<BaseAvatar url="img/ellipsis.svg" name="..." width={36} height={36} />
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true}
onClick={onClick} />
);

View file

@ -155,12 +155,12 @@ export default class MessageComposer extends React.Component {
const fileAcceptedOrError = this.props.uploadAllowed(files[i]);
if (fileAcceptedOrError === true) {
acceptedFiles.push(<li key={i}>
<TintableSvg key={i} src="img/files.svg" width="16" height="16" /> { files[i].name || _t('Attachment') }
<TintableSvg key={i} src={require("../../../../res/img/files.svg")} width="16" height="16" /> { files[i].name || _t('Attachment') }
</li>);
fileList.push(files[i]);
} else {
failedFiles.push(<li key={i}>
<TintableSvg key={i} src="img/files.svg" width="16" height="16" /> { files[i].name || _t('Attachment') } <p>{ _t('Reason') + ": " + fileAcceptedOrError}</p>
<TintableSvg key={i} src={require("../../../../res/img/files.svg")} width="16" height="16" /> { files[i].name || _t('Attachment') } <p>{ _t('Reason') + ": " + fileAcceptedOrError}</p>
</li>);
}
}
@ -320,11 +320,11 @@ export default class MessageComposer extends React.Component {
const roomIsEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
if (roomIsEncrypted) {
// FIXME: show a /!\ if there are untrusted devices in the room...
e2eImg = 'img/e2e-verified.svg';
e2eImg = require("../../../../res/img/e2e-verified.svg");
e2eTitle = _t('Encrypted room');
e2eClass = 'mx_MessageComposer_e2eIcon';
} else {
e2eImg = 'img/e2e-unencrypted.svg';
e2eImg = require("../../../../res/img/e2e-unencrypted.svg");
e2eTitle = _t('Unencrypted room');
e2eClass = 'mx_MessageComposer_e2eIcon mx_filterFlipColor';
}
@ -344,16 +344,16 @@ export default class MessageComposer extends React.Component {
if (this.props.callState && this.props.callState !== 'ended') {
hangupButton =
<AccessibleButton key="controls_hangup" className="mx_MessageComposer_hangup" onClick={this.onHangupClick}>
<img src="img/hangup.svg" alt={_t('Hangup')} title={_t('Hangup')} width="25" height="25" />
<img src={require("../../../../res/img/hangup.svg")} alt={_t('Hangup')} title={_t('Hangup')} width="25" height="25" />
</AccessibleButton>;
} else {
callButton =
<AccessibleButton key="controls_call" className="mx_MessageComposer_voicecall" onClick={this.onVoiceCallClick} title={_t('Voice call')}>
<TintableSvg src="img/feather-icons/phone.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/phone.svg")} width="20" height="20" />
</AccessibleButton>;
videoCallButton =
<AccessibleButton key="controls_videocall" className="mx_MessageComposer_videocall" onClick={this.onCallClick} title={_t('Video call')}>
<TintableSvg src="img/feather-icons/video.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/video.svg")} width="20" height="20" />
</AccessibleButton>;
}
@ -395,7 +395,7 @@ export default class MessageComposer extends React.Component {
const uploadButton = (
<AccessibleButton key="controls_upload" className="mx_MessageComposer_upload"
onClick={this.onUploadClick} title={_t('Upload file')}>
<TintableSvg src="img/feather-icons/paperclip.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/paperclip.svg")} width="20" height="20" />
<input ref="uploadInput" type="file"
style={uploadInputStyle}
multiple
@ -407,7 +407,7 @@ export default class MessageComposer extends React.Component {
<AccessibleButton element="img" className="mx_MessageComposer_formatting"
alt={_t("Show Text Formatting Toolbar")}
title={_t("Show Text Formatting Toolbar")}
src="img/button-text-formatting.svg"
src={require("../../../../res/img/button-text-formatting.svg")}
onClick={this.onToggleFormattingClicked}
style={{visibility: this.state.showFormatting ? 'hidden' : 'visible'}}
key="controls_formatting" />
@ -451,7 +451,7 @@ export default class MessageComposer extends React.Component {
controls.push(<div className="mx_MessageComposer_replaced_wrapper">
<div className="mx_MessageComposer_replaced_valign">
<img className="mx_MessageComposer_roomReplaced_icon" src="img/room_replaced.svg" />
<img className="mx_MessageComposer_roomReplaced_icon" src={require("../../../../res/img/room_replaced.svg")} />
<span className="mx_MessageComposer_roomReplaced_header">
{_t("This room has been replaced and is no longer active.")}
</span><br />
@ -487,7 +487,7 @@ export default class MessageComposer extends React.Component {
title={_t(name)}
onMouseDown={onFormatButtonClicked}
key={name}
src={`img/button-text-${name}${suffix}.svg`}
src={require(`../../../../res/img/button-text-${name}${suffix}.svg`)}
height="17" />;
},
);
@ -500,11 +500,11 @@ export default class MessageComposer extends React.Component {
<img title={this.state.inputState.isRichTextEnabled ? _t("Turn Markdown on") : _t("Turn Markdown off")}
onMouseDown={this.onToggleMarkdownClicked}
className="mx_MessageComposer_formatbar_markdown mx_filterFlipColor"
src={`img/button-md-${!this.state.inputState.isRichTextEnabled}.png`} />
src={require(`../../../../res/img/button-md-${!this.state.inputState.isRichTextEnabled}.png`)} />
<AccessibleButton element="img" title={_t("Hide Text Formatting Toolbar")}
onClick={this.onToggleFormattingClicked}
className="mx_MessageComposer_formatbar_cancel mx_filterFlipColor"
src="img/icon-text-cancel.svg" />
src={require("../../../../res/img/icon-text-cancel.svg")} />
</div>
</div>;
}

View file

@ -1599,7 +1599,7 @@ export default class MessageComposerInput extends React.Component {
<img className="mx_MessageComposer_input_markdownIndicator mx_filterFlipColor"
onMouseDown={this.onMarkdownToggleClicked}
title={this.state.isRichTextEnabled ? _t("Markdown is disabled") : _t("Markdown is enabled")}
src={`img/button-md-${!this.state.isRichTextEnabled}.png`} />
src={require(`../../../../res/img/button-md-${!this.state.isRichTextEnabled}.png`)} />
<Editor ref={this._collectEditor}
dir="auto"
className="mx_MessageComposer_editor"

View file

@ -67,7 +67,7 @@ module.exports = React.createClass({
if (this._canUnpin()) {
unpinButton = (
<AccessibleButton onClick={this.onUnpinClicked} className="mx_PinnedEventTile_unpinButton">
<img src="img/cancel-red.svg" width="8" height="8" alt={_t('Unpin Message')} title={_t('Unpin Message')} />
<img src={require("../../../../res/img/cancel-red.svg")} width="8" height="8" alt={_t('Unpin Message')} title={_t('Unpin Message')} />
</AccessibleButton>
);
}

View file

@ -130,7 +130,7 @@ module.exports = React.createClass({
<div className="mx_PinnedEventsPanel">
<div className="mx_PinnedEventsPanel_body">
<AccessibleButton className="mx_PinnedEventsPanel_cancel" onClick={this.props.onCancelClick}>
<img className="mx_filterFlipColor" src="img/cancel.svg" width="18" height="18" />
<img className="mx_filterFlipColor" src={require("../../../../res/img/cancel.svg")} width="18" height="18" />
</AccessibleButton>
<h3 className="mx_PinnedEventsPanel_header">{ _t("Pinned Messages") }</h3>
{ tiles }

View file

@ -68,7 +68,7 @@ export default class ReplyPreview extends React.Component {
{ '💬 ' + _t('Replying') }
</EmojiText>
<div className="mx_ReplyPreview_header mx_ReplyPreview_cancel">
<img className="mx_filterFlipColor" src="img/cancel.svg" width="18" height="18"
<img className="mx_filterFlipColor" src={require("../../../../res/img/cancel.svg")} width="18" height="18"
onClick={cancelQuoting} />
</div>
<div className="mx_ReplyPreview_clear" />

View file

@ -312,14 +312,14 @@ module.exports = React.createClass({
</div>
<div className="mx_RoomHeader_avatarPicker_edit">
<label htmlFor="avatarInput" ref="file_label">
<img src="img/camera.svg"
<img src={require("../../../../res/img/camera.svg")}
alt={_t("Upload avatar")} title={_t("Upload avatar")}
width="17" height="15" />
</label>
<input id="avatarInput" type="file" onChange={this.onAvatarSelected} />
</div>
<div className="mx_RoomHeader_avatarPicker_remove" onClick={this.onAvatarRemoveClick}>
<img src="img/cancel.svg"
<img src={require("../../../../res/img/cancel.svg")}
className="mx_filterFlipColor"
width="10"
alt={_t("Remove avatar")}
@ -337,7 +337,7 @@ module.exports = React.createClass({
if (this.props.onSettingsClick) {
settingsButton =
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title={_t("Settings")}>
<TintableSvg src="img/feather-icons/settings.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/settings.svg")} width="20" height="20" />
</AccessibleButton>;
}
@ -353,7 +353,7 @@ module.exports = React.createClass({
<AccessibleButton className="mx_RoomHeader_button mx_RoomHeader_pinnedButton"
onClick={this.props.onPinnedClick} title={_t("Pinned Messages")}>
{ pinsIndicator }
<TintableSvg src="img/icons-pin.svg" width="16" height="16" />
<TintableSvg src={require("../../../../res/img/icons-pin.svg")} width="16" height="16" />
</AccessibleButton>;
}
@ -361,7 +361,7 @@ module.exports = React.createClass({
// if (this.props.onLeaveClick) {
// leave_button =
// <div className="mx_RoomHeader_button" onClick={this.props.onLeaveClick} title="Leave room">
// <TintableSvg src="img/leave.svg" width="26" height="20"/>
// <TintableSvg src={require("../../../../res/img/leave.svg")} width="26" height="20"/>
// </div>;
// }
@ -369,7 +369,7 @@ module.exports = React.createClass({
if (this.props.onForgetClick) {
forgetButton =
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title={_t("Forget room")}>
<TintableSvg src="img/leave.svg" width="26" height="20" />
<TintableSvg src={require("../../../../res/img/leave.svg")} width="26" height="20" />
</AccessibleButton>;
}
@ -377,7 +377,7 @@ module.exports = React.createClass({
if (this.props.onSearchClick && this.props.inRoom) {
searchButton =
<AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title={_t("Search")}>
<TintableSvg src="img/feather-icons/search.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/search.svg")} width="20" height="20" />
</AccessibleButton>;
}
@ -385,7 +385,7 @@ module.exports = React.createClass({
if (this.props.inRoom) {
shareRoomButton =
<AccessibleButton className="mx_RoomHeader_button" onClick={this.onShareRoomClick} title={_t('Share room')}>
<TintableSvg src="img/feather-icons/share.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/share.svg")} width="20" height="20" />
</AccessibleButton>;
}

View file

@ -124,7 +124,7 @@ module.exports = React.createClass({
emailMatchBlock =
<div className="mx_RoomPreviewBar_warning">
<div className="mx_RoomPreviewBar_warningIcon">
<img src="img/warning.svg" width="24" height="23" title= "/!\\" alt="/!\\" />
<img src={require("../../../../res/img/warning.svg")} width="24" height="23" title= "/!\\" alt="/!\\" />
</div>
<div className="mx_RoomPreviewBar_warningText">
{ _t("This invitation was sent to an email address which is not associated with this account:") }

View file

@ -616,7 +616,7 @@ module.exports = React.createClass({
<div>
<label>
<input type="checkbox" ref="encrypt" onClick={this.onEnableEncryptionClick} />
<img className="mx_RoomSettings_e2eIcon mx_filterFlipColor" src="img/e2e-unencrypted.svg" width="12" height="12" />
<img className="mx_RoomSettings_e2eIcon mx_filterFlipColor" src={require("../../../../res/img/e2e-unencrypted.svg")} width="12" height="12" />
{ _t('Enable encryption') } { _t('(warning: cannot be disabled again!)') }
</label>
{ settings }
@ -627,8 +627,8 @@ module.exports = React.createClass({
<div>
<label>
{ isEncrypted
? <img className="mx_RoomSettings_e2eIcon" src="img/e2e-verified.svg" width="10" height="12" />
: <img className="mx_RoomSettings_e2eIcon mx_filterFlipColor" src="img/e2e-unencrypted.svg" width="12" height="12" />
? <img className="mx_RoomSettings_e2eIcon" src={require("../../../../res/img/e2e-verified.svg")} width="10" height="12" />
: <img className="mx_RoomSettings_e2eIcon mx_filterFlipColor" src={require("../../../../res/img/e2e-unencrypted.svg")} width="12" height="12" />
}
{ isEncrypted ? _t("Encryption is enabled in this room") : _t("Encryption is not enabled in this room") }.
</label>

View file

@ -392,7 +392,13 @@ module.exports = React.createClass({
let dmIndicator;
if (this._isDirectMessageRoom(this.props.room.roomId)) {
dmIndicator = <img src="img/icon_person.svg" className="mx_RoomTile_dm" width="11" height="13" alt="dm" />;
dmIndicator = <img
src={require("../../../../res/img/icon_person.svg")}
className="mx_RoomTile_dm"
width="11"
height="13"
alt="dm"
/>;
}
return <AccessibleButton tabIndex="0"

View file

@ -120,7 +120,7 @@ const SearchableEntityList = React.createClass({
const text = _t("and %(count)s others...", { count: overflowCount });
return (
<EntityTile className="mx_EntityTile_ellipsis" avatarJsx={
<BaseAvatar url="img/ellipsis.svg" name="..." width={36} height={36} />
<BaseAvatar url={require("../../../../res/img/ellipsis.svg")} name="..." width={36} height={36} />
} name={text} presenceState="online" suppressOnHover={true}
onClick={this._showAll} />
);

View file

@ -26,7 +26,7 @@ export function CancelButton(props) {
return (
<AccessibleButton className='mx_RoomHeader_cancelButton' onClick={onClick}>
<img src="img/cancel.svg" className='mx_filterFlipColor'
<img src={require("../../../../res/img/cancel.svg")} className='mx_filterFlipColor'
width="18" height="18" alt={_t("Cancel")} />
</AccessibleButton>
);

View file

@ -152,7 +152,7 @@ export default class Stickerpicker extends React.Component {
className='mx_Stickers_contentPlaceholder'>
<p>{ _t("You don't currently have any stickerpacks enabled") }</p>
<p className='mx_Stickers_addLink'>{ _t("Add some now") }</p>
<img src='img/stickerpack-placeholder.png' alt="" />
<img src={require("../../../../res/img/stickerpack-placeholder.png")} alt="" />
</AccessibleButton>
);
}
@ -351,7 +351,7 @@ export default class Stickerpicker extends React.Component {
onClick={this._onHideStickersClick}
ref='target'
title={_t("Hide Stickers")}>
<TintableSvg src="img/feather-icons/face.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/face.svg")} width="20" height="20" />
</AccessibleButton>;
} else {
// Show show-stickers button
@ -362,7 +362,7 @@ export default class Stickerpicker extends React.Component {
className="mx_MessageComposer_stickers"
onClick={this._onShowStickersClick}
title={_t("Show Stickers")}>
<TintableSvg src="img/feather-icons/face.svg" width="20" height="20" />
<TintableSvg src={require("../../../../res/img/feather-icons/face.svg")} width="20" height="20" />
</AccessibleButton>;
}
return <div>