Merge branch 'develop' into bwindels/stylepreviewbar

This commit is contained in:
Bruno Windels 2019-04-17 11:06:21 +02:00
commit 22874f62ab
25 changed files with 280 additions and 139 deletions

View file

@ -52,7 +52,7 @@ export default class RoomSettingsDialog extends React.Component {
tabs.push(new Tab(
_td("Advanced"),
"mx_RoomSettingsDialog_warningIcon",
<AdvancedRoomSettingsTab roomId={this.props.roomId} />,
<AdvancedRoomSettingsTab roomId={this.props.roomId} closeSettingsFn={this.props.onFinished} />,
));
return tabs;

View file

@ -19,23 +19,30 @@ limitations under the License.
import React from 'react';
import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher';
import HeaderButton from './HeaderButton';
import HeaderButtons from './HeaderButtons';
import RightPanel from '../../structures/RightPanel';
const GROUP_PHASES = [
RightPanel.Phase.GroupMemberInfo,
RightPanel.Phase.GroupMemberList,
];
const ROOM_PHASES = [
RightPanel.Phase.GroupRoomList,
RightPanel.Phase.GroupRoomInfo,
];
export default class GroupHeaderButtons extends HeaderButtons {
constructor(props) {
super(props, RightPanel.Phase.GroupMemberList);
this._onMembersClicked = this._onMembersClicked.bind(this);
this._onRoomsClicked = this._onRoomsClicked.bind(this);
}
onAction(payload) {
super.onAction(payload);
if (payload.action === "view_user") {
dis.dispatch({
action: 'show_right_panel',
});
if (payload.member) {
this.setPhase(RightPanel.Phase.RoomMemberInfo, {member: payload.member});
} else {
@ -54,27 +61,26 @@ export default class GroupHeaderButtons extends HeaderButtons {
}
}
renderButtons() {
const groupPhases = [
RightPanel.Phase.GroupMemberInfo,
RightPanel.Phase.GroupMemberList,
];
const roomPhases = [
RightPanel.Phase.GroupRoomList,
RightPanel.Phase.GroupRoomInfo,
];
_onMembersClicked() {
this.togglePhase(RightPanel.Phase.GroupMemberList, GROUP_PHASES);
}
_onRoomsClicked() {
this.togglePhase(RightPanel.Phase.GroupRoomList, ROOM_PHASES);
}
renderButtons() {
return [
<HeaderButton key="groupMembersButton" name="groupMembersButton"
title={_t('Members')}
isHighlighted={this.isPhase(groupPhases)}
clickPhase={RightPanel.Phase.GroupMemberList}
isHighlighted={this.isPhase(GROUP_PHASES)}
onClick={this._onMembersClicked}
analytics={['Right Panel', 'Group Member List Button', 'click']}
/>,
<HeaderButton key="roomsButton" name="roomsButton"
title={_t('Rooms')}
isHighlighted={this.isPhase(roomPhases)}
clickPhase={RightPanel.Phase.GroupRoomList}
isHighlighted={this.isPhase(ROOM_PHASES)}
onClick={this._onRoomsClicked}
analytics={['Right Panel', 'Group Room List Button', 'click']}
/>,
];

View file

@ -20,7 +20,6 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import dis from '../../../dispatcher';
import Analytics from '../../../Analytics';
import AccessibleButton from '../elements/AccessibleButton';
@ -32,11 +31,7 @@ export default class HeaderButton extends React.Component {
onClick(ev) {
Analytics.trackEvent(...this.props.analytics);
dis.dispatch({
action: 'view_right_panel_phase',
phase: this.props.clickPhase,
fromHeader: true,
});
this.props.onClick();
}
render() {
@ -59,9 +54,8 @@ export default class HeaderButton extends React.Component {
HeaderButton.propTypes = {
// Whether this button is highlighted
isHighlighted: PropTypes.bool.isRequired,
// The phase to swap to when the button is clicked
clickPhase: PropTypes.string.isRequired,
// click handler
onClick: PropTypes.func.isRequired,
// The badge to display above the icon
badge: PropTypes.node,
// The parameters to track the click event

View file

@ -40,14 +40,36 @@ export default class HeaderButtons extends React.Component {
dis.unregister(this.dispatcherRef);
}
componentDidUpdate(prevProps) {
if (!prevProps.collapsedRhs && this.props.collapsedRhs) {
this.setState({
phase: null,
});
}
}
setPhase(phase, extras) {
// TODO: delay?
if (this.props.collapsedRhs) {
dis.dispatch({
action: 'show_right_panel',
});
}
dis.dispatch(Object.assign({
action: 'view_right_panel_phase',
phase: phase,
}, extras));
}
togglePhase(phase, validPhases = [phase]) {
if (validPhases.includes(this.state.phase)) {
dis.dispatch({
action: 'hide_right_panel',
});
} else {
this.setPhase(phase);
}
}
isPhase(phases) {
if (this.props.collapsedRhs) {
return false;
@ -61,28 +83,9 @@ export default class HeaderButtons extends React.Component {
onAction(payload) {
if (payload.action === "view_right_panel_phase") {
// only actions coming from header buttons should collapse the right panel
if (this.state.phase === payload.phase && payload.fromHeader) {
dis.dispatch({
action: 'hide_right_panel',
});
this.setState({
phase: null,
});
} else {
if (this.props.collapsedRhs && payload.fromHeader) {
dis.dispatch({
action: 'show_right_panel',
});
// emit payload again as the RightPanel didn't exist up
// till show_right_panel, just without the fromHeader flag
// as that would hide the right panel again
dis.dispatch(Object.assign({}, payload, {fromHeader: false}));
}
this.setState({
phase: payload.phase,
});
}
this.setState({
phase: payload.phase,
});
}
}

View file

@ -19,28 +19,33 @@ limitations under the License.
import React from 'react';
import { _t } from '../../../languageHandler';
import dis from '../../../dispatcher';
import HeaderButton from './HeaderButton';
import HeaderButtons from './HeaderButtons';
import RightPanel from '../../structures/RightPanel';
const MEMBER_PHASES = [
RightPanel.Phase.RoomMemberList,
RightPanel.Phase.RoomMemberInfo,
RightPanel.Phase.Room3pidMemberInfo,
];
export default class RoomHeaderButtons extends HeaderButtons {
constructor(props) {
super(props, RightPanel.Phase.RoomMemberList);
this._onMembersClicked = this._onMembersClicked.bind(this);
this._onFilesClicked = this._onFilesClicked.bind(this);
this._onNotificationsClicked = this._onNotificationsClicked.bind(this);
}
onAction(payload) {
super.onAction(payload);
if (payload.action === "view_user") {
dis.dispatch({
action: 'show_right_panel',
});
if (payload.member) {
this.setPhase(RightPanel.Phase.RoomMemberInfo, {member: payload.member});
} else {
this.setPhase(RightPanel.Phase.RoomMemberList);
}
} else if (payload.action === "view_room") {
} else if (payload.action === "view_room" && !this.props.collapsedRhs) {
this.setPhase(RightPanel.Phase.RoomMemberList);
} else if (payload.action === "view_3pid_invite") {
if (payload.event) {
@ -51,30 +56,36 @@ export default class RoomHeaderButtons extends HeaderButtons {
}
}
renderButtons() {
const membersPhases = [
RightPanel.Phase.RoomMemberList,
RightPanel.Phase.RoomMemberInfo,
RightPanel.Phase.Room3pidMemberInfo,
];
_onMembersClicked() {
this.togglePhase(RightPanel.Phase.RoomMemberList, MEMBER_PHASES);
}
_onFilesClicked() {
this.togglePhase(RightPanel.Phase.FilePanel);
}
_onNotificationsClicked() {
this.togglePhase(RightPanel.Phase.NotificationPanel);
}
renderButtons() {
return [
<HeaderButton key="membersButton" name="membersButton"
title={_t('Members')}
isHighlighted={this.isPhase(membersPhases)}
clickPhase={RightPanel.Phase.RoomMemberList}
isHighlighted={this.isPhase(MEMBER_PHASES)}
onClick={this._onMembersClicked}
analytics={['Right Panel', 'Member List Button', 'click']}
/>,
<HeaderButton key="filesButton" name="filesButton"
title={_t('Files')}
isHighlighted={this.isPhase(RightPanel.Phase.FilePanel)}
clickPhase={RightPanel.Phase.FilePanel}
onClick={this._onFilesClicked}
analytics={['Right Panel', 'File List Button', 'click']}
/>,
<HeaderButton key="notifsButton" name="notifsButton"
title={_t('Notifications')}
isHighlighted={this.isPhase(RightPanel.Phase.NotificationPanel)}
clickPhase={RightPanel.Phase.NotificationPanel}
onClick={this._onNotificationsClicked}
analytics={['Right Panel', 'Notification List Button', 'click']}
/>,
];

View file

@ -33,12 +33,7 @@ const MAX_ROOMS = 20;
export default class RoomBreadcrumbs extends React.Component {
constructor(props) {
super(props);
const tolerances = SettingsStore.getValue("breadcrumb_scroll_tolerances");
this.state = {rooms: [], scrollTolerances: tolerances};
// Record this for debugging purposes
console.log("Breadcrumbs scroll tolerances:", tolerances);
this.state = {rooms: []};
this.onAction = this.onAction.bind(this);
this._dispatcherRef = null;
@ -343,8 +338,7 @@ export default class RoomBreadcrumbs extends React.Component {
});
return (
<IndicatorScrollbar ref="scroller" className="mx_RoomBreadcrumbs"
trackHorizontalOverflow={true} verticalScrollsHorizontally={true}
scrollTolerances={this.state.scrollTolerances}>
trackHorizontalOverflow={true} verticalScrollsHorizontally={true}>
{ avatars }
</IndicatorScrollbar>
);

View file

@ -187,12 +187,17 @@ export default class KeyBackupPanel extends React.PureComponent {
clientBackupStatus = <div>
<p>{encryptedMessageAreEncrypted}</p>
<p>{_t(
"This device is <b>not backing up your keys</b>.", {},
"This device is <b>not backing up your keys</b>, " +
"but you do have an existing backup you can restore from " +
"and add to going forward.", {},
{b: sub => <b>{sub}</b>},
)}</p>
<p>{_t("Back up your keys before signing out to avoid losing them.")}</p>
<p>{_t(
"Connect this device to key backup before signing out to avoid " +
"losing any keys that may only be on this device.",
)}</p>
</div>;
restoreButtonCaption = _t("Use key backup");
restoreButtonCaption = _t("Connect this device to Key Backup");
}
let uploadStatus;
@ -221,7 +226,10 @@ export default class KeyBackupPanel extends React.PureComponent {
{sub}
</span>;
const device = sub => <span className="mx_KeyBackupPanel_deviceName">{deviceName}</span>;
const fromThisDevice = sig.device.getFingerprint() === MatrixClientPeg.get().getDeviceEd25519Key();
const fromThisDevice = (
sig.device &&
sig.device.getFingerprint() === MatrixClientPeg.get().getDeviceEd25519Key()
);
let sigStatus;
if (!sig.device) {
sigStatus = _t(

View file

@ -21,10 +21,12 @@ import MatrixClientPeg from "../../../../../MatrixClientPeg";
import sdk from "../../../../..";
import AccessibleButton from "../../../elements/AccessibleButton";
import Modal from "../../../../../Modal";
import dis from "../../../../../dispatcher";
export default class AdvancedRoomSettingsTab extends React.Component {
static propTypes = {
roomId: PropTypes.string.isRequired,
closeSettingsFn: PropTypes.func.isRequired,
};
constructor() {
@ -41,9 +43,21 @@ export default class AdvancedRoomSettingsTab extends React.Component {
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
room.getRecommendedVersion().then((v) => {
const tombstone = room.currentState.getStateEvents("m.room.tombstone", "");
const additionalStateChanges = {};
const createEvent = room.currentState.getStateEvents("m.room.create", "");
const predecessor = createEvent ? createEvent.getContent().predecessor : null;
if (predecessor && predecessor.room_id) {
additionalStateChanges['oldRoomId'] = predecessor.room_id;
additionalStateChanges['oldEventId'] = predecessor.event_id;
additionalStateChanges['hasPreviousRoom'] = true;
}
this.setState({
upgraded: tombstone && tombstone.getContent().replacement_room,
upgradeRecommendation: v,
...additionalStateChanges,
});
});
}
@ -59,6 +73,18 @@ export default class AdvancedRoomSettingsTab extends React.Component {
Modal.createDialog(DevtoolsDialog, {roomId: this.props.roomId});
};
_onOldRoomClicked = (e) => {
e.preventDefault();
e.stopPropagation();
dis.dispatch({
action: 'view_room',
room_id: this.state.oldRoomId,
event_id: this.state.oldEventId,
});
this.props.closeSettingsFn();
};
render() {
const client = MatrixClientPeg.get();
const room = client.getRoom(this.props.roomId);
@ -91,6 +117,18 @@ export default class AdvancedRoomSettingsTab extends React.Component {
);
}
let oldRoomLink;
if (this.state.hasPreviousRoom) {
let name = _t("this room");
const room = MatrixClientPeg.get().getRoom(this.props.roomId);
if (room && room.name) name = room.name;
oldRoomLink = (
<AccessibleButton element='a' onClick={this._onOldRoomClicked}>
{_t("View older messages in %(roomName)s.", {roomName: name})}
</AccessibleButton>
);
}
return (
<div className="mx_SettingsTab">
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
@ -108,6 +146,7 @@ export default class AdvancedRoomSettingsTab extends React.Component {
<span>{_t("Room version:")}</span>&nbsp;
{room.getVersion()}
</div>
{oldRoomLink}
{roomUpgradeButton}
</div>
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>

View file

@ -136,7 +136,7 @@ export default class HelpUserSettingsTab extends React.Component {
<li>
The <a href="themes/riot/img/backgrounds/valley.jpg" rel="noopener" target="_blank">
default cover photo</a> is (C)&nbsp;
<a href="https://www.flickr.com/golan" rel="noopener" target="_blank">Jesús Roncero</a>&nbsp;
<a href="https://www.flickr.com/golan" rel="noopener" target="_blank">Jesús Roncero</a>{' '}
used under the terms of&nbsp;
<a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="noopener" target="_blank">
CC-BY-SA 4.0</a>. No warranties are given.