layout for file & notif panel
This commit is contained in:
parent
bae6409edb
commit
34bb37aaba
9 changed files with 186 additions and 44 deletions
|
@ -103,6 +103,7 @@ var FilePanel = React.createClass({
|
||||||
manageReadMarkers={false}
|
manageReadMarkers={false}
|
||||||
timelineSet={this.state.timelineSet}
|
timelineSet={this.state.timelineSet}
|
||||||
showUrlPreview = { false }
|
showUrlPreview = { false }
|
||||||
|
tileShape="file_grid"
|
||||||
opacity={ this.props.opacity }
|
opacity={ this.props.opacity }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -79,6 +79,9 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
// className for the panel
|
// className for the panel
|
||||||
className: React.PropTypes.string.isRequired,
|
className: React.PropTypes.string.isRequired,
|
||||||
|
|
||||||
|
// shape parameter to be passed to EventTiles
|
||||||
|
tileShape: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
|
@ -392,6 +395,7 @@ module.exports = React.createClass({
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
checkUnmounting={this._isUnmounting}
|
checkUnmounting={this._isUnmounting}
|
||||||
eventSendStatus={mxEv.status}
|
eventSendStatus={mxEv.status}
|
||||||
|
tileShape={this.props.tileShape}
|
||||||
last={last} isSelectedEvent={highlight}/>
|
last={last} isSelectedEvent={highlight}/>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|
|
@ -47,6 +47,7 @@ var NotificationPanel = React.createClass({
|
||||||
timelineSet={timelineSet}
|
timelineSet={timelineSet}
|
||||||
showUrlPreview = { false }
|
showUrlPreview = { false }
|
||||||
opacity={ this.props.opacity }
|
opacity={ this.props.opacity }
|
||||||
|
tileShape="notif"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,9 @@ var TimelinePanel = React.createClass({
|
||||||
|
|
||||||
// classname to use for the messagepanel
|
// classname to use for the messagepanel
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
|
|
||||||
|
// shape property to be passed to EventTiles
|
||||||
|
tileShape: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
statics: {
|
statics: {
|
||||||
|
@ -979,6 +982,7 @@ var TimelinePanel = React.createClass({
|
||||||
onFillRequest={ this.onMessageListFillRequest }
|
onFillRequest={ this.onMessageListFillRequest }
|
||||||
opacity={ this.props.opacity }
|
opacity={ this.props.opacity }
|
||||||
className={ this.props.className }
|
className={ this.props.className }
|
||||||
|
tileShape={ this.props.tileShape }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -57,6 +57,21 @@ module.exports = React.createClass({
|
||||||
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
var TintableSvg = sdk.getComponent("elements.TintableSvg");
|
||||||
|
|
||||||
if (httpUrl) {
|
if (httpUrl) {
|
||||||
|
if (this.props.tileShape === "file_grid") {
|
||||||
|
return (
|
||||||
|
<span className="mx_MFileBody">
|
||||||
|
<div className="mx_MImageBody_download">
|
||||||
|
<a className="mx_ImageBody_downloadLink" href={cli.mxcUrlToHttp(content.url)} target="_blank" rel="noopener">
|
||||||
|
{ content.body && content.body.length > 0 ? content.body : "Attachment" }
|
||||||
|
</a>
|
||||||
|
<div className="mx_MImageBody_size">
|
||||||
|
{ content.info && content.info.size ? filesize(content.info.size) : "" }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return (
|
return (
|
||||||
<span className="mx_MFileBody">
|
<span className="mx_MFileBody">
|
||||||
<div className="mx_MImageBody_download">
|
<div className="mx_MImageBody_download">
|
||||||
|
@ -67,8 +82,9 @@ module.exports = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
var extra = text ? ': '+text : '';
|
var extra = text ? (': ' + text) : '';
|
||||||
return <span className="mx_MFileBody">
|
return <span className="mx_MFileBody">
|
||||||
Invalid file{extra}
|
Invalid file{extra}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -123,6 +123,30 @@ module.exports = React.createClass({
|
||||||
var content = this.props.mxEvent.getContent();
|
var content = this.props.mxEvent.getContent();
|
||||||
var cli = MatrixClientPeg.get();
|
var cli = MatrixClientPeg.get();
|
||||||
|
|
||||||
|
var download;
|
||||||
|
if (this.props.tileShape === "file_grid") {
|
||||||
|
download = (
|
||||||
|
<div className="mx_MImageBody_download">
|
||||||
|
<a className="mx_MImageBody_downloadLink" href={cli.mxcUrlToHttp(content.url)} target="_blank" rel="noopener">
|
||||||
|
{content.body}
|
||||||
|
</a>
|
||||||
|
<div className="mx_MImageBody_size">
|
||||||
|
{ content.info && content.info.size ? filesize(content.info.size) : "" }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
download = (
|
||||||
|
<div className="mx_MImageBody_download">
|
||||||
|
<a href={cli.mxcUrlToHttp(content.url)} target="_blank" rel="noopener">
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var thumbUrl = this._getThumbUrl();
|
var thumbUrl = this._getThumbUrl();
|
||||||
if (thumbUrl) {
|
if (thumbUrl) {
|
||||||
return (
|
return (
|
||||||
|
@ -133,12 +157,7 @@ module.exports = React.createClass({
|
||||||
onMouseEnter={this.onImageEnter}
|
onMouseEnter={this.onImageEnter}
|
||||||
onMouseLeave={this.onImageLeave} />
|
onMouseLeave={this.onImageLeave} />
|
||||||
</a>
|
</a>
|
||||||
<div className="mx_MImageBody_download">
|
{ download }
|
||||||
<a href={cli.mxcUrlToHttp(content.url)} target="_blank" rel="noopener">
|
|
||||||
<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>
|
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else if (content.body) {
|
} else if (content.body) {
|
||||||
|
|
|
@ -69,12 +69,37 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var download;
|
||||||
|
if (this.props.tileShape === "file_grid") {
|
||||||
|
download = (
|
||||||
|
<div className="mx_MImageBody_download">
|
||||||
|
<a className="mx_MImageBody_downloadLink" href={cli.mxcUrlToHttp(content.url)} target="_blank" rel="noopener">
|
||||||
|
{content.body}
|
||||||
|
</a>
|
||||||
|
<div className="mx_MImageBody_size">
|
||||||
|
{ content.info && content.info.size ? filesize(content.info.size) : "" }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
download = (
|
||||||
|
<div className="mx_MImageBody_download">
|
||||||
|
<a href={cli.mxcUrlToHttp(content.url)} target="_blank" rel="noopener">
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="mx_MVideoBody">
|
<span className="mx_MVideoBody">
|
||||||
<video className="mx_MVideoBody" src={cli.mxcUrlToHttp(content.url)} alt={content.body}
|
<video className="mx_MVideoBody" src={cli.mxcUrlToHttp(content.url)} alt={content.body}
|
||||||
controls preload={preload} autoPlay={false}
|
controls preload={preload} autoPlay={false}
|
||||||
height={height} width={width} poster={poster}>
|
height={height} width={width} poster={poster}>
|
||||||
</video>
|
</video>
|
||||||
|
{ download }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -37,6 +37,9 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
/* callback called when dynamic content in events are loaded */
|
/* callback called when dynamic content in events are loaded */
|
||||||
onWidgetLoad: React.PropTypes.func,
|
onWidgetLoad: React.PropTypes.func,
|
||||||
|
|
||||||
|
/* the shsape of the tile, used */
|
||||||
|
tileShape: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
getEventTileOps: function() {
|
getEventTileOps: function() {
|
||||||
|
@ -69,6 +72,7 @@ module.exports = React.createClass({
|
||||||
return <BodyType ref="body" mxEvent={this.props.mxEvent} highlights={this.props.highlights}
|
return <BodyType ref="body" mxEvent={this.props.mxEvent} highlights={this.props.highlights}
|
||||||
highlightLink={this.props.highlightLink}
|
highlightLink={this.props.highlightLink}
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
|
tileShape={this.props.tileShape}
|
||||||
onWidgetLoad={this.props.onWidgetLoad} />;
|
onWidgetLoad={this.props.onWidgetLoad} />;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -128,6 +128,15 @@ module.exports = React.createClass({
|
||||||
/* the status of this event - ie, mxEvent.status. Denormalised to here so
|
/* the status of this event - ie, mxEvent.status. Denormalised to here so
|
||||||
* that we can tell when it changes. */
|
* that we can tell when it changes. */
|
||||||
eventSendStatus: React.PropTypes.string,
|
eventSendStatus: React.PropTypes.string,
|
||||||
|
|
||||||
|
/* the shape of the tile. by default, the layout is intended for the
|
||||||
|
* normal room timeline. alternative values are: "file_list", "file_grid"
|
||||||
|
* and "notif". This could be done by CSS, but it'd be horribly inefficient.
|
||||||
|
* It could also be done by subclassing EventTile, but that'd be quite
|
||||||
|
* boiilerplatey. So just make the necessary render decisions conditional
|
||||||
|
* for now.
|
||||||
|
*/
|
||||||
|
tileShape: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -382,18 +391,16 @@ module.exports = React.createClass({
|
||||||
this.props.eventSendStatus
|
this.props.eventSendStatus
|
||||||
) !== -1,
|
) !== -1,
|
||||||
mx_EventTile_notSent: this.props.eventSendStatus == 'not_sent',
|
mx_EventTile_notSent: this.props.eventSendStatus == 'not_sent',
|
||||||
mx_EventTile_highlight: this.shouldHighlight(),
|
mx_EventTile_highlight: this.props.tileShape === 'notif' ? false : this.shouldHighlight(),
|
||||||
mx_EventTile_selected: this.props.isSelectedEvent,
|
mx_EventTile_selected: this.props.isSelectedEvent,
|
||||||
mx_EventTile_continuation: this.props.continuation,
|
mx_EventTile_continuation: this.props.tileShape ? '' : this.props.continuation,
|
||||||
mx_EventTile_last: this.props.last,
|
mx_EventTile_last: this.props.last,
|
||||||
mx_EventTile_contextual: this.props.contextual,
|
mx_EventTile_contextual: this.props.contextual,
|
||||||
menu: this.state.menu,
|
menu: this.state.menu,
|
||||||
mx_EventTile_verified: this.state.verified == true,
|
mx_EventTile_verified: this.state.verified == true,
|
||||||
mx_EventTile_unverified: this.state.verified == false,
|
mx_EventTile_unverified: this.state.verified == false,
|
||||||
});
|
});
|
||||||
var timestamp = <a href={ "#/room/" + this.props.mxEvent.getRoomId() +"/"+ this.props.mxEvent.getId() }>
|
var permalink = "#/room/" + this.props.mxEvent.getRoomId() +"/"+ this.props.mxEvent.getId();
|
||||||
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
var readAvatars = this.getReadAvatars();
|
var readAvatars = this.getReadAvatars();
|
||||||
|
|
||||||
|
@ -401,7 +408,10 @@ module.exports = React.createClass({
|
||||||
let avatarSize;
|
let avatarSize;
|
||||||
let needsSenderProfile;
|
let needsSenderProfile;
|
||||||
|
|
||||||
if (isInfoMessage) {
|
if (this.props.tileShape === "notif") {
|
||||||
|
avatarSize = 24;
|
||||||
|
needsSenderProfile = true;
|
||||||
|
} else if (isInfoMessage) {
|
||||||
// a small avatar, with no sender profile, for emotes and
|
// a small avatar, with no sender profile, for emotes and
|
||||||
// joins/parts/etc
|
// joins/parts/etc
|
||||||
avatarSize = 14;
|
avatarSize = 14;
|
||||||
|
@ -428,17 +438,72 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
if (needsSenderProfile) {
|
if (needsSenderProfile) {
|
||||||
let aux = null;
|
let aux = null;
|
||||||
|
if (!this.props.tileShape) {
|
||||||
if (msgtype === 'm.image') aux = "sent an image";
|
if (msgtype === 'm.image') aux = "sent an image";
|
||||||
else if (msgtype === 'm.video') aux = "sent a video";
|
else if (msgtype === 'm.video') aux = "sent a video";
|
||||||
else if (msgtype === 'm.file') aux = "uploaded a file";
|
else if (msgtype === 'm.file') aux = "uploaded a file";
|
||||||
|
|
||||||
sender = <SenderProfile onClick={ this.onSenderProfileClick } mxEvent={this.props.mxEvent} aux={aux} />;
|
sender = <SenderProfile onClick={ this.onSenderProfileClick } mxEvent={this.props.mxEvent} aux={aux} />;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
sender = <SenderProfile mxEvent={this.props.mxEvent} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var editButton = (
|
var editButton = (
|
||||||
<img className="mx_EventTile_editButton" src="img/icon_context_message.svg" width="19" height="19" alt="Options" title="Options" onClick={this.onEditClicked} />
|
<img className="mx_EventTile_editButton" src="img/icon_context_message.svg" width="19" height="19" alt="Options" title="Options" onClick={this.onEditClicked} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (this.props.tileShape === "notif") {
|
||||||
|
var room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes}>
|
||||||
|
<div className="mx_EventTile_roomName">
|
||||||
|
<a href={ permalink }>
|
||||||
|
{ room.name }
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="mx_EventTile_senderDetails">
|
||||||
|
{ avatar }
|
||||||
|
<a href={ permalink }>
|
||||||
|
{ sender }
|
||||||
|
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="mx_EventTile_line" >
|
||||||
|
<EventTileType ref="tile"
|
||||||
|
mxEvent={this.props.mxEvent}
|
||||||
|
highlights={this.props.highlights}
|
||||||
|
highlightLink={this.props.highlightLink}
|
||||||
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
|
onWidgetLoad={this.props.onWidgetLoad} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (this.props.tileShape === "file_grid") {
|
||||||
|
return (
|
||||||
|
<div className={classes}>
|
||||||
|
<div className="mx_EventTile_line" >
|
||||||
|
<EventTileType ref="tile"
|
||||||
|
mxEvent={this.props.mxEvent}
|
||||||
|
highlights={this.props.highlights}
|
||||||
|
highlightLink={this.props.highlightLink}
|
||||||
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
|
tileShape={this.props.tileShape}
|
||||||
|
onWidgetLoad={this.props.onWidgetLoad} />
|
||||||
|
</div>
|
||||||
|
<a className="mx_EventTile_senderDetailsLink" href={ permalink }>
|
||||||
|
<div className="mx_EventTile_senderDetails">
|
||||||
|
{ sender }
|
||||||
|
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<div className="mx_EventTile_msgOption">
|
<div className="mx_EventTile_msgOption">
|
||||||
|
@ -447,7 +512,9 @@ module.exports = React.createClass({
|
||||||
{ avatar }
|
{ avatar }
|
||||||
{ sender }
|
{ sender }
|
||||||
<div className="mx_EventTile_line">
|
<div className="mx_EventTile_line">
|
||||||
{ timestamp }
|
<a href={ permalink }>
|
||||||
|
<MessageTimestamp ts={this.props.mxEvent.getTs()} />
|
||||||
|
</a>
|
||||||
<EventTileType ref="tile"
|
<EventTileType ref="tile"
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
highlights={this.props.highlights}
|
highlights={this.props.highlights}
|
||||||
|
@ -458,5 +525,6 @@ module.exports = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue