Merge branch 'develop' of github.com:vector-im/riot-web into t3chguy/devtools-118247
This commit is contained in:
commit
04bca93e0d
84 changed files with 670 additions and 465 deletions
|
@ -17,10 +17,8 @@ limitations under the License.
|
|||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import { DragDropContext } from 'react-dnd';
|
||||
import HTML5Backend from 'react-dnd-html5-backend';
|
||||
import classNames from 'classnames';
|
||||
import KeyCode from 'matrix-react-sdk/lib/KeyCode';
|
||||
import { KeyCode } from 'matrix-react-sdk/lib/Keyboard';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
|
@ -199,4 +197,4 @@ var LeftPanel = React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
module.exports = DragDropContext(HTML5Backend)(LeftPanel);
|
||||
module.exports = LeftPanel;
|
||||
|
|
|
@ -24,7 +24,7 @@ import sdk from 'matrix-react-sdk';
|
|||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
import Analytics from 'matrix-react-sdk/lib/Analytics';
|
||||
import rate_limited_func from 'matrix-react-sdk/lib/ratelimitedfunc';
|
||||
import RateLimitedFunc from 'matrix-react-sdk/lib/ratelimitedfunc';
|
||||
import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
|
||||
import { showGroupInviteDialog, showGroupAddRoomDialog } from 'matrix-react-sdk/lib/GroupAddressPicker';
|
||||
import GroupStoreCache from 'matrix-react-sdk/lib/stores/GroupStoreCache';
|
||||
|
@ -58,8 +58,8 @@ class HeaderButton extends React.Component {
|
|||
<div className="mx_RightPanel_headerButton_badge">
|
||||
{ this.props.badge ? this.props.badge : <span> </span> }
|
||||
</div>
|
||||
<TintableSvg src={this.props.iconSrc} width="25" height="25"/>
|
||||
{ this.props.isHighlighted ? <div className="mx_RightPanel_headerButton_highlight"></div> : <div/> }
|
||||
<TintableSvg src={this.props.iconSrc} width="25" height="25" />
|
||||
{ this.props.isHighlighted ? <div className="mx_RightPanel_headerButton_highlight" /> : <div /> }
|
||||
|
||||
</AccessibleButton>;
|
||||
}
|
||||
|
@ -184,18 +184,17 @@ module.exports = React.createClass({
|
|||
|
||||
onRoomStateMember: function(ev, state, member) {
|
||||
// redraw the badge on the membership list
|
||||
if (this.state.phase == this.Phase.RoomMemberList && member.roomId === this.props.roomId) {
|
||||
if (this.state.phase === this.Phase.RoomMemberList && member.roomId === this.props.roomId) {
|
||||
this._delayedUpdate();
|
||||
}
|
||||
else if (this.state.phase === this.Phase.RoomMemberInfo && member.roomId === this.props.roomId &&
|
||||
} else if (this.state.phase === this.Phase.RoomMemberInfo && member.roomId === this.props.roomId &&
|
||||
member.userId === this.state.member.userId) {
|
||||
// refresh the member info (e.g. new power level)
|
||||
this._delayedUpdate();
|
||||
}
|
||||
},
|
||||
|
||||
_delayedUpdate: new rate_limited_func(function() {
|
||||
this.forceUpdate();
|
||||
_delayedUpdate: new RateLimitedFunc(function() {
|
||||
this.forceUpdate(); // eslint-disable-line babel/no-invalid-this
|
||||
}, 500),
|
||||
|
||||
onAction: function(payload) {
|
||||
|
@ -266,22 +265,23 @@ module.exports = React.createClass({
|
|||
let inviteGroup;
|
||||
|
||||
let membersBadge;
|
||||
if ((this.state.phase == this.Phase.RoomMemberList || this.state.phase === this.Phase.RoomMemberInfo)
|
||||
let membersTitle = _t('Members');
|
||||
if ((this.state.phase === this.Phase.RoomMemberList || this.state.phase === this.Phase.RoomMemberInfo)
|
||||
&& this.props.roomId
|
||||
) {
|
||||
const cli = this.context.matrixClient;
|
||||
const room = cli.getRoom(this.props.roomId);
|
||||
let userIsInRoom;
|
||||
let isUserInRoom;
|
||||
if (room) {
|
||||
membersBadge = formatCount(room.getJoinedMembers().length);
|
||||
userIsInRoom = room.hasMembershipState(
|
||||
this.context.matrixClient.credentials.userId, 'join',
|
||||
);
|
||||
const numMembers = room.getJoinedMembers().length;
|
||||
membersTitle = _t('%(count)s Members', { count: numMembers });
|
||||
membersBadge = <div title={membersTitle}>{ formatCount(numMembers) }</div>;
|
||||
isUserInRoom = room.hasMembershipState(this.context.matrixClient.credentials.userId, 'join');
|
||||
}
|
||||
|
||||
if (userIsInRoom) {
|
||||
if (isUserInRoom) {
|
||||
inviteGroup =
|
||||
<AccessibleButton className="mx_RightPanel_invite" onClick={ this.onInviteButtonClick } >
|
||||
<AccessibleButton className="mx_RightPanel_invite" onClick={this.onInviteButtonClick}>
|
||||
<div className="mx_RightPanel_icon" >
|
||||
<TintableSvg src="img/icon-invite-people.svg" width="35" height="35" />
|
||||
</div>
|
||||
|
@ -292,13 +292,13 @@ module.exports = React.createClass({
|
|||
|
||||
const isPhaseGroup = [
|
||||
this.Phase.GroupMemberInfo,
|
||||
this.Phase.GroupMemberList
|
||||
this.Phase.GroupMemberList,
|
||||
].includes(this.state.phase);
|
||||
|
||||
let headerButtons = [];
|
||||
if (this.props.roomId) {
|
||||
headerButtons = [
|
||||
<HeaderButton key="_membersButton" title={_t('Members')} iconSrc="img/icons-people.svg"
|
||||
<HeaderButton key="_membersButton" title={membersTitle} iconSrc="img/icons-people.svg"
|
||||
isHighlighted={[this.Phase.RoomMemberList, this.Phase.RoomMemberInfo].includes(this.state.phase)}
|
||||
clickPhase={this.Phase.RoomMemberList}
|
||||
badge={membersBadge}
|
||||
|
@ -336,54 +336,54 @@ module.exports = React.createClass({
|
|||
// button on these 2 screens or you won't be able to re-expand the panel.
|
||||
headerButtons.push(
|
||||
<div className="mx_RightPanel_headerButton mx_RightPanel_collapsebutton" key="_minimizeButton"
|
||||
title={ _t("Hide panel") } aria-label={ _t("Hide panel") } onClick={ this.onCollapseClick }
|
||||
title={_t("Hide panel")} aria-label={_t("Hide panel")} onClick={this.onCollapseClick}
|
||||
>
|
||||
<TintableSvg src="img/minimise.svg" width="10" height="16"/>
|
||||
<TintableSvg src="img/minimise.svg" width="10" height="16" />
|
||||
</div>,
|
||||
);
|
||||
}
|
||||
|
||||
let panel = <div />;
|
||||
if (!this.props.collapsed) {
|
||||
if (this.props.roomId && this.state.phase == this.Phase.RoomMemberList) {
|
||||
if (this.props.roomId && this.state.phase === this.Phase.RoomMemberList) {
|
||||
panel = <MemberList roomId={this.props.roomId} key={this.props.roomId} />;
|
||||
} else if (this.props.groupId && this.state.phase == this.Phase.GroupMemberList) {
|
||||
} else if (this.props.groupId && this.state.phase === this.Phase.GroupMemberList) {
|
||||
panel = <GroupMemberList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||
} else if (this.state.phase === this.Phase.GroupRoomList) {
|
||||
panel = <GroupRoomList groupId={this.props.groupId} key={this.props.groupId} />;
|
||||
} else if (this.state.phase == this.Phase.RoomMemberInfo) {
|
||||
} else if (this.state.phase === this.Phase.RoomMemberInfo) {
|
||||
panel = <MemberInfo member={this.state.member} key={this.props.roomId || this.state.member.userId} />;
|
||||
} else if (this.state.phase == this.Phase.GroupMemberInfo) {
|
||||
} else if (this.state.phase === this.Phase.GroupMemberInfo) {
|
||||
panel = <GroupMemberInfo
|
||||
groupMember={this.state.member}
|
||||
groupId={this.props.groupId}
|
||||
key={this.state.member.user_id} />;
|
||||
} else if (this.state.phase == this.Phase.GroupRoomInfo) {
|
||||
} else if (this.state.phase === this.Phase.GroupRoomInfo) {
|
||||
panel = <GroupRoomInfo
|
||||
groupRoomId={this.state.groupRoomId}
|
||||
groupId={this.props.groupId}
|
||||
key={this.state.groupRoomId} />;
|
||||
} else if (this.state.phase == this.Phase.NotificationPanel) {
|
||||
} else if (this.state.phase === this.Phase.NotificationPanel) {
|
||||
panel = <NotificationPanel />;
|
||||
} else if (this.state.phase == this.Phase.FilePanel) {
|
||||
} else if (this.state.phase === this.Phase.FilePanel) {
|
||||
panel = <FilePanel roomId={this.props.roomId} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (!panel) {
|
||||
panel = <div className="mx_RightPanel_blank"></div>;
|
||||
panel = <div className="mx_RightPanel_blank" />;
|
||||
}
|
||||
|
||||
if (this.props.groupId && this.state.isUserPrivilegedInGroup) {
|
||||
inviteGroup = isPhaseGroup ? (
|
||||
<AccessibleButton className="mx_RightPanel_invite" onClick={ this.onInviteButtonClick } >
|
||||
<AccessibleButton className="mx_RightPanel_invite" onClick={this.onInviteButtonClick}>
|
||||
<div className="mx_RightPanel_icon" >
|
||||
<TintableSvg src="img/icon-invite-people.svg" width="35" height="35" />
|
||||
</div>
|
||||
<div className="mx_RightPanel_message">{ _t('Invite to this community') }</div>
|
||||
</AccessibleButton>
|
||||
) : (
|
||||
<AccessibleButton className="mx_RightPanel_invite" onClick={ this.onInviteButtonClick } >
|
||||
<AccessibleButton className="mx_RightPanel_invite" onClick={this.onInviteButtonClick}>
|
||||
<div className="mx_RightPanel_icon" >
|
||||
<TintableSvg src="img/icons-room-add.svg" width="35" height="35" />
|
||||
</div>
|
||||
|
@ -392,19 +392,16 @@ module.exports = React.createClass({
|
|||
);
|
||||
}
|
||||
|
||||
let classes = classNames(
|
||||
"mx_RightPanel", "mx_fadable",
|
||||
{
|
||||
"collapsed": this.props.collapsed,
|
||||
"mx_fadable_faded": this.props.disabled,
|
||||
}
|
||||
);
|
||||
const classes = classNames("mx_RightPanel", "mx_fadable", {
|
||||
"collapsed": this.props.collapsed,
|
||||
"mx_fadable_faded": this.props.disabled,
|
||||
});
|
||||
|
||||
return (
|
||||
<aside className={classes}>
|
||||
<div className="mx_RightPanel_header">
|
||||
<div className="mx_RightPanel_headerButtonGroup">
|
||||
{headerButtons}
|
||||
{ headerButtons }
|
||||
</div>
|
||||
</div>
|
||||
{ panel }
|
||||
|
|
|
@ -20,8 +20,8 @@ limitations under the License.
|
|||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var classNames = require('classnames');
|
||||
var DropTarget = require('react-dnd').DropTarget;
|
||||
var sdk = require('matrix-react-sdk');
|
||||
import { Droppable } from 'react-beautiful-dnd';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
var dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
var Unread = require('matrix-react-sdk/lib/Unread');
|
||||
|
@ -30,7 +30,8 @@ var RoomNotifs = require('matrix-react-sdk/lib/RoomNotifs');
|
|||
var FormattingUtils = require('matrix-react-sdk/lib/utils/FormattingUtils');
|
||||
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
|
||||
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||
import KeyCode from 'matrix-react-sdk/lib/KeyCode';
|
||||
import { KeyCode } from 'matrix-react-sdk/lib/Keyboard';
|
||||
|
||||
|
||||
// turn this on for drop & drag console debugging galore
|
||||
var debug = false;
|
||||
|
@ -326,44 +327,45 @@ var RoomSubList = React.createClass({
|
|||
});
|
||||
},
|
||||
|
||||
calcManualOrderTagData: function(room) {
|
||||
var index = this.state.sortedList.indexOf(room);
|
||||
|
||||
calcManualOrderTagData: function(index) {
|
||||
// we sort rooms by the lexicographic ordering of the 'order' metadata on their tags.
|
||||
// for convenience, we calculate this for now a floating point number between 0.0 and 1.0.
|
||||
|
||||
var orderA = 0.0; // by default we're next to the beginning of the list
|
||||
let orderA = 0.0; // by default we're next to the beginning of the list
|
||||
if (index > 0) {
|
||||
var prevTag = this.state.sortedList[index - 1].tags[this.props.tagName];
|
||||
const prevTag = this.state.sortedList[index - 1].tags[this.props.tagName];
|
||||
if (!prevTag) {
|
||||
console.error("Previous room in sublist is not tagged to be in this list. This should never happen.")
|
||||
}
|
||||
else if (prevTag.order === undefined) {
|
||||
console.error("Previous room in sublist is not tagged to be in this list. This should never happen.");
|
||||
} else if (prevTag.order === undefined) {
|
||||
console.error("Previous room in sublist has no ordering metadata. This should never happen.");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
orderA = prevTag.order;
|
||||
}
|
||||
}
|
||||
|
||||
var orderB = 1.0; // by default we're next to the end of the list too
|
||||
let orderB = 1.0; // by default we're next to the end of the list too
|
||||
if (index < this.state.sortedList.length - 1) {
|
||||
var nextTag = this.state.sortedList[index + 1].tags[this.props.tagName];
|
||||
const nextTag = this.state.sortedList[index + 1].tags[this.props.tagName];
|
||||
if (!nextTag) {
|
||||
console.error("Next room in sublist is not tagged to be in this list. This should never happen.")
|
||||
}
|
||||
else if (nextTag.order === undefined) {
|
||||
console.error("Next room in sublist is not tagged to be in this list. This should never happen.");
|
||||
} else if (nextTag.order === undefined) {
|
||||
console.error("Next room in sublist has no ordering metadata. This should never happen.");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
orderB = nextTag.order;
|
||||
}
|
||||
}
|
||||
|
||||
var order = (orderA + orderB) / 2.0;
|
||||
const order = (orderA + orderB) / 2.0;
|
||||
|
||||
if (order === orderA || order === orderB) {
|
||||
console.error("Cannot describe new list position. This should be incredibly unlikely.");
|
||||
// TODO: renumber the list
|
||||
this.state.sortedList.forEach((room, index) => {
|
||||
MatrixClientPeg.get().setRoomTag(
|
||||
room.roomId, this.props.tagName,
|
||||
{order: index / this.state.sortedList.length},
|
||||
);
|
||||
});
|
||||
return index / this.state.sortedList.length;
|
||||
}
|
||||
|
||||
return order;
|
||||
|
@ -372,12 +374,14 @@ var RoomSubList = React.createClass({
|
|||
makeRoomTiles: function() {
|
||||
var self = this;
|
||||
var DNDRoomTile = sdk.getComponent("rooms.DNDRoomTile");
|
||||
return this.state.sortedList.map(function(room) {
|
||||
return this.state.sortedList.map(function(room, index) {
|
||||
// XXX: is it evil to pass in self as a prop to RoomTile?
|
||||
return (
|
||||
<DNDRoomTile
|
||||
index={index} // For DND
|
||||
room={ room }
|
||||
roomSubList={ self }
|
||||
tagName={self.props.tagName}
|
||||
key={ room.roomId }
|
||||
collapsed={ self.props.collapsed || false}
|
||||
unread={ Unread.doesRoomHaveUnreadMessages(room) }
|
||||
|
@ -563,12 +567,18 @@ var RoomSubList = React.createClass({
|
|||
</TruncatedList>;
|
||||
}
|
||||
|
||||
return connectDropTarget(
|
||||
<div>
|
||||
{ this._getHeaderJsx() }
|
||||
{ subList }
|
||||
</div>
|
||||
);
|
||||
const subListContent = <div>
|
||||
{ this._getHeaderJsx() }
|
||||
{ subList }
|
||||
</div>;
|
||||
|
||||
return this.props.editable ? <Droppable droppableId={"room-sub-list-droppable_" + this.props.tagName}>
|
||||
{ (provided, snapshot) => (
|
||||
<div ref={provided.innerRef}>
|
||||
{ subListContent }
|
||||
</div>
|
||||
) }
|
||||
</Droppable> : subListContent;
|
||||
}
|
||||
else {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
|
@ -582,11 +592,4 @@ var RoomSubList = React.createClass({
|
|||
}
|
||||
});
|
||||
|
||||
// Export the wrapped version, inlining the 'collect' functions
|
||||
// to more closely resemble the ES7
|
||||
module.exports =
|
||||
DropTarget('RoomTile', roomListTarget, function(connect) {
|
||||
return {
|
||||
connectDropTarget: connect.dropTarget(),
|
||||
}
|
||||
})(RoomSubList);
|
||||
module.exports = RoomSubList;
|
||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import KeyCode from 'matrix-react-sdk/lib/KeyCode';
|
||||
import { KeyCode } from 'matrix-react-sdk/lib/Keyboard';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import rate_limited_func from 'matrix-react-sdk/lib/ratelimitedfunc';
|
||||
|
|
|
@ -16,14 +16,17 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import SyntaxHighlight from '../views/elements/SyntaxHighlight';
|
||||
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'ViewSource',
|
||||
|
||||
propTypes: {
|
||||
content: React.PropTypes.object.isRequired,
|
||||
onFinished: React.PropTypes.func.isRequired,
|
||||
content: PropTypes.object.isRequired,
|
||||
onFinished: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
|
@ -45,9 +48,9 @@ module.exports = React.createClass({
|
|||
render: function() {
|
||||
return (
|
||||
<div className="mx_ViewSource">
|
||||
<pre>
|
||||
{JSON.stringify(this.props.content, null, 2)}
|
||||
</pre>
|
||||
<SyntaxHighlight className="json">
|
||||
{ JSON.stringify(this.props.content, null, 2) }
|
||||
</SyntaxHighlight>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,15 +16,16 @@ limitations under the License.
|
|||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
import React from 'react';
|
||||
|
||||
const MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
const dis = require('matrix-react-sdk/lib/dispatcher');
|
||||
const sdk = require('matrix-react-sdk');
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
const Modal = require('matrix-react-sdk/lib/Modal');
|
||||
const Resend = require("matrix-react-sdk/lib/Resend");
|
||||
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||
import Resend from "matrix-react-sdk/lib/Resend";
|
||||
import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
|
||||
import {makeEventPermalink} from 'matrix-react-sdk/lib/matrix-to';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MessageContextMenu',
|
||||
|
@ -107,15 +108,14 @@ module.exports = React.createClass({
|
|||
onFinished: (proceed) => {
|
||||
if (!proceed) return;
|
||||
|
||||
MatrixClientPeg.get().redactEvent(
|
||||
this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
|
||||
).catch(function(e) {
|
||||
const cli = MatrixClientPeg.get();
|
||||
cli.redactEvent(this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()).catch(function(e) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
// display error message stating you couldn't delete this.
|
||||
const code = e.errcode || e.statusCode;
|
||||
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
|
||||
title: _t('Error'),
|
||||
description: _t('You cannot delete this message. (%(code)s)', {code: code})
|
||||
description: _t('You cannot delete this message. (%(code)s)', {code}),
|
||||
});
|
||||
}).done();
|
||||
},
|
||||
|
@ -138,12 +138,12 @@ module.exports = React.createClass({
|
|||
|
||||
onPinClick: function() {
|
||||
MatrixClientPeg.get().getStateEvent(this.props.mxEvent.getRoomId(), 'm.room.pinned_events', '')
|
||||
.catch(e => {
|
||||
.catch((e) => {
|
||||
// Intercept the Event Not Found error and fall through the promise chain with no event.
|
||||
if (e.errcode === "M_NOT_FOUND") return null;
|
||||
throw e;
|
||||
})
|
||||
.then(event => {
|
||||
.then((event) => {
|
||||
const eventIds = (event ? event.pinned : []) || [];
|
||||
if (!eventIds.includes(this.props.mxEvent.getId())) {
|
||||
// Not pinned - add
|
||||
|
@ -153,7 +153,8 @@ module.exports = React.createClass({
|
|||
eventIds.splice(eventIds.indexOf(this.props.mxEvent.getId()), 1);
|
||||
}
|
||||
|
||||
MatrixClientPeg.get().sendStateEvent(this.props.mxEvent.getRoomId(), 'm.room.pinned_events', {pinned: eventIds}, '');
|
||||
const cli = MatrixClientPeg.get();
|
||||
cli.sendStateEvent(this.props.mxEvent.getRoomId(), 'm.room.pinned_events', {pinned: eventIds}, '');
|
||||
});
|
||||
this.closeMenu();
|
||||
},
|
||||
|
@ -177,6 +178,14 @@ module.exports = React.createClass({
|
|||
this.closeMenu();
|
||||
},
|
||||
|
||||
onReplyClick: function() {
|
||||
dis.dispatch({
|
||||
action: 'quote_event',
|
||||
event: this.props.mxEvent,
|
||||
});
|
||||
this.closeMenu();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const eventStatus = this.props.mxEvent.status;
|
||||
let resendButton;
|
||||
|
@ -184,12 +193,11 @@ module.exports = React.createClass({
|
|||
let cancelButton;
|
||||
let forwardButton;
|
||||
let pinButton;
|
||||
let viewSourceButton;
|
||||
let viewClearSourceButton;
|
||||
let unhidePreviewButton;
|
||||
let permalinkButton;
|
||||
let externalURLButton;
|
||||
let quoteButton;
|
||||
let replyButton;
|
||||
|
||||
if (eventStatus === 'not_sent') {
|
||||
resendButton = (
|
||||
|
@ -224,17 +232,25 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
);
|
||||
|
||||
if (SettingsStore.isFeatureEnabled("feature_rich_quoting")) {
|
||||
replyButton = (
|
||||
<div className="mx_MessageContextMenu_field" onClick={this.onReplyClick}>
|
||||
{ _t('Reply') }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.state.canPin) {
|
||||
pinButton = (
|
||||
<div className="mx_MessageContextMenu_field" onClick={this.onPinClick}>
|
||||
{this._isPinned() ? _t('Unpin Message') : _t('Pin Message')}
|
||||
{ this._isPinned() ? _t('Unpin Message') : _t('Pin Message') }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewSourceButton = (
|
||||
const viewSourceButton = (
|
||||
<div className="mx_MessageContextMenu_field" onClick={this.onViewSourceClick}>
|
||||
{ _t('View Source') }
|
||||
</div>
|
||||
|
@ -259,10 +275,10 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
|
||||
permalinkButton = (
|
||||
const permalinkButton = (
|
||||
<div className="mx_MessageContextMenu_field">
|
||||
<a href={ "https://matrix.to/#/" + this.props.mxEvent.getRoomId() +"/"+ this.props.mxEvent.getId() }
|
||||
target="_blank" rel="noopener" onClick={ this.closeMenu }>{ _t('Permalink') }</a>
|
||||
<a href={makeEventPermalink(this.props.mxEvent.getRoomId(), this.props.mxEvent.getId())}
|
||||
target="_blank" rel="noopener" onClick={this.closeMenu}>{ _t('Permalink') }</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -275,29 +291,30 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
// Bridges can provide a 'external_url' to link back to the source.
|
||||
if( typeof(this.props.mxEvent.event.content.external_url) === "string") {
|
||||
externalURLButton = (
|
||||
<div className="mx_MessageContextMenu_field">
|
||||
<a href={ this.props.mxEvent.event.content.external_url }
|
||||
rel="noopener" target="_blank" onClick={ this.closeMenu }>{ _t('Source URL') }</a>
|
||||
</div>
|
||||
);
|
||||
if (typeof(this.props.mxEvent.event.content.external_url) === "string") {
|
||||
externalURLButton = (
|
||||
<div className="mx_MessageContextMenu_field">
|
||||
<a href={this.props.mxEvent.event.content.external_url}
|
||||
rel="noopener" target="_blank" onClick={this.closeMenu}>{ _t('Source URL') }</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
{resendButton}
|
||||
{redactButton}
|
||||
{cancelButton}
|
||||
{forwardButton}
|
||||
{pinButton}
|
||||
{viewSourceButton}
|
||||
{viewClearSourceButton}
|
||||
{unhidePreviewButton}
|
||||
{permalinkButton}
|
||||
{quoteButton}
|
||||
{externalURLButton}
|
||||
{ resendButton }
|
||||
{ redactButton }
|
||||
{ cancelButton }
|
||||
{ forwardButton }
|
||||
{ pinButton }
|
||||
{ viewSourceButton }
|
||||
{ viewClearSourceButton }
|
||||
{ unhidePreviewButton }
|
||||
{ permalinkButton }
|
||||
{ quoteButton }
|
||||
{ replyButton }
|
||||
{ externalURLButton }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -275,7 +275,7 @@ module.exports = React.createClass({
|
|||
<div className={ alertMeClasses } onClick={this._onClickAlertMe} >
|
||||
<img className="mx_RoomTileContextMenu_notif_activeIcon" src="img/notif-active.svg" width="12" height="12" />
|
||||
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src="img/icon-context-mute-off-copy.svg" width="16" height="12" />
|
||||
{ _t('All messages (loud)') }
|
||||
{ _t('All messages (noisy)') }
|
||||
</div>
|
||||
<div className={ allNotifsClasses } onClick={this._onClickAllNotifs} >
|
||||
<img className="mx_RoomTileContextMenu_notif_activeIcon" src="img/notif-active.svg" width="12" height="12" />
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import SyntaxHighlight from '../elements/SyntaxHighlight';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
|
||||
|
@ -60,7 +61,7 @@ class GenericEditor extends DevtoolsComponent {
|
|||
<label htmlFor={id}>{ label }</label>
|
||||
</div>
|
||||
<div className="mx_DevTools_inputCell">
|
||||
<input id={id} onChange={this._onChange} value={this.state[id]} size="32" />
|
||||
<input id={id} className="mx_TextInputDialog_input" onChange={this._onChange} value={this.state[id]} size="32" />
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
@ -363,7 +364,9 @@ class RoomStateExplorer extends DevtoolsComponent {
|
|||
|
||||
return <div className="mx_ViewSource">
|
||||
<div className="mx_Dialog_content">
|
||||
<pre>{ JSON.stringify(this.state.event.event, null, 2) }</pre>
|
||||
<SyntaxHighlight className="json">
|
||||
{ JSON.stringify(this.state.event.event, null, 2) }
|
||||
</SyntaxHighlight>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||
|
@ -492,7 +495,9 @@ class AccountDataExplorer extends DevtoolsComponent {
|
|||
|
||||
return <div className="mx_ViewSource">
|
||||
<div className="mx_Dialog_content">
|
||||
<pre>{ JSON.stringify(this.state.event.event, null, 2) }</pre>
|
||||
<SyntaxHighlight className="json">
|
||||
{ JSON.stringify(this.state.event.event, null, 2) }
|
||||
</SyntaxHighlight>
|
||||
</div>
|
||||
<div className="mx_Dialog_buttons">
|
||||
<button onClick={this.onBack}>{ _t('Back') }</button>
|
||||
|
|
|
@ -20,7 +20,7 @@ var React = require('react');
|
|||
|
||||
var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
|
||||
|
||||
var DateUtils = require('matrix-react-sdk/lib/DateUtils');
|
||||
import {formatDate} from 'matrix-react-sdk/lib/DateUtils';
|
||||
var filesize = require('filesize');
|
||||
var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
|
||||
const Modal = require('matrix-react-sdk/lib/Modal');
|
||||
|
@ -159,7 +159,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
eventMeta = (<div className="mx_ImageView_metadata">
|
||||
{ _t('Uploaded on %(date)s by %(user)s', {date: DateUtils.formatDate(new Date(this.props.mxEvent.getTs())), user: sender}) }
|
||||
{ _t('Uploaded on %(date)s by %(user)s', {date: formatDate(new Date(this.props.mxEvent.getTs())), user: sender}) }
|
||||
</div>);
|
||||
}
|
||||
|
||||
|
|
53
src/components/views/elements/SyntaxHighlight.js
Normal file
53
src/components/views/elements/SyntaxHighlight.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {highlightBlock} from 'highlight.js';
|
||||
|
||||
export default class SyntaxHighlight extends React.Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._ref = this._ref.bind(this);
|
||||
}
|
||||
|
||||
// componentDidUpdate used here for reusability
|
||||
// componentWillReceiveProps fires too early to call highlightBlock on.
|
||||
componentDidUpdate() {
|
||||
if (this._el) highlightBlock(this._el);
|
||||
}
|
||||
|
||||
// call componentDidUpdate because _ref is fired on initial render
|
||||
// which does not fire componentDidUpdate
|
||||
_ref(el) {
|
||||
this._el = el;
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className, children } = this.props;
|
||||
|
||||
return <pre className={`${className} mx_SyntaxHighlight`} ref={this._ref}>
|
||||
<code>{ children }</code>
|
||||
</pre>;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -15,8 +16,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import DateUtils from 'matrix-react-sdk/lib/DateUtils';
|
||||
import {formatFullDateNoTime} from 'matrix-react-sdk/lib/DateUtils';
|
||||
|
||||
function getdaysArray() {
|
||||
return [
|
||||
|
@ -30,30 +32,30 @@ function getdaysArray() {
|
|||
];
|
||||
}
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'DateSeparator',
|
||||
render: function() {
|
||||
var date = new Date(this.props.ts);
|
||||
var today = new Date();
|
||||
var yesterday = new Date();
|
||||
var days = getdaysArray();
|
||||
yesterday.setDate(today.getDate() - 1);
|
||||
var label;
|
||||
if (date.toDateString() === today.toDateString()) {
|
||||
label = _t('Today');
|
||||
}
|
||||
else if (date.toDateString() === yesterday.toDateString()) {
|
||||
label = _t('Yesterday');
|
||||
}
|
||||
else if (today.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) {
|
||||
label = days[date.getDay()];
|
||||
}
|
||||
else {
|
||||
label = DateUtils.formatFullDate(date, this.props.showTwelveHour);
|
||||
}
|
||||
export default class DateSeparator extends React.Component {
|
||||
static propTypes = {
|
||||
ts: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
return (
|
||||
<h2 className="mx_DateSeparator">{ label }</h2>
|
||||
);
|
||||
getLabel() {
|
||||
const date = new Date(this.props.ts);
|
||||
const today = new Date();
|
||||
const yesterday = new Date();
|
||||
const days = getdaysArray();
|
||||
yesterday.setDate(today.getDate() - 1);
|
||||
|
||||
if (date.toDateString() === today.toDateString()) {
|
||||
return _t('Today');
|
||||
} else if (date.toDateString() === yesterday.toDateString()) {
|
||||
return _t('Yesterday');
|
||||
} else if (today.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) {
|
||||
return days[date.getDay()];
|
||||
} else {
|
||||
return formatFullDateNoTime(date);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
render() {
|
||||
return <h2 className="mx_DateSeparator">{ this.getLabel() }</h2>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2018 Michael Telatynski <7t3chguy@gmail.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -14,24 +15,22 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import DateUtils from 'matrix-react-sdk/lib/DateUtils';
|
||||
import PropTypes from 'prop-types';
|
||||
import {formatFullDate, formatTime} from 'matrix-react-sdk/lib/DateUtils';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'MessageTimestamp',
|
||||
export default class MessageTimestamp extends React.Component {
|
||||
static propTypes = {
|
||||
ts: PropTypes.number.isRequired,
|
||||
showTwelveHour: PropTypes.bool,
|
||||
};
|
||||
|
||||
propTypes: {
|
||||
showTwelveHour: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
render() {
|
||||
const date = new Date(this.props.ts);
|
||||
return (
|
||||
<span className="mx_MessageTimestamp" title={ DateUtils.formatFullDate(date, this.props.showTwelveHour) }>
|
||||
{ DateUtils.formatTime(date, this.props.showTwelveHour) }
|
||||
<span className="mx_MessageTimestamp" title={formatFullDate(date, this.props.showTwelveHour)}>
|
||||
{ formatTime(date, this.props.showTwelveHour) }
|
||||
</span>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,227 +14,51 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import {DragSource} from 'react-dnd';
|
||||
import {DropTarget} from 'react-dnd';
|
||||
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import { Draggable } from 'react-beautiful-dnd';
|
||||
import RoomTile from 'matrix-react-sdk/lib/components/views/rooms/RoomTile';
|
||||
import * as Rooms from 'matrix-react-sdk/lib/Rooms';
|
||||
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||
|
||||
/**
|
||||
* Defines a new Component, DNDRoomTile that wraps RoomTile, making it draggable.
|
||||
* Requires extra props:
|
||||
* roomSubList: React.PropTypes.object.isRequired,
|
||||
* refreshSubList: React.PropTypes.func.isRequired,
|
||||
*/
|
||||
import classNames from 'classnames';
|
||||
|
||||
/**
|
||||
* Specifies the drag source contract.
|
||||
* Only `beginDrag` function is required.
|
||||
*/
|
||||
var roomTileSource = {
|
||||
canDrag: function(props, monitor) {
|
||||
return props.roomSubList.props.editable;
|
||||
},
|
||||
|
||||
beginDrag: function (props) {
|
||||
// Return the data describing the dragged item
|
||||
var item = {
|
||||
room: props.room,
|
||||
originalList: props.roomSubList,
|
||||
originalIndex: props.roomSubList.findRoomTile(props.room).index,
|
||||
targetList: props.roomSubList, // at first target is same as original
|
||||
// lastTargetRoom: null,
|
||||
// lastYOffset: null,
|
||||
// lastYDelta: null,
|
||||
};
|
||||
|
||||
if (props.roomSubList.debug) console.log("roomTile beginDrag for " + item.room.roomId);
|
||||
|
||||
// doing this 'correctly' with state causes react-dnd to break seemingly due to the state transitions
|
||||
props.room._dragging = true;
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
endDrag: function (props, monitor, component) {
|
||||
var item = monitor.getItem();
|
||||
|
||||
if (props.roomSubList.debug) console.log("roomTile endDrag for " + item.room.roomId + " with didDrop=" + monitor.didDrop());
|
||||
|
||||
props.room._dragging = false;
|
||||
if (monitor.didDrop()) {
|
||||
if (props.roomSubList.debug) console.log("force updating component " + item.targetList.props.label);
|
||||
item.targetList.forceUpdate(); // as we're not using state
|
||||
}
|
||||
|
||||
const prevTag = item.originalList.props.tagName;
|
||||
const newTag = item.targetList.props.tagName;
|
||||
|
||||
if (monitor.didDrop() && item.targetList.props.editable) {
|
||||
// Evil hack to get DMs behaving
|
||||
if ((prevTag === undefined && newTag === 'im.vector.fake.direct') ||
|
||||
(prevTag === 'im.vector.fake.direct' && newTag === undefined)
|
||||
) {
|
||||
Rooms.guessAndSetDMRoom(
|
||||
item.room, newTag === 'im.vector.fake.direct',
|
||||
).done(() => {
|
||||
item.originalList.removeRoomTile(item.room);
|
||||
}, (err) => {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to set direct chat tag " + err);
|
||||
Modal.createTrackedDialog('Failed to set direct chat tag', '', ErrorDialog, {
|
||||
title: _t('Failed to set direct chat tag'),
|
||||
description: ((err && err.message) ? err.message : _t('Operation failed')),
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// More evilness: We will still be dealing with moving to favourites/low prio,
|
||||
// but we avoid ever doing a request with 'im.vector.fake.direct`.
|
||||
|
||||
// if we moved lists, remove the old tag
|
||||
if (prevTag && prevTag !== 'im.vector.fake.direct' &&
|
||||
item.targetList !== item.originalList
|
||||
) {
|
||||
// commented out attempts to set a spinner on our target component as component is actually
|
||||
// the original source component being dragged, not our target. To fix we just need to
|
||||
// move all of this to endDrop in the target instead. FIXME later.
|
||||
|
||||
//component.state.set({ spinner: component.state.spinner ? component.state.spinner++ : 1 });
|
||||
MatrixClientPeg.get().deleteRoomTag(item.room.roomId, prevTag).finally(function() {
|
||||
//component.state.set({ spinner: component.state.spinner-- });
|
||||
}).catch(function(err) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to remove tag " + prevTag + " from room: " + err);
|
||||
Modal.createTrackedDialog('Failed to remove tag from room', '', ErrorDialog, {
|
||||
title: _t('Failed to remove tag %(tagName)s from room', {tagName: prevTag}),
|
||||
description: ((err && err.message) ? err.message : _t('Operation failed')),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var newOrder= {};
|
||||
if (item.targetList.props.order === 'manual') {
|
||||
newOrder['order'] = item.targetList.calcManualOrderTagData(item.room);
|
||||
}
|
||||
|
||||
// if we moved lists or the ordering changed, add the new tag
|
||||
if (newTag && newTag !== 'im.vector.fake.direct' &&
|
||||
(item.targetList !== item.originalList || newOrder)
|
||||
) {
|
||||
MatrixClientPeg.get().setRoomTag(item.room.roomId, newTag, newOrder).catch(function(err) {
|
||||
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
console.error("Failed to add tag " + newTag + " to room: " + err);
|
||||
Modal.createTrackedDialog('Failed to add tag to room', '', ErrorDialog, {
|
||||
title: _t('Failed to add tag %(tagName)s to room', {tagName: newTag}),
|
||||
description: ((err && err.message) ? err.message : _t('Operation failed')),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// cancel the drop and reset our original position
|
||||
if (props.roomSubList.debug) console.log("cancelling drop & drag");
|
||||
props.roomSubList.moveRoomTile(item.room, item.originalIndex);
|
||||
if (item.targetList && item.targetList !== item.originalList) {
|
||||
item.targetList.removeRoomTile(item.room);
|
||||
}
|
||||
}
|
||||
export default class DNDRoomTile extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.getClassName = this.getClassName.bind(this);
|
||||
}
|
||||
};
|
||||
|
||||
var roomTileTarget = {
|
||||
canDrop: function() {
|
||||
return false;
|
||||
},
|
||||
|
||||
hover: function(props, monitor) {
|
||||
var item = monitor.getItem();
|
||||
//var off = monitor.getClientOffset();
|
||||
// console.log("hovering on room " + props.room.roomId + ", isOver=" + monitor.isOver());
|
||||
|
||||
//console.log("item.targetList=" + item.targetList + ", roomSubList=" + props.roomSubList);
|
||||
|
||||
var switchedTarget = false;
|
||||
if (item.targetList !== props.roomSubList) {
|
||||
// we've switched target, so remove the tile from the previous target.
|
||||
// n.b. the previous target might actually be the source list.
|
||||
if (props.roomSubList.debug) console.log("switched target sublist");
|
||||
switchedTarget = true;
|
||||
item.targetList.removeRoomTile(item.room);
|
||||
item.targetList = props.roomSubList;
|
||||
}
|
||||
|
||||
if (!item.targetList.props.editable) return;
|
||||
|
||||
if (item.targetList.props.order === 'manual') {
|
||||
if (item.room.roomId !== props.room.roomId && props.room !== item.lastTargetRoom) {
|
||||
// find the offset of the target tile in the list.
|
||||
var roomTile = props.roomSubList.findRoomTile(props.room);
|
||||
// shuffle the list to add our tile to that position.
|
||||
props.roomSubList.moveRoomTile(item.room, roomTile.index);
|
||||
}
|
||||
|
||||
// stop us from flickering between our droptarget and the previous room.
|
||||
// whenever the cursor changes direction we have to reset the flicker-damping.
|
||||
/*
|
||||
var yDelta = off.y - item.lastYOffset;
|
||||
|
||||
if ((yDelta > 0 && item.lastYDelta < 0) ||
|
||||
(yDelta < 0 && item.lastYDelta > 0))
|
||||
{
|
||||
// the cursor changed direction - forget our previous room
|
||||
item.lastTargetRoom = null;
|
||||
}
|
||||
else {
|
||||
// track the last room we were hovering over so we can stop
|
||||
// bouncing back and forth if the droptarget is narrower than
|
||||
// the other list items. The other way to do this would be
|
||||
// to reduce the size of the hittarget on the list items, but
|
||||
// can't see an easy way to do that.
|
||||
item.lastTargetRoom = props.room;
|
||||
}
|
||||
|
||||
if (yDelta) item.lastYDelta = yDelta;
|
||||
item.lastYOffset = off.y;
|
||||
*/
|
||||
}
|
||||
else if (switchedTarget) {
|
||||
if (!props.roomSubList.findRoomTile(item.room).room) {
|
||||
// add to the list in the right place
|
||||
props.roomSubList.moveRoomTile(item.room, 0);
|
||||
}
|
||||
// we have to sort the list whatever to recalculate it
|
||||
props.roomSubList.sortList();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Export the wrapped version, inlining the 'collect' functions
|
||||
// to more closely resemble the ES7
|
||||
module.exports =
|
||||
DropTarget('RoomTile', roomTileTarget, function(connect, monitor) {
|
||||
return {
|
||||
// Call this function inside render()
|
||||
// to let React DnD handle the drag events:
|
||||
connectDropTarget: connect.dropTarget(),
|
||||
isOver: monitor.isOver(),
|
||||
getClassName(isDragging) {
|
||||
return classNames({
|
||||
"mx_DNDRoomTile": true,
|
||||
"mx_DNDRoomTile_dragging": isDragging,
|
||||
});
|
||||
}
|
||||
})(
|
||||
DragSource('RoomTile', roomTileSource, function(connect, monitor) {
|
||||
return {
|
||||
// Call this function inside render()
|
||||
// to let React DnD handle the drag events:
|
||||
connectDragSource: connect.dragSource(),
|
||||
// You can ask the monitor about the current drag state:
|
||||
isDragging: monitor.isDragging()
|
||||
};
|
||||
})(RoomTile));
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
|
||||
return <div>
|
||||
<Draggable
|
||||
key={props.room.roomId}
|
||||
draggableId={props.tagName + '_' + props.room.roomId}
|
||||
index={props.index}
|
||||
>
|
||||
{ (provided, snapshot) => {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
>
|
||||
<div className={this.getClassName(snapshot.isDragging)}>
|
||||
<RoomTile {...props} />
|
||||
</div>
|
||||
</div>
|
||||
{ provided.placeholder }
|
||||
</div>
|
||||
);
|
||||
} }
|
||||
</Draggable>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue