Merge branch 'develop' into t3chguy/mention_user
This commit is contained in:
commit
1d5b4a9d50
26 changed files with 295 additions and 206 deletions
|
@ -116,7 +116,6 @@ const FilePanel = React.createClass({
|
|||
timelineSet={this.state.timelineSet}
|
||||
showUrlPreview = {false}
|
||||
tileShape="file_grid"
|
||||
opacity={this.props.opacity}
|
||||
empty={_t('There are no visible files in this room')}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -482,8 +482,8 @@ export default React.createClass({
|
|||
profileForm: Object.assign({}, this.state.summary.profile),
|
||||
});
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
sideOpacity: 0.3,
|
||||
action: 'panel_disable',
|
||||
sideDisabled: true,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -492,7 +492,7 @@ export default React.createClass({
|
|||
editing: false,
|
||||
profileForm: null,
|
||||
});
|
||||
dis.dispatch({action: 'ui_opacity'});
|
||||
dis.dispatch({action: 'panel_disable'});
|
||||
},
|
||||
|
||||
_onNameChange: function(value) {
|
||||
|
@ -549,7 +549,7 @@ export default React.createClass({
|
|||
editing: false,
|
||||
summary: null,
|
||||
});
|
||||
dis.dispatch({action: 'ui_opacity'});
|
||||
dis.dispatch({action: 'panel_disable'});
|
||||
this._initGroupStore(this.props.groupId);
|
||||
}).catch((e) => {
|
||||
this.setState({
|
||||
|
@ -787,8 +787,8 @@ export default React.createClass({
|
|||
</div>;
|
||||
} else if (group.myMembership === 'join' && this.state.editing) {
|
||||
const leaveButtonTooltip = this.state.isUserPrivileged ?
|
||||
_t("You are a member of this community") :
|
||||
_t("You are an administrator of this community");
|
||||
_t("You are an administrator of this community") :
|
||||
_t("You are a member of this community");
|
||||
const leaveButtonClasses = classnames({
|
||||
"mx_RoomHeader_textButton": true,
|
||||
"mx_GroupView_textButton": true,
|
||||
|
@ -964,13 +964,15 @@ export default React.createClass({
|
|||
</AccessibleButton>,
|
||||
);
|
||||
} else {
|
||||
rightButtons.push(
|
||||
<AccessibleButton className="mx_GroupHeader_button"
|
||||
onClick={this._onEditClick} title={_t("Community Settings")} key="_editButton"
|
||||
>
|
||||
<TintableSvg src="img/icons-settings-room.svg" width="16" height="16" />
|
||||
</AccessibleButton>,
|
||||
);
|
||||
if (summary.user && summary.user.membership === 'join') {
|
||||
rightButtons.push(
|
||||
<AccessibleButton className="mx_GroupHeader_button"
|
||||
onClick={this._onEditClick} title={_t("Community Settings")} key="_editButton"
|
||||
>
|
||||
<TintableSvg src="img/icons-settings-room.svg" width="16" height="16" />
|
||||
</AccessibleButton>,
|
||||
);
|
||||
}
|
||||
if (this.props.collapsedRhs) {
|
||||
rightButtons.push(
|
||||
<AccessibleButton className="mx_GroupHeader_button"
|
||||
|
|
|
@ -240,11 +240,13 @@ export default React.createClass({
|
|||
oobData={this.props.roomOobData}
|
||||
eventPixelOffset={this.props.initialEventPixelOffset}
|
||||
key={this.props.currentRoomId || 'roomview'}
|
||||
opacity={this.props.middleOpacity}
|
||||
disabled={this.props.middleDisabled}
|
||||
collapsedRhs={this.props.collapseRhs}
|
||||
ConferenceHandler={this.props.ConferenceHandler}
|
||||
/>;
|
||||
if (!this.props.collapseRhs) right_panel = <RightPanel roomId={this.props.currentRoomId} opacity={this.props.rightOpacity} />;
|
||||
if (!this.props.collapseRhs) {
|
||||
right_panel = <RightPanel roomId={this.props.currentRoomId} disabled={this.props.rightDisabled} />;
|
||||
}
|
||||
break;
|
||||
|
||||
case PageTypes.UserSettings:
|
||||
|
@ -254,7 +256,7 @@ export default React.createClass({
|
|||
referralBaseUrl={this.props.config.referralBaseUrl}
|
||||
teamToken={this.props.teamToken}
|
||||
/>;
|
||||
if (!this.props.collapseRhs) right_panel = <RightPanel opacity={this.props.rightOpacity} />;
|
||||
if (!this.props.collapseRhs) right_panel = <RightPanel disabled={this.props.rightDisabled} />;
|
||||
break;
|
||||
|
||||
case PageTypes.MyGroups:
|
||||
|
@ -266,7 +268,7 @@ export default React.createClass({
|
|||
onRoomCreated={this.props.onRoomCreated}
|
||||
collapsedRhs={this.props.collapseRhs}
|
||||
/>;
|
||||
if (!this.props.collapseRhs) right_panel = <RightPanel opacity={this.props.rightOpacity} />;
|
||||
if (!this.props.collapseRhs) right_panel = <RightPanel disabled={this.props.rightDisabled} />;
|
||||
break;
|
||||
|
||||
case PageTypes.RoomDirectory:
|
||||
|
@ -294,14 +296,14 @@ export default React.createClass({
|
|||
|
||||
case PageTypes.UserView:
|
||||
page_element = null; // deliberately null for now
|
||||
right_panel = <RightPanel opacity={this.props.rightOpacity} />;
|
||||
right_panel = <RightPanel disabled={this.props.rightDisabled} />;
|
||||
break;
|
||||
case PageTypes.GroupView:
|
||||
page_element = <GroupView
|
||||
groupId={this.props.currentGroupId}
|
||||
collapsedRhs={this.props.collapseRhs}
|
||||
/>;
|
||||
if (!this.props.collapseRhs) right_panel = <RightPanel groupId={this.props.currentGroupId} opacity={this.props.rightOpacity} />;
|
||||
if (!this.props.collapseRhs) right_panel = <RightPanel groupId={this.props.currentGroupId} disabled={this.props.rightDisabled} />;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -334,7 +336,7 @@ export default React.createClass({
|
|||
<LeftPanel
|
||||
selectedRoom={this.props.currentRoomId}
|
||||
collapsed={this.props.collapseLhs || false}
|
||||
opacity={this.props.leftOpacity}
|
||||
disabled={this.props.leftDisabled}
|
||||
/>
|
||||
<main className='mx_MatrixChat_middlePanel'>
|
||||
{ page_element }
|
||||
|
|
|
@ -145,9 +145,9 @@ module.exports = React.createClass({
|
|||
|
||||
collapseLhs: false,
|
||||
collapseRhs: false,
|
||||
leftOpacity: 1.0,
|
||||
middleOpacity: 1.0,
|
||||
rightOpacity: 1.0,
|
||||
leftDisabled: false,
|
||||
middleDisabled: false,
|
||||
rightDisabled: false,
|
||||
|
||||
version: null,
|
||||
newVersion: null,
|
||||
|
@ -534,12 +534,11 @@ module.exports = React.createClass({
|
|||
collapseRhs: false,
|
||||
});
|
||||
break;
|
||||
case 'ui_opacity': {
|
||||
const sideDefault = payload.sideOpacity >= 0.0 ? payload.sideOpacity : 1.0;
|
||||
case 'panel_disable': {
|
||||
this.setState({
|
||||
leftOpacity: payload.leftOpacity >= 0.0 ? payload.leftOpacity : sideDefault,
|
||||
middleOpacity: payload.middleOpacity || 1.0,
|
||||
rightOpacity: payload.rightOpacity >= 0.0 ? payload.rightOpacity : sideDefault,
|
||||
leftDisabled: payload.leftDisabled || payload.sideDisabled || false,
|
||||
middleDisabled: payload.middleDisabled || false,
|
||||
rightDisabled: payload.rightDisabled || payload.sideDisabled || false,
|
||||
});
|
||||
break; }
|
||||
case 'set_theme':
|
||||
|
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
import UserSettingsStore from '../../UserSettingsStore';
|
||||
import shouldHideEvent from '../../shouldHideEvent';
|
||||
import dis from "../../dispatcher";
|
||||
|
@ -78,9 +79,6 @@ module.exports = React.createClass({
|
|||
// callback which is called when more content is needed.
|
||||
onFillRequest: React.PropTypes.func,
|
||||
|
||||
// opacity for dynamic UI fading effects
|
||||
opacity: React.PropTypes.number,
|
||||
|
||||
// className for the panel
|
||||
className: React.PropTypes.string.isRequired,
|
||||
|
||||
|
@ -353,7 +351,7 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
if (!isMembershipChange(collapsedMxEv) ||
|
||||
this._wantsDateSeparator(this.props.events[i], collapsedMxEv.getDate())) {
|
||||
this._wantsDateSeparator(mxEv, collapsedMxEv.getDate())) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -376,9 +374,7 @@ module.exports = React.createClass({
|
|||
// of MemberEventListSummary, render each member event as if the previous
|
||||
// one was itself. This way, the timestamp of the previous event === the
|
||||
// timestamp of the current event, and no DateSeperator is inserted.
|
||||
const ret = this._getTilesForEvent(e, e, e === lastShownEvent);
|
||||
prevEvent = e;
|
||||
return ret;
|
||||
return this._getTilesForEvent(e, e, e === lastShownEvent);
|
||||
}).reduce((a, b) => a.concat(b));
|
||||
|
||||
if (eventTiles.length === 0) {
|
||||
|
@ -397,6 +393,7 @@ module.exports = React.createClass({
|
|||
ret.push(this._getReadMarkerTile(visible));
|
||||
}
|
||||
|
||||
prevEvent = mxEv;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -649,12 +646,13 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
const style = this.props.hidden ? { display: 'none' } : {};
|
||||
style.opacity = this.props.opacity;
|
||||
|
||||
let className = this.props.className + " mx_fadable";
|
||||
if (this.props.alwaysShowTimestamps) {
|
||||
className += " mx_MessagePanel_alwaysShowTimestamps";
|
||||
}
|
||||
const className = classNames(
|
||||
this.props.className,
|
||||
{
|
||||
"mx_MessagePanel_alwaysShowTimestamps": this.props.alwaysShowTimestamps,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<ScrollPanel ref="scrollPanel" className={className}
|
||||
|
|
|
@ -45,7 +45,6 @@ const NotificationPanel = React.createClass({
|
|||
manageReadMarkers={false}
|
||||
timelineSet={timelineSet}
|
||||
showUrlPreview = {false}
|
||||
opacity={this.props.opacity}
|
||||
tileShape="notif"
|
||||
empty={_t('You have no visible notifications')}
|
||||
/>
|
||||
|
|
|
@ -1697,7 +1697,7 @@ module.exports = React.createClass({
|
|||
onResize={this.onChildResize}
|
||||
uploadFile={this.uploadFile}
|
||||
callState={this.state.callState}
|
||||
opacity={this.props.opacity}
|
||||
disabled={this.props.disabled}
|
||||
showApps={this.state.showApps}
|
||||
/>;
|
||||
}
|
||||
|
@ -1758,7 +1758,6 @@ module.exports = React.createClass({
|
|||
className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel"
|
||||
onFillRequest={this.onSearchResultsFillRequest}
|
||||
onResize={this.onSearchResultsResize}
|
||||
style={{ opacity: this.props.opacity }}
|
||||
>
|
||||
<li className={scrollheader_classes}></li>
|
||||
{ this.getSearchResultTiles() }
|
||||
|
@ -1789,7 +1788,6 @@ module.exports = React.createClass({
|
|||
onScroll={this.onMessageListScroll}
|
||||
onReadMarkerUpdated={this._updateTopUnreadMessagesBar}
|
||||
showUrlPreview = {this.state.showUrlPreview}
|
||||
opacity={this.props.opacity}
|
||||
className="mx_RoomView_messagePanel"
|
||||
/>);
|
||||
|
||||
|
@ -1797,7 +1795,7 @@ module.exports = React.createClass({
|
|||
if (this.state.showTopUnreadMessagesBar) {
|
||||
const TopUnreadMessagesBar = sdk.getComponent('rooms.TopUnreadMessagesBar');
|
||||
topUnreadMessagesBar = (
|
||||
<div className="mx_RoomView_topUnreadMessagesBar mx_fadable" style={{ opacity: this.props.opacity }}>
|
||||
<div className="mx_RoomView_topUnreadMessagesBar">
|
||||
<TopUnreadMessagesBar
|
||||
onScrollUpClick={this.jumpToReadMarker}
|
||||
onCloseClick={this.forgetReadMarker}
|
||||
|
@ -1805,10 +1803,19 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
let statusBarAreaClass = "mx_RoomView_statusArea mx_fadable";
|
||||
if (isStatusAreaExpanded) {
|
||||
statusBarAreaClass += " mx_RoomView_statusArea_expanded";
|
||||
}
|
||||
const statusBarAreaClass = classNames(
|
||||
"mx_RoomView_statusArea",
|
||||
{
|
||||
"mx_RoomView_statusArea_expanded": isStatusAreaExpanded,
|
||||
},
|
||||
);
|
||||
|
||||
const fadableSectionClasses = classNames(
|
||||
"mx_RoomView_body", "mx_fadable",
|
||||
{
|
||||
"mx_fadable_faded": this.props.disabled,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={"mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "")} ref="roomView">
|
||||
|
@ -1827,16 +1834,18 @@ module.exports = React.createClass({
|
|||
onLeaveClick={(myMember && myMember.membership === "join") ? this.onLeaveClick : null}
|
||||
/>
|
||||
{ auxPanel }
|
||||
{ topUnreadMessagesBar }
|
||||
{ messagePanel }
|
||||
{ searchResultsPanel }
|
||||
<div className={statusBarAreaClass} style={{opacity: this.props.opacity}}>
|
||||
<div className="mx_RoomView_statusAreaBox">
|
||||
<div className="mx_RoomView_statusAreaBox_line"></div>
|
||||
{ statusBar }
|
||||
<div className={fadableSectionClasses}>
|
||||
{ topUnreadMessagesBar }
|
||||
{ messagePanel }
|
||||
{ searchResultsPanel }
|
||||
<div className={statusBarAreaClass}>
|
||||
<div className="mx_RoomView_statusAreaBox">
|
||||
<div className="mx_RoomView_statusAreaBox_line"></div>
|
||||
{ statusBar }
|
||||
</div>
|
||||
</div>
|
||||
{ messageComposer }
|
||||
</div>
|
||||
{ messageComposer }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -89,9 +89,6 @@ var TimelinePanel = React.createClass({
|
|||
// callback which is called when the read-up-to mark is updated.
|
||||
onReadMarkerUpdated: React.PropTypes.func,
|
||||
|
||||
// opacity for dynamic UI fading effects
|
||||
opacity: React.PropTypes.number,
|
||||
|
||||
// maximum number of events to show in a timeline
|
||||
timelineCap: React.PropTypes.number,
|
||||
|
||||
|
@ -1157,7 +1154,6 @@ var TimelinePanel = React.createClass({
|
|||
onScroll={this.onMessageListScroll}
|
||||
onFillRequest={this.onMessageListFillRequest}
|
||||
onUnfillRequest={this.onMessageListUnfillRequest}
|
||||
opacity={this.props.opacity}
|
||||
isTwelveHour={this.state.isTwelveHour}
|
||||
alwaysShowTimestamps={this.state.alwaysShowTimestamps}
|
||||
className={this.props.className}
|
||||
|
|
|
@ -118,6 +118,10 @@ const SETTINGS_LABELS = [
|
|||
id: 'TextualBody.disableBigEmoji',
|
||||
label: _td('Disable big emoji in chat'),
|
||||
},
|
||||
{
|
||||
id: 'VideoView.flipVideoHorizontally',
|
||||
label: _td('Mirror local video feed'),
|
||||
},
|
||||
/*
|
||||
{
|
||||
id: 'useFixedWidthFont',
|
||||
|
@ -271,9 +275,9 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().on("RoomMember.membership", this._onInviteStateChange);
|
||||
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
sideOpacity: 0.3,
|
||||
middleOpacity: 0.3,
|
||||
action: 'panel_disable',
|
||||
sideDisabled: true,
|
||||
middleDisabled: true,
|
||||
});
|
||||
this._refreshFromServer();
|
||||
|
||||
|
@ -311,9 +315,9 @@ module.exports = React.createClass({
|
|||
componentWillUnmount: function() {
|
||||
this._unmounted = true;
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
sideOpacity: 1.0,
|
||||
middleOpacity: 1.0,
|
||||
action: 'panel_disable',
|
||||
sideDisabled: false,
|
||||
middleDisabled: false,
|
||||
});
|
||||
dis.unregister(this.dispatcherRef);
|
||||
const cli = MatrixClientPeg.get();
|
||||
|
@ -1328,8 +1332,11 @@ module.exports = React.createClass({
|
|||
|
||||
<div className="mx_UserSettings_avatarPicker">
|
||||
<div className="mx_UserSettings_avatarPicker_remove" onClick={this.onAvatarRemoveClick}>
|
||||
<img src="img/cancel.svg" width="15" height="15"
|
||||
alt={_t("Remove avatar")} title={_t("Remove avatar")} />
|
||||
<img src="img/cancel.svg"
|
||||
width="15" height="15"
|
||||
className="mx_filterFlipColor"
|
||||
alt={_t("Remove avatar")}
|
||||
title={_t("Remove avatar")} />
|
||||
</div>
|
||||
<div onClick={this.onAvatarPickerClick} className="mx_UserSettings_avatarPicker_imgContainer">
|
||||
<ChangeAvatar ref="changeAvatar" initialAvatarUrl={avatarUrl}
|
||||
|
|
|
@ -272,20 +272,27 @@ module.exports = React.createClass({
|
|||
const topicEvent = room.currentState.getStateEvents('m.room.topic', '');
|
||||
const name = nameEvent ? nameEvent.getContent().name : '';
|
||||
const canonicalAlias = room.getCanonicalAlias();
|
||||
const aliasEvents = room.currentState.getStateEvents('m.room.aliases');
|
||||
const aliases = aliasEvents.map((ev) => ev.getContent().aliases).reduce((a, b) => {
|
||||
return a.concat(b);
|
||||
}, []);
|
||||
const topic = topicEvent ? topicEvent.getContent().topic : '';
|
||||
|
||||
const nameMatch = (name || '').toLowerCase().includes(lowerCaseQuery);
|
||||
const aliasMatch = (canonicalAlias || '').toLowerCase().includes(lowerCaseQuery);
|
||||
const aliasMatch = aliases.some((alias) =>
|
||||
(alias || '').toLowerCase().includes(lowerCaseQuery),
|
||||
);
|
||||
const topicMatch = (topic || '').toLowerCase().includes(lowerCaseQuery);
|
||||
if (!(nameMatch || topicMatch || aliasMatch)) {
|
||||
return;
|
||||
}
|
||||
const avatarEvent = room.currentState.getStateEvents('m.room.avatar', '');
|
||||
const avatarUrl = avatarEvent ? avatarEvent.getContent().url : undefined;
|
||||
|
||||
results.push({
|
||||
room_id: room.roomId,
|
||||
avatar_url: avatarUrl,
|
||||
name: name || canonicalAlias,
|
||||
name: name || canonicalAlias || aliases[0] || _t('Unnamed Room'),
|
||||
});
|
||||
});
|
||||
this._processResults(results, query);
|
||||
|
|
|
@ -172,18 +172,29 @@ export default React.createClass({
|
|||
*/
|
||||
_onDeleteClick: function() {
|
||||
if (this._canUserModify()) {
|
||||
console.log("Delete widget %s", this.props.id);
|
||||
this.setState({deleting: true});
|
||||
MatrixClientPeg.get().sendStateEvent(
|
||||
this.props.room.roomId,
|
||||
'im.vector.modular.widgets',
|
||||
{}, // empty content
|
||||
this.props.id,
|
||||
).then(() => {
|
||||
console.log('Deleted widget');
|
||||
}, (e) => {
|
||||
console.error('Failed to delete widget', e);
|
||||
this.setState({deleting: false});
|
||||
// Show delete confirmation dialog
|
||||
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
|
||||
Modal.createTrackedDialog('Delete Widget', '', QuestionDialog, {
|
||||
title: _t("Delete Widget"),
|
||||
description: _t(
|
||||
"Deleting a widget removes it for all users in this room." +
|
||||
" Are you sure you want to delete this widget?"),
|
||||
button: _t("Delete widget"),
|
||||
onFinished: (confirmed) => {
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
this.setState({deleting: true});
|
||||
MatrixClientPeg.get().sendStateEvent(
|
||||
this.props.room.roomId,
|
||||
'im.vector.modular.widgets',
|
||||
{}, // empty content
|
||||
this.props.id,
|
||||
).catch((e) => {
|
||||
console.error('Failed to delete widget', e);
|
||||
this.setState({deleting: false});
|
||||
});
|
||||
},
|
||||
});
|
||||
} else {
|
||||
console.log("Revoke widget permissions - %s", this.props.id);
|
||||
|
@ -305,7 +316,7 @@ export default React.createClass({
|
|||
let deleteIcon = 'img/cancel.svg';
|
||||
let deleteClasses = 'mx_filterFlipColor mx_AppTileMenuBarWidget';
|
||||
if(this._canUserModify()) {
|
||||
deleteIcon = 'img/cancel-red.svg';
|
||||
deleteIcon = 'img/icon-delete-pink.svg';
|
||||
deleteClasses += ' mx_AppTileMenuBarWidgetDelete';
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,9 @@ module.exports = React.createClass({
|
|||
onNewItemChanged: PropTypes.func,
|
||||
onItemAdded: PropTypes.func,
|
||||
onItemEdited: PropTypes.func,
|
||||
onItemRemoved: PropTypes. func,
|
||||
onItemRemoved: PropTypes.func,
|
||||
|
||||
canEdit: PropTypes.bool,
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
|
@ -136,14 +138,16 @@ module.exports = React.createClass({
|
|||
{ label }
|
||||
</div>
|
||||
{ editableItems }
|
||||
<EditableItem
|
||||
key={-1}
|
||||
initialValue={this.props.newItem}
|
||||
onAdd={this.onItemAdded}
|
||||
onChange={this.onNewItemChanged}
|
||||
addOnChange={true}
|
||||
placeholder={this.props.placeholder}
|
||||
/>
|
||||
{ this.props.canEdit ?
|
||||
<EditableItem
|
||||
key={-1}
|
||||
initialValue={this.props.newItem}
|
||||
onAdd={this.onItemAdded}
|
||||
onChange={this.onNewItemChanged}
|
||||
addOnChange={true}
|
||||
placeholder={this.props.placeholder}
|
||||
/> : <div />
|
||||
}
|
||||
</div>);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -173,7 +173,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
<div className="mx_MemberInfo">
|
||||
<GeminiScrollbar autoshow={true}>
|
||||
<AccessibleButton className="mx_MemberInfo_cancel"onClick={this._onCancel}>
|
||||
<img src="img/cancel.svg" width="18" height="18" />
|
||||
<img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" />
|
||||
</AccessibleButton>
|
||||
<div className="mx_MemberInfo_avatar">
|
||||
{ avatar }
|
||||
|
|
|
@ -120,8 +120,11 @@ const GroupRoomTile = React.createClass({
|
|||
<div className="mx_GroupRoomTile_name">
|
||||
{ this.state.name }
|
||||
</div>
|
||||
<AccessibleButton className="mx_GroupRoomTile_delete" onClick={this.onDeleteClick}>
|
||||
<img src="img/cancel-small.svg" />
|
||||
<AccessibleButton className="mx_GroupRoomTile_delete"
|
||||
onClick={this.onDeleteClick}
|
||||
tooltip={_t("Remove this room from the community")}
|
||||
>
|
||||
<img src="img/cancel.svg" width="15" height="15" className="mx_filterFlipColor" />
|
||||
</AccessibleButton>
|
||||
</AccessibleButton>
|
||||
);
|
||||
|
|
|
@ -25,7 +25,10 @@ module.exports = React.createClass({
|
|||
render: function() {
|
||||
let tooltip = _t("Removed or unknown message type");
|
||||
if (this.props.mxEvent.isRedacted()) {
|
||||
tooltip = _t("Message removed by %(userId)s", {userId: this.props.mxEvent.getSender()});
|
||||
const redactedBecauseUserId = this.props.mxEvent.getUnsigned().redacted_because.sender;
|
||||
tooltip = redactedBecauseUserId ?
|
||||
_t("Message removed by %(userId)s", { userId: redactedBecauseUserId }) :
|
||||
_t("Message removed");
|
||||
}
|
||||
|
||||
const text = this.props.mxEvent.getContent().body;
|
||||
|
|
|
@ -262,6 +262,7 @@ module.exports = React.createClass({
|
|||
items={this.state.domainToAliases[localDomain] || []}
|
||||
newItem={this.state.newAlias}
|
||||
onNewItemChanged={this.onNewAliasChanged}
|
||||
canEdit={this.props.canSetAliases}
|
||||
onItemAdded={this.onLocalAliasAdded}
|
||||
onItemEdited={this.onLocalAliasChanged}
|
||||
onItemRemoved={this.onLocalAliasDeleted}
|
||||
|
|
|
@ -27,7 +27,7 @@ module.exports = React.createClass({
|
|||
|
||||
propTypes: {
|
||||
roomId: React.PropTypes.string.isRequired,
|
||||
canSetRelatedRooms: React.PropTypes.bool.isRequired,
|
||||
canSetRelatedGroups: React.PropTypes.bool.isRequired,
|
||||
relatedGroupsEvent: React.PropTypes.instanceOf(MatrixEvent),
|
||||
},
|
||||
|
||||
|
@ -37,7 +37,7 @@ module.exports = React.createClass({
|
|||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
canSetRelatedRooms: false,
|
||||
canSetRelatedGroups: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -110,6 +110,7 @@ module.exports = React.createClass({
|
|||
items={this.state.newGroupsList}
|
||||
className={"mx_RelatedGroupSettings"}
|
||||
newItem={this.state.newGroupId}
|
||||
canEdit={this.props.canSetRelatedGroups}
|
||||
onNewItemChanged={this.onNewGroupChanged}
|
||||
onItemAdded={this.onGroupAdded}
|
||||
onItemEdited={this.onGroupEdited}
|
||||
|
|
|
@ -30,10 +30,9 @@ module.exports = React.createClass({
|
|||
|
||||
componentWillMount: function() {
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
leftOpacity: 1.0,
|
||||
rightOpacity: 0.3,
|
||||
middleOpacity: 0.5,
|
||||
action: 'panel_disable',
|
||||
rightDisabled: true,
|
||||
middleDisabled: true,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -43,9 +42,9 @@ module.exports = React.createClass({
|
|||
|
||||
componentWillUnmount: function() {
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
sideOpacity: 1.0,
|
||||
middleOpacity: 1.0,
|
||||
action: 'panel_disable',
|
||||
sideDisabled: false,
|
||||
middleDisabled: false,
|
||||
});
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
},
|
||||
|
|
|
@ -133,8 +133,9 @@ module.exports = React.createClass({
|
|||
{ p["og:description"] }
|
||||
</div>
|
||||
</div>
|
||||
<img className="mx_LinkPreviewWidget_cancel" src="img/cancel.svg" width="18" height="18"
|
||||
onClick={this.props.onCancelClick} />
|
||||
<img className="mx_LinkPreviewWidget_cancel mx_filterFlipColor"
|
||||
src="img/cancel.svg" width="18" height="18"
|
||||
onClick={this.props.onCancelClick} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -39,6 +39,7 @@ import { findReadReceiptFromUserId } from '../../../utils/Receipt';
|
|||
import withMatrixClient from '../../../wrappers/withMatrixClient';
|
||||
import AccessibleButton from '../elements/AccessibleButton';
|
||||
import GeminiScrollbar from 'react-gemini-scrollbar';
|
||||
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||
|
||||
|
||||
module.exports = withMatrixClient(React.createClass({
|
||||
|
@ -81,6 +82,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
cli.on("Room.receipt", this.onRoomReceipt);
|
||||
cli.on("RoomState.events", this.onRoomStateEvents);
|
||||
cli.on("RoomMember.name", this.onRoomMemberName);
|
||||
cli.on("RoomMember.membership", this.onRoomMemberMembership);
|
||||
cli.on("accountData", this.onAccountData);
|
||||
|
||||
this._checkIgnoreState();
|
||||
|
@ -91,7 +93,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
if (this.props.member.userId != newProps.member.userId) {
|
||||
if (this.props.member.userId !== newProps.member.userId) {
|
||||
this._updateStateForNewMember(newProps.member);
|
||||
}
|
||||
},
|
||||
|
@ -107,6 +109,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
client.removeListener("Room.receipt", this.onRoomReceipt);
|
||||
client.removeListener("RoomState.events", this.onRoomStateEvents);
|
||||
client.removeListener("RoomMember.name", this.onRoomMemberName);
|
||||
client.removeListener("RoomMember.membership", this.onRoomMemberMembership);
|
||||
client.removeListener("accountData", this.onAccountData);
|
||||
}
|
||||
if (this._cancelDeviceList) {
|
||||
|
@ -122,12 +125,12 @@ module.exports = withMatrixClient(React.createClass({
|
|||
_disambiguateDevices: function(devices) {
|
||||
const names = Object.create(null);
|
||||
for (let i = 0; i < devices.length; i++) {
|
||||
var name = devices[i].getDisplayName();
|
||||
const name = devices[i].getDisplayName();
|
||||
const indexList = names[name] || [];
|
||||
indexList.push(i);
|
||||
names[name] = indexList;
|
||||
}
|
||||
for (name in names) {
|
||||
for (const name in names) {
|
||||
if (names[name].length > 1) {
|
||||
names[name].forEach((j)=>{
|
||||
devices[j].ambiguous = true;
|
||||
|
@ -141,7 +144,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
return;
|
||||
}
|
||||
|
||||
if (userId == this.props.member.userId) {
|
||||
if (userId === this.props.member.userId) {
|
||||
// no need to re-download the whole thing; just update our copy of
|
||||
// the list.
|
||||
|
||||
|
@ -186,8 +189,12 @@ module.exports = withMatrixClient(React.createClass({
|
|||
this.forceUpdate();
|
||||
},
|
||||
|
||||
onRoomMemberMembership: function(ev, member) {
|
||||
if (this.props.member.userId === member.userId) this.forceUpdate();
|
||||
},
|
||||
|
||||
onAccountData: function(ev) {
|
||||
if (ev.getType() == 'm.direct') {
|
||||
if (ev.getType() === 'm.direct') {
|
||||
this.forceUpdate();
|
||||
}
|
||||
},
|
||||
|
@ -242,7 +249,9 @@ module.exports = withMatrixClient(React.createClass({
|
|||
ignoredUsers.push(this.props.member.userId);
|
||||
}
|
||||
|
||||
this.props.matrixClient.setIgnoredUsers(ignoredUsers).then(() => this.setState({isIgnoring: !this.state.isIgnoring}));
|
||||
this.props.matrixClient.setIgnoredUsers(ignoredUsers).then(() => {
|
||||
return this.setState({isIgnoring: !this.state.isIgnoring});
|
||||
});
|
||||
},
|
||||
|
||||
onKick: function() {
|
||||
|
@ -252,7 +261,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
Modal.createTrackedDialog('Confirm User Action Dialog', 'onKick', ConfirmUserActionDialog, {
|
||||
member: this.props.member,
|
||||
action: kickLabel,
|
||||
askReason: membership == "join",
|
||||
askReason: membership === "join",
|
||||
danger: true,
|
||||
onFinished: (proceed, reason) => {
|
||||
if (!proceed) return;
|
||||
|
@ -284,15 +293,15 @@ module.exports = withMatrixClient(React.createClass({
|
|||
const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
|
||||
Modal.createTrackedDialog('Confirm User Action Dialog', 'onBanOrUnban', ConfirmUserActionDialog, {
|
||||
member: this.props.member,
|
||||
action: this.props.member.membership == 'ban' ? _t("Unban") : _t("Ban"),
|
||||
askReason: this.props.member.membership != 'ban',
|
||||
danger: this.props.member.membership != 'ban',
|
||||
action: this.props.member.membership === 'ban' ? _t("Unban") : _t("Ban"),
|
||||
askReason: this.props.member.membership !== 'ban',
|
||||
danger: this.props.member.membership !== 'ban',
|
||||
onFinished: (proceed, reason) => {
|
||||
if (!proceed) return;
|
||||
|
||||
this.setState({ updating: this.state.updating + 1 });
|
||||
let promise;
|
||||
if (this.props.member.membership == 'ban') {
|
||||
if (this.props.member.membership === 'ban') {
|
||||
promise = this.props.matrixClient.unban(
|
||||
this.props.member.roomId, this.props.member.userId,
|
||||
);
|
||||
|
@ -327,15 +336,11 @@ module.exports = withMatrixClient(React.createClass({
|
|||
const roomId = this.props.member.roomId;
|
||||
const target = this.props.member.userId;
|
||||
const room = this.props.matrixClient.getRoom(roomId);
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
const powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", "",
|
||||
);
|
||||
if (!powerLevelEvent) {
|
||||
return;
|
||||
}
|
||||
if (!room) return;
|
||||
|
||||
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
|
||||
if (!powerLevelEvent) return;
|
||||
|
||||
const isMuted = this.state.muted;
|
||||
const powerLevels = powerLevelEvent.getContent();
|
||||
const levelToSend = (
|
||||
|
@ -350,7 +355,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
}
|
||||
level = parseInt(level);
|
||||
|
||||
if (level !== NaN) {
|
||||
if (!isNaN(level)) {
|
||||
this.setState({ updating: this.state.updating + 1 });
|
||||
this.props.matrixClient.setPowerLevel(roomId, target, level, powerLevelEvent).then(
|
||||
function() {
|
||||
|
@ -375,19 +380,14 @@ module.exports = withMatrixClient(React.createClass({
|
|||
const roomId = this.props.member.roomId;
|
||||
const target = this.props.member.userId;
|
||||
const room = this.props.matrixClient.getRoom(roomId);
|
||||
if (!room) {
|
||||
return;
|
||||
}
|
||||
const powerLevelEvent = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", "",
|
||||
);
|
||||
if (!powerLevelEvent) {
|
||||
return;
|
||||
}
|
||||
if (!room) return;
|
||||
|
||||
const powerLevelEvent = room.currentState.getStateEvents("m.room.power_levels", "");
|
||||
if (!powerLevelEvent) return;
|
||||
|
||||
const me = room.getMember(this.props.matrixClient.credentials.userId);
|
||||
if (!me) {
|
||||
return;
|
||||
}
|
||||
if (!me) return;
|
||||
|
||||
const defaultLevel = powerLevelEvent.getContent().users_default;
|
||||
let modLevel = me.powerLevel - 1;
|
||||
if (modLevel > 50 && defaultLevel < 50) modLevel = 50; // try to stick with the vector level defaults
|
||||
|
@ -400,7 +400,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
// get out of sync if we force setState here!
|
||||
console.log("Mod toggle success");
|
||||
}, function(err) {
|
||||
if (err.errcode == 'M_GUEST_ACCESS_FORBIDDEN') {
|
||||
if (err.errcode === 'M_GUEST_ACCESS_FORBIDDEN') {
|
||||
dis.dispatch({action: 'view_set_mxid'});
|
||||
} else {
|
||||
console.error("Toggle moderator error:" + err);
|
||||
|
@ -436,7 +436,6 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
onPowerChange: function(powerLevel) {
|
||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||
const roomId = this.props.member.roomId;
|
||||
const target = this.props.member.userId;
|
||||
const room = this.props.matrixClient.getRoom(roomId);
|
||||
|
@ -497,19 +496,14 @@ module.exports = withMatrixClient(React.createClass({
|
|||
modifyLevel: false,
|
||||
};
|
||||
const room = this.props.matrixClient.getRoom(member.roomId);
|
||||
if (!room) {
|
||||
return defaultPerms;
|
||||
}
|
||||
const powerLevels = room.currentState.getStateEvents(
|
||||
"m.room.power_levels", "",
|
||||
);
|
||||
if (!powerLevels) {
|
||||
return defaultPerms;
|
||||
}
|
||||
if (!room) return defaultPerms;
|
||||
|
||||
const powerLevels = room.currentState.getStateEvents("m.room.power_levels", "");
|
||||
if (!powerLevels) return defaultPerms;
|
||||
|
||||
const me = room.getMember(this.props.matrixClient.credentials.userId);
|
||||
if (!me) {
|
||||
return defaultPerms;
|
||||
}
|
||||
if (!me) return defaultPerms;
|
||||
|
||||
const them = member;
|
||||
return {
|
||||
can: this._calculateCanPermissions(
|
||||
|
@ -545,14 +539,13 @@ module.exports = withMatrixClient(React.createClass({
|
|||
can.ban = me.powerLevel >= powerLevels.ban;
|
||||
can.mute = me.powerLevel >= editPowerLevel;
|
||||
can.toggleMod = me.powerLevel > them.powerLevel && them.powerLevel >= levelToSend;
|
||||
can.modifyLevel = me.powerLevel > them.powerLevel;
|
||||
can.modifyLevel = me.powerLevel > them.powerLevel && me.powerLevel >= editPowerLevel;
|
||||
return can;
|
||||
},
|
||||
|
||||
_isMuted: function(member, powerLevelContent) {
|
||||
if (!powerLevelContent || !member) {
|
||||
return false;
|
||||
}
|
||||
if (!powerLevelContent || !member) return false;
|
||||
|
||||
const levelToSend = (
|
||||
(powerLevelContent.events ? powerLevelContent.events["m.room.message"] : null) ||
|
||||
powerLevelContent.events_default
|
||||
|
@ -568,14 +561,15 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
onMemberAvatarClick: function() {
|
||||
const avatarUrl = this.props.member.user ? this.props.member.user.avatarUrl : this.props.member.events.member.getContent().avatar_url;
|
||||
const member = this.props.member;
|
||||
const avatarUrl = member.user ? member.user.avatarUrl : member.events.member.getContent().avatar_url;
|
||||
if(!avatarUrl) return;
|
||||
|
||||
const httpUrl = this.props.matrixClient.mxcUrlToHttp(avatarUrl);
|
||||
const ImageView = sdk.getComponent("elements.ImageView");
|
||||
const params = {
|
||||
src: httpUrl,
|
||||
name: this.props.member.name,
|
||||
name: member.name,
|
||||
};
|
||||
|
||||
Modal.createDialog(ImageView, params, "mx_Dialog_lightbox");
|
||||
|
@ -589,9 +583,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
},
|
||||
|
||||
_renderDevices: function() {
|
||||
if (!this._enableDevices) {
|
||||
return null;
|
||||
}
|
||||
if (!this._enableDevices) return null;
|
||||
|
||||
const devices = this.state.devices;
|
||||
const MemberDeviceInfo = sdk.getComponent('rooms.MemberDeviceInfo');
|
||||
|
@ -630,6 +622,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
|
||||
let ignoreButton = null;
|
||||
let insertPillButton = null;
|
||||
let inviteUserButton = null;
|
||||
let readReceiptButton = null;
|
||||
|
||||
// Only allow the user to ignore the user if its not ourselves
|
||||
|
@ -673,9 +666,30 @@ module.exports = withMatrixClient(React.createClass({
|
|||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
if (!member || !member.membership || member.membership === 'leave') {
|
||||
const roomId = member && member.roomId ? member.roomId : RoomViewStore.getRoomId();
|
||||
const onInviteUserButton = async () => {
|
||||
try {
|
||||
await cli.invite(roomId, member.userId);
|
||||
} catch (err) {
|
||||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog');
|
||||
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
|
||||
title: _t('Failed to invite'),
|
||||
description: ((err && err.message) ? err.message : "Operation failed"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
inviteUserButton = (
|
||||
<AccessibleButton onClick={onInviteUserButton} className="mx_MemberInfo_field">
|
||||
{ _t('Invite') }
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignoreButton && !readReceiptButton && !insertPillButton) return null;
|
||||
if (!ignoreButton && !readReceiptButton && !insertPillButton && !inviteUserButton) return null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -684,13 +698,20 @@ module.exports = withMatrixClient(React.createClass({
|
|||
{ readReceiptButton }
|
||||
{ insertPillButton }
|
||||
{ ignoreButton }
|
||||
{ inviteUserButton }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
let startChat, kickButton, banButton, muteButton, giveModButton, spinner;
|
||||
let startChat;
|
||||
let kickButton;
|
||||
let banButton;
|
||||
let muteButton;
|
||||
let giveModButton;
|
||||
let spinner;
|
||||
|
||||
if (this.props.member.userId !== this.props.matrixClient.credentials.userId) {
|
||||
const dmRoomMap = new DMRoomMap(this.props.matrixClient);
|
||||
const dmRooms = dmRoomMap.getDMRoomsForUserId(this.props.member.userId);
|
||||
|
@ -704,7 +725,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
const me = room.getMember(this.props.matrixClient.credentials.userId);
|
||||
const highlight = (
|
||||
room.getUnreadNotificationCount('highlight') > 0 ||
|
||||
me.membership == "invite"
|
||||
me.membership === "invite"
|
||||
);
|
||||
tiles.push(
|
||||
<RoomTile key={room.roomId} room={room}
|
||||
|
@ -712,7 +733,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
selected={false}
|
||||
unread={Unread.doesRoomHaveUnreadMessages(room)}
|
||||
highlight={highlight}
|
||||
isInvite={me.membership == "invite"}
|
||||
isInvite={me.membership === "invite"}
|
||||
onClick={this.onRoomTileClick}
|
||||
/>,
|
||||
);
|
||||
|
@ -757,7 +778,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
}
|
||||
if (this.state.can.ban) {
|
||||
let label = _t("Ban");
|
||||
if (this.props.member.membership == 'ban') {
|
||||
if (this.props.member.membership === 'ban') {
|
||||
label = _t("Unban");
|
||||
}
|
||||
banButton = (
|
||||
|
@ -783,9 +804,6 @@ module.exports = withMatrixClient(React.createClass({
|
|||
</AccessibleButton>;
|
||||
}
|
||||
|
||||
// TODO: we should have an invite button if this MemberInfo is showing a user who isn't actually in the current room yet
|
||||
// e.g. clicking on a linkified userid in a room
|
||||
|
||||
let adminTools;
|
||||
if (kickButton || banButton || muteButton || giveModButton) {
|
||||
adminTools =
|
||||
|
@ -803,16 +821,39 @@ module.exports = withMatrixClient(React.createClass({
|
|||
|
||||
const memberName = this.props.member.name;
|
||||
|
||||
let presenceState;
|
||||
let presenceLastActiveAgo;
|
||||
let presenceCurrentlyActive;
|
||||
|
||||
if (this.props.member.user) {
|
||||
var presenceState = this.props.member.user.presence;
|
||||
var presenceLastActiveAgo = this.props.member.user.lastActiveAgo;
|
||||
const presenceLastTs = this.props.member.user.lastPresenceTs;
|
||||
var presenceCurrentlyActive = this.props.member.user.currentlyActive;
|
||||
presenceState = this.props.member.user.presence;
|
||||
presenceLastActiveAgo = this.props.member.user.lastActiveAgo;
|
||||
presenceCurrentlyActive = this.props.member.user.currentlyActive;
|
||||
}
|
||||
|
||||
let roomMemberDetails = null;
|
||||
|
||||
if (this.props.member.roomId) { // is in room
|
||||
const PowerSelector = sdk.getComponent('elements.PowerSelector');
|
||||
const PresenceLabel = sdk.getComponent('rooms.PresenceLabel');
|
||||
roomMemberDetails = <div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
{ _t("Level:") } <b>
|
||||
<PowerSelector controlled={true}
|
||||
value={parseInt(this.props.member.powerLevel)}
|
||||
disabled={!this.state.can.modifyLevel}
|
||||
onChange={this.onPowerChange} />
|
||||
</b>
|
||||
</div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
<PresenceLabel activeAgo={presenceLastActiveAgo}
|
||||
currentlyActive={presenceCurrentlyActive}
|
||||
presenceState={presenceState} />
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
const MemberAvatar = sdk.getComponent('avatars.MemberAvatar');
|
||||
const PowerSelector = sdk.getComponent('elements.PowerSelector');
|
||||
const PresenceLabel = sdk.getComponent('rooms.PresenceLabel');
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
return (
|
||||
<div className="mx_MemberInfo">
|
||||
|
@ -828,14 +869,7 @@ module.exports = withMatrixClient(React.createClass({
|
|||
<div className="mx_MemberInfo_profileField">
|
||||
{ this.props.member.userId }
|
||||
</div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
{ _t("Level:") } <b><PowerSelector controlled={true} value={parseInt(this.props.member.powerLevel)} disabled={!this.state.can.modifyLevel} onChange={this.onPowerChange} /></b>
|
||||
</div>
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
<PresenceLabel activeAgo={presenceLastActiveAgo}
|
||||
currentlyActive={presenceCurrentlyActive}
|
||||
presenceState={presenceState} />
|
||||
</div>
|
||||
{ roomMemberDetails }
|
||||
</div>
|
||||
|
||||
{ this._renderUserOptions() }
|
||||
|
|
|
@ -371,7 +371,7 @@ export default class MessageComposer extends React.Component {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className="mx_MessageComposer mx_fadable" style={{ opacity: this.props.opacity }}>
|
||||
<div className="mx_MessageComposer">
|
||||
<div className="mx_MessageComposer_wrapper">
|
||||
<div className="mx_MessageComposer_row">
|
||||
{ controls }
|
||||
|
@ -410,9 +410,6 @@ MessageComposer.propTypes = {
|
|||
// callback when a file to upload is chosen
|
||||
uploadFile: React.PropTypes.func.isRequired,
|
||||
|
||||
// opacity for dynamic UI fading effects
|
||||
opacity: React.PropTypes.number,
|
||||
|
||||
// string representing the current room app drawer state
|
||||
showApps: React.PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -95,7 +95,9 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<div className="mx_PinnedEventsPanel">
|
||||
<div className="mx_PinnedEventsPanel_body">
|
||||
<AccessibleButton className="mx_PinnedEventsPanel_cancel" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" /></AccessibleButton>
|
||||
<AccessibleButton className="mx_PinnedEventsPanel_cancel" onClick={this.props.onCancelClick}>
|
||||
<img className="mx_filterFlipColor" src="img/cancel.svg" width="18" height="18" />
|
||||
</AccessibleButton>
|
||||
<h3 className="mx_PinnedEventsPanel_header">{ _t("Pinned Messages") }</h3>
|
||||
{ tiles }
|
||||
</div>
|
||||
|
|
|
@ -281,8 +281,11 @@ module.exports = React.createClass({
|
|||
<input id="avatarInput" type="file" onChange={this.onAvatarSelected} />
|
||||
</div>
|
||||
<div className="mx_RoomHeader_avatarPicker_remove" onClick={this.onAvatarRemoveClick}>
|
||||
<img src="img/cancel.svg" width="10"
|
||||
alt={_t("Remove avatar")} title={_t("Remove avatar")} />
|
||||
<img src="img/cancel.svg"
|
||||
className="mx_filterFlipColor"
|
||||
width="10"
|
||||
alt={_t("Remove avatar")}
|
||||
title={_t("Remove avatar")} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -19,7 +19,6 @@ import Promise from 'bluebird';
|
|||
import React from 'react';
|
||||
import { _t, _tJsx, _td } from '../../../languageHandler';
|
||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import SdkConfig from '../../../SdkConfig';
|
||||
import sdk from '../../../index';
|
||||
import Modal from '../../../Modal';
|
||||
import ObjectUtils from '../../../ObjectUtils';
|
||||
|
@ -158,9 +157,9 @@ module.exports = React.createClass({
|
|||
});
|
||||
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
sideOpacity: 0.3,
|
||||
middleOpacity: 0.3,
|
||||
action: 'panel_disable',
|
||||
sideDisabled: true,
|
||||
middleDisabled: true,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -171,9 +170,9 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
dis.dispatch({
|
||||
action: 'ui_opacity',
|
||||
sideOpacity: 1.0,
|
||||
middleOpacity: 1.0,
|
||||
action: 'panel_disable',
|
||||
sideDisabled: false,
|
||||
middleDisabled: false,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -18,10 +18,13 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
|
||||
import UserSettingsStore from '../../../UserSettingsStore';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'VideoView',
|
||||
|
||||
|
@ -108,14 +111,18 @@ module.exports = React.createClass({
|
|||
document.mozFullScreenElement ||
|
||||
document.webkitFullscreenElement);
|
||||
const maxVideoHeight = fullscreenElement ? null : this.props.maxHeight;
|
||||
|
||||
const localVideoFeedClasses = classNames("mx_VideoView_localVideoFeed",
|
||||
{ "mx_VideoView_localVideoFeed_flipped":
|
||||
UserSettingsStore.getSyncedSetting('VideoView.flipVideoHorizontally', false),
|
||||
},
|
||||
);
|
||||
return (
|
||||
<div className="mx_VideoView" ref={this.setContainer} onClick={this.props.onClick}>
|
||||
<div className="mx_VideoView_remoteVideoFeed">
|
||||
<VideoFeed ref="remote" onResize={this.props.onResize}
|
||||
maxHeight={maxVideoHeight} />
|
||||
</div>
|
||||
<div className="mx_VideoView_localVideoFeed">
|
||||
<div className={localVideoFeedClasses}>
|
||||
<VideoFeed ref="local" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -240,6 +240,7 @@
|
|||
"Unignore": "Unignore",
|
||||
"Ignore": "Ignore",
|
||||
"Jump to read receipt": "Jump to read receipt",
|
||||
"Invite": "Invite",
|
||||
"User Options": "User Options",
|
||||
"Direct chats": "Direct chats",
|
||||
"Unmute": "Unmute",
|
||||
|
@ -451,6 +452,7 @@
|
|||
"You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?",
|
||||
"Removed or unknown message type": "Removed or unknown message type",
|
||||
"Message removed by %(userId)s": "Message removed by %(userId)s",
|
||||
"Message removed": "Message removed",
|
||||
"Robot check is currently unavailable on desktop - please use a <a>web browser</a>": "Robot check is currently unavailable on desktop - please use a <a>web browser</a>",
|
||||
"This Home Server would like to make sure you are not a robot": "This Home Server would like to make sure you are not a robot",
|
||||
"Sign in with CAS": "Sign in with CAS",
|
||||
|
@ -494,10 +496,13 @@
|
|||
"Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Are you sure you want to remove '%(roomName)s' from %(groupId)s?",
|
||||
"Removing a room from the community will also remove it from the community page.": "Removing a room from the community will also remove it from the community page.",
|
||||
"Remove": "Remove",
|
||||
"Remove this room from the community": "Remove this room from the community",
|
||||
"Unknown Address": "Unknown Address",
|
||||
"NOTE: Apps are not end-to-end encrypted": "NOTE: Apps are not end-to-end encrypted",
|
||||
"Do you want to load widget from URL:": "Do you want to load widget from URL:",
|
||||
"Allow": "Allow",
|
||||
"Delete Widget": "Delete Widget",
|
||||
"Deleting a widget removes it for all users in this room. Are you sure you want to delete this widget?": "Deleting a widget removes it for all users in this room. Are you sure you want to delete this widget?",
|
||||
"Delete widget": "Delete widget",
|
||||
"Revoke widget access": "Revoke widget access",
|
||||
"Edit": "Edit",
|
||||
|
@ -677,17 +682,17 @@
|
|||
"Leave %(groupName)s?": "Leave %(groupName)s?",
|
||||
"Leave": "Leave",
|
||||
"Unable to leave room": "Unable to leave room",
|
||||
"Community Settings": "Community Settings",
|
||||
"Add rooms to this community": "Add rooms to this community",
|
||||
"Featured Rooms:": "Featured Rooms:",
|
||||
"Featured Users:": "Featured Users:",
|
||||
"%(inviter)s has invited you to join this community": "%(inviter)s has invited you to join this community",
|
||||
"You are a member of this community": "You are a member of this community",
|
||||
"You are an administrator of this community": "You are an administrator of this community",
|
||||
"You are a member of this community": "You are a member of this community",
|
||||
"Community Member Settings": "Community Member Settings",
|
||||
"Publish this community on your profile": "Publish this community on your profile",
|
||||
"Long Description (HTML)": "Long Description (HTML)",
|
||||
"Description": "Description",
|
||||
"Community Settings": "Community Settings",
|
||||
"Community %(groupId)s not found": "Community %(groupId)s not found",
|
||||
"This Home server does not support communities": "This Home server does not support communities",
|
||||
"Failed to load %(groupId)s": "Failed to load %(groupId)s",
|
||||
|
@ -753,6 +758,7 @@
|
|||
"Disable Emoji suggestions while typing": "Disable Emoji suggestions while typing",
|
||||
"Hide avatars in user and room mentions": "Hide avatars in user and room mentions",
|
||||
"Disable big emoji in chat": "Disable big emoji in chat",
|
||||
"Mirror local video feed": "Mirror local video feed",
|
||||
"Opt out of analytics": "Opt out of analytics",
|
||||
"Disable Peer-to-Peer for 1:1 calls": "Disable Peer-to-Peer for 1:1 calls",
|
||||
"Never send encrypted messages to unverified devices from this device": "Never send encrypted messages to unverified devices from this device",
|
||||
|
|
Loading…
Reference in a new issue