Migrate string refs over to createRef
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
4c55f3c5b5
commit
d22985f12e
39 changed files with 438 additions and 302 deletions
|
@ -174,12 +174,6 @@ React
|
||||||
<Foo onClick={this.onFooClick}> // Best, if onFooClick would do anything other than directly calling doStuff
|
<Foo onClick={this.onFooClick}> // Best, if onFooClick would do anything other than directly calling doStuff
|
||||||
```
|
```
|
||||||
|
|
||||||
Not doing so is acceptable in a single case: in function-refs:
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
<Foo ref={(self) => this.component = self}>
|
|
||||||
```
|
|
||||||
|
|
||||||
- Prefer classes that extend `React.Component` (or `React.PureComponent`) instead of `React.createClass`
|
- Prefer classes that extend `React.Component` (or `React.PureComponent`) instead of `React.createClass`
|
||||||
- You can avoid the need to bind handler functions by using [property initializers](https://reactjs.org/docs/react-component.html#constructor):
|
- You can avoid the need to bind handler functions by using [property initializers](https://reactjs.org/docs/react-component.html#constructor):
|
||||||
|
|
||||||
|
@ -208,3 +202,5 @@ React
|
||||||
```
|
```
|
||||||
- Think about whether your component really needs state: are you duplicating
|
- Think about whether your component really needs state: are you duplicating
|
||||||
information in component state that could be derived from the model?
|
information in component state that could be derived from the model?
|
||||||
|
|
||||||
|
- Avoid things marked as Legacy or Deprecated in React 16 (e.g string refs and legacy contexts)
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import FileSaver from 'file-saver';
|
import FileSaver from 'file-saver';
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
|
@ -44,6 +44,9 @@ export default createReactClass({
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
this._unmounted = false;
|
this._unmounted = false;
|
||||||
|
|
||||||
|
this._passphrase1 = createRef();
|
||||||
|
this._passphrase2 = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
@ -53,8 +56,8 @@ export default createReactClass({
|
||||||
_onPassphraseFormSubmit: function(ev) {
|
_onPassphraseFormSubmit: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
const passphrase = this.refs.passphrase1.value;
|
const passphrase = this._passphrase1.current.value;
|
||||||
if (passphrase !== this.refs.passphrase2.value) {
|
if (passphrase !== this._passphrase2.current.value) {
|
||||||
this.setState({errStr: _t('Passphrases must match')});
|
this.setState({errStr: _t('Passphrases must match')});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +151,7 @@ export default createReactClass({
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputCell'>
|
<div className='mx_E2eKeysDialog_inputCell'>
|
||||||
<input ref='passphrase1' id='passphrase1'
|
<input ref={this._passphrase1} id='passphrase1'
|
||||||
autoFocus={true} size='64' type='password'
|
autoFocus={true} size='64' type='password'
|
||||||
disabled={disableForm}
|
disabled={disableForm}
|
||||||
/>
|
/>
|
||||||
|
@ -161,7 +164,7 @@ export default createReactClass({
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputCell'>
|
<div className='mx_E2eKeysDialog_inputCell'>
|
||||||
<input ref='passphrase2' id='passphrase2'
|
<input ref={this._passphrase2} id='passphrase2'
|
||||||
size='64' type='password'
|
size='64' type='password'
|
||||||
disabled={disableForm}
|
disabled={disableForm}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
|
|
||||||
|
@ -56,6 +56,9 @@ export default createReactClass({
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
this._unmounted = false;
|
this._unmounted = false;
|
||||||
|
|
||||||
|
this._file = createRef();
|
||||||
|
this._passphrase = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
@ -63,15 +66,15 @@ export default createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_onFormChange: function(ev) {
|
_onFormChange: function(ev) {
|
||||||
const files = this.refs.file.files || [];
|
const files = this._file.current.files || [];
|
||||||
this.setState({
|
this.setState({
|
||||||
enableSubmit: (this.refs.passphrase.value !== "" && files.length > 0),
|
enableSubmit: (this._passphrase.current.value !== "" && files.length > 0),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_onFormSubmit: function(ev) {
|
_onFormSubmit: function(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this._startImport(this.refs.file.files[0], this.refs.passphrase.value);
|
this._startImport(this._file.current.files[0], this._passphrase.current.value);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -146,7 +149,10 @@ export default createReactClass({
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputCell'>
|
<div className='mx_E2eKeysDialog_inputCell'>
|
||||||
<input ref='file' id='importFile' type='file'
|
<input
|
||||||
|
ref={this._file}
|
||||||
|
id='importFile'
|
||||||
|
type='file'
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onChange={this._onFormChange}
|
onChange={this._onFormChange}
|
||||||
disabled={disableForm} />
|
disabled={disableForm} />
|
||||||
|
@ -159,8 +165,11 @@ export default createReactClass({
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className='mx_E2eKeysDialog_inputCell'>
|
<div className='mx_E2eKeysDialog_inputCell'>
|
||||||
<input ref='passphrase' id='passphrase'
|
<input
|
||||||
size='64' type='password'
|
ref={this._passphrase}
|
||||||
|
id='passphrase'
|
||||||
|
size='64'
|
||||||
|
type='password'
|
||||||
onChange={this._onFormChange}
|
onChange={this._onFormChange}
|
||||||
disabled={disableForm} />
|
disabled={disableForm} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,7 +18,7 @@ limitations under the License.
|
||||||
import Matrix from 'matrix-js-sdk';
|
import Matrix from 'matrix-js-sdk';
|
||||||
const InteractiveAuth = Matrix.InteractiveAuth;
|
const InteractiveAuth = Matrix.InteractiveAuth;
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
@ -129,6 +129,8 @@ export default createReactClass({
|
||||||
this._authLogic.poll();
|
this._authLogic.poll();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._stageComponent = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
@ -153,8 +155,8 @@ export default createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
tryContinue: function() {
|
tryContinue: function() {
|
||||||
if (this.refs.stageComponent && this.refs.stageComponent.tryContinue) {
|
if (this._stageComponent.current && this._stageComponent.current.tryContinue) {
|
||||||
this.refs.stageComponent.tryContinue();
|
this._stageComponent.current.tryContinue();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -192,8 +194,8 @@ export default createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_setFocus: function() {
|
_setFocus: function() {
|
||||||
if (this.refs.stageComponent && this.refs.stageComponent.focus) {
|
if (this._stageComponent.current && this._stageComponent.current.focus) {
|
||||||
this.refs.stageComponent.focus();
|
this._stageComponent.current.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -214,7 +216,8 @@ export default createReactClass({
|
||||||
|
|
||||||
const StageComponent = getEntryComponentForLoginType(stage);
|
const StageComponent = getEntryComponentForLoginType(stage);
|
||||||
return (
|
return (
|
||||||
<StageComponent ref="stageComponent"
|
<StageComponent
|
||||||
|
ref={this._stageComponent}
|
||||||
loginType={stage}
|
loginType={stage}
|
||||||
matrixClient={this.props.matrixClient}
|
matrixClient={this.props.matrixClient}
|
||||||
authSessionId={this._authLogic.getSessionId()}
|
authSessionId={this._authLogic.getSessionId()}
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { MatrixClient } from 'matrix-js-sdk';
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { DragDropContext } from 'react-beautiful-dnd';
|
import { DragDropContext } from 'react-beautiful-dnd';
|
||||||
|
@ -129,6 +129,8 @@ const LoggedInView = createReactClass({
|
||||||
this._matrixClient.on("RoomState.events", this.onRoomStateEvents);
|
this._matrixClient.on("RoomState.events", this.onRoomStateEvents);
|
||||||
|
|
||||||
fixupColorFonts();
|
fixupColorFonts();
|
||||||
|
|
||||||
|
this._roomView = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
@ -165,10 +167,10 @@ const LoggedInView = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
canResetTimelineInRoom: function(roomId) {
|
canResetTimelineInRoom: function(roomId) {
|
||||||
if (!this.refs.roomView) {
|
if (!this._roomView.current) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this.refs.roomView.canResetTimeline();
|
return this._roomView.current.canResetTimeline();
|
||||||
},
|
},
|
||||||
|
|
||||||
_setStateFromSessionStore() {
|
_setStateFromSessionStore() {
|
||||||
|
@ -428,8 +430,8 @@ const LoggedInView = createReactClass({
|
||||||
* @param {Object} ev The key event
|
* @param {Object} ev The key event
|
||||||
*/
|
*/
|
||||||
_onScrollKeyPressed: function(ev) {
|
_onScrollKeyPressed: function(ev) {
|
||||||
if (this.refs.roomView) {
|
if (this._roomView.current) {
|
||||||
this.refs.roomView.handleScrollKey(ev);
|
this._roomView.current.handleScrollKey(ev);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -543,7 +545,7 @@ const LoggedInView = createReactClass({
|
||||||
switch (this.props.page_type) {
|
switch (this.props.page_type) {
|
||||||
case PageTypes.RoomView:
|
case PageTypes.RoomView:
|
||||||
pageElement = <RoomView
|
pageElement = <RoomView
|
||||||
ref='roomView'
|
ref={this._roomView}
|
||||||
autoJoin={this.props.autoJoin}
|
autoJoin={this.props.autoJoin}
|
||||||
onRegistered={this.props.onRegistered}
|
onRegistered={this.props.onRegistered}
|
||||||
thirdPartyInvite={this.props.thirdPartyInvite}
|
thirdPartyInvite={this.props.thirdPartyInvite}
|
||||||
|
|
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
@ -159,6 +159,10 @@ export default class MessagePanel extends React.Component {
|
||||||
SettingsStore.getValue("showHiddenEventsInTimeline");
|
SettingsStore.getValue("showHiddenEventsInTimeline");
|
||||||
|
|
||||||
this._isMounted = false;
|
this._isMounted = false;
|
||||||
|
|
||||||
|
this._readMarkerNode = createRef();
|
||||||
|
this._whoIsTyping = createRef();
|
||||||
|
this._scrollPanel = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -191,8 +195,7 @@ export default class MessagePanel extends React.Component {
|
||||||
/* return true if the content is fully scrolled down right now; else false.
|
/* return true if the content is fully scrolled down right now; else false.
|
||||||
*/
|
*/
|
||||||
isAtBottom() {
|
isAtBottom() {
|
||||||
return this.refs.scrollPanel
|
return this._scrollPanel.current && this._scrollPanel.current.isAtBottom();
|
||||||
&& this.refs.scrollPanel.isAtBottom();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the current scroll state. See ScrollPanel.getScrollState for
|
/* get the current scroll state. See ScrollPanel.getScrollState for
|
||||||
|
@ -201,8 +204,7 @@ export default class MessagePanel extends React.Component {
|
||||||
* returns null if we are not mounted.
|
* returns null if we are not mounted.
|
||||||
*/
|
*/
|
||||||
getScrollState() {
|
getScrollState() {
|
||||||
if (!this.refs.scrollPanel) { return null; }
|
return this._scrollPanel.current ? this._scrollPanel.current.getScrollState() : null;
|
||||||
return this.refs.scrollPanel.getScrollState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns one of:
|
// returns one of:
|
||||||
|
@ -212,8 +214,8 @@ export default class MessagePanel extends React.Component {
|
||||||
// 0: read marker is within the window
|
// 0: read marker is within the window
|
||||||
// +1: read marker is below the window
|
// +1: read marker is below the window
|
||||||
getReadMarkerPosition() {
|
getReadMarkerPosition() {
|
||||||
const readMarker = this.refs.readMarkerNode;
|
const readMarker = this._readMarkerNode.current;
|
||||||
const messageWrapper = this.refs.scrollPanel;
|
const messageWrapper = this._scrollPanel.current;
|
||||||
|
|
||||||
if (!readMarker || !messageWrapper) {
|
if (!readMarker || !messageWrapper) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -236,16 +238,16 @@ export default class MessagePanel extends React.Component {
|
||||||
/* jump to the top of the content.
|
/* jump to the top of the content.
|
||||||
*/
|
*/
|
||||||
scrollToTop() {
|
scrollToTop() {
|
||||||
if (this.refs.scrollPanel) {
|
if (this._scrollPanel.current) {
|
||||||
this.refs.scrollPanel.scrollToTop();
|
this._scrollPanel.current.scrollToTop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* jump to the bottom of the content.
|
/* jump to the bottom of the content.
|
||||||
*/
|
*/
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
if (this.refs.scrollPanel) {
|
if (this._scrollPanel.current) {
|
||||||
this.refs.scrollPanel.scrollToBottom();
|
this._scrollPanel.current.scrollToBottom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,8 +257,8 @@ export default class MessagePanel extends React.Component {
|
||||||
* @param {number} mult: -1 to page up, +1 to page down
|
* @param {number} mult: -1 to page up, +1 to page down
|
||||||
*/
|
*/
|
||||||
scrollRelative(mult) {
|
scrollRelative(mult) {
|
||||||
if (this.refs.scrollPanel) {
|
if (this._scrollPanel.current) {
|
||||||
this.refs.scrollPanel.scrollRelative(mult);
|
this._scrollPanel.current.scrollRelative(mult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,8 +268,8 @@ export default class MessagePanel extends React.Component {
|
||||||
* @param {KeyboardEvent} ev: the keyboard event to handle
|
* @param {KeyboardEvent} ev: the keyboard event to handle
|
||||||
*/
|
*/
|
||||||
handleScrollKey(ev) {
|
handleScrollKey(ev) {
|
||||||
if (this.refs.scrollPanel) {
|
if (this._scrollPanel.current) {
|
||||||
this.refs.scrollPanel.handleScrollKey(ev);
|
this._scrollPanel.current.handleScrollKey(ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,8 +284,8 @@ export default class MessagePanel extends React.Component {
|
||||||
* defaults to 0.
|
* defaults to 0.
|
||||||
*/
|
*/
|
||||||
scrollToEvent(eventId, pixelOffset, offsetBase) {
|
scrollToEvent(eventId, pixelOffset, offsetBase) {
|
||||||
if (this.refs.scrollPanel) {
|
if (this._scrollPanel.current) {
|
||||||
this.refs.scrollPanel.scrollToToken(eventId, pixelOffset, offsetBase);
|
this._scrollPanel.current.scrollToToken(eventId, pixelOffset, offsetBase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,8 +299,8 @@ export default class MessagePanel extends React.Component {
|
||||||
/* check the scroll state and send out pagination requests if necessary.
|
/* check the scroll state and send out pagination requests if necessary.
|
||||||
*/
|
*/
|
||||||
checkFillState() {
|
checkFillState() {
|
||||||
if (this.refs.scrollPanel) {
|
if (this._scrollPanel.current) {
|
||||||
this.refs.scrollPanel.checkFillState();
|
this._scrollPanel.current.checkFillState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +347,7 @@ export default class MessagePanel extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={"readMarker_"+eventId} ref="readMarkerNode"
|
<li key={"readMarker_"+eventId} ref={this._readMarkerNode}
|
||||||
className="mx_RoomView_myReadMarker_container">
|
className="mx_RoomView_myReadMarker_container">
|
||||||
{ hr }
|
{ hr }
|
||||||
</li>
|
</li>
|
||||||
|
@ -829,14 +831,14 @@ export default class MessagePanel extends React.Component {
|
||||||
// once dynamic content in the events load, make the scrollPanel check the
|
// once dynamic content in the events load, make the scrollPanel check the
|
||||||
// scroll offsets.
|
// scroll offsets.
|
||||||
_onHeightChanged = () => {
|
_onHeightChanged = () => {
|
||||||
const scrollPanel = this.refs.scrollPanel;
|
const scrollPanel = this._scrollPanel.current;
|
||||||
if (scrollPanel) {
|
if (scrollPanel) {
|
||||||
scrollPanel.checkScroll();
|
scrollPanel.checkScroll();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_onTypingShown = () => {
|
_onTypingShown = () => {
|
||||||
const scrollPanel = this.refs.scrollPanel;
|
const scrollPanel = this._scrollPanel.current;
|
||||||
// this will make the timeline grow, so checkScroll
|
// this will make the timeline grow, so checkScroll
|
||||||
scrollPanel.checkScroll();
|
scrollPanel.checkScroll();
|
||||||
if (scrollPanel && scrollPanel.getScrollState().stuckAtBottom) {
|
if (scrollPanel && scrollPanel.getScrollState().stuckAtBottom) {
|
||||||
|
@ -845,7 +847,7 @@ export default class MessagePanel extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
_onTypingHidden = () => {
|
_onTypingHidden = () => {
|
||||||
const scrollPanel = this.refs.scrollPanel;
|
const scrollPanel = this._scrollPanel.current;
|
||||||
if (scrollPanel) {
|
if (scrollPanel) {
|
||||||
// as hiding the typing notifications doesn't
|
// as hiding the typing notifications doesn't
|
||||||
// update the scrollPanel, we tell it to apply
|
// update the scrollPanel, we tell it to apply
|
||||||
|
@ -858,11 +860,11 @@ export default class MessagePanel extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
updateTimelineMinHeight() {
|
updateTimelineMinHeight() {
|
||||||
const scrollPanel = this.refs.scrollPanel;
|
const scrollPanel = this._scrollPanel.current;
|
||||||
|
|
||||||
if (scrollPanel) {
|
if (scrollPanel) {
|
||||||
const isAtBottom = scrollPanel.isAtBottom();
|
const isAtBottom = scrollPanel.isAtBottom();
|
||||||
const whoIsTyping = this.refs.whoIsTyping;
|
const whoIsTyping = this._whoIsTyping.current;
|
||||||
const isTypingVisible = whoIsTyping && whoIsTyping.isVisible();
|
const isTypingVisible = whoIsTyping && whoIsTyping.isVisible();
|
||||||
// when messages get added to the timeline,
|
// when messages get added to the timeline,
|
||||||
// but somebody else is still typing,
|
// but somebody else is still typing,
|
||||||
|
@ -875,7 +877,7 @@ export default class MessagePanel extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onTimelineReset() {
|
onTimelineReset() {
|
||||||
const scrollPanel = this.refs.scrollPanel;
|
const scrollPanel = this._scrollPanel.current;
|
||||||
if (scrollPanel) {
|
if (scrollPanel) {
|
||||||
scrollPanel.clearPreventShrinking();
|
scrollPanel.clearPreventShrinking();
|
||||||
}
|
}
|
||||||
|
@ -909,19 +911,22 @@ export default class MessagePanel extends React.Component {
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
onShown={this._onTypingShown}
|
onShown={this._onTypingShown}
|
||||||
onHidden={this._onTypingHidden}
|
onHidden={this._onTypingHidden}
|
||||||
ref="whoIsTyping" />
|
ref={this._whoIsTyping} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollPanel ref="scrollPanel" className={className}
|
<ScrollPanel
|
||||||
|
ref={this._scrollPanel}
|
||||||
|
className={className}
|
||||||
onScroll={this.props.onScroll}
|
onScroll={this.props.onScroll}
|
||||||
onResize={this.onResize}
|
onResize={this.onResize}
|
||||||
onFillRequest={this.props.onFillRequest}
|
onFillRequest={this.props.onFillRequest}
|
||||||
onUnfillRequest={this.props.onUnfillRequest}
|
onUnfillRequest={this.props.onUnfillRequest}
|
||||||
style={style}
|
style={style}
|
||||||
stickyBottom={this.props.stickyBottom}
|
stickyBottom={this.props.stickyBottom}
|
||||||
resizeNotifier={this.props.resizeNotifier}>
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
|
>
|
||||||
{ topSpinner }
|
{ topSpinner }
|
||||||
{ this._getEventTiles() }
|
{ this._getEventTiles() }
|
||||||
{ whoIsTyping }
|
{ whoIsTyping }
|
||||||
|
|
|
@ -82,8 +82,14 @@ const RoomSubList = createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._header = createRef();
|
||||||
|
this._subList = createRef();
|
||||||
|
this._scroller = createRef();
|
||||||
this._headerButton = createRef();
|
this._headerButton = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
|
componentDidMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -103,7 +109,7 @@ const RoomSubList = createReactClass({
|
||||||
// The header is collapsible if it is hidden or not stuck
|
// The header is collapsible if it is hidden or not stuck
|
||||||
// The dataset elements are added in the RoomList _initAndPositionStickyHeaders method
|
// The dataset elements are added in the RoomList _initAndPositionStickyHeaders method
|
||||||
isCollapsibleOnClick: function() {
|
isCollapsibleOnClick: function() {
|
||||||
const stuck = this.refs.header.dataset.stuck;
|
const stuck = this._header.current.dataset.stuck;
|
||||||
if (!this.props.forceExpand && (this.state.hidden || stuck === undefined || stuck === "none")) {
|
if (!this.props.forceExpand && (this.state.hidden || stuck === undefined || stuck === "none")) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,7 +141,7 @@ const RoomSubList = createReactClass({
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// The header is stuck, so the click is to be interpreted as a scroll to the header
|
// The header is stuck, so the click is to be interpreted as a scroll to the header
|
||||||
this.props.onHeaderClick(this.state.hidden, this.refs.header.dataset.originalPosition);
|
this.props.onHeaderClick(this.state.hidden, this._header.current.dataset.originalPosition);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -159,7 +165,7 @@ const RoomSubList = createReactClass({
|
||||||
this.onClick();
|
this.onClick();
|
||||||
} else if (!this.props.forceExpand) {
|
} else if (!this.props.forceExpand) {
|
||||||
// sublist is expanded, go to first room
|
// sublist is expanded, go to first room
|
||||||
const element = this.refs.subList && this.refs.subList.querySelector(".mx_RoomTile");
|
const element = this._subList.current && this._subList.current.querySelector(".mx_RoomTile");
|
||||||
if (element) {
|
if (element) {
|
||||||
element.focus();
|
element.focus();
|
||||||
}
|
}
|
||||||
|
@ -328,7 +334,7 @@ const RoomSubList = createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_RoomSubList_labelContainer" title={title} ref="header" onKeyDown={this.onHeaderKeyDown}>
|
<div className="mx_RoomSubList_labelContainer" title={title} ref={this._header} onKeyDown={this.onHeaderKeyDown}>
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
onClick={this.onClick}
|
onClick={this.onClick}
|
||||||
className="mx_RoomSubList_label"
|
className="mx_RoomSubList_label"
|
||||||
|
@ -349,14 +355,14 @@ const RoomSubList = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
checkOverflow: function() {
|
checkOverflow: function() {
|
||||||
if (this.refs.scroller) {
|
if (this._scroller.current) {
|
||||||
this.refs.scroller.checkOverflow();
|
this._scroller.current.checkOverflow();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setHeight: function(height) {
|
setHeight: function(height) {
|
||||||
if (this.refs.subList) {
|
if (this._subList.current) {
|
||||||
this.refs.subList.style.height = `${height}px`;
|
this._subList.current.style.height = `${height}px`;
|
||||||
}
|
}
|
||||||
this._updateLazyRenderHeight(height);
|
this._updateLazyRenderHeight(height);
|
||||||
},
|
},
|
||||||
|
@ -366,7 +372,7 @@ const RoomSubList = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_onScroll: function() {
|
_onScroll: function() {
|
||||||
this.setState({scrollTop: this.refs.scroller.getScrollTop()});
|
this.setState({scrollTop: this._scroller.current.getScrollTop()});
|
||||||
},
|
},
|
||||||
|
|
||||||
_canUseLazyListRendering() {
|
_canUseLazyListRendering() {
|
||||||
|
@ -391,7 +397,7 @@ const RoomSubList = createReactClass({
|
||||||
// no body
|
// no body
|
||||||
} else if (this._canUseLazyListRendering()) {
|
} else if (this._canUseLazyListRendering()) {
|
||||||
content = (
|
content = (
|
||||||
<IndicatorScrollbar ref="scroller" className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
|
<IndicatorScrollbar ref={this._scroller} className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
|
||||||
<LazyRenderList
|
<LazyRenderList
|
||||||
scrollTop={this.state.scrollTop }
|
scrollTop={this.state.scrollTop }
|
||||||
height={ this.state.scrollerHeight }
|
height={ this.state.scrollerHeight }
|
||||||
|
@ -404,7 +410,7 @@ const RoomSubList = createReactClass({
|
||||||
const roomTiles = this.props.list.map(r => this.makeRoomTile(r));
|
const roomTiles = this.props.list.map(r => this.makeRoomTile(r));
|
||||||
const tiles = roomTiles.concat(this.props.extraTiles);
|
const tiles = roomTiles.concat(this.props.extraTiles);
|
||||||
content = (
|
content = (
|
||||||
<IndicatorScrollbar ref="scroller" className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
|
<IndicatorScrollbar ref={this._scroller} className="mx_RoomSubList_scroll" onScroll={this._onScroll}>
|
||||||
{ tiles }
|
{ tiles }
|
||||||
</IndicatorScrollbar>
|
</IndicatorScrollbar>
|
||||||
);
|
);
|
||||||
|
@ -418,7 +424,7 @@ const RoomSubList = createReactClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref="subList"
|
ref={this._subList}
|
||||||
className={subListClasses}
|
className={subListClasses}
|
||||||
role="group"
|
role="group"
|
||||||
aria-label={this.props.label}
|
aria-label={this.props.label}
|
||||||
|
|
|
@ -23,7 +23,7 @@ limitations under the License.
|
||||||
|
|
||||||
import shouldHideEvent from '../../shouldHideEvent';
|
import shouldHideEvent from '../../shouldHideEvent';
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
@ -207,6 +207,9 @@ module.exports = createReactClass({
|
||||||
this._onCiderUpdated();
|
this._onCiderUpdated();
|
||||||
this._ciderWatcherRef = SettingsStore.watchSetting(
|
this._ciderWatcherRef = SettingsStore.watchSetting(
|
||||||
"useCiderComposer", null, this._onCiderUpdated);
|
"useCiderComposer", null, this._onCiderUpdated);
|
||||||
|
|
||||||
|
this._roomView = createRef();
|
||||||
|
this._searchResultsPanel = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onCiderUpdated: function() {
|
_onCiderUpdated: function() {
|
||||||
|
@ -459,8 +462,8 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate: function() {
|
componentDidUpdate: function() {
|
||||||
if (this.refs.roomView) {
|
if (this._roomView.current) {
|
||||||
const roomView = ReactDOM.findDOMNode(this.refs.roomView);
|
const roomView = ReactDOM.findDOMNode(this._roomView.current);
|
||||||
if (!roomView.ondrop) {
|
if (!roomView.ondrop) {
|
||||||
roomView.addEventListener('drop', this.onDrop);
|
roomView.addEventListener('drop', this.onDrop);
|
||||||
roomView.addEventListener('dragover', this.onDragOver);
|
roomView.addEventListener('dragover', this.onDragOver);
|
||||||
|
@ -474,10 +477,10 @@ module.exports = createReactClass({
|
||||||
// in render() prevents the ref from being set on first mount, so we try and
|
// in render() prevents the ref from being set on first mount, so we try and
|
||||||
// catch the messagePanel when it does mount. Because we only want the ref once,
|
// catch the messagePanel when it does mount. Because we only want the ref once,
|
||||||
// we use a boolean flag to avoid duplicate work.
|
// we use a boolean flag to avoid duplicate work.
|
||||||
if (this.refs.messagePanel && !this.state.atEndOfLiveTimelineInit) {
|
if (this._messagePanel && !this.state.atEndOfLiveTimelineInit) {
|
||||||
this.setState({
|
this.setState({
|
||||||
atEndOfLiveTimelineInit: true,
|
atEndOfLiveTimelineInit: true,
|
||||||
atEndOfLiveTimeline: this.refs.messagePanel.isAtEndOfLiveTimeline(),
|
atEndOfLiveTimeline: this._messagePanel.isAtEndOfLiveTimeline(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -499,12 +502,12 @@ module.exports = createReactClass({
|
||||||
// stop tracking room changes to format permalinks
|
// stop tracking room changes to format permalinks
|
||||||
this._stopAllPermalinkCreators();
|
this._stopAllPermalinkCreators();
|
||||||
|
|
||||||
if (this.refs.roomView) {
|
if (this._roomView.current) {
|
||||||
// disconnect the D&D event listeners from the room view. This
|
// disconnect the D&D event listeners from the room view. This
|
||||||
// is really just for hygiene - we're going to be
|
// is really just for hygiene - we're going to be
|
||||||
// deleted anyway, so it doesn't matter if the event listeners
|
// deleted anyway, so it doesn't matter if the event listeners
|
||||||
// don't get cleaned up.
|
// don't get cleaned up.
|
||||||
const roomView = ReactDOM.findDOMNode(this.refs.roomView);
|
const roomView = ReactDOM.findDOMNode(this._roomView.current);
|
||||||
roomView.removeEventListener('drop', this.onDrop);
|
roomView.removeEventListener('drop', this.onDrop);
|
||||||
roomView.removeEventListener('dragover', this.onDragOver);
|
roomView.removeEventListener('dragover', this.onDragOver);
|
||||||
roomView.removeEventListener('dragleave', this.onDragLeaveOrEnd);
|
roomView.removeEventListener('dragleave', this.onDragLeaveOrEnd);
|
||||||
|
@ -701,10 +704,10 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
canResetTimeline: function() {
|
canResetTimeline: function() {
|
||||||
if (!this.refs.messagePanel) {
|
if (!this._messagePanel) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this.refs.messagePanel.canResetTimeline();
|
return this._messagePanel.canResetTimeline();
|
||||||
},
|
},
|
||||||
|
|
||||||
// called when state.room is first initialised (either at initial load,
|
// called when state.room is first initialised (either at initial load,
|
||||||
|
@ -1046,7 +1049,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onMessageListScroll: function(ev) {
|
onMessageListScroll: function(ev) {
|
||||||
if (this.refs.messagePanel.isAtEndOfLiveTimeline()) {
|
if (this._messagePanel.isAtEndOfLiveTimeline()) {
|
||||||
this.setState({
|
this.setState({
|
||||||
numUnreadMessages: 0,
|
numUnreadMessages: 0,
|
||||||
atEndOfLiveTimeline: true,
|
atEndOfLiveTimeline: true,
|
||||||
|
@ -1119,8 +1122,8 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
// if we already have a search panel, we need to tell it to forget
|
// if we already have a search panel, we need to tell it to forget
|
||||||
// about its scroll state.
|
// about its scroll state.
|
||||||
if (this.refs.searchResultsPanel) {
|
if (this._searchResultsPanel.current) {
|
||||||
this.refs.searchResultsPanel.resetScrollState();
|
this._searchResultsPanel.current.resetScrollState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure that we don't end up showing results from
|
// make sure that we don't end up showing results from
|
||||||
|
@ -1225,7 +1228,7 @@ module.exports = createReactClass({
|
||||||
// once dynamic content in the search results load, make the scrollPanel check
|
// once dynamic content in the search results load, make the scrollPanel check
|
||||||
// the scroll offsets.
|
// the scroll offsets.
|
||||||
const onHeightChanged = () => {
|
const onHeightChanged = () => {
|
||||||
const scrollPanel = this.refs.searchResultsPanel;
|
const scrollPanel = this._searchResultsPanel.current;
|
||||||
if (scrollPanel) {
|
if (scrollPanel) {
|
||||||
scrollPanel.checkScroll();
|
scrollPanel.checkScroll();
|
||||||
}
|
}
|
||||||
|
@ -1370,28 +1373,28 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
// jump down to the bottom of this room, where new events are arriving
|
// jump down to the bottom of this room, where new events are arriving
|
||||||
jumpToLiveTimeline: function() {
|
jumpToLiveTimeline: function() {
|
||||||
this.refs.messagePanel.jumpToLiveTimeline();
|
this._messagePanel.jumpToLiveTimeline();
|
||||||
dis.dispatch({action: 'focus_composer'});
|
dis.dispatch({action: 'focus_composer'});
|
||||||
},
|
},
|
||||||
|
|
||||||
// jump up to wherever our read marker is
|
// jump up to wherever our read marker is
|
||||||
jumpToReadMarker: function() {
|
jumpToReadMarker: function() {
|
||||||
this.refs.messagePanel.jumpToReadMarker();
|
this._messagePanel.jumpToReadMarker();
|
||||||
},
|
},
|
||||||
|
|
||||||
// update the read marker to match the read-receipt
|
// update the read marker to match the read-receipt
|
||||||
forgetReadMarker: function(ev) {
|
forgetReadMarker: function(ev) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.refs.messagePanel.forgetReadMarker();
|
this._messagePanel.forgetReadMarker();
|
||||||
},
|
},
|
||||||
|
|
||||||
// decide whether or not the top 'unread messages' bar should be shown
|
// decide whether or not the top 'unread messages' bar should be shown
|
||||||
_updateTopUnreadMessagesBar: function() {
|
_updateTopUnreadMessagesBar: function() {
|
||||||
if (!this.refs.messagePanel) {
|
if (!this._messagePanel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const showBar = this.refs.messagePanel.canJumpToReadMarker();
|
const showBar = this._messagePanel.canJumpToReadMarker();
|
||||||
if (this.state.showTopUnreadMessagesBar != showBar) {
|
if (this.state.showTopUnreadMessagesBar != showBar) {
|
||||||
this.setState({showTopUnreadMessagesBar: showBar});
|
this.setState({showTopUnreadMessagesBar: showBar});
|
||||||
}
|
}
|
||||||
|
@ -1401,7 +1404,7 @@ module.exports = createReactClass({
|
||||||
// restored when we switch back to it.
|
// restored when we switch back to it.
|
||||||
//
|
//
|
||||||
_getScrollState: function() {
|
_getScrollState: function() {
|
||||||
const messagePanel = this.refs.messagePanel;
|
const messagePanel = this._messagePanel;
|
||||||
if (!messagePanel) return null;
|
if (!messagePanel) return null;
|
||||||
|
|
||||||
// if we're following the live timeline, we want to return null; that
|
// if we're following the live timeline, we want to return null; that
|
||||||
|
@ -1506,10 +1509,10 @@ module.exports = createReactClass({
|
||||||
*/
|
*/
|
||||||
handleScrollKey: function(ev) {
|
handleScrollKey: function(ev) {
|
||||||
let panel;
|
let panel;
|
||||||
if (this.refs.searchResultsPanel) {
|
if (this._searchResultsPanel.current) {
|
||||||
panel = this.refs.searchResultsPanel;
|
panel = this._searchResultsPanel.current;
|
||||||
} else if (this.refs.messagePanel) {
|
} else if (this._messagePanel) {
|
||||||
panel = this.refs.messagePanel;
|
panel = this._messagePanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel) {
|
if (panel) {
|
||||||
|
@ -1530,7 +1533,7 @@ module.exports = createReactClass({
|
||||||
// this has to be a proper method rather than an unnamed function,
|
// this has to be a proper method rather than an unnamed function,
|
||||||
// otherwise react calls it with null on each update.
|
// otherwise react calls it with null on each update.
|
||||||
_gatherTimelinePanelRef: function(r) {
|
_gatherTimelinePanelRef: function(r) {
|
||||||
this.refs.messagePanel = r;
|
this._messagePanel = r;
|
||||||
if (r) {
|
if (r) {
|
||||||
console.log("updateTint from RoomView._gatherTimelinePanelRef");
|
console.log("updateTint from RoomView._gatherTimelinePanelRef");
|
||||||
this.updateTint();
|
this.updateTint();
|
||||||
|
@ -1875,7 +1878,7 @@ module.exports = createReactClass({
|
||||||
searchResultsPanel = (<div className="mx_RoomView_messagePanel mx_RoomView_messagePanelSearchSpinner" />);
|
searchResultsPanel = (<div className="mx_RoomView_messagePanel mx_RoomView_messagePanelSearchSpinner" />);
|
||||||
} else {
|
} else {
|
||||||
searchResultsPanel = (
|
searchResultsPanel = (
|
||||||
<ScrollPanel ref="searchResultsPanel"
|
<ScrollPanel ref={this._searchResultsPanel}
|
||||||
className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel"
|
className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel"
|
||||||
onFillRequest={this.onSearchResultsFillRequest}
|
onFillRequest={this.onSearchResultsFillRequest}
|
||||||
resizeNotifier={this.props.resizeNotifier}
|
resizeNotifier={this.props.resizeNotifier}
|
||||||
|
@ -1898,7 +1901,8 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
// console.info("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
|
// console.info("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
|
||||||
const messagePanel = (
|
const messagePanel = (
|
||||||
<TimelinePanel ref={this._gatherTimelinePanelRef}
|
<TimelinePanel
|
||||||
|
ref={this._gatherTimelinePanelRef}
|
||||||
timelineSet={this.state.room.getUnfilteredTimelineSet()}
|
timelineSet={this.state.room.getUnfilteredTimelineSet()}
|
||||||
showReadReceipts={SettingsStore.getValue('showReadReceipts')}
|
showReadReceipts={SettingsStore.getValue('showReadReceipts')}
|
||||||
manageReadReceipts={!this.state.isPeeking}
|
manageReadReceipts={!this.state.isPeeking}
|
||||||
|
@ -1952,9 +1956,11 @@ module.exports = createReactClass({
|
||||||
const collapsedRhs = hideRightPanel || this.props.collapsedRhs;
|
const collapsedRhs = hideRightPanel || this.props.collapsedRhs;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref="roomView">
|
<main className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref={this._roomView}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo}
|
<RoomHeader
|
||||||
|
room={this.state.room}
|
||||||
|
searchInfo={searchInfo}
|
||||||
oobData={this.props.oobData}
|
oobData={this.props.oobData}
|
||||||
inRoom={myMembership === 'join'}
|
inRoom={myMembership === 'join'}
|
||||||
collapsedRhs={collapsedRhs}
|
collapsedRhs={collapsedRhs}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React, {createRef} from "react";
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { KeyCode } from '../../Keyboard';
|
import { KeyCode } from '../../Keyboard';
|
||||||
|
@ -166,6 +166,8 @@ module.exports = createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resetScrollState();
|
this.resetScrollState();
|
||||||
|
|
||||||
|
this._itemlist = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
|
@ -328,7 +330,7 @@ module.exports = createReactClass({
|
||||||
this._isFilling = true;
|
this._isFilling = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const itemlist = this.refs.itemlist;
|
const itemlist = this._itemlist.current;
|
||||||
const firstTile = itemlist && itemlist.firstElementChild;
|
const firstTile = itemlist && itemlist.firstElementChild;
|
||||||
const contentTop = firstTile && firstTile.offsetTop;
|
const contentTop = firstTile && firstTile.offsetTop;
|
||||||
const fillPromises = [];
|
const fillPromises = [];
|
||||||
|
@ -373,7 +375,7 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
const origExcessHeight = excessHeight;
|
const origExcessHeight = excessHeight;
|
||||||
|
|
||||||
const tiles = this.refs.itemlist.children;
|
const tiles = this._itemlist.current.children;
|
||||||
|
|
||||||
// The scroll token of the first/last tile to be unpaginated
|
// The scroll token of the first/last tile to be unpaginated
|
||||||
let markerScrollToken = null;
|
let markerScrollToken = null;
|
||||||
|
@ -602,7 +604,7 @@ module.exports = createReactClass({
|
||||||
const scrollNode = this._getScrollNode();
|
const scrollNode = this._getScrollNode();
|
||||||
const viewportBottom = scrollNode.scrollHeight - (scrollNode.scrollTop + scrollNode.clientHeight);
|
const viewportBottom = scrollNode.scrollHeight - (scrollNode.scrollTop + scrollNode.clientHeight);
|
||||||
|
|
||||||
const itemlist = this.refs.itemlist;
|
const itemlist = this._itemlist.current;
|
||||||
const messages = itemlist.children;
|
const messages = itemlist.children;
|
||||||
let node = null;
|
let node = null;
|
||||||
|
|
||||||
|
@ -644,7 +646,7 @@ module.exports = createReactClass({
|
||||||
const sn = this._getScrollNode();
|
const sn = this._getScrollNode();
|
||||||
sn.scrollTop = sn.scrollHeight;
|
sn.scrollTop = sn.scrollHeight;
|
||||||
} else if (scrollState.trackedScrollToken) {
|
} else if (scrollState.trackedScrollToken) {
|
||||||
const itemlist = this.refs.itemlist;
|
const itemlist = this._itemlist.current;
|
||||||
const trackedNode = this._getTrackedNode();
|
const trackedNode = this._getTrackedNode();
|
||||||
if (trackedNode) {
|
if (trackedNode) {
|
||||||
const newBottomOffset = this._topFromBottom(trackedNode);
|
const newBottomOffset = this._topFromBottom(trackedNode);
|
||||||
|
@ -682,7 +684,7 @@ module.exports = createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
const sn = this._getScrollNode();
|
const sn = this._getScrollNode();
|
||||||
const itemlist = this.refs.itemlist;
|
const itemlist = this._itemlist.current;
|
||||||
const contentHeight = this._getMessagesHeight();
|
const contentHeight = this._getMessagesHeight();
|
||||||
const minHeight = sn.clientHeight;
|
const minHeight = sn.clientHeight;
|
||||||
const height = Math.max(minHeight, contentHeight);
|
const height = Math.max(minHeight, contentHeight);
|
||||||
|
@ -724,7 +726,7 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
if (!trackedNode || !trackedNode.parentElement) {
|
if (!trackedNode || !trackedNode.parentElement) {
|
||||||
let node;
|
let node;
|
||||||
const messages = this.refs.itemlist.children;
|
const messages = this._itemlist.current.children;
|
||||||
const scrollToken = scrollState.trackedScrollToken;
|
const scrollToken = scrollState.trackedScrollToken;
|
||||||
|
|
||||||
for (let i = messages.length-1; i >= 0; --i) {
|
for (let i = messages.length-1; i >= 0; --i) {
|
||||||
|
@ -756,7 +758,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_getMessagesHeight() {
|
_getMessagesHeight() {
|
||||||
const itemlist = this.refs.itemlist;
|
const itemlist = this._itemlist.current;
|
||||||
const lastNode = itemlist.lastElementChild;
|
const lastNode = itemlist.lastElementChild;
|
||||||
const lastNodeBottom = lastNode ? lastNode.offsetTop + lastNode.clientHeight : 0;
|
const lastNodeBottom = lastNode ? lastNode.offsetTop + lastNode.clientHeight : 0;
|
||||||
const firstNodeTop = itemlist.firstElementChild ? itemlist.firstElementChild.offsetTop : 0;
|
const firstNodeTop = itemlist.firstElementChild ? itemlist.firstElementChild.offsetTop : 0;
|
||||||
|
@ -765,7 +767,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_topFromBottom(node) {
|
_topFromBottom(node) {
|
||||||
return this.refs.itemlist.clientHeight - node.offsetTop;
|
return this._itemlist.current.clientHeight - node.offsetTop;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* get the DOM node which has the scrollTop property we care about for our
|
/* get the DOM node which has the scrollTop property we care about for our
|
||||||
|
@ -797,7 +799,7 @@ module.exports = createReactClass({
|
||||||
the same minimum bottom offset, effectively preventing the timeline to shrink.
|
the same minimum bottom offset, effectively preventing the timeline to shrink.
|
||||||
*/
|
*/
|
||||||
preventShrinking: function() {
|
preventShrinking: function() {
|
||||||
const messageList = this.refs.itemlist;
|
const messageList = this._itemlist.current;
|
||||||
const tiles = messageList && messageList.children;
|
const tiles = messageList && messageList.children;
|
||||||
if (!messageList) {
|
if (!messageList) {
|
||||||
return;
|
return;
|
||||||
|
@ -824,7 +826,7 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
/** Clear shrinking prevention. Used internally, and when the timeline is reloaded. */
|
/** Clear shrinking prevention. Used internally, and when the timeline is reloaded. */
|
||||||
clearPreventShrinking: function() {
|
clearPreventShrinking: function() {
|
||||||
const messageList = this.refs.itemlist;
|
const messageList = this._itemlist.current;
|
||||||
const balanceElement = messageList && messageList.parentElement;
|
const balanceElement = messageList && messageList.parentElement;
|
||||||
if (balanceElement) balanceElement.style.paddingBottom = null;
|
if (balanceElement) balanceElement.style.paddingBottom = null;
|
||||||
this.preventShrinkingState = null;
|
this.preventShrinkingState = null;
|
||||||
|
@ -843,7 +845,7 @@ module.exports = createReactClass({
|
||||||
if (this.preventShrinkingState) {
|
if (this.preventShrinkingState) {
|
||||||
const sn = this._getScrollNode();
|
const sn = this._getScrollNode();
|
||||||
const scrollState = this.scrollState;
|
const scrollState = this.scrollState;
|
||||||
const messageList = this.refs.itemlist;
|
const messageList = this._itemlist.current;
|
||||||
const {offsetNode, offsetFromBottom} = this.preventShrinkingState;
|
const {offsetNode, offsetFromBottom} = this.preventShrinkingState;
|
||||||
// element used to set paddingBottom to balance the typing notifs disappearing
|
// element used to set paddingBottom to balance the typing notifs disappearing
|
||||||
const balanceElement = messageList.parentElement;
|
const balanceElement = messageList.parentElement;
|
||||||
|
@ -879,7 +881,7 @@ module.exports = createReactClass({
|
||||||
onScroll={this.onScroll}
|
onScroll={this.onScroll}
|
||||||
className={`mx_ScrollPanel ${this.props.className}`} style={this.props.style}>
|
className={`mx_ScrollPanel ${this.props.className}`} style={this.props.style}>
|
||||||
<div className="mx_RoomView_messageListWrapper">
|
<div className="mx_RoomView_messageListWrapper">
|
||||||
<ol ref="itemlist" className="mx_RoomView_MessageList" aria-live="polite">
|
<ol ref={this._itemlist} className="mx_RoomView_MessageList" aria-live="polite">
|
||||||
{ this.props.children }
|
{ this.props.children }
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { KeyCode } from '../../Keyboard';
|
import { KeyCode } from '../../Keyboard';
|
||||||
|
@ -53,6 +53,10 @@ module.exports = createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._search = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
},
|
},
|
||||||
|
@ -66,26 +70,26 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
case 'view_room':
|
case 'view_room':
|
||||||
if (this.refs.search && payload.clear_search) {
|
if (this._search.current && payload.clear_search) {
|
||||||
this._clearSearch();
|
this._clearSearch();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'focus_room_filter':
|
case 'focus_room_filter':
|
||||||
if (this.refs.search) {
|
if (this._search.current) {
|
||||||
this.refs.search.focus();
|
this._search.current.focus();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onChange: function() {
|
onChange: function() {
|
||||||
if (!this.refs.search) return;
|
if (!this._search.current) return;
|
||||||
this.setState({ searchTerm: this.refs.search.value });
|
this.setState({ searchTerm: this._search.current.value });
|
||||||
this.onSearch();
|
this.onSearch();
|
||||||
},
|
},
|
||||||
|
|
||||||
onSearch: throttle(function() {
|
onSearch: throttle(function() {
|
||||||
this.props.onSearch(this.refs.search.value);
|
this.props.onSearch(this._search.current.value);
|
||||||
}, 200, {trailing: true, leading: true}),
|
}, 200, {trailing: true, leading: true}),
|
||||||
|
|
||||||
_onKeyDown: function(ev) {
|
_onKeyDown: function(ev) {
|
||||||
|
@ -113,7 +117,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_clearSearch: function(source) {
|
_clearSearch: function(source) {
|
||||||
this.refs.search.value = "";
|
this._search.current.value = "";
|
||||||
this.onChange();
|
this.onChange();
|
||||||
if (this.props.onCleared) {
|
if (this.props.onCleared) {
|
||||||
this.props.onCleared(source);
|
this.props.onCleared(source);
|
||||||
|
@ -146,7 +150,7 @@ module.exports = createReactClass({
|
||||||
<input
|
<input
|
||||||
key="searchfield"
|
key="searchfield"
|
||||||
type="text"
|
type="text"
|
||||||
ref="search"
|
ref={this._search}
|
||||||
className={"mx_textinput_icon mx_textinput_search " + className}
|
className={"mx_textinput_icon mx_textinput_search " + className}
|
||||||
value={ this.state.searchTerm }
|
value={ this.state.searchTerm }
|
||||||
onFocus={ this._onFocus }
|
onFocus={ this._onFocus }
|
||||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
|
|
||||||
import SettingsStore from "../../settings/SettingsStore";
|
import SettingsStore from "../../settings/SettingsStore";
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
@ -225,6 +225,8 @@ const TimelinePanel = createReactClass({
|
||||||
MatrixClientPeg.get().on("sync", this.onSync);
|
MatrixClientPeg.get().on("sync", this.onSync);
|
||||||
|
|
||||||
this._initTimeline(this.props);
|
this._initTimeline(this.props);
|
||||||
|
|
||||||
|
this._messagePanel = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillReceiveProps: function(newProps) {
|
componentWillReceiveProps: function(newProps) {
|
||||||
|
@ -425,8 +427,8 @@ const TimelinePanel = createReactClass({
|
||||||
if (payload.action === "edit_event") {
|
if (payload.action === "edit_event") {
|
||||||
const editState = payload.event ? new EditorStateTransfer(payload.event) : null;
|
const editState = payload.event ? new EditorStateTransfer(payload.event) : null;
|
||||||
this.setState({editState}, () => {
|
this.setState({editState}, () => {
|
||||||
if (payload.event && this.refs.messagePanel) {
|
if (payload.event && this._messagePanel.current) {
|
||||||
this.refs.messagePanel.scrollToEventIfNeeded(
|
this._messagePanel.current.scrollToEventIfNeeded(
|
||||||
payload.event.getId(),
|
payload.event.getId(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -442,9 +444,9 @@ const TimelinePanel = createReactClass({
|
||||||
// updates from pagination will happen when the paginate completes.
|
// updates from pagination will happen when the paginate completes.
|
||||||
if (toStartOfTimeline || !data || !data.liveEvent) return;
|
if (toStartOfTimeline || !data || !data.liveEvent) return;
|
||||||
|
|
||||||
if (!this.refs.messagePanel) return;
|
if (!this._messagePanel.current) return;
|
||||||
|
|
||||||
if (!this.refs.messagePanel.getScrollState().stuckAtBottom) {
|
if (!this._messagePanel.current.getScrollState().stuckAtBottom) {
|
||||||
// we won't load this event now, because we don't want to push any
|
// we won't load this event now, because we don't want to push any
|
||||||
// events off the other end of the timeline. But we need to note
|
// events off the other end of the timeline. But we need to note
|
||||||
// that we can now paginate.
|
// that we can now paginate.
|
||||||
|
@ -499,7 +501,7 @@ const TimelinePanel = createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(updatedState, () => {
|
this.setState(updatedState, () => {
|
||||||
this.refs.messagePanel.updateTimelineMinHeight();
|
this._messagePanel.current.updateTimelineMinHeight();
|
||||||
if (callRMUpdated) {
|
if (callRMUpdated) {
|
||||||
this.props.onReadMarkerUpdated();
|
this.props.onReadMarkerUpdated();
|
||||||
}
|
}
|
||||||
|
@ -510,13 +512,13 @@ const TimelinePanel = createReactClass({
|
||||||
onRoomTimelineReset: function(room, timelineSet) {
|
onRoomTimelineReset: function(room, timelineSet) {
|
||||||
if (timelineSet !== this.props.timelineSet) return;
|
if (timelineSet !== this.props.timelineSet) return;
|
||||||
|
|
||||||
if (this.refs.messagePanel && this.refs.messagePanel.isAtBottom()) {
|
if (this._messagePanel.current && this._messagePanel.current.isAtBottom()) {
|
||||||
this._loadTimeline();
|
this._loadTimeline();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
canResetTimeline: function() {
|
canResetTimeline: function() {
|
||||||
return this.refs.messagePanel && this.refs.messagePanel.isAtBottom();
|
return this._messagePanel.current && this._messagePanel.current.isAtBottom();
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoomRedaction: function(ev, room) {
|
onRoomRedaction: function(ev, room) {
|
||||||
|
@ -629,7 +631,7 @@ const TimelinePanel = createReactClass({
|
||||||
sendReadReceipt: function() {
|
sendReadReceipt: function() {
|
||||||
if (SettingsStore.getValue("lowBandwidth")) return;
|
if (SettingsStore.getValue("lowBandwidth")) return;
|
||||||
|
|
||||||
if (!this.refs.messagePanel) return;
|
if (!this._messagePanel.current) return;
|
||||||
if (!this.props.manageReadReceipts) return;
|
if (!this.props.manageReadReceipts) return;
|
||||||
// This happens on user_activity_end which is delayed, and it's
|
// This happens on user_activity_end which is delayed, and it's
|
||||||
// very possible have logged out within that timeframe, so check
|
// very possible have logged out within that timeframe, so check
|
||||||
|
@ -815,8 +817,8 @@ const TimelinePanel = createReactClass({
|
||||||
if (this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
|
if (this._timelineWindow.canPaginate(EventTimeline.FORWARDS)) {
|
||||||
this._loadTimeline();
|
this._loadTimeline();
|
||||||
} else {
|
} else {
|
||||||
if (this.refs.messagePanel) {
|
if (this._messagePanel.current) {
|
||||||
this.refs.messagePanel.scrollToBottom();
|
this._messagePanel.current.scrollToBottom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -826,7 +828,7 @@ const TimelinePanel = createReactClass({
|
||||||
*/
|
*/
|
||||||
jumpToReadMarker: function() {
|
jumpToReadMarker: function() {
|
||||||
if (!this.props.manageReadMarkers) return;
|
if (!this.props.manageReadMarkers) return;
|
||||||
if (!this.refs.messagePanel) return;
|
if (!this._messagePanel.current) return;
|
||||||
if (!this.state.readMarkerEventId) return;
|
if (!this.state.readMarkerEventId) return;
|
||||||
|
|
||||||
// we may not have loaded the event corresponding to the read-marker
|
// we may not have loaded the event corresponding to the read-marker
|
||||||
|
@ -835,11 +837,11 @@ const TimelinePanel = createReactClass({
|
||||||
//
|
//
|
||||||
// a quick way to figure out if we've loaded the relevant event is
|
// a quick way to figure out if we've loaded the relevant event is
|
||||||
// simply to check if the messagepanel knows where the read-marker is.
|
// simply to check if the messagepanel knows where the read-marker is.
|
||||||
const ret = this.refs.messagePanel.getReadMarkerPosition();
|
const ret = this._messagePanel.current.getReadMarkerPosition();
|
||||||
if (ret !== null) {
|
if (ret !== null) {
|
||||||
// The messagepanel knows where the RM is, so we must have loaded
|
// The messagepanel knows where the RM is, so we must have loaded
|
||||||
// the relevant event.
|
// the relevant event.
|
||||||
this.refs.messagePanel.scrollToEvent(this.state.readMarkerEventId,
|
this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId,
|
||||||
0, 1/3);
|
0, 1/3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -874,8 +876,8 @@ const TimelinePanel = createReactClass({
|
||||||
* at the end of the live timeline.
|
* at the end of the live timeline.
|
||||||
*/
|
*/
|
||||||
isAtEndOfLiveTimeline: function() {
|
isAtEndOfLiveTimeline: function() {
|
||||||
return this.refs.messagePanel
|
return this._messagePanel.current
|
||||||
&& this.refs.messagePanel.isAtBottom()
|
&& this._messagePanel.current.isAtBottom()
|
||||||
&& this._timelineWindow
|
&& this._timelineWindow
|
||||||
&& !this._timelineWindow.canPaginate(EventTimeline.FORWARDS);
|
&& !this._timelineWindow.canPaginate(EventTimeline.FORWARDS);
|
||||||
},
|
},
|
||||||
|
@ -887,8 +889,8 @@ const TimelinePanel = createReactClass({
|
||||||
* returns null if we are not mounted.
|
* returns null if we are not mounted.
|
||||||
*/
|
*/
|
||||||
getScrollState: function() {
|
getScrollState: function() {
|
||||||
if (!this.refs.messagePanel) { return null; }
|
if (!this._messagePanel.current) { return null; }
|
||||||
return this.refs.messagePanel.getScrollState();
|
return this._messagePanel.current.getScrollState();
|
||||||
},
|
},
|
||||||
|
|
||||||
// returns one of:
|
// returns one of:
|
||||||
|
@ -899,9 +901,9 @@ const TimelinePanel = createReactClass({
|
||||||
// +1: read marker is below the window
|
// +1: read marker is below the window
|
||||||
getReadMarkerPosition: function() {
|
getReadMarkerPosition: function() {
|
||||||
if (!this.props.manageReadMarkers) return null;
|
if (!this.props.manageReadMarkers) return null;
|
||||||
if (!this.refs.messagePanel) return null;
|
if (!this._messagePanel.current) return null;
|
||||||
|
|
||||||
const ret = this.refs.messagePanel.getReadMarkerPosition();
|
const ret = this._messagePanel.current.getReadMarkerPosition();
|
||||||
if (ret !== null) {
|
if (ret !== null) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -936,7 +938,7 @@ const TimelinePanel = createReactClass({
|
||||||
* We pass it down to the scroll panel.
|
* We pass it down to the scroll panel.
|
||||||
*/
|
*/
|
||||||
handleScrollKey: function(ev) {
|
handleScrollKey: function(ev) {
|
||||||
if (!this.refs.messagePanel) { return; }
|
if (!this._messagePanel.current) { return; }
|
||||||
|
|
||||||
// jump to the live timeline on ctrl-end, rather than the end of the
|
// jump to the live timeline on ctrl-end, rather than the end of the
|
||||||
// timeline window.
|
// timeline window.
|
||||||
|
@ -944,7 +946,7 @@ const TimelinePanel = createReactClass({
|
||||||
ev.keyCode == KeyCode.END) {
|
ev.keyCode == KeyCode.END) {
|
||||||
this.jumpToLiveTimeline();
|
this.jumpToLiveTimeline();
|
||||||
} else {
|
} else {
|
||||||
this.refs.messagePanel.handleScrollKey(ev);
|
this._messagePanel.current.handleScrollKey(ev);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -986,8 +988,8 @@ const TimelinePanel = createReactClass({
|
||||||
const onLoaded = () => {
|
const onLoaded = () => {
|
||||||
// clear the timeline min-height when
|
// clear the timeline min-height when
|
||||||
// (re)loading the timeline
|
// (re)loading the timeline
|
||||||
if (this.refs.messagePanel) {
|
if (this._messagePanel.current) {
|
||||||
this.refs.messagePanel.onTimelineReset();
|
this._messagePanel.current.onTimelineReset();
|
||||||
}
|
}
|
||||||
this._reloadEvents();
|
this._reloadEvents();
|
||||||
|
|
||||||
|
@ -1002,7 +1004,7 @@ const TimelinePanel = createReactClass({
|
||||||
timelineLoading: false,
|
timelineLoading: false,
|
||||||
}, () => {
|
}, () => {
|
||||||
// initialise the scroll state of the message panel
|
// initialise the scroll state of the message panel
|
||||||
if (!this.refs.messagePanel) {
|
if (!this._messagePanel.current) {
|
||||||
// this shouldn't happen - we know we're mounted because
|
// this shouldn't happen - we know we're mounted because
|
||||||
// we're in a setState callback, and we know
|
// we're in a setState callback, and we know
|
||||||
// timelineLoading is now false, so render() should have
|
// timelineLoading is now false, so render() should have
|
||||||
|
@ -1012,10 +1014,10 @@ const TimelinePanel = createReactClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (eventId) {
|
if (eventId) {
|
||||||
this.refs.messagePanel.scrollToEvent(eventId, pixelOffset,
|
this._messagePanel.current.scrollToEvent(eventId, pixelOffset,
|
||||||
offsetBase);
|
offsetBase);
|
||||||
} else {
|
} else {
|
||||||
this.refs.messagePanel.scrollToBottom();
|
this._messagePanel.current.scrollToBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendReadReceipt();
|
this.sendReadReceipt();
|
||||||
|
@ -1134,7 +1136,7 @@ const TimelinePanel = createReactClass({
|
||||||
const ignoreOwn = opts.ignoreOwn || false;
|
const ignoreOwn = opts.ignoreOwn || false;
|
||||||
const allowPartial = opts.allowPartial || false;
|
const allowPartial = opts.allowPartial || false;
|
||||||
|
|
||||||
const messagePanel = this.refs.messagePanel;
|
const messagePanel = this._messagePanel.current;
|
||||||
if (messagePanel === undefined) return null;
|
if (messagePanel === undefined) return null;
|
||||||
|
|
||||||
const EventTile = sdk.getComponent('rooms.EventTile');
|
const EventTile = sdk.getComponent('rooms.EventTile');
|
||||||
|
@ -1313,7 +1315,8 @@ const TimelinePanel = createReactClass({
|
||||||
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
|
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<MessagePanel ref="messagePanel"
|
<MessagePanel
|
||||||
|
ref={this._messagePanel}
|
||||||
room={this.props.timelineSet.room}
|
room={this.props.timelineSet.room}
|
||||||
permalinkCreator={this.props.permalinkCreator}
|
permalinkCreator={this.props.permalinkCreator}
|
||||||
hidden={this.props.hidden}
|
hidden={this.props.hidden}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
|
@ -48,6 +48,8 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
this._captchaWidgetId = null;
|
this._captchaWidgetId = null;
|
||||||
|
|
||||||
|
this._recaptchaContainer = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
|
@ -67,7 +69,7 @@ module.exports = createReactClass({
|
||||||
scriptTag.setAttribute(
|
scriptTag.setAttribute(
|
||||||
'src', `${protocol}//www.recaptcha.net/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit`,
|
'src', `${protocol}//www.recaptcha.net/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit`,
|
||||||
);
|
);
|
||||||
this.refs.recaptchaContainer.appendChild(scriptTag);
|
this._recaptchaContainer.current.appendChild(scriptTag);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -124,11 +126,11 @@ module.exports = createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref="recaptchaContainer">
|
<div ref={this._recaptchaContainer}>
|
||||||
<p>{_t(
|
<p>{_t(
|
||||||
"This homeserver would like to make sure you are not a robot.",
|
"This homeserver would like to make sure you are not a robot.",
|
||||||
)}</p>
|
)}</p>
|
||||||
<div id={DIV_ID}></div>
|
<div id={DIV_ID} />
|
||||||
{ error }
|
{ error }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
|
@ -581,6 +581,8 @@ export const FallbackAuthEntry = createReactClass({
|
||||||
// the popup if we open it immediately.
|
// the popup if we open it immediately.
|
||||||
this._popupWindow = null;
|
this._popupWindow = null;
|
||||||
window.addEventListener("message", this._onReceiveMessage);
|
window.addEventListener("message", this._onReceiveMessage);
|
||||||
|
|
||||||
|
this._fallbackButton = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
|
@ -591,8 +593,8 @@ export const FallbackAuthEntry = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
focus: function() {
|
focus: function() {
|
||||||
if (this.refs.fallbackButton) {
|
if (this._fallbackButton.current) {
|
||||||
this.refs.fallbackButton.focus();
|
this._fallbackButton.current.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -624,7 +626,7 @@ export const FallbackAuthEntry = createReactClass({
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<a ref="fallbackButton" onClick={this._onShowFallbackClick}>{ _t("Start authentication") }</a>
|
<a ref={this._fallbackButton} onClick={this._onShowFallbackClick}>{ _t("Start authentication") }</a>
|
||||||
{errorSection}
|
{errorSection}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
|
|
||||||
|
@ -106,10 +106,14 @@ module.exports = createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._textinput = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
if (this.props.focus) {
|
if (this.props.focus) {
|
||||||
// Set the cursor at the end of the text input
|
// Set the cursor at the end of the text input
|
||||||
this.refs.textinput.value = this.props.value;
|
this._textinput.current.value = this.props.value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -126,8 +130,8 @@ module.exports = createReactClass({
|
||||||
let selectedList = this.state.selectedList.slice();
|
let selectedList = this.state.selectedList.slice();
|
||||||
// Check the text input field to see if user has an unconverted address
|
// Check the text input field to see if user has an unconverted address
|
||||||
// If there is and it's valid add it to the local selectedList
|
// If there is and it's valid add it to the local selectedList
|
||||||
if (this.refs.textinput.value !== '') {
|
if (this._textinput.current.value !== '') {
|
||||||
selectedList = this._addAddressesToList([this.refs.textinput.value]);
|
selectedList = this._addAddressesToList([this._textinput.current.value]);
|
||||||
if (selectedList === null) return;
|
if (selectedList === null) return;
|
||||||
}
|
}
|
||||||
this.props.onFinished(true, selectedList);
|
this.props.onFinished(true, selectedList);
|
||||||
|
@ -154,23 +158,23 @@ module.exports = createReactClass({
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.addressSelector) this.addressSelector.chooseSelection();
|
if (this.addressSelector) this.addressSelector.chooseSelection();
|
||||||
} else if (this.refs.textinput.value.length === 0 && this.state.selectedList.length && e.keyCode === 8) { // backspace
|
} else if (this._textinput.current.value.length === 0 && this.state.selectedList.length && e.keyCode === 8) { // backspace
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.onDismissed(this.state.selectedList.length - 1)();
|
this.onDismissed(this.state.selectedList.length - 1)();
|
||||||
} else if (e.keyCode === 13) { // enter
|
} else if (e.keyCode === 13) { // enter
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.refs.textinput.value === '') {
|
if (this._textinput.current.value === '') {
|
||||||
// if there's nothing in the input box, submit the form
|
// if there's nothing in the input box, submit the form
|
||||||
this.onButtonClick();
|
this.onButtonClick();
|
||||||
} else {
|
} else {
|
||||||
this._addAddressesToList([this.refs.textinput.value]);
|
this._addAddressesToList([this._textinput.current.value]);
|
||||||
}
|
}
|
||||||
} else if (e.keyCode === 188 || e.keyCode === 9) { // comma or tab
|
} else if (e.keyCode === 188 || e.keyCode === 9) { // comma or tab
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this._addAddressesToList([this.refs.textinput.value]);
|
this._addAddressesToList([this._textinput.current.value]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -647,7 +651,7 @@ module.exports = createReactClass({
|
||||||
onPaste={this._onPaste}
|
onPaste={this._onPaste}
|
||||||
rows="1"
|
rows="1"
|
||||||
id="textinput"
|
id="textinput"
|
||||||
ref="textinput"
|
ref={this._textinput}
|
||||||
className="mx_AddressPickerDialog_input"
|
className="mx_AddressPickerDialog_input"
|
||||||
onChange={this.onQueryChanged}
|
onChange={this.onQueryChanged}
|
||||||
placeholder={this.getPlaceholder()}
|
placeholder={this.getPlaceholder()}
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
@ -62,8 +62,13 @@ export default createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._input_value = createRef();
|
||||||
|
this._uiAuth = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.refs.input_value.select();
|
this._input_value.current.select();
|
||||||
|
|
||||||
this._matrixClient = MatrixClientPeg.get();
|
this._matrixClient = MatrixClientPeg.get();
|
||||||
},
|
},
|
||||||
|
@ -102,8 +107,8 @@ export default createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubmit: function(ev) {
|
onSubmit: function(ev) {
|
||||||
if (this.refs.uiAuth) {
|
if (this._uiAuth.current) {
|
||||||
this.refs.uiAuth.tryContinue();
|
this._uiAuth.current.tryContinue();
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
doingUIAuth: true,
|
doingUIAuth: true,
|
||||||
|
@ -215,7 +220,7 @@ export default createReactClass({
|
||||||
onAuthFinished={this._onUIAuthFinished}
|
onAuthFinished={this._onUIAuthFinished}
|
||||||
inputs={{}}
|
inputs={{}}
|
||||||
poll={true}
|
poll={true}
|
||||||
ref="uiAuth"
|
ref={this._uiAuth}
|
||||||
continueIsManaged={true}
|
continueIsManaged={true}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
@ -257,7 +262,7 @@ export default createReactClass({
|
||||||
>
|
>
|
||||||
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
||||||
<div className="mx_SetMxIdDialog_input_group">
|
<div className="mx_SetMxIdDialog_input_group">
|
||||||
<input type="text" ref="input_value" value={this.state.username}
|
<input type="text" ref={this._input_value} value={this.state.username}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onChange={this.onValueChange}
|
onChange={this.onValueChange}
|
||||||
onKeyUp={this.onKeyUp}
|
onKeyUp={this.onKeyUp}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {Room, User, Group, RoomMember, MatrixEvent} from 'matrix-js-sdk';
|
import {Room, User, Group, RoomMember, MatrixEvent} from 'matrix-js-sdk';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
@ -74,6 +74,8 @@ export default class ShareDialog extends React.Component {
|
||||||
// MatrixEvent defaults to share linkSpecificEvent
|
// MatrixEvent defaults to share linkSpecificEvent
|
||||||
linkSpecificEvent: this.props.target instanceof MatrixEvent,
|
linkSpecificEvent: this.props.target instanceof MatrixEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this._link = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
static _selectText(target) {
|
static _selectText(target) {
|
||||||
|
@ -94,7 +96,7 @@ export default class ShareDialog extends React.Component {
|
||||||
onCopyClick(e) {
|
onCopyClick(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
ShareDialog._selectText(this.refs.link);
|
ShareDialog._selectText(this._link.current);
|
||||||
|
|
||||||
let successful;
|
let successful;
|
||||||
try {
|
try {
|
||||||
|
@ -195,7 +197,7 @@ export default class ShareDialog extends React.Component {
|
||||||
>
|
>
|
||||||
<div className="mx_ShareDialog_content">
|
<div className="mx_ShareDialog_content">
|
||||||
<div className="mx_ShareDialog_matrixto">
|
<div className="mx_ShareDialog_matrixto">
|
||||||
<a ref="link"
|
<a ref={this._link}
|
||||||
href={matrixToUrl}
|
href={matrixToUrl}
|
||||||
onClick={ShareDialog.onLinkClick}
|
onClick={ShareDialog.onLinkClick}
|
||||||
className="mx_ShareDialog_matrixto_link"
|
className="mx_ShareDialog_matrixto_link"
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
@ -42,15 +42,19 @@ export default createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._textinput = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
if (this.props.focus) {
|
if (this.props.focus) {
|
||||||
// Set the cursor at the end of the text input
|
// Set the cursor at the end of the text input
|
||||||
this.refs.textinput.value = this.props.value;
|
this._textinput.current.value = this.props.value;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onOk: function() {
|
onOk: function() {
|
||||||
this.props.onFinished(true, this.refs.textinput.value);
|
this.props.onFinished(true, this._textinput.current.value);
|
||||||
},
|
},
|
||||||
|
|
||||||
onCancel: function() {
|
onCancel: function() {
|
||||||
|
@ -70,7 +74,13 @@ export default createReactClass({
|
||||||
<label htmlFor="textinput"> { this.props.description } </label>
|
<label htmlFor="textinput"> { this.props.description } </label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input id="textinput" ref="textinput" className="mx_TextInputDialog_input" defaultValue={this.props.value} autoFocus={this.props.focus} size="64" />
|
<input
|
||||||
|
id="textinput"
|
||||||
|
ref={this._textinput}
|
||||||
|
className="mx_TextInputDialog_input"
|
||||||
|
defaultValue={this.props.value}
|
||||||
|
autoFocus={this.props.focus}
|
||||||
|
size="64" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -64,6 +64,8 @@ export default class AppTile extends React.Component {
|
||||||
this._onReloadWidgetClick = this._onReloadWidgetClick.bind(this);
|
this._onReloadWidgetClick = this._onReloadWidgetClick.bind(this);
|
||||||
|
|
||||||
this._contextMenuButton = createRef();
|
this._contextMenuButton = createRef();
|
||||||
|
this._appFrame = createRef();
|
||||||
|
this._menu_bar = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -337,14 +339,14 @@ export default class AppTile extends React.Component {
|
||||||
// HACK: This is a really dirty way to ensure that Jitsi cleans up
|
// HACK: This is a really dirty way to ensure that Jitsi cleans up
|
||||||
// its hold on the webcam. Without this, the widget holds a media
|
// its hold on the webcam. Without this, the widget holds a media
|
||||||
// stream open, even after death. See https://github.com/vector-im/riot-web/issues/7351
|
// stream open, even after death. See https://github.com/vector-im/riot-web/issues/7351
|
||||||
if (this.refs.appFrame) {
|
if (this._appFrame.current) {
|
||||||
// In practice we could just do `+= ''` to trick the browser
|
// In practice we could just do `+= ''` to trick the browser
|
||||||
// into thinking the URL changed, however I can foresee this
|
// into thinking the URL changed, however I can foresee this
|
||||||
// being optimized out by a browser. Instead, we'll just point
|
// being optimized out by a browser. Instead, we'll just point
|
||||||
// the iframe at a page that is reasonably safe to use in the
|
// the iframe at a page that is reasonably safe to use in the
|
||||||
// event the iframe doesn't wink away.
|
// event the iframe doesn't wink away.
|
||||||
// This is relative to where the Riot instance is located.
|
// This is relative to where the Riot instance is located.
|
||||||
this.refs.appFrame.src = 'about:blank';
|
this._appFrame.current.src = 'about:blank';
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetUtils.setRoomWidget(
|
WidgetUtils.setRoomWidget(
|
||||||
|
@ -389,7 +391,7 @@ export default class AppTile extends React.Component {
|
||||||
// FIXME: There's probably no reason to do this here: it should probably be done entirely
|
// FIXME: There's probably no reason to do this here: it should probably be done entirely
|
||||||
// in ActiveWidgetStore.
|
// in ActiveWidgetStore.
|
||||||
const widgetMessaging = new WidgetMessaging(
|
const widgetMessaging = new WidgetMessaging(
|
||||||
this.props.id, this.props.url, this.props.userWidget, this.refs.appFrame.contentWindow);
|
this.props.id, this.props.url, this.props.userWidget, this._appFrame.current.contentWindow);
|
||||||
ActiveWidgetStore.setWidgetMessaging(this.props.id, widgetMessaging);
|
ActiveWidgetStore.setWidgetMessaging(this.props.id, widgetMessaging);
|
||||||
widgetMessaging.getCapabilities().then((requestedCapabilities) => {
|
widgetMessaging.getCapabilities().then((requestedCapabilities) => {
|
||||||
console.log(`Widget ${this.props.id} requested capabilities: ` + requestedCapabilities);
|
console.log(`Widget ${this.props.id} requested capabilities: ` + requestedCapabilities);
|
||||||
|
@ -496,7 +498,7 @@ export default class AppTile extends React.Component {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
// Ignore clicks on menu bar children
|
// Ignore clicks on menu bar children
|
||||||
if (ev.target !== this.refs.menu_bar) {
|
if (ev.target !== this._menu_bar.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +557,7 @@ export default class AppTile extends React.Component {
|
||||||
|
|
||||||
_onReloadWidgetClick() {
|
_onReloadWidgetClick() {
|
||||||
// Reload iframe in this way to avoid cross-origin restrictions
|
// Reload iframe in this way to avoid cross-origin restrictions
|
||||||
this.refs.appFrame.src = this.refs.appFrame.src;
|
this._appFrame.current.src = this._appFrame.current.src;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onContextMenuClick = () => {
|
_onContextMenuClick = () => {
|
||||||
|
@ -626,7 +628,7 @@ export default class AppTile extends React.Component {
|
||||||
{ this.state.loading && loadingElement }
|
{ this.state.loading && loadingElement }
|
||||||
<iframe
|
<iframe
|
||||||
allow={iframeFeatures}
|
allow={iframeFeatures}
|
||||||
ref="appFrame"
|
ref={this._appFrame}
|
||||||
src={this._getSafeUrl()}
|
src={this._getSafeUrl()}
|
||||||
allowFullScreen={true}
|
allowFullScreen={true}
|
||||||
sandbox={sandboxFlags}
|
sandbox={sandboxFlags}
|
||||||
|
@ -694,7 +696,7 @@ export default class AppTile extends React.Component {
|
||||||
return <React.Fragment>
|
return <React.Fragment>
|
||||||
<div className={appTileClass} id={this.props.id}>
|
<div className={appTileClass} id={this.props.id}>
|
||||||
{ this.props.showMenubar &&
|
{ this.props.showMenubar &&
|
||||||
<div ref="menu_bar" className={menuBarClasses} onClick={this.onClickMenuBar}>
|
<div ref={this._menu_bar} className={menuBarClasses} onClick={this.onClickMenuBar}>
|
||||||
<span className="mx_AppTileMenuBarTitle" style={{pointerEvents: (this.props.handleMinimisePointerEvents ? 'all' : false)}}>
|
<span className="mx_AppTileMenuBarTitle" style={{pointerEvents: (this.props.handleMinimisePointerEvents ? 'all' : false)}}>
|
||||||
{ /* Minimise widget */ }
|
{ /* Minimise widget */ }
|
||||||
{ showMinimiseButton && <AccessibleButton
|
{ showMinimiseButton && <AccessibleButton
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import {Key} from "../../../Keyboard";
|
import {Key} from "../../../Keyboard";
|
||||||
|
@ -65,7 +65,7 @@ module.exports = createReactClass({
|
||||||
componentWillReceiveProps: function(nextProps) {
|
componentWillReceiveProps: function(nextProps) {
|
||||||
if (nextProps.initialValue !== this.props.initialValue) {
|
if (nextProps.initialValue !== this.props.initialValue) {
|
||||||
this.value = nextProps.initialValue;
|
this.value = nextProps.initialValue;
|
||||||
if (this.refs.editable_div) {
|
if (this._editable_div.current) {
|
||||||
this.showPlaceholder(!this.value);
|
this.showPlaceholder(!this.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,24 +76,27 @@ module.exports = createReactClass({
|
||||||
// as React doesn't play nice with contentEditable.
|
// as React doesn't play nice with contentEditable.
|
||||||
this.value = '';
|
this.value = '';
|
||||||
this.placeholder = false;
|
this.placeholder = false;
|
||||||
|
|
||||||
|
this._editable_div = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.value = this.props.initialValue;
|
this.value = this.props.initialValue;
|
||||||
if (this.refs.editable_div) {
|
if (this._editable_div.current) {
|
||||||
this.showPlaceholder(!this.value);
|
this.showPlaceholder(!this.value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showPlaceholder: function(show) {
|
showPlaceholder: function(show) {
|
||||||
if (show) {
|
if (show) {
|
||||||
this.refs.editable_div.textContent = this.props.placeholder;
|
this._editable_div.current.textContent = this.props.placeholder;
|
||||||
this.refs.editable_div.setAttribute("class", this.props.className + " " + this.props.placeholderClassName);
|
this._editable_div.current.setAttribute("class", this.props.className
|
||||||
|
+ " " + this.props.placeholderClassName);
|
||||||
this.placeholder = true;
|
this.placeholder = true;
|
||||||
this.value = '';
|
this.value = '';
|
||||||
} else {
|
} else {
|
||||||
this.refs.editable_div.textContent = this.value;
|
this._editable_div.current.textContent = this.value;
|
||||||
this.refs.editable_div.setAttribute("class", this.props.className);
|
this._editable_div.current.setAttribute("class", this.props.className);
|
||||||
this.placeholder = false;
|
this.placeholder = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -120,7 +123,7 @@ module.exports = createReactClass({
|
||||||
this.value = this.props.initialValue;
|
this.value = this.props.initialValue;
|
||||||
this.showPlaceholder(!this.value);
|
this.showPlaceholder(!this.value);
|
||||||
this.onValueChanged(false);
|
this.onValueChanged(false);
|
||||||
this.refs.editable_div.blur();
|
this._editable_div.current.blur();
|
||||||
},
|
},
|
||||||
|
|
||||||
onValueChanged: function(shouldSubmit) {
|
onValueChanged: function(shouldSubmit) {
|
||||||
|
@ -219,7 +222,7 @@ module.exports = createReactClass({
|
||||||
</div>;
|
</div>;
|
||||||
} else {
|
} else {
|
||||||
// show the content editable div, but manually manage its contents as react and contentEditable don't play nice together
|
// show the content editable div, but manually manage its contents as react and contentEditable don't play nice together
|
||||||
editableEl = <div ref="editable_div"
|
editableEl = <div ref={this._editable_div}
|
||||||
contentEditable={true}
|
contentEditable={true}
|
||||||
className={className}
|
className={className}
|
||||||
onKeyDown={this.onKeyDown}
|
onKeyDown={this.onKeyDown}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
|
@ -34,6 +34,10 @@ module.exports = createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._user_id_input = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
addUser: function(user_id) {
|
addUser: function(user_id) {
|
||||||
if (this.props.selected_users.indexOf(user_id == -1)) {
|
if (this.props.selected_users.indexOf(user_id == -1)) {
|
||||||
this.props.onChange(this.props.selected_users.concat([user_id]));
|
this.props.onChange(this.props.selected_users.concat([user_id]));
|
||||||
|
@ -47,20 +51,20 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onAddUserId: function() {
|
onAddUserId: function() {
|
||||||
this.addUser(this.refs.user_id_input.value);
|
this.addUser(this._user_id_input.current.value);
|
||||||
this.refs.user_id_input.value = "";
|
this._user_id_input.current.value = "";
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
const self = this;
|
const self = this;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ul className="mx_UserSelector_UserIdList" ref="list">
|
<ul className="mx_UserSelector_UserIdList">
|
||||||
{ this.props.selected_users.map(function(user_id, i) {
|
{ this.props.selected_users.map(function(user_id, i) {
|
||||||
return <li key={user_id}>{ user_id } - <span onClick={function() {self.removeUser(user_id);}}>X</span></li>;
|
return <li key={user_id}>{ user_id } - <span onClick={function() {self.removeUser(user_id);}}>X</span></li>;
|
||||||
}) }
|
}) }
|
||||||
</ul>
|
</ul>
|
||||||
<input type="text" ref="user_id_input" defaultValue="" className="mx_UserSelector_userIdInput" placeholder={_t("ex. @bob:example.com")} />
|
<input type="text" ref={this._user_id_input} defaultValue="" className="mx_UserSelector_userIdInput" placeholder={_t("ex. @bob:example.com")} />
|
||||||
<button onClick={this.onAddUserId} className="mx_UserSelector_AddUserId">
|
<button onClick={this.onAddUserId} className="mx_UserSelector_AddUserId">
|
||||||
{ _t("Add User") }
|
{ _t("Add User") }
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import * as HtmlUtils from '../../../HtmlUtils';
|
import * as HtmlUtils from '../../../HtmlUtils';
|
||||||
import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils';
|
import { editBodyDiffToHtml } from '../../../utils/MessageDiffUtils';
|
||||||
|
@ -51,6 +51,8 @@ export default class EditHistoryMessage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
const canRedact = room.currentState.maySendRedactionForEvent(event, userId);
|
const canRedact = room.currentState.maySendRedactionForEvent(event, userId);
|
||||||
this.state = {canRedact, sendStatus: event.getAssociatedStatus()};
|
this.state = {canRedact, sendStatus: event.getAssociatedStatus()};
|
||||||
|
|
||||||
|
this._content = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAssociatedStatusChanged = () => {
|
_onAssociatedStatusChanged = () => {
|
||||||
|
@ -78,8 +80,8 @@ export default class EditHistoryMessage extends React.PureComponent {
|
||||||
|
|
||||||
pillifyLinks() {
|
pillifyLinks() {
|
||||||
// not present for redacted events
|
// not present for redacted events
|
||||||
if (this.refs.content) {
|
if (this._content.current) {
|
||||||
pillifyLinks(this.refs.content.children, this.props.mxEvent);
|
pillifyLinks(this._content.current.children, this.props.mxEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,13 +142,13 @@ export default class EditHistoryMessage extends React.PureComponent {
|
||||||
if (mxEvent.getContent().msgtype === "m.emote") {
|
if (mxEvent.getContent().msgtype === "m.emote") {
|
||||||
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
||||||
contentContainer = (
|
contentContainer = (
|
||||||
<div className="mx_EventTile_content" ref="content">*
|
<div className="mx_EventTile_content" ref={this._content}>*
|
||||||
<span className="mx_MEmoteBody_sender">{ name }</span>
|
<span className="mx_MEmoteBody_sender">{ name }</span>
|
||||||
{contentElements}
|
{contentElements}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
contentContainer = <div className="mx_EventTile_content" ref="content">{contentElements}</div>;
|
contentContainer = <div className="mx_EventTile_content" ref={this._content}>{contentElements}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import filesize from 'filesize';
|
import filesize from 'filesize';
|
||||||
|
@ -251,6 +251,12 @@ module.exports = createReactClass({
|
||||||
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
return MatrixClientPeg.get().mxcUrlToHttp(content.url);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._iframe = createRef();
|
||||||
|
this._dummyLink = createRef();
|
||||||
|
this._downloadImage = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
// Add this to the list of mounted components to receive notifications
|
// Add this to the list of mounted components to receive notifications
|
||||||
// when the tint changes.
|
// when the tint changes.
|
||||||
|
@ -272,17 +278,17 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
tint: function() {
|
tint: function() {
|
||||||
// Update our tinted copy of require("../../../../res/img/download.svg")
|
// Update our tinted copy of require("../../../../res/img/download.svg")
|
||||||
if (this.refs.downloadImage) {
|
if (this._downloadImage.current) {
|
||||||
this.refs.downloadImage.src = tintedDownloadImageURL;
|
this._downloadImage.current.src = tintedDownloadImageURL;
|
||||||
}
|
}
|
||||||
if (this.refs.iframe) {
|
if (this._iframe.current) {
|
||||||
// If the attachment is encrypted then the download image
|
// If the attachment is encrypted then the download image
|
||||||
// will be inside the iframe so we wont be able to update
|
// will be inside the iframe so we wont be able to update
|
||||||
// it directly.
|
// it directly.
|
||||||
this.refs.iframe.contentWindow.postMessage({
|
this._iframe.current.contentWindow.postMessage({
|
||||||
code: remoteSetTint.toString(),
|
code: remoteSetTint.toString(),
|
||||||
imgSrc: tintedDownloadImageURL,
|
imgSrc: tintedDownloadImageURL,
|
||||||
style: computedStyle(this.refs.dummyLink),
|
style: computedStyle(this._dummyLink.current),
|
||||||
}, "*");
|
}, "*");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -340,7 +346,7 @@ module.exports = createReactClass({
|
||||||
ev.target.contentWindow.postMessage({
|
ev.target.contentWindow.postMessage({
|
||||||
code: remoteRender.toString(),
|
code: remoteRender.toString(),
|
||||||
imgSrc: tintedDownloadImageURL,
|
imgSrc: tintedDownloadImageURL,
|
||||||
style: computedStyle(this.refs.dummyLink),
|
style: computedStyle(this._dummyLink.current),
|
||||||
blob: this.state.decryptedBlob,
|
blob: this.state.decryptedBlob,
|
||||||
// Set a download attribute for encrypted files so that the file
|
// Set a download attribute for encrypted files so that the file
|
||||||
// will have the correct name when the user tries to download it.
|
// will have the correct name when the user tries to download it.
|
||||||
|
@ -367,9 +373,9 @@ module.exports = createReactClass({
|
||||||
* We'll use it to learn how the download link
|
* We'll use it to learn how the download link
|
||||||
* would have been styled if it was rendered inline.
|
* would have been styled if it was rendered inline.
|
||||||
*/ }
|
*/ }
|
||||||
<a ref="dummyLink" />
|
<a ref={this._dummyLink} />
|
||||||
</div>
|
</div>
|
||||||
<iframe src={renderer_url} onLoad={onIframeLoad} ref="iframe" />
|
<iframe src={renderer_url} onLoad={onIframeLoad} ref={this._iframe} />
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
@ -439,7 +445,7 @@ module.exports = createReactClass({
|
||||||
<span className="mx_MFileBody">
|
<span className="mx_MFileBody">
|
||||||
<div className="mx_MFileBody_download">
|
<div className="mx_MFileBody_download">
|
||||||
<a {...downloadProps}>
|
<a {...downloadProps}>
|
||||||
<img src={tintedDownloadImageURL} width="12" height="14" ref="downloadImage" />
|
<img src={tintedDownloadImageURL} width="12" height="14" ref={this._downloadImage} />
|
||||||
{ _t("Download %(text)s", { text: text }) }
|
{ _t("Download %(text)s", { text: text }) }
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { MatrixClient } from 'matrix-js-sdk';
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@ export default class MImageBody extends React.Component {
|
||||||
hover: false,
|
hover: false,
|
||||||
showImage: SettingsStore.getValue("showImages"),
|
showImage: SettingsStore.getValue("showImages"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this._image = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
@ -158,8 +160,8 @@ export default class MImageBody extends React.Component {
|
||||||
|
|
||||||
let loadedImageDimensions;
|
let loadedImageDimensions;
|
||||||
|
|
||||||
if (this.refs.image) {
|
if (this._image.current) {
|
||||||
const { naturalWidth, naturalHeight } = this.refs.image;
|
const { naturalWidth, naturalHeight } = this._image.current;
|
||||||
// this is only used as a fallback in case content.info.w/h is missing
|
// this is only used as a fallback in case content.info.w/h is missing
|
||||||
loadedImageDimensions = { naturalWidth, naturalHeight };
|
loadedImageDimensions = { naturalWidth, naturalHeight };
|
||||||
}
|
}
|
||||||
|
@ -342,7 +344,7 @@ export default class MImageBody extends React.Component {
|
||||||
imageElement = <HiddenImagePlaceholder />;
|
imageElement = <HiddenImagePlaceholder />;
|
||||||
} else {
|
} else {
|
||||||
imageElement = (
|
imageElement = (
|
||||||
<img style={{display: 'none'}} src={thumbUrl} ref="image"
|
<img style={{display: 'none'}} src={thumbUrl} ref={this._image}
|
||||||
alt={content.body}
|
alt={content.body}
|
||||||
onError={this.onImageError}
|
onError={this.onImageError}
|
||||||
onLoad={this.onImageLoad}
|
onLoad={this.onImageLoad}
|
||||||
|
@ -385,7 +387,7 @@ export default class MImageBody extends React.Component {
|
||||||
// which has the same width as the timeline
|
// which has the same width as the timeline
|
||||||
// mx_MImageBody_thumbnail resizes img to exactly container size
|
// mx_MImageBody_thumbnail resizes img to exactly container size
|
||||||
img = (
|
img = (
|
||||||
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref="image"
|
<img className="mx_MImageBody_thumbnail" src={thumbUrl} ref={this._image}
|
||||||
style={{ maxWidth: maxWidth + "px" }}
|
style={{ maxWidth: maxWidth + "px" }}
|
||||||
alt={content.body}
|
alt={content.body}
|
||||||
onError={this.onImageError}
|
onError={this.onImageError}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
|
@ -47,8 +47,12 @@ module.exports = createReactClass({
|
||||||
maxImageHeight: PropTypes.number,
|
maxImageHeight: PropTypes.number,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._body = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
getEventTileOps: function() {
|
getEventTileOps: function() {
|
||||||
return this.refs.body && this.refs.body.getEventTileOps ? this.refs.body.getEventTileOps() : null;
|
return this._body.current && this._body.current.getEventTileOps ? this._body.current.getEventTileOps() : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
onTileUpdate: function() {
|
onTileUpdate: function() {
|
||||||
|
@ -103,7 +107,8 @@ module.exports = createReactClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
return <BodyType
|
return <BodyType
|
||||||
ref="body" mxEvent={this.props.mxEvent}
|
ref={this._body}
|
||||||
|
mxEvent={this.props.mxEvent}
|
||||||
highlights={this.props.highlights}
|
highlights={this.props.highlights}
|
||||||
highlightLink={this.props.highlightLink}
|
highlightLink={this.props.highlightLink}
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
|
|
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
|
@ -86,6 +86,10 @@ module.exports = createReactClass({
|
||||||
return successful;
|
return successful;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._content = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this._unmounted = false;
|
this._unmounted = false;
|
||||||
if (!this.props.editState) {
|
if (!this.props.editState) {
|
||||||
|
@ -94,13 +98,13 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_applyFormatting() {
|
_applyFormatting() {
|
||||||
this.activateSpoilers(this.refs.content.children);
|
this.activateSpoilers(this._content.current.children);
|
||||||
|
|
||||||
// pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
|
// pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer
|
||||||
// are still sent as plaintext URLs. If these are ever pillified in the composer,
|
// are still sent as plaintext URLs. If these are ever pillified in the composer,
|
||||||
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
|
// we should be pillify them here by doing the linkifying BEFORE the pillifying.
|
||||||
pillifyLinks(this.refs.content.children, this.props.mxEvent);
|
pillifyLinks(this._content.current.children, this.props.mxEvent);
|
||||||
HtmlUtils.linkifyElement(this.refs.content);
|
HtmlUtils.linkifyElement(this._content.current);
|
||||||
this.calculateUrlPreview();
|
this.calculateUrlPreview();
|
||||||
|
|
||||||
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") {
|
if (this.props.mxEvent.getContent().format === "org.matrix.custom.html") {
|
||||||
|
@ -163,7 +167,7 @@ module.exports = createReactClass({
|
||||||
//console.info("calculateUrlPreview: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
|
//console.info("calculateUrlPreview: ShowUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview);
|
||||||
|
|
||||||
if (this.props.showUrlPreview) {
|
if (this.props.showUrlPreview) {
|
||||||
let links = this.findLinks(this.refs.content.children);
|
let links = this.findLinks(this._content.current.children);
|
||||||
if (links.length) {
|
if (links.length) {
|
||||||
// de-dup the links (but preserve ordering)
|
// de-dup the links (but preserve ordering)
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
|
@ -327,7 +331,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getInnerText: () => {
|
getInnerText: () => {
|
||||||
return this.refs.content.innerText;
|
return this._content.current.innerText;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -452,7 +456,7 @@ module.exports = createReactClass({
|
||||||
case "m.emote":
|
case "m.emote":
|
||||||
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
|
||||||
return (
|
return (
|
||||||
<span ref="content" className="mx_MEmoteBody mx_EventTile_content">
|
<span ref={this._content} className="mx_MEmoteBody mx_EventTile_content">
|
||||||
*
|
*
|
||||||
<span
|
<span
|
||||||
className="mx_MEmoteBody_sender"
|
className="mx_MEmoteBody_sender"
|
||||||
|
@ -467,14 +471,14 @@ module.exports = createReactClass({
|
||||||
);
|
);
|
||||||
case "m.notice":
|
case "m.notice":
|
||||||
return (
|
return (
|
||||||
<span ref="content" className="mx_MNoticeBody mx_EventTile_content">
|
<span ref={this._content} className="mx_MNoticeBody mx_EventTile_content">
|
||||||
{ body }
|
{ body }
|
||||||
{ widgets }
|
{ widgets }
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
default: // including "m.text"
|
default: // including "m.text"
|
||||||
return (
|
return (
|
||||||
<span ref="content" className="mx_MTextBody mx_EventTile_content">
|
<span ref={this._content} className="mx_MTextBody mx_EventTile_content">
|
||||||
{ body }
|
{ body }
|
||||||
{ widgets }
|
{ widgets }
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import MatrixClientPeg from "../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../MatrixClientPeg";
|
||||||
|
@ -58,13 +58,15 @@ export default class RoomProfileSettings extends React.Component {
|
||||||
canSetTopic: room.currentState.maySendStateEvent('m.room.topic', client.getUserId()),
|
canSetTopic: room.currentState.maySendStateEvent('m.room.topic', client.getUserId()),
|
||||||
canSetAvatar: room.currentState.maySendStateEvent('m.room.avatar', client.getUserId()),
|
canSetAvatar: room.currentState.maySendStateEvent('m.room.avatar', client.getUserId()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this._avatarUpload = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
_uploadAvatar = (e) => {
|
_uploadAvatar = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
this.refs.avatarUpload.click();
|
this._avatarUpload.current.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
_saveProfile = async (e) => {
|
_saveProfile = async (e) => {
|
||||||
|
@ -178,7 +180,7 @@ export default class RoomProfileSettings extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
||||||
<input type="file" ref="avatarUpload" className="mx_ProfileSettings_avatarUpload"
|
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
||||||
onChange={this._onAvatarChanged} accept="image/*" />
|
onChange={this._onAvatarChanged} accept="image/*" />
|
||||||
<div className="mx_ProfileSettings_profile">
|
<div className="mx_ProfileSettings_profile">
|
||||||
<div className="mx_ProfileSettings_controls">
|
<div className="mx_ProfileSettings_controls">
|
||||||
|
|
|
@ -19,7 +19,7 @@ limitations under the License.
|
||||||
|
|
||||||
import ReplyThread from "../elements/ReplyThread";
|
import ReplyThread from "../elements/ReplyThread";
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
const classNames = require("classnames");
|
const classNames = require("classnames");
|
||||||
|
@ -224,6 +224,9 @@ module.exports = createReactClass({
|
||||||
// don't do RR animations until we are mounted
|
// don't do RR animations until we are mounted
|
||||||
this._suppressReadReceiptAnimation = true;
|
this._suppressReadReceiptAnimation = true;
|
||||||
this._verifyEvent(this.props.mxEvent);
|
this._verifyEvent(this.props.mxEvent);
|
||||||
|
|
||||||
|
this._tile = createRef();
|
||||||
|
this._replyThread = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
|
@ -512,11 +515,11 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getTile() {
|
getTile() {
|
||||||
return this.refs.tile;
|
return this._tile.current;
|
||||||
},
|
},
|
||||||
|
|
||||||
getReplyThread() {
|
getReplyThread() {
|
||||||
return this.refs.replyThread;
|
return this._replyThread.current;
|
||||||
},
|
},
|
||||||
|
|
||||||
getReactions() {
|
getReactions() {
|
||||||
|
@ -748,7 +751,7 @@ module.exports = createReactClass({
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_EventTile_line">
|
<div className="mx_EventTile_line">
|
||||||
<EventTileType ref="tile"
|
<EventTileType ref={this._tile}
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
highlights={this.props.highlights}
|
highlights={this.props.highlights}
|
||||||
highlightLink={this.props.highlightLink}
|
highlightLink={this.props.highlightLink}
|
||||||
|
@ -762,7 +765,7 @@ module.exports = createReactClass({
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<div className="mx_EventTile_line">
|
<div className="mx_EventTile_line">
|
||||||
<EventTileType ref="tile"
|
<EventTileType ref={this._tile}
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
highlights={this.props.highlights}
|
highlights={this.props.highlights}
|
||||||
highlightLink={this.props.highlightLink}
|
highlightLink={this.props.highlightLink}
|
||||||
|
@ -792,7 +795,7 @@ module.exports = createReactClass({
|
||||||
this.props.mxEvent,
|
this.props.mxEvent,
|
||||||
this.props.onHeightChanged,
|
this.props.onHeightChanged,
|
||||||
this.props.permalinkCreator,
|
this.props.permalinkCreator,
|
||||||
'replyThread',
|
this._replyThread,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -805,7 +808,7 @@ module.exports = createReactClass({
|
||||||
</a>
|
</a>
|
||||||
{ !isBubbleMessage && this._renderE2EPadlock() }
|
{ !isBubbleMessage && this._renderE2EPadlock() }
|
||||||
{ thread }
|
{ thread }
|
||||||
<EventTileType ref="tile"
|
<EventTileType ref={this._tile}
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
highlights={this.props.highlights}
|
highlights={this.props.highlights}
|
||||||
highlightLink={this.props.highlightLink}
|
highlightLink={this.props.highlightLink}
|
||||||
|
@ -820,7 +823,7 @@ module.exports = createReactClass({
|
||||||
this.props.mxEvent,
|
this.props.mxEvent,
|
||||||
this.props.onHeightChanged,
|
this.props.onHeightChanged,
|
||||||
this.props.permalinkCreator,
|
this.props.permalinkCreator,
|
||||||
'replyThread',
|
this._replyThread,
|
||||||
);
|
);
|
||||||
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
||||||
return (
|
return (
|
||||||
|
@ -839,7 +842,7 @@ module.exports = createReactClass({
|
||||||
</a>
|
</a>
|
||||||
{ !isBubbleMessage && this._renderE2EPadlock() }
|
{ !isBubbleMessage && this._renderE2EPadlock() }
|
||||||
{ thread }
|
{ thread }
|
||||||
<EventTileType ref="tile"
|
<EventTileType ref={this._tile}
|
||||||
mxEvent={this.props.mxEvent}
|
mxEvent={this.props.mxEvent}
|
||||||
replacingEventId={this.props.replacingEventId}
|
replacingEventId={this.props.replacingEventId}
|
||||||
editState={this.props.editState}
|
editState={this.props.editState}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import { linkifyElement } from '../../../HtmlUtils';
|
import { linkifyElement } from '../../../HtmlUtils';
|
||||||
|
@ -54,17 +54,19 @@ module.exports = createReactClass({
|
||||||
}, (error)=>{
|
}, (error)=>{
|
||||||
console.error("Failed to get URL preview: " + error);
|
console.error("Failed to get URL preview: " + error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._description = createRef();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
if (this.refs.description) {
|
if (this._description.current) {
|
||||||
linkifyElement(this.refs.description);
|
linkifyElement(this._description.current);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate: function() {
|
componentDidUpdate: function() {
|
||||||
if (this.refs.description) {
|
if (this._description.current) {
|
||||||
linkifyElement(this.refs.description);
|
linkifyElement(this._description.current);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -129,7 +131,7 @@ module.exports = createReactClass({
|
||||||
<div className="mx_LinkPreviewWidget_caption">
|
<div className="mx_LinkPreviewWidget_caption">
|
||||||
<div className="mx_LinkPreviewWidget_title"><a href={this.props.link} target="_blank" rel="noopener">{ p["og:title"] }</a></div>
|
<div className="mx_LinkPreviewWidget_title"><a href={this.props.link} target="_blank" rel="noopener">{ p["og:title"] }</a></div>
|
||||||
<div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div>
|
<div className="mx_LinkPreviewWidget_siteName">{ p["og:site_name"] ? (" - " + p["og:site_name"]) : null }</div>
|
||||||
<div className="mx_LinkPreviewWidget_description" ref="description">
|
<div className="mx_LinkPreviewWidget_description" ref={this._description}>
|
||||||
{ p["og:description"] }
|
{ p["og:description"] }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,7 +14,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import CallHandler from '../../../CallHandler';
|
import CallHandler from '../../../CallHandler';
|
||||||
|
@ -111,6 +111,8 @@ class UploadButton extends React.Component {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.onUploadClick = this.onUploadClick.bind(this);
|
this.onUploadClick = this.onUploadClick.bind(this);
|
||||||
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
|
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
|
||||||
|
|
||||||
|
this._uploadInput = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUploadClick(ev) {
|
onUploadClick(ev) {
|
||||||
|
@ -118,7 +120,7 @@ class UploadButton extends React.Component {
|
||||||
dis.dispatch({action: 'require_registration'});
|
dis.dispatch({action: 'require_registration'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.refs.uploadInput.click();
|
this._uploadInput.current.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUploadFileInputChange(ev) {
|
onUploadFileInputChange(ev) {
|
||||||
|
@ -150,7 +152,9 @@ class UploadButton extends React.Component {
|
||||||
onClick={this.onUploadClick}
|
onClick={this.onUploadClick}
|
||||||
title={_t('Upload file')}
|
title={_t('Upload file')}
|
||||||
>
|
>
|
||||||
<input ref="uploadInput" type="file"
|
<input
|
||||||
|
ref={this._uploadInput}
|
||||||
|
type="file"
|
||||||
style={uploadInputStyle}
|
style={uploadInputStyle}
|
||||||
multiple
|
multiple
|
||||||
onChange={this.onUploadFileInputChange}
|
onChange={this.onUploadFileInputChange}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React, {createRef} from "react";
|
||||||
import dis from "../../../dispatcher";
|
import dis from "../../../dispatcher";
|
||||||
import MatrixClientPeg from "../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../MatrixClientPeg";
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||||
|
@ -45,6 +45,8 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
// The room IDs we're waiting to come down the Room handler and when we
|
// The room IDs we're waiting to come down the Room handler and when we
|
||||||
// started waiting for them. Used to track a room over an upgrade/autojoin.
|
// started waiting for them. Used to track a room over an upgrade/autojoin.
|
||||||
this._waitingRoomQueue = [/* { roomId, addedTs } */];
|
this._waitingRoomQueue = [/* { roomId, addedTs } */];
|
||||||
|
|
||||||
|
this._scroller = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
|
@ -284,8 +286,8 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
}
|
}
|
||||||
this.setState({rooms});
|
this.setState({rooms});
|
||||||
|
|
||||||
if (this.refs.scroller) {
|
if (this._scroller.current) {
|
||||||
this.refs.scroller.moveToOrigin();
|
this._scroller.current.moveToOrigin();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't track room aesthetics (badges, membership, etc) over the wire so we
|
// We don't track room aesthetics (badges, membership, etc) over the wire so we
|
||||||
|
@ -390,7 +392,7 @@ export default class RoomBreadcrumbs extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div role="toolbar" aria-label={_t("Recent rooms")}>
|
<div role="toolbar" aria-label={_t("Recent rooms")}>
|
||||||
<IndicatorScrollbar
|
<IndicatorScrollbar
|
||||||
ref="scroller"
|
ref={this._scroller}
|
||||||
className="mx_RoomBreadcrumbs"
|
className="mx_RoomBreadcrumbs"
|
||||||
trackHorizontalOverflow={true}
|
trackHorizontalOverflow={true}
|
||||||
verticalScrollsHorizontally={true}
|
verticalScrollsHorizontally={true}
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import { linkifyElement } from '../../../HtmlUtils';
|
import { linkifyElement } from '../../../HtmlUtils';
|
||||||
import { ContentRepo } from 'matrix-js-sdk';
|
import { ContentRepo } from 'matrix-js-sdk';
|
||||||
|
@ -49,11 +49,15 @@ export default createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_linkifyTopic: function() {
|
_linkifyTopic: function() {
|
||||||
if (this.refs.topic) {
|
if (this._topic.current) {
|
||||||
linkifyElement(this.refs.topic);
|
linkifyElement(this._topic.current);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._topic = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this._linkifyTopic();
|
this._linkifyTopic();
|
||||||
},
|
},
|
||||||
|
@ -104,7 +108,7 @@ export default createReactClass({
|
||||||
<td className="mx_RoomDirectory_roomDescription">
|
<td className="mx_RoomDirectory_roomDescription">
|
||||||
<div className="mx_RoomDirectory_name">{ name }</div>
|
<div className="mx_RoomDirectory_name">{ name }</div>
|
||||||
{ perms }
|
{ perms }
|
||||||
<div className="mx_RoomDirectory_topic" ref="topic" onClick={this.onTopicClick}>
|
<div className="mx_RoomDirectory_topic" ref={this._topic} onClick={this.onTopicClick}>
|
||||||
{ room.topic }
|
{ room.topic }
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_RoomDirectory_alias">{ getDisplayAliasForRoom(room) }</div>
|
<div className="mx_RoomDirectory_alias">{ getDisplayAliasForRoom(room) }</div>
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
@ -56,6 +56,10 @@ module.exports = createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._topic = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
cli.on("RoomState.events", this._onRoomStateEvents);
|
cli.on("RoomState.events", this._onRoomStateEvents);
|
||||||
|
@ -70,8 +74,8 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate: function() {
|
componentDidUpdate: function() {
|
||||||
if (this.refs.topic) {
|
if (this._topic.current) {
|
||||||
linkifyElement(this.refs.topic);
|
linkifyElement(this._topic.current);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -204,7 +208,7 @@ module.exports = createReactClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const topicElement =
|
const topicElement =
|
||||||
<div className="mx_RoomHeader_topic" ref="topic" title={topic} dir="auto">{ topic }</div>;
|
<div className="mx_RoomHeader_topic" ref={this._topic} title={topic} dir="auto">{ topic }</div>;
|
||||||
const avatarSize = 28;
|
const avatarSize = 28;
|
||||||
let roomAvatar;
|
let roomAvatar;
|
||||||
if (this.props.room) {
|
if (this.props.room) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
const classNames = require('classnames');
|
const classNames = require('classnames');
|
||||||
const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
|
const AccessibleButton = require('../../../components/views/elements/AccessibleButton');
|
||||||
|
@ -29,6 +29,10 @@ module.exports = createReactClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._search_term = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
onThisRoomClick: function() {
|
onThisRoomClick: function() {
|
||||||
this.setState({ scope: 'Room' }, () => this._searchIfQuery());
|
this.setState({ scope: 'Room' }, () => this._searchIfQuery());
|
||||||
},
|
},
|
||||||
|
@ -47,13 +51,13 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
_searchIfQuery: function() {
|
_searchIfQuery: function() {
|
||||||
if (this.refs.search_term.value) {
|
if (this._search_term.current.value) {
|
||||||
this.onSearch();
|
this.onSearch();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onSearch: function() {
|
onSearch: function() {
|
||||||
this.props.onSearch(this.refs.search_term.value, this.state.scope);
|
this.props.onSearch(this._search_term.current.value, this.state.scope);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -66,10 +70,10 @@ module.exports = createReactClass({
|
||||||
<AccessibleButton className={ thisRoomClasses } onClick={this.onThisRoomClick}>{_t("This Room")}</AccessibleButton>
|
<AccessibleButton className={ thisRoomClasses } onClick={this.onThisRoomClick}>{_t("This Room")}</AccessibleButton>
|
||||||
<AccessibleButton className={ allRoomsClasses } onClick={this.onAllRoomsClick}>{_t("All Rooms")}</AccessibleButton>
|
<AccessibleButton className={ allRoomsClasses } onClick={this.onAllRoomsClick}>{_t("All Rooms")}</AccessibleButton>
|
||||||
<div className="mx_SearchBar_input mx_textinput">
|
<div className="mx_SearchBar_input mx_textinput">
|
||||||
<input ref="search_term" type="text" autoFocus={true} placeholder={_t("Search…")} onKeyDown={this.onSearchChange} />
|
<input ref={this._search_term} type="text" autoFocus={true} placeholder={_t("Search…")} onKeyDown={this.onSearchChange} />
|
||||||
<AccessibleButton className={ searchButtonClasses } onClick={this.onSearch}></AccessibleButton>
|
<AccessibleButton className={ searchButtonClasses } onClick={this.onSearch} />
|
||||||
</div>
|
</div>
|
||||||
<AccessibleButton className="mx_SearchBar_cancel" onClick={this.props.onCancelClick}></AccessibleButton>
|
<AccessibleButton className="mx_SearchBar_cancel" onClick={this.props.onCancelClick} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,12 +14,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { _t, _td } from '../../../languageHandler';
|
import { _t, _td } from '../../../languageHandler';
|
||||||
import CallHandler from '../../../CallHandler';
|
import CallHandler from '../../../CallHandler';
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||||
import Modal from '../../../Modal';
|
|
||||||
import sdk from '../../../index';
|
import sdk from '../../../index';
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
import RoomViewStore from '../../../stores/RoomViewStore';
|
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||||
|
@ -27,7 +26,6 @@ import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||||
import Stickerpicker from './Stickerpicker';
|
import Stickerpicker from './Stickerpicker';
|
||||||
import { makeRoomPermalink } from '../../../utils/permalinks/Permalinks';
|
import { makeRoomPermalink } from '../../../utils/permalinks/Permalinks';
|
||||||
import ContentMessages from '../../../ContentMessages';
|
import ContentMessages from '../../../ContentMessages';
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
import E2EIcon from './E2EIcon';
|
import E2EIcon from './E2EIcon';
|
||||||
|
|
||||||
|
@ -143,6 +141,8 @@ class UploadButton extends React.Component {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
this.onUploadClick = this.onUploadClick.bind(this);
|
this.onUploadClick = this.onUploadClick.bind(this);
|
||||||
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
|
this.onUploadFileInputChange = this.onUploadFileInputChange.bind(this);
|
||||||
|
|
||||||
|
this._uploadInput = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUploadClick(ev) {
|
onUploadClick(ev) {
|
||||||
|
@ -150,7 +150,7 @@ class UploadButton extends React.Component {
|
||||||
dis.dispatch({action: 'require_registration'});
|
dis.dispatch({action: 'require_registration'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.refs.uploadInput.click();
|
this._uploadInput.current.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUploadFileInputChange(ev) {
|
onUploadFileInputChange(ev) {
|
||||||
|
@ -182,7 +182,7 @@ class UploadButton extends React.Component {
|
||||||
onClick={this.onUploadClick}
|
onClick={this.onUploadClick}
|
||||||
title={_t('Upload file')}
|
title={_t('Upload file')}
|
||||||
>
|
>
|
||||||
<input ref="uploadInput" type="file"
|
<input ref={this._uploadInput} type="file"
|
||||||
style={uploadInputStyle}
|
style={uploadInputStyle}
|
||||||
multiple
|
multiple
|
||||||
onChange={this.onUploadFileInputChange}
|
onChange={this.onUploadFileInputChange}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import {_t} from "../../../languageHandler";
|
import {_t} from "../../../languageHandler";
|
||||||
import MatrixClientPeg from "../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../MatrixClientPeg";
|
||||||
import Field from "../elements/Field";
|
import Field from "../elements/Field";
|
||||||
|
@ -48,13 +48,15 @@ export default class ProfileSettings extends React.Component {
|
||||||
avatarFile: null,
|
avatarFile: null,
|
||||||
enableProfileSave: false,
|
enableProfileSave: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this._avatarUpload = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
_uploadAvatar = (e) => {
|
_uploadAvatar = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
this.refs.avatarUpload.click();
|
this._avatarUpload.current.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
_saveProfile = async (e) => {
|
_saveProfile = async (e) => {
|
||||||
|
@ -156,7 +158,7 @@ export default class ProfileSettings extends React.Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
<form onSubmit={this._saveProfile} autoComplete="off" noValidate={true}>
|
||||||
<input type="file" ref="avatarUpload" className="mx_ProfileSettings_avatarUpload"
|
<input type="file" ref={this._avatarUpload} className="mx_ProfileSettings_avatarUpload"
|
||||||
onChange={this._onAvatarChanged} accept="image/*" />
|
onChange={this._onAvatarChanged} accept="image/*" />
|
||||||
<div className="mx_ProfileSettings_profile">
|
<div className="mx_ProfileSettings_profile">
|
||||||
<div className="mx_ProfileSettings_controls">
|
<div className="mx_ProfileSettings_controls">
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {_t} from "../../../../../languageHandler";
|
import {_t} from "../../../../../languageHandler";
|
||||||
import MatrixClientPeg from "../../../../../MatrixClientPeg";
|
import MatrixClientPeg from "../../../../../MatrixClientPeg";
|
||||||
|
@ -44,13 +44,15 @@ export default class NotificationsSettingsTab extends React.Component {
|
||||||
}
|
}
|
||||||
this.setState({currentSound: soundData.name || soundData.url});
|
this.setState({currentSound: soundData.name || soundData.url});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._soundUpload = createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
async _triggerUploader(e) {
|
async _triggerUploader(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
this.refs.soundUpload.click();
|
this._soundUpload.current.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onSoundUploadChanged(e) {
|
async _onSoundUploadChanged(e) {
|
||||||
|
@ -157,7 +159,7 @@ export default class NotificationsSettingsTab extends React.Component {
|
||||||
<div>
|
<div>
|
||||||
<h3>{_t("Set a new custom sound")}</h3>
|
<h3>{_t("Set a new custom sound")}</h3>
|
||||||
<form autoComplete="off" noValidate={true}>
|
<form autoComplete="off" noValidate={true}>
|
||||||
<input ref="soundUpload" className="mx_NotificationSound_soundUpload" type="file" onChange={this._onSoundUploadChanged.bind(this)} accept="audio/*" />
|
<input ref={this._soundUpload} className="mx_NotificationSound_soundUpload" type="file" onChange={this._onSoundUploadChanged.bind(this)} accept="audio/*" />
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{currentUploadedFile}
|
{currentUploadedFile}
|
||||||
|
|
|
@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
import dis from '../../../dispatcher';
|
import dis from '../../../dispatcher';
|
||||||
|
@ -56,6 +56,10 @@ module.exports = createReactClass({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._video = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
this.showCall();
|
this.showCall();
|
||||||
|
@ -128,7 +132,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getVideoView: function() {
|
getVideoView: function() {
|
||||||
return this.refs.video;
|
return this._video.current;
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -147,7 +151,9 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<VideoView ref="video" onClick={this.props.onClick}
|
<VideoView
|
||||||
|
ref={this._video}
|
||||||
|
onClick={this.props.onClick}
|
||||||
onResize={this.props.onResize}
|
onResize={this.props.onResize}
|
||||||
maxHeight={this.props.maxVideoHeight}
|
maxHeight={this.props.maxVideoHeight}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
|
|
||||||
|
@ -30,12 +30,16 @@ module.exports = createReactClass({
|
||||||
onResize: PropTypes.func,
|
onResize: PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount() {
|
||||||
|
this._vid = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.refs.vid.addEventListener('resize', this.onResize);
|
this._vid.current.addEventListener('resize', this.onResize);
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.refs.vid.removeEventListener('resize', this.onResize);
|
this._vid.current.removeEventListener('resize', this.onResize);
|
||||||
},
|
},
|
||||||
|
|
||||||
onResize: function(e) {
|
onResize: function(e) {
|
||||||
|
@ -46,7 +50,7 @@ module.exports = createReactClass({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<video ref="vid" style={{maxHeight: this.props.maxHeight}}>
|
<video ref={this._vid} style={{maxHeight: this.props.maxHeight}}>
|
||||||
</video>
|
</video>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {createRef} from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import createReactClass from 'create-react-class';
|
import createReactClass from 'create-react-class';
|
||||||
|
@ -49,6 +49,11 @@ module.exports = createReactClass({
|
||||||
onResize: PropTypes.func,
|
onResize: PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UNSAFE_componentWillMount: function() {
|
||||||
|
this._local = createRef();
|
||||||
|
this._remote = createRef();
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
},
|
},
|
||||||
|
@ -58,7 +63,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getRemoteVideoElement: function() {
|
getRemoteVideoElement: function() {
|
||||||
return ReactDOM.findDOMNode(this.refs.remote);
|
return ReactDOM.findDOMNode(this._remote.current);
|
||||||
},
|
},
|
||||||
|
|
||||||
getRemoteAudioElement: function() {
|
getRemoteAudioElement: function() {
|
||||||
|
@ -74,7 +79,7 @@ module.exports = createReactClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
getLocalVideoElement: function() {
|
getLocalVideoElement: function() {
|
||||||
return ReactDOM.findDOMNode(this.refs.local);
|
return ReactDOM.findDOMNode(this._local.current);
|
||||||
},
|
},
|
||||||
|
|
||||||
setContainer: function(c) {
|
setContainer: function(c) {
|
||||||
|
@ -125,11 +130,11 @@ module.exports = createReactClass({
|
||||||
return (
|
return (
|
||||||
<div className="mx_VideoView" ref={this.setContainer} onClick={this.props.onClick}>
|
<div className="mx_VideoView" ref={this.setContainer} onClick={this.props.onClick}>
|
||||||
<div className="mx_VideoView_remoteVideoFeed">
|
<div className="mx_VideoView_remoteVideoFeed">
|
||||||
<VideoFeed ref="remote" onResize={this.props.onResize}
|
<VideoFeed ref={this._remote} onResize={this.props.onResize}
|
||||||
maxHeight={maxVideoHeight} />
|
maxHeight={maxVideoHeight} />
|
||||||
</div>
|
</div>
|
||||||
<div className={localVideoFeedClasses}>
|
<div className={localVideoFeedClasses}>
|
||||||
<VideoFeed ref="local" />
|
<VideoFeed ref={this._local} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue