mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-25 09:58:11 +08:00
Merge branch 'develop' into show-room-name
This commit is contained in:
commit
58ab5c36bb
@ -1,3 +1,10 @@
|
|||||||
|
Changes in [3.13.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.13.1) (2021-02-04)
|
||||||
|
=====================================================================================================
|
||||||
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.13.0...v3.13.1)
|
||||||
|
|
||||||
|
* [Release] Fix z-index of stickerpicker
|
||||||
|
[\#5618](https://github.com/matrix-org/matrix-react-sdk/pull/5618)
|
||||||
|
|
||||||
Changes in [3.13.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.13.0) (2021-02-03)
|
Changes in [3.13.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.13.0) (2021-02-03)
|
||||||
=====================================================================================================
|
=====================================================================================================
|
||||||
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.13.0-rc.1...v3.13.0)
|
[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.13.0-rc.1...v3.13.0)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "matrix-react-sdk",
|
"name": "matrix-react-sdk",
|
||||||
"version": "3.13.0",
|
"version": "3.13.1",
|
||||||
"description": "SDK for matrix.org using React",
|
"description": "SDK for matrix.org using React",
|
||||||
"author": "matrix.org",
|
"author": "matrix.org",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -21,6 +21,11 @@ limitations under the License.
|
|||||||
|
|
||||||
$hover-transition: 0.08s cubic-bezier(.46, .03, .52, .96); // quadratic
|
$hover-transition: 0.08s cubic-bezier(.46, .03, .52, .96); // quadratic
|
||||||
|
|
||||||
|
$EventTile_e2e_state_indicator_width: 4px;
|
||||||
|
|
||||||
|
$MessageTimestamp_width: 46px; /* 8 + 30 (avatar) + 8 */
|
||||||
|
$MessageTimestamp_width_hover: calc($MessageTimestamp_width - 2 * $EventTile_e2e_state_indicator_width);
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ limitations under the License.
|
|||||||
mask-size: contain;
|
mask-size: contain;
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 2px;
|
top: 1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ $left-gutter: 64px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile.mx_EventTile_info {
|
.mx_EventTile.mx_EventTile_info {
|
||||||
padding-top: 0px;
|
padding-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile_avatar {
|
.mx_EventTile_avatar {
|
||||||
@ -37,7 +37,7 @@ $left-gutter: 64px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile.mx_EventTile_info .mx_EventTile_avatar {
|
.mx_EventTile.mx_EventTile_info .mx_EventTile_avatar {
|
||||||
top: $font-8px;
|
top: $font-6px;
|
||||||
left: $left-gutter;
|
left: $left-gutter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,15 +420,15 @@ $left-gutter: 64px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line {
|
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line {
|
||||||
border-left: $e2e-verified-color 4px solid;
|
border-left: $e2e-verified-color $EventTile_e2e_state_indicator_width solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line {
|
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line {
|
||||||
border-left: $e2e-unverified-color 4px solid;
|
border-left: $e2e-unverified-color $EventTile_e2e_state_indicator_width solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
|
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line {
|
||||||
border-left: $e2e-unknown-color 4px solid;
|
border-left: $e2e-unknown-color $EventTile_e2e_state_indicator_width solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile:hover.mx_EventTile_verified.mx_EventTile_info .mx_EventTile_line,
|
.mx_EventTile:hover.mx_EventTile_verified.mx_EventTile_info .mx_EventTile_line,
|
||||||
@ -446,8 +446,7 @@ $left-gutter: 64px;
|
|||||||
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line > a > .mx_MessageTimestamp,
|
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line > a > .mx_MessageTimestamp,
|
||||||
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line > a > .mx_MessageTimestamp,
|
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line > a > .mx_MessageTimestamp,
|
||||||
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line > a > .mx_MessageTimestamp {
|
.mx_EventTile:hover.mx_EventTile_unknown .mx_EventTile_line > a > .mx_MessageTimestamp {
|
||||||
left: 3px;
|
width: $MessageTimestamp_width_hover;
|
||||||
width: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies)
|
// Explicit relationships so that it doesn't apply to nested EventTile components (e.g in Replies)
|
||||||
|
@ -34,7 +34,7 @@ $left-gutter: 64px;
|
|||||||
|
|
||||||
.mx_MessageTimestamp {
|
.mx_MessageTimestamp {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 46px; /* 8 + 30 (avatar) + 8 */
|
width: $MessageTimestamp_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile_line, .mx_EventTile_reply {
|
.mx_EventTile_line, .mx_EventTile_reply {
|
||||||
|
@ -755,6 +755,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||||||
break;
|
break;
|
||||||
case 'on_logged_in':
|
case 'on_logged_in':
|
||||||
if (
|
if (
|
||||||
|
// Skip this handling for token login as that always calls onLoggedIn itself
|
||||||
|
!this.tokenLogin &&
|
||||||
!Lifecycle.isSoftLogout() &&
|
!Lifecycle.isSoftLogout() &&
|
||||||
this.state.view !== Views.LOGIN &&
|
this.state.view !== Views.LOGIN &&
|
||||||
this.state.view !== Views.REGISTER &&
|
this.state.view !== Views.REGISTER &&
|
||||||
@ -1652,10 +1654,16 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
|||||||
// TODO: Handle encoded room/event IDs: https://github.com/vector-im/element-web/issues/9149
|
// TODO: Handle encoded room/event IDs: https://github.com/vector-im/element-web/issues/9149
|
||||||
|
|
||||||
let threepidInvite: IThreepidInvite;
|
let threepidInvite: IThreepidInvite;
|
||||||
|
// if we landed here from a 3PID invite, persist it
|
||||||
if (params.signurl && params.email) {
|
if (params.signurl && params.email) {
|
||||||
threepidInvite = ThreepidInviteStore.instance
|
threepidInvite = ThreepidInviteStore.instance
|
||||||
.storeInvite(roomString, params as IThreepidInviteWireFormat);
|
.storeInvite(roomString, params as IThreepidInviteWireFormat);
|
||||||
}
|
}
|
||||||
|
// otherwise check that this room doesn't already have a known invite
|
||||||
|
if (!threepidInvite) {
|
||||||
|
const invites = ThreepidInviteStore.instance.getInvites();
|
||||||
|
threepidInvite = invites.find(invite => invite.roomId === roomString);
|
||||||
|
}
|
||||||
|
|
||||||
// on our URLs there might be a ?via=matrix.org or similar to help
|
// on our URLs there might be a ?via=matrix.org or similar to help
|
||||||
// joins to the room succeed. We'll pass these through as an array
|
// joins to the room succeed. We'll pass these through as an array
|
||||||
|
@ -229,7 +229,7 @@ export default class MessagePanel extends React.Component {
|
|||||||
|
|
||||||
onAction = (payload) => {
|
onAction = (payload) => {
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
case "message_sent":
|
case "scroll_to_bottom":
|
||||||
this.scrollToBottom();
|
this.scrollToBottom();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ import MatrixClientContext from "../../contexts/MatrixClientContext";
|
|||||||
import {Action} from "../../dispatcher/actions";
|
import {Action} from "../../dispatcher/actions";
|
||||||
import RoomSummaryCard from "../views/right_panel/RoomSummaryCard";
|
import RoomSummaryCard from "../views/right_panel/RoomSummaryCard";
|
||||||
import WidgetCard from "../views/right_panel/WidgetCard";
|
import WidgetCard from "../views/right_panel/WidgetCard";
|
||||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
|
||||||
|
|
||||||
export default class RightPanel extends React.Component {
|
export default class RightPanel extends React.Component {
|
||||||
static get propTypes() {
|
static get propTypes() {
|
||||||
@ -186,7 +185,7 @@ export default class RightPanel extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onCloseUserInfo = () => {
|
onClose = () => {
|
||||||
// XXX: There are three different ways of 'closing' this panel depending on what state
|
// XXX: There are three different ways of 'closing' this panel depending on what state
|
||||||
// things are in... this knows far more than it should do about the state of the rest
|
// things are in... this knows far more than it should do about the state of the rest
|
||||||
// of the app and is generally a bit silly.
|
// of the app and is generally a bit silly.
|
||||||
@ -198,31 +197,21 @@ export default class RightPanel extends React.Component {
|
|||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: "view_home_page",
|
action: "view_home_page",
|
||||||
});
|
});
|
||||||
} else if (this.state.phase === RightPanelPhases.EncryptionPanel &&
|
} else if (
|
||||||
|
this.state.phase === RightPanelPhases.EncryptionPanel &&
|
||||||
this.state.verificationRequest && this.state.verificationRequest.pending
|
this.state.verificationRequest && this.state.verificationRequest.pending
|
||||||
) {
|
) {
|
||||||
// When the user clicks close on the encryption panel cancel the pending request first if any
|
// When the user clicks close on the encryption panel cancel the pending request first if any
|
||||||
this.state.verificationRequest.cancel();
|
this.state.verificationRequest.cancel();
|
||||||
} else {
|
} else {
|
||||||
// Otherwise we have got our user from RoomViewStore which means we're being shown
|
// the RightPanelStore has no way of knowing which mode room/group it is in, so we handle closing here
|
||||||
// within a room/group, so go back to the member panel if we were in the encryption panel,
|
|
||||||
// or the member list if we were in the member panel... phew.
|
|
||||||
const isEncryptionPhase = this.state.phase === RightPanelPhases.EncryptionPanel;
|
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: Action.ViewUser,
|
action: Action.ToggleRightPanel,
|
||||||
member: isEncryptionPhase ? this.state.member : null,
|
type: this.props.groupId ? "group" : "room",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onClose = () => {
|
|
||||||
// the RightPanelStore has no way of knowing which mode room/group it is in, so we handle closing here
|
|
||||||
defaultDispatcher.dispatch({
|
|
||||||
action: Action.ToggleRightPanel,
|
|
||||||
type: this.props.groupId ? "group" : "room",
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const MemberList = sdk.getComponent('rooms.MemberList');
|
const MemberList = sdk.getComponent('rooms.MemberList');
|
||||||
const UserInfo = sdk.getComponent('right_panel.UserInfo');
|
const UserInfo = sdk.getComponent('right_panel.UserInfo');
|
||||||
@ -260,7 +249,7 @@ export default class RightPanel extends React.Component {
|
|||||||
user={this.state.member}
|
user={this.state.member}
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
key={roomId || this.state.member.userId}
|
key={roomId || this.state.member.userId}
|
||||||
onClose={this.onCloseUserInfo}
|
onClose={this.onClose}
|
||||||
phase={this.state.phase}
|
phase={this.state.phase}
|
||||||
verificationRequest={this.state.verificationRequest}
|
verificationRequest={this.state.verificationRequest}
|
||||||
verificationRequestPromise={this.state.verificationRequestPromise}
|
verificationRequestPromise={this.state.verificationRequestPromise}
|
||||||
@ -276,7 +265,7 @@ export default class RightPanel extends React.Component {
|
|||||||
user={this.state.member}
|
user={this.state.member}
|
||||||
groupId={this.props.groupId}
|
groupId={this.props.groupId}
|
||||||
key={this.state.member.userId}
|
key={this.state.member.userId}
|
||||||
onClose={this.onCloseUserInfo} />;
|
onClose={this.onClose} />;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RightPanelPhases.GroupRoomInfo:
|
case RightPanelPhases.GroupRoomInfo:
|
||||||
|
@ -23,6 +23,7 @@ import ResizeObserver from 'resize-observer-polyfill';
|
|||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
import {MatrixClientPeg} from "../../../MatrixClientPeg";
|
||||||
|
import {isNullOrUndefined} from "matrix-js-sdk/src/utils";
|
||||||
|
|
||||||
// Shamelessly ripped off Modal.js. There's probably a better way
|
// Shamelessly ripped off Modal.js. There's probably a better way
|
||||||
// of doing reusable widgets like dialog boxes & menus where we go and
|
// of doing reusable widgets like dialog boxes & menus where we go and
|
||||||
@ -61,6 +62,9 @@ export default class PersistedElement extends React.Component {
|
|||||||
// Any PersistedElements with the same persistKey will use
|
// Any PersistedElements with the same persistKey will use
|
||||||
// the same DOM container.
|
// the same DOM container.
|
||||||
persistKey: PropTypes.string.isRequired,
|
persistKey: PropTypes.string.isRequired,
|
||||||
|
|
||||||
|
// z-index for the element. Defaults to 9.
|
||||||
|
zIndex: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -165,7 +169,7 @@ export default class PersistedElement extends React.Component {
|
|||||||
|
|
||||||
const parentRect = parent.getBoundingClientRect();
|
const parentRect = parent.getBoundingClientRect();
|
||||||
Object.assign(child.style, {
|
Object.assign(child.style, {
|
||||||
zIndex: 9,
|
zIndex: isNullOrUndefined(this.props.zIndex) ? 9 : this.props.zIndex,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: parentRect.top + 'px',
|
top: parentRect.top + 'px',
|
||||||
left: parentRect.left + 'px',
|
left: parentRect.left + 'px',
|
||||||
|
@ -33,6 +33,7 @@ interface IProps {
|
|||||||
previousPhase?: RightPanelPhases;
|
previousPhase?: RightPanelPhases;
|
||||||
closeLabel?: string;
|
closeLabel?: string;
|
||||||
onClose?(): void;
|
onClose?(): void;
|
||||||
|
refireParams?;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IGroupProps {
|
interface IGroupProps {
|
||||||
@ -56,6 +57,7 @@ const BaseCard: React.FC<IProps> = ({
|
|||||||
withoutScrollContainer,
|
withoutScrollContainer,
|
||||||
previousPhase,
|
previousPhase,
|
||||||
children,
|
children,
|
||||||
|
refireParams,
|
||||||
}) => {
|
}) => {
|
||||||
let backButton;
|
let backButton;
|
||||||
if (previousPhase) {
|
if (previousPhase) {
|
||||||
@ -63,6 +65,7 @@ const BaseCard: React.FC<IProps> = ({
|
|||||||
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
|
||||||
action: Action.SetRightPanelPhase,
|
action: Action.SetRightPanelPhase,
|
||||||
phase: previousPhase,
|
phase: previousPhase,
|
||||||
|
refireParams: refireParams,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
backButton = <AccessibleButton className="mx_BaseCard_back" onClick={onBackClick} title={_t("Back")} />;
|
backButton = <AccessibleButton className="mx_BaseCard_back" onClick={onBackClick} title={_t("Back")} />;
|
||||||
|
@ -60,6 +60,7 @@ import QuestionDialog from "../dialogs/QuestionDialog";
|
|||||||
import ConfirmUserActionDialog from "../dialogs/ConfirmUserActionDialog";
|
import ConfirmUserActionDialog from "../dialogs/ConfirmUserActionDialog";
|
||||||
import InfoDialog from "../dialogs/InfoDialog";
|
import InfoDialog from "../dialogs/InfoDialog";
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
import {SetRightPanelPhasePayload} from "../../../dispatcher/payloads/SetRightPanelPhasePayload";
|
||||||
|
|
||||||
interface IDevice {
|
interface IDevice {
|
||||||
deviceId: string;
|
deviceId: string;
|
||||||
@ -1534,6 +1535,24 @@ const UserInfo: React.FC<Props> = ({
|
|||||||
|
|
||||||
const classes = ["mx_UserInfo"];
|
const classes = ["mx_UserInfo"];
|
||||||
|
|
||||||
|
let refireParams;
|
||||||
|
let previousPhase: RightPanelPhases;
|
||||||
|
// We have no previousPhase for when viewing a UserInfo from a Group or without a Room at this time
|
||||||
|
if (room && phase === RightPanelPhases.EncryptionPanel) {
|
||||||
|
previousPhase = RightPanelPhases.RoomMemberInfo;
|
||||||
|
refireParams = {member: member};
|
||||||
|
} else if (room) {
|
||||||
|
previousPhase = RightPanelPhases.RoomMemberList;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEncryptionPanelClose = () => {
|
||||||
|
dis.dispatch<SetRightPanelPhasePayload>({
|
||||||
|
action: Action.SetRightPanelPhase,
|
||||||
|
phase: previousPhase,
|
||||||
|
refireParams: refireParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case RightPanelPhases.RoomMemberInfo:
|
case RightPanelPhases.RoomMemberInfo:
|
||||||
@ -1553,19 +1572,13 @@ const UserInfo: React.FC<Props> = ({
|
|||||||
<EncryptionPanel
|
<EncryptionPanel
|
||||||
{...props as React.ComponentProps<typeof EncryptionPanel>}
|
{...props as React.ComponentProps<typeof EncryptionPanel>}
|
||||||
member={member}
|
member={member}
|
||||||
onClose={onClose}
|
onClose={onEncryptionPanelClose}
|
||||||
isRoomEncrypted={isRoomEncrypted}
|
isRoomEncrypted={isRoomEncrypted}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let previousPhase: RightPanelPhases;
|
|
||||||
// We have no previousPhase for when viewing a UserInfo from a Group or without a Room at this time
|
|
||||||
if (room) {
|
|
||||||
previousPhase = RightPanelPhases.RoomMemberList;
|
|
||||||
}
|
|
||||||
|
|
||||||
let closeLabel = undefined;
|
let closeLabel = undefined;
|
||||||
if (phase === RightPanelPhases.EncryptionPanel) {
|
if (phase === RightPanelPhases.EncryptionPanel) {
|
||||||
const verificationRequest = (props as React.ComponentProps<typeof EncryptionPanel>).verificationRequest;
|
const verificationRequest = (props as React.ComponentProps<typeof EncryptionPanel>).verificationRequest;
|
||||||
@ -1581,6 +1594,7 @@ const UserInfo: React.FC<Props> = ({
|
|||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
closeLabel={closeLabel}
|
closeLabel={closeLabel}
|
||||||
previousPhase={previousPhase}
|
previousPhase={previousPhase}
|
||||||
|
refireParams={refireParams}
|
||||||
>
|
>
|
||||||
{ content }
|
{ content }
|
||||||
</BaseCard>;
|
</BaseCard>;
|
||||||
|
@ -69,19 +69,24 @@ export default class RoomProfileSettings extends React.Component {
|
|||||||
// clear file upload field so same file can be selected
|
// clear file upload field so same file can be selected
|
||||||
this._avatarUpload.current.value = "";
|
this._avatarUpload.current.value = "";
|
||||||
this.setState({
|
this.setState({
|
||||||
avatarUrl: undefined,
|
avatarUrl: null,
|
||||||
avatarFile: undefined,
|
avatarFile: null,
|
||||||
enableProfileSave: true,
|
enableProfileSave: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_clearProfile = async (e) => {
|
_cancelProfileChanges = async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (!this.state.enableProfileSave) return;
|
if (!this.state.enableProfileSave) return;
|
||||||
this._removeAvatar();
|
this.setState({
|
||||||
this.setState({enableProfileSave: false, displayName: this.state.originalDisplayName});
|
enableProfileSave: false,
|
||||||
|
displayName: this.state.originalDisplayName,
|
||||||
|
topic: this.state.originalTopic,
|
||||||
|
avatarUrl: this.state.originalAvatarUrl,
|
||||||
|
avatarFile: null,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_saveProfile = async (e) => {
|
_saveProfile = async (e) => {
|
||||||
@ -108,7 +113,7 @@ export default class RoomProfileSettings extends React.Component {
|
|||||||
newState.originalAvatarUrl = newState.avatarUrl;
|
newState.originalAvatarUrl = newState.avatarUrl;
|
||||||
newState.avatarFile = null;
|
newState.avatarFile = null;
|
||||||
} else if (this.state.originalAvatarUrl !== this.state.avatarUrl) {
|
} else if (this.state.originalAvatarUrl !== this.state.avatarUrl) {
|
||||||
await client.sendStateEvent(this.props.roomId, 'm.room.avatar', {url: undefined}, '');
|
await client.sendStateEvent(this.props.roomId, 'm.room.avatar', {}, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.originalTopic !== this.state.topic) {
|
if (this.state.originalTopic !== this.state.topic) {
|
||||||
@ -164,11 +169,15 @@ export default class RoomProfileSettings extends React.Component {
|
|||||||
const AvatarSetting = sdk.getComponent('settings.AvatarSetting');
|
const AvatarSetting = sdk.getComponent('settings.AvatarSetting');
|
||||||
|
|
||||||
let profileSettingsButtons;
|
let profileSettingsButtons;
|
||||||
if (this.state.canSetTopic && this.state.canSetName) {
|
if (
|
||||||
|
this.state.canSetName ||
|
||||||
|
this.state.canSetTopic ||
|
||||||
|
this.state.canSetAvatar
|
||||||
|
) {
|
||||||
profileSettingsButtons = (
|
profileSettingsButtons = (
|
||||||
<div className="mx_ProfileSettings_buttons">
|
<div className="mx_ProfileSettings_buttons">
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
onClick={this._clearProfile}
|
onClick={this._cancelProfileChanges}
|
||||||
kind="link"
|
kind="link"
|
||||||
disabled={!this.state.enableProfileSave}
|
disabled={!this.state.enableProfileSave}
|
||||||
>
|
>
|
||||||
|
@ -426,7 +426,8 @@ export default class MessageComposer extends React.Component {
|
|||||||
<EmojiButton key="emoji_button" addEmoji={this.addEmoji} />,
|
<EmojiButton key="emoji_button" addEmoji={this.addEmoji} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (SettingsStore.getValue(UIFeature.Widgets)) {
|
if (SettingsStore.getValue(UIFeature.Widgets) &&
|
||||||
|
SettingsStore.getValue("MessageComposerInput.showStickersButton")) {
|
||||||
controls.push(<Stickerpicker key="stickerpicker_controls_button" room={this.props.room} />);
|
controls.push(<Stickerpicker key="stickerpicker_controls_button" room={this.props.room} />);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,6 +403,7 @@ export default class SendMessageComposer extends React.Component {
|
|||||||
this._editorRef.clearUndoHistory();
|
this._editorRef.clearUndoHistory();
|
||||||
this._editorRef.focus();
|
this._editorRef.focus();
|
||||||
this._clearStoredEditorState();
|
this._clearStoredEditorState();
|
||||||
|
dis.dispatch({action: "scroll_to_bottom"});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -264,7 +264,7 @@ export default class Stickerpicker extends React.Component {
|
|||||||
width: this.popoverWidth,
|
width: this.popoverWidth,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PersistedElement persistKey={PERSISTED_ELEMENT_KEY} style={{zIndex: STICKERPICKER_Z_INDEX}}>
|
<PersistedElement persistKey={PERSISTED_ELEMENT_KEY} zIndex={STICKERPICKER_Z_INDEX}>
|
||||||
<AppTile
|
<AppTile
|
||||||
app={stickerApp}
|
app={stickerApp}
|
||||||
room={this.props.room}
|
room={this.props.room}
|
||||||
|
@ -52,19 +52,23 @@ export default class ProfileSettings extends React.Component {
|
|||||||
// clear file upload field so same file can be selected
|
// clear file upload field so same file can be selected
|
||||||
this._avatarUpload.current.value = "";
|
this._avatarUpload.current.value = "";
|
||||||
this.setState({
|
this.setState({
|
||||||
avatarUrl: undefined,
|
avatarUrl: null,
|
||||||
avatarFile: undefined,
|
avatarFile: null,
|
||||||
enableProfileSave: true,
|
enableProfileSave: true,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_clearProfile = async (e) => {
|
_cancelProfileChanges = async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (!this.state.enableProfileSave) return;
|
if (!this.state.enableProfileSave) return;
|
||||||
this._removeAvatar();
|
this.setState({
|
||||||
this.setState({enableProfileSave: false, displayName: this.state.originalDisplayName});
|
enableProfileSave: false,
|
||||||
|
displayName: this.state.originalDisplayName,
|
||||||
|
avatarUrl: this.state.originalAvatarUrl,
|
||||||
|
avatarFile: null,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_saveProfile = async (e) => {
|
_saveProfile = async (e) => {
|
||||||
@ -186,7 +190,7 @@ export default class ProfileSettings extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mx_ProfileSettings_buttons">
|
<div className="mx_ProfileSettings_buttons">
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
onClick={this._clearProfile}
|
onClick={this._cancelProfileChanges}
|
||||||
kind="link"
|
kind="link"
|
||||||
disabled={!this.state.enableProfileSave}
|
disabled={!this.state.enableProfileSave}
|
||||||
>
|
>
|
||||||
|
@ -34,6 +34,7 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
|||||||
'MessageComposerInput.suggestEmoji',
|
'MessageComposerInput.suggestEmoji',
|
||||||
'sendTypingNotifications',
|
'sendTypingNotifications',
|
||||||
'MessageComposerInput.ctrlEnterToSend',
|
'MessageComposerInput.ctrlEnterToSend',
|
||||||
|
'MessageComposerInput.showStickersButton',
|
||||||
];
|
];
|
||||||
|
|
||||||
static TIMELINE_SETTINGS = [
|
static TIMELINE_SETTINGS = [
|
||||||
|
@ -795,6 +795,7 @@
|
|||||||
"Font size": "Font size",
|
"Font size": "Font size",
|
||||||
"Use custom size": "Use custom size",
|
"Use custom size": "Use custom size",
|
||||||
"Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
|
"Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing",
|
||||||
|
"Show stickers button": "Show stickers button",
|
||||||
"Use a more compact ‘Modern’ layout": "Use a more compact ‘Modern’ layout",
|
"Use a more compact ‘Modern’ layout": "Use a more compact ‘Modern’ layout",
|
||||||
"Show a placeholder for removed messages": "Show a placeholder for removed messages",
|
"Show a placeholder for removed messages": "Show a placeholder for removed messages",
|
||||||
"Show join/leave messages (invites/kicks/bans unaffected)": "Show join/leave messages (invites/kicks/bans unaffected)",
|
"Show join/leave messages (invites/kicks/bans unaffected)": "Show join/leave messages (invites/kicks/bans unaffected)",
|
||||||
|
@ -240,6 +240,11 @@ export const SETTINGS: {[setting: string]: ISetting} = {
|
|||||||
default: true,
|
default: true,
|
||||||
invertedSettingName: 'MessageComposerInput.dontSuggestEmoji',
|
invertedSettingName: 'MessageComposerInput.dontSuggestEmoji',
|
||||||
},
|
},
|
||||||
|
"MessageComposerInput.showStickersButton": {
|
||||||
|
supportedLevels: LEVELS_ACCOUNT_SETTINGS,
|
||||||
|
displayName: _td('Show stickers button'),
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
// TODO: Wire up appropriately to UI (FTUE notifications)
|
// TODO: Wire up appropriately to UI (FTUE notifications)
|
||||||
"Notifications.alwaysShowBadgeCounts": {
|
"Notifications.alwaysShowBadgeCounts": {
|
||||||
supportedLevels: LEVELS_ROOM_OR_ACCOUNT,
|
supportedLevels: LEVELS_ROOM_OR_ACCOUNT,
|
||||||
|
Loading…
Reference in New Issue
Block a user