mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-17 14:05:04 +08:00
Merge branch 'develop' into travis/poc/theme-command
This commit is contained in:
commit
65d7bb2ef9
@ -34,7 +34,7 @@ All code lands on the `develop` branch - `master` is only used for stable releas
|
|||||||
**Please file PRs against `develop`!!**
|
**Please file PRs against `develop`!!**
|
||||||
|
|
||||||
Please follow the standard Matrix contributor's guide:
|
Please follow the standard Matrix contributor's guide:
|
||||||
https://github.com/matrix-org/synapse/tree/master/CONTRIBUTING.rst
|
https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.rst
|
||||||
|
|
||||||
Please follow the Matrix JS/React code style as per:
|
Please follow the Matrix JS/React code style as per:
|
||||||
https://github.com/matrix-org/matrix-react-sdk/blob/master/code_style.md
|
https://github.com/matrix-org/matrix-react-sdk/blob/master/code_style.md
|
||||||
|
@ -289,17 +289,11 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
top: 29px;
|
top: -19px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile_continuation .mx_EventTile_readAvatars,
|
|
||||||
.mx_EventTile_info .mx_EventTile_readAvatars,
|
|
||||||
.mx_EventTile_emote .mx_EventTile_readAvatars {
|
|
||||||
top: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_EventTile_readAvatars .mx_BaseAvatar {
|
.mx_EventTile_readAvatars .mx_BaseAvatar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -634,15 +628,6 @@ div.mx_EventTile_notSent.mx_EventTile_redacted .mx_UnknownBody {
|
|||||||
top: 27px;
|
top: 27px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_EventTile_continuation .mx_EventTile_readAvatars,
|
|
||||||
.mx_EventTile_emote .mx_EventTile_readAvatars {
|
|
||||||
top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_EventTile_info .mx_EventTile_readAvatars {
|
|
||||||
top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_RoomView_MessageList h2 {
|
.mx_RoomView_MessageList h2 {
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
|
@ -56,3 +56,17 @@ limitations under the License.
|
|||||||
mask-position: 9px 13px;
|
mask-position: 9px 13px;
|
||||||
background: $roomtile-name-color;
|
background: $roomtile-name-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_TopUnreadMessagesBar_markAsRead {
|
||||||
|
display: block;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
background-image: url('$(res)/img/cancel.svg');
|
||||||
|
background-position: center;
|
||||||
|
background-size: 10px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-color: $primary-bg-color;
|
||||||
|
border: 1.3px solid $roomtile-name-color;
|
||||||
|
border-radius: 99px;
|
||||||
|
margin: 5px auto;
|
||||||
|
}
|
||||||
|
@ -141,15 +141,17 @@ export default class ManageEventIndexDialog extends React.Component {
|
|||||||
let crawlerState;
|
let crawlerState;
|
||||||
|
|
||||||
if (this.state.currentRoom === null) {
|
if (this.state.currentRoom === null) {
|
||||||
crawlerState = _t("Not currently downloading messages for any room.");
|
crawlerState = _t("Not currently indexing messages for any room.");
|
||||||
} else {
|
} else {
|
||||||
crawlerState = (
|
crawlerState = (
|
||||||
_t("Downloading mesages for %(currentRoom)s.", { currentRoom: this.state.currentRoom })
|
_t("Currently indexing: %(currentRoom)s.", { currentRoom: this.state.currentRoom })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Field = sdk.getComponent('views.elements.Field');
|
const Field = sdk.getComponent('views.elements.Field');
|
||||||
|
|
||||||
|
const doneRooms = Math.max(0, (this.state.roomCount - this.state.crawlingRoomsCount));
|
||||||
|
|
||||||
const eventIndexingSettings = (
|
const eventIndexingSettings = (
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
@ -158,13 +160,13 @@ export default class ManageEventIndexDialog extends React.Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
<div className='mx_SettingsTab_subsectionText'>
|
<div className='mx_SettingsTab_subsectionText'>
|
||||||
|
{crawlerState}<br />
|
||||||
{_t("Space used:")} {formatBytes(this.state.eventIndexSize, 0)}<br />
|
{_t("Space used:")} {formatBytes(this.state.eventIndexSize, 0)}<br />
|
||||||
{_t("Indexed messages:")} {formatCountLong(this.state.eventCount)}<br />
|
{_t("Indexed messages:")} {formatCountLong(this.state.eventCount)}<br />
|
||||||
{_t("Indexed rooms:")} {_t("%(crawlingRooms)s out of %(totalRooms)s", {
|
{_t("Indexed rooms:")} {_t("%(doneRooms)s out of %(totalRooms)s", {
|
||||||
crawlingRooms: formatCountLong(this.state.crawlingRoomsCount),
|
doneRooms: formatCountLong(doneRooms),
|
||||||
totalRooms: formatCountLong(this.state.roomCount),
|
totalRooms: formatCountLong(this.state.roomCount),
|
||||||
})} <br />
|
})} <br />
|
||||||
{crawlerState}<br />
|
|
||||||
<Field
|
<Field
|
||||||
id={"crawlerSleepTimeMs"}
|
id={"crawlerSleepTimeMs"}
|
||||||
label={_t('Message downloading sleep time(ms)')}
|
label={_t('Message downloading sleep time(ms)')}
|
||||||
|
@ -1495,26 +1495,29 @@ export default createReactClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (SettingsStore.isFeatureEnabled("feature_cross_signing")) {
|
cli.on("crypto.verification.request", request => {
|
||||||
cli.on("crypto.verification.request", request => {
|
const isFlagOn = SettingsStore.isFeatureEnabled("feature_cross_signing");
|
||||||
if (request.pending) {
|
|
||||||
ToastStore.sharedInstance().addOrReplaceToast({
|
if (!isFlagOn && !request.channel.deviceId) {
|
||||||
key: 'verifreq_' + request.channel.transactionId,
|
request.cancel({code: "m.invalid_message", reason: "This client has cross-signing disabled"});
|
||||||
title: _t("Verification Request"),
|
return;
|
||||||
icon: "verification",
|
}
|
||||||
props: {request},
|
|
||||||
component: sdk.getComponent("toasts.VerificationRequestToast"),
|
if (request.verifier) {
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
cli.on("crypto.verification.start", (verifier) => {
|
|
||||||
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
|
const IncomingSasDialog = sdk.getComponent("views.dialogs.IncomingSasDialog");
|
||||||
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
|
||||||
verifier,
|
verifier: request.verifier,
|
||||||
}, null, /* priority = */ false, /* static = */ true);
|
}, null, /* priority = */ false, /* static = */ true);
|
||||||
});
|
} else if (request.pending) {
|
||||||
}
|
ToastStore.sharedInstance().addOrReplaceToast({
|
||||||
|
key: 'verifreq_' + request.channel.transactionId,
|
||||||
|
title: _t("Verification Request"),
|
||||||
|
icon: "verification",
|
||||||
|
props: {request},
|
||||||
|
component: sdk.getComponent("toasts.VerificationRequestToast"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
// Fire the tinter right on startup to ensure the default theme is applied
|
// Fire the tinter right on startup to ensure the default theme is applied
|
||||||
// A later sync can/will correct the tint to be the right value for the user
|
// A later sync can/will correct the tint to be the right value for the user
|
||||||
const colorScheme = SettingsStore.getValue("roomColor");
|
const colorScheme = SettingsStore.getValue("roomColor");
|
||||||
|
@ -182,6 +182,7 @@ export default class RightPanel extends React.Component {
|
|||||||
member: payload.member,
|
member: payload.member,
|
||||||
event: payload.event,
|
event: payload.event,
|
||||||
verificationRequest: payload.verificationRequest,
|
verificationRequest: payload.verificationRequest,
|
||||||
|
verificationRequestPromise: payload.verificationRequestPromise,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,6 +232,7 @@ export default class RightPanel extends React.Component {
|
|||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
phase={this.state.phase}
|
phase={this.state.phase}
|
||||||
verificationRequest={this.state.verificationRequest}
|
verificationRequest={this.state.verificationRequest}
|
||||||
|
verificationRequestPromise={this.state.verificationRequestPromise}
|
||||||
/>;
|
/>;
|
||||||
} else {
|
} else {
|
||||||
panel = <MemberInfo
|
panel = <MemberInfo
|
||||||
|
@ -121,10 +121,12 @@ export default class MessageActionBar extends React.PureComponent {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
|
this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
|
||||||
|
this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted);
|
this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted);
|
||||||
|
this.props.mxEvent.removeListener("Event.beforeRedaction", this.onBeforeRedaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDecrypted = () => {
|
onDecrypted = () => {
|
||||||
@ -133,6 +135,11 @@ export default class MessageActionBar extends React.PureComponent {
|
|||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onBeforeRedaction = () => {
|
||||||
|
// When an event is redacted, we can't edit it so update the available actions.
|
||||||
|
this.forceUpdate();
|
||||||
|
};
|
||||||
|
|
||||||
onFocusChange = (focused) => {
|
onFocusChange = (focused) => {
|
||||||
if (!this.props.onFocusChange) {
|
if (!this.props.onFocusChange) {
|
||||||
return;
|
return;
|
||||||
|
@ -30,7 +30,7 @@ import {_t} from "../../../languageHandler";
|
|||||||
// cancellation codes which constitute a key mismatch
|
// cancellation codes which constitute a key mismatch
|
||||||
const MISMATCHES = ["m.key_mismatch", "m.user_error", "m.mismatched_sas"];
|
const MISMATCHES = ["m.key_mismatch", "m.user_error", "m.mismatched_sas"];
|
||||||
|
|
||||||
const EncryptionPanel = ({verificationRequest, member, onClose, layout}) => {
|
const EncryptionPanel = ({verificationRequest, verificationRequestPromise, member, onClose, layout}) => {
|
||||||
const [request, setRequest] = useState(verificationRequest);
|
const [request, setRequest] = useState(verificationRequest);
|
||||||
// state to show a spinner immediately after clicking "start verification",
|
// state to show a spinner immediately after clicking "start verification",
|
||||||
// before we have a request
|
// before we have a request
|
||||||
@ -43,6 +43,19 @@ const EncryptionPanel = ({verificationRequest, member, onClose, layout}) => {
|
|||||||
setPhase(verificationRequest.phase);
|
setPhase(verificationRequest.phase);
|
||||||
}
|
}
|
||||||
}, [verificationRequest]);
|
}, [verificationRequest]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function awaitPromise() {
|
||||||
|
setRequesting(true);
|
||||||
|
const request = await verificationRequestPromise;
|
||||||
|
setRequesting(false);
|
||||||
|
setRequest(request);
|
||||||
|
setPhase(request.phase);
|
||||||
|
}
|
||||||
|
if (verificationRequestPromise) {
|
||||||
|
awaitPromise();
|
||||||
|
}
|
||||||
|
}, [verificationRequestPromise]);
|
||||||
const changeHandler = useCallback(() => {
|
const changeHandler = useCallback(() => {
|
||||||
// handle transitions -> cancelled for mismatches which fire a modal instead of showing a card
|
// handle transitions -> cancelled for mismatches which fire a modal instead of showing a card
|
||||||
if (request && request.cancelled && MISMATCHES.includes(request.cancellationCode)) {
|
if (request && request.cancelled && MISMATCHES.includes(request.cancellationCode)) {
|
||||||
|
@ -171,14 +171,14 @@ async function verifyDevice(userId, device) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const verificationRequest = await cli.requestVerification(
|
const verificationRequestPromise = cli.requestVerification(
|
||||||
userId,
|
userId,
|
||||||
[device.deviceId],
|
[device.deviceId],
|
||||||
);
|
);
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: "set_right_panel_phase",
|
action: "set_right_panel_phase",
|
||||||
phase: RIGHT_PANEL_PHASES.EncryptionPanel,
|
phase: RIGHT_PANEL_PHASES.EncryptionPanel,
|
||||||
refireParams: {member, verificationRequest},
|
refireParams: {member, verificationRequestPromise},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
primaryButton: _t("Done"),
|
primaryButton: _t("Done"),
|
||||||
|
@ -880,9 +880,6 @@ export default createReactClass({
|
|||||||
// 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 (
|
||||||
<div className={classes} tabIndex={-1}>
|
<div className={classes} tabIndex={-1}>
|
||||||
<div className="mx_EventTile_msgOption">
|
|
||||||
{ readAvatars }
|
|
||||||
</div>
|
|
||||||
{ sender }
|
{ sender }
|
||||||
<div className="mx_EventTile_line">
|
<div className="mx_EventTile_line">
|
||||||
<a
|
<a
|
||||||
@ -906,6 +903,9 @@ export default createReactClass({
|
|||||||
{ reactionsRow }
|
{ reactionsRow }
|
||||||
{ actionBar }
|
{ actionBar }
|
||||||
</div>
|
</div>
|
||||||
|
<div className="mx_EventTile_msgOption">
|
||||||
|
{ readAvatars }
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
// The avatar goes after the event tile as it's absolutely positioned to be over the
|
// The avatar goes after the event tile as it's absolutely positioned to be over the
|
||||||
// event tile line, so needs to be later in the DOM so it appears on top (this avoids
|
// event tile line, so needs to be later in the DOM so it appears on top (this avoids
|
||||||
|
@ -490,16 +490,16 @@ export default createReactClass({
|
|||||||
height="13"
|
height="13"
|
||||||
alt="dm"
|
alt="dm"
|
||||||
/>;
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
const { room } = this.props;
|
const { room } = this.props;
|
||||||
const member = room.getMember(dmUserId);
|
const member = room.getMember(dmUserId);
|
||||||
if (
|
if (
|
||||||
member && member.membership === "join" && room.getJoinedMemberCount() === 2 &&
|
member && member.membership === "join" && room.getJoinedMemberCount() === 2 &&
|
||||||
SettingsStore.isFeatureEnabled("feature_presence_in_room_list")
|
SettingsStore.isFeatureEnabled("feature_presence_in_room_list")
|
||||||
) {
|
) {
|
||||||
const UserOnlineDot = sdk.getComponent('rooms.UserOnlineDot');
|
const UserOnlineDot = sdk.getComponent('rooms.UserOnlineDot');
|
||||||
dmOnline = <UserOnlineDot userId={dmUserId} />;
|
dmOnline = <UserOnlineDot userId={dmUserId} />;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following labels are written in such a fashion to increase screen reader efficiency (speed).
|
// The following labels are written in such a fashion to increase screen reader efficiency (speed).
|
||||||
|
@ -27,6 +27,7 @@ export default createReactClass({
|
|||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
onScrollUpClick: PropTypes.func,
|
onScrollUpClick: PropTypes.func,
|
||||||
|
onCloseClick: PropTypes.func,
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
@ -36,6 +37,10 @@ export default createReactClass({
|
|||||||
title={_t('Jump to first unread message.')}
|
title={_t('Jump to first unread message.')}
|
||||||
onClick={this.props.onScrollUpClick}>
|
onClick={this.props.onScrollUpClick}>
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
<AccessibleButton className="mx_TopUnreadMessagesBar_markAsRead"
|
||||||
|
title={_t('Mark all as read')}
|
||||||
|
onClick={this.props.onCloseClick}>
|
||||||
|
</AccessibleButton>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1145,6 +1145,7 @@
|
|||||||
"Revoke invite": "Revoke invite",
|
"Revoke invite": "Revoke invite",
|
||||||
"Invited by %(sender)s": "Invited by %(sender)s",
|
"Invited by %(sender)s": "Invited by %(sender)s",
|
||||||
"Jump to first unread message.": "Jump to first unread message.",
|
"Jump to first unread message.": "Jump to first unread message.",
|
||||||
|
"Mark all as read": "Mark all as read",
|
||||||
"Error updating main address": "Error updating main address",
|
"Error updating main address": "Error updating main address",
|
||||||
"There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.",
|
"There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.": "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.",
|
||||||
"Error creating alias": "Error creating alias",
|
"Error creating alias": "Error creating alias",
|
||||||
@ -2134,13 +2135,13 @@
|
|||||||
"If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.",
|
"If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.",
|
||||||
"If disabled, messages from encrypted rooms won't appear in search results.": "If disabled, messages from encrypted rooms won't appear in search results.",
|
"If disabled, messages from encrypted rooms won't appear in search results.": "If disabled, messages from encrypted rooms won't appear in search results.",
|
||||||
"Disable": "Disable",
|
"Disable": "Disable",
|
||||||
"Not currently downloading messages for any room.": "Not currently downloading messages for any room.",
|
"Not currently indexing messages for any room.": "Not currently indexing messages for any room.",
|
||||||
"Downloading mesages for %(currentRoom)s.": "Downloading mesages for %(currentRoom)s.",
|
"Currently indexing: %(currentRoom)s.": "Currently indexing: %(currentRoom)s.",
|
||||||
"Riot is securely caching encrypted messages locally for them to appear in search results:": "Riot is securely caching encrypted messages locally for them to appear in search results:",
|
"Riot is securely caching encrypted messages locally for them to appear in search results:": "Riot is securely caching encrypted messages locally for them to appear in search results:",
|
||||||
"Space used:": "Space used:",
|
"Space used:": "Space used:",
|
||||||
"Indexed messages:": "Indexed messages:",
|
"Indexed messages:": "Indexed messages:",
|
||||||
"Indexed rooms:": "Indexed rooms:",
|
"Indexed rooms:": "Indexed rooms:",
|
||||||
"%(crawlingRooms)s out of %(totalRooms)s": "%(crawlingRooms)s out of %(totalRooms)s",
|
"%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s out of %(totalRooms)s",
|
||||||
"Message downloading sleep time(ms)": "Message downloading sleep time(ms)",
|
"Message downloading sleep time(ms)": "Message downloading sleep time(ms)",
|
||||||
"Failed to set direct chat tag": "Failed to set direct chat tag",
|
"Failed to set direct chat tag": "Failed to set direct chat tag",
|
||||||
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
|
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
|
||||||
|
@ -46,7 +46,7 @@ export function isContentActionable(mxEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function canEditContent(mxEvent) {
|
export function canEditContent(mxEvent) {
|
||||||
if (mxEvent.status === EventStatus.CANCELLED || mxEvent.getType() !== "m.room.message") {
|
if (mxEvent.status === EventStatus.CANCELLED || mxEvent.getType() !== "m.room.message" || mxEvent.isRedacted()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const content = mxEvent.getOriginalContent();
|
const content = mxEvent.getOriginalContent();
|
||||||
|
Loading…
Reference in New Issue
Block a user