mirror of https://github.com/vector-im/riot-web
Make encryption events into bubble-style tiles
Factors out the verification tile stuff into encryption event styles so we can reuse them betwen all the encryption event tiles. Also makes the event list summary stuff even more gnarly by putting the encryption event tile above the group. We really need to refactor that. :/ Fixes https://github.com/vector-im/riot-web/issues/12006pull/21833/head
parent
8a09cfbfbd
commit
39e9bffe1f
|
@ -128,7 +128,6 @@
|
||||||
@import "./views/messages/_MEmoteBody.scss";
|
@import "./views/messages/_MEmoteBody.scss";
|
||||||
@import "./views/messages/_MFileBody.scss";
|
@import "./views/messages/_MFileBody.scss";
|
||||||
@import "./views/messages/_MImageBody.scss";
|
@import "./views/messages/_MImageBody.scss";
|
||||||
@import "./views/messages/_MKeyVerificationRequest.scss";
|
|
||||||
@import "./views/messages/_MNoticeBody.scss";
|
@import "./views/messages/_MNoticeBody.scss";
|
||||||
@import "./views/messages/_MStickerBody.scss";
|
@import "./views/messages/_MStickerBody.scss";
|
||||||
@import "./views/messages/_MTextBody.scss";
|
@import "./views/messages/_MTextBody.scss";
|
||||||
|
@ -143,6 +142,7 @@
|
||||||
@import "./views/messages/_TextualEvent.scss";
|
@import "./views/messages/_TextualEvent.scss";
|
||||||
@import "./views/messages/_UnknownBody.scss";
|
@import "./views/messages/_UnknownBody.scss";
|
||||||
@import "./views/messages/_ViewSourceEvent.scss";
|
@import "./views/messages/_ViewSourceEvent.scss";
|
||||||
|
@import "./views/messages/_common_CryptoEvent.scss";
|
||||||
@import "./views/right_panel/_EncryptionInfo.scss";
|
@import "./views/right_panel/_EncryptionInfo.scss";
|
||||||
@import "./views/right_panel/_UserInfo.scss";
|
@import "./views/right_panel/_UserInfo.scss";
|
||||||
@import "./views/right_panel/_VerificationPanel.scss";
|
@import "./views/right_panel/_VerificationPanel.scss";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,60 +14,62 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.mx_KeyVerification {
|
.mx_cryptoEvent {
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 24px minmax(0, 1fr) min-content;
|
grid-template-columns: 24px minmax(0, 1fr) min-content;
|
||||||
|
|
||||||
&.mx_KeyVerification_icon::after {
|
&.mx_cryptoEvent_icon::after {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
grid-row: 1 / 3;
|
grid-row: 1 / 3;
|
||||||
width: 12px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
content: "";
|
content: "";
|
||||||
mask-image: url("$(res)/img/e2e/normal.svg");
|
background-image: url("$(res)/img/e2e/normal.svg");
|
||||||
mask-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
mask-size: 100%;
|
background-size: 100%;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
background-color: $primary-fg-color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mx_KeyVerification_icon_verified::after {
|
&.mx_cryptoEvent_icon_verified::after {
|
||||||
mask-image: url("$(res)/img/e2e/verified.svg");
|
background-image: url("$(res)/img/e2e/verified.svg");
|
||||||
background-color: $accent-color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_KeyVerification_title, .mx_KeyVerification_subtitle, .mx_KeyVerification_state {
|
&.mx_cryptoEvent_icon_warning::after {
|
||||||
|
background-image: url("$(res)/img/e2e/warning.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_cryptoEvent_title, .mx_cryptoEvent_subtitle, .mx_cryptoEvent_state {
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_KeyVerification_title {
|
.mx_cryptoEvent_title {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_KeyVerification_subtitle {
|
.mx_cryptoEvent_subtitle {
|
||||||
grid-column: 2;
|
grid-column: 2;
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_KeyVerification_state, .mx_KeyVerification_subtitle {
|
.mx_cryptoEvent_state, .mx_cryptoEvent_subtitle {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_KeyVerification_state, .mx_KeyVerification_buttons {
|
.mx_cryptoEvent_state, .mx_cryptoEvent_buttons {
|
||||||
grid-column: 3;
|
grid-column: 3;
|
||||||
grid-row: 1 / 3;
|
grid-row: 1 / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_KeyVerification_buttons {
|
.mx_cryptoEvent_buttons {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_KeyVerification_state {
|
.mx_cryptoEvent_state {
|
||||||
width: 130px;
|
width: 130px;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
margin: auto 0;
|
margin: auto 0;
|
|
@ -465,6 +465,12 @@ export default class MessagePanel extends React.Component {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
// events that we include in the group but then eject out and place
|
||||||
|
// above the group.
|
||||||
|
const shouldEject = (ev) => {
|
||||||
|
if (ev.getType() === "m.room.encryption") return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
if (mxEv.getType() === "m.room.create") {
|
if (mxEv.getType() === "m.room.create") {
|
||||||
let summaryReadMarker = null;
|
let summaryReadMarker = null;
|
||||||
const ts1 = mxEv.getTs();
|
const ts1 = mxEv.getTs();
|
||||||
|
@ -484,6 +490,7 @@ export default class MessagePanel extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const summarisedEvents = []; // Don't add m.room.create here as we don't want it inside the summary
|
const summarisedEvents = []; // Don't add m.room.create here as we don't want it inside the summary
|
||||||
|
const ejectedEvents = [];
|
||||||
for (;i + 1 < this.props.events.length; i++) {
|
for (;i + 1 < this.props.events.length; i++) {
|
||||||
const collapsedMxEv = this.props.events[i + 1];
|
const collapsedMxEv = this.props.events[i + 1];
|
||||||
|
|
||||||
|
@ -501,7 +508,11 @@ export default class MessagePanel extends React.Component {
|
||||||
// If RM event is in the summary, mark it as such and the RM will be appended after the summary.
|
// If RM event is in the summary, mark it as such and the RM will be appended after the summary.
|
||||||
summaryReadMarker = summaryReadMarker || this._readMarkerForEvent(collapsedMxEv.getId());
|
summaryReadMarker = summaryReadMarker || this._readMarkerForEvent(collapsedMxEv.getId());
|
||||||
|
|
||||||
summarisedEvents.push(collapsedMxEv);
|
if (shouldEject(collapsedMxEv)) {
|
||||||
|
ejectedEvents.push(collapsedMxEv);
|
||||||
|
} else {
|
||||||
|
summarisedEvents.push(collapsedMxEv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, i = the index of the last event in the summary sequence
|
// At this point, i = the index of the last event in the summary sequence
|
||||||
|
@ -513,6 +524,10 @@ export default class MessagePanel extends React.Component {
|
||||||
return this._getTilesForEvent(e, e, e === lastShownEvent);
|
return this._getTilesForEvent(e, e, e === lastShownEvent);
|
||||||
}).reduce((a, b) => a.concat(b), []);
|
}).reduce((a, b) => a.concat(b), []);
|
||||||
|
|
||||||
|
for (const ejected of ejectedEvents) {
|
||||||
|
ret.push(...this._getTilesForEvent(mxEv, ejected, last));
|
||||||
|
}
|
||||||
|
|
||||||
// Get sender profile from the latest event in the summary as the m.room.create doesn't contain one
|
// Get sender profile from the latest event in the summary as the m.room.create doesn't contain one
|
||||||
const ev = this.props.events[i];
|
const ev = this.props.events[i];
|
||||||
ret.push(<EventListSummary
|
ret.push(<EventListSummary
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -94,12 +94,12 @@ export default class MKeyVerificationConclusion extends React.Component {
|
||||||
|
|
||||||
if (title) {
|
if (title) {
|
||||||
const subtitle = userLabelForEventRoom(request.otherUserId, mxEvent.getRoomId());
|
const subtitle = userLabelForEventRoom(request.otherUserId, mxEvent.getRoomId());
|
||||||
const classes = classNames("mx_EventTile_bubble", "mx_KeyVerification", "mx_KeyVerification_icon", {
|
const classes = classNames("mx_EventTile_bubble", "mx_cryptoEvent", "mx_cryptoEvent_icon", {
|
||||||
mx_KeyVerification_icon_verified: request.done,
|
mx_cryptoEvent_icon_verified: request.done,
|
||||||
});
|
});
|
||||||
return (<div className={classes}>
|
return (<div className={classes}>
|
||||||
<div className="mx_KeyVerification_title">{title}</div>
|
<div className="mx_cryptoEvent_title">{title}</div>
|
||||||
<div className="mx_KeyVerification_subtitle">{subtitle}</div>
|
<div className="mx_cryptoEvent_subtitle">{subtitle}</div>
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -125,30 +125,30 @@ export default class MKeyVerificationRequest extends React.Component {
|
||||||
} else {
|
} else {
|
||||||
stateLabel = this._cancelledLabel(request.cancellingUserId);
|
stateLabel = this._cancelledLabel(request.cancellingUserId);
|
||||||
}
|
}
|
||||||
stateNode = (<div className="mx_KeyVerification_state">{stateLabel}</div>);
|
stateNode = (<div className="mx_cryptoEvent_state">{stateLabel}</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request.initiatedByMe) {
|
if (!request.initiatedByMe) {
|
||||||
const name = getNameForEventRoom(request.requestingUserId, mxEvent.getRoomId());
|
const name = getNameForEventRoom(request.requestingUserId, mxEvent.getRoomId());
|
||||||
title = (<div className="mx_KeyVerification_title">{
|
title = (<div className="mx_cryptoEvent_title">{
|
||||||
_t("%(name)s wants to verify", {name})}</div>);
|
_t("%(name)s wants to verify", {name})}</div>);
|
||||||
subtitle = (<div className="mx_KeyVerification_subtitle">{
|
subtitle = (<div className="mx_cryptoEvent_subtitle">{
|
||||||
userLabelForEventRoom(request.requestingUserId, mxEvent.getRoomId())}</div>);
|
userLabelForEventRoom(request.requestingUserId, mxEvent.getRoomId())}</div>);
|
||||||
if (request.requested && !request.observeOnly) {
|
if (request.requested && !request.observeOnly) {
|
||||||
stateNode = (<div className="mx_KeyVerification_buttons">
|
stateNode = (<div className="mx_cryptoEvent_buttons">
|
||||||
<FormButton kind="danger" onClick={this._onRejectClicked} label={_t("Decline")} />
|
<FormButton kind="danger" onClick={this._onRejectClicked} label={_t("Decline")} />
|
||||||
<FormButton onClick={this._onAcceptClicked} label={_t("Accept")} />
|
<FormButton onClick={this._onAcceptClicked} label={_t("Accept")} />
|
||||||
</div>);
|
</div>);
|
||||||
}
|
}
|
||||||
} else { // request sent by us
|
} else { // request sent by us
|
||||||
title = (<div className="mx_KeyVerification_title">{
|
title = (<div className="mx_cryptoEvent_title">{
|
||||||
_t("You sent a verification request")}</div>);
|
_t("You sent a verification request")}</div>);
|
||||||
subtitle = (<div className="mx_KeyVerification_subtitle">{
|
subtitle = (<div className="mx_cryptoEvent_subtitle">{
|
||||||
userLabelForEventRoom(request.receivingUserId, mxEvent.getRoomId())}</div>);
|
userLabelForEventRoom(request.receivingUserId, mxEvent.getRoomId())}</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title) {
|
if (title) {
|
||||||
return (<div className="mx_EventTile_bubble mx_KeyVerification mx_KeyVerification_icon">
|
return (<div className="mx_EventTile_bubble mx_cryptoEvent mx_cryptoEvent_icon">
|
||||||
{title}
|
{title}
|
||||||
{subtitle}
|
{subtitle}
|
||||||
{stateNode}
|
{stateNode}
|
||||||
|
|
|
@ -40,12 +40,14 @@ const eventTileTypes = {
|
||||||
'm.sticker': 'messages.MessageEvent',
|
'm.sticker': 'messages.MessageEvent',
|
||||||
'm.key.verification.cancel': 'messages.MKeyVerificationConclusion',
|
'm.key.verification.cancel': 'messages.MKeyVerificationConclusion',
|
||||||
'm.key.verification.done': 'messages.MKeyVerificationConclusion',
|
'm.key.verification.done': 'messages.MKeyVerificationConclusion',
|
||||||
|
'm.room.encryption': 'messages.EncryptionEvent',
|
||||||
'm.call.invite': 'messages.TextualEvent',
|
'm.call.invite': 'messages.TextualEvent',
|
||||||
'm.call.answer': 'messages.TextualEvent',
|
'm.call.answer': 'messages.TextualEvent',
|
||||||
'm.call.hangup': 'messages.TextualEvent',
|
'm.call.hangup': 'messages.TextualEvent',
|
||||||
};
|
};
|
||||||
|
|
||||||
const stateEventTileTypes = {
|
const stateEventTileTypes = {
|
||||||
|
'm.room.encryption': 'messages.EncryptionEvent',
|
||||||
'm.room.aliases': 'messages.TextualEvent',
|
'm.room.aliases': 'messages.TextualEvent',
|
||||||
// 'm.room.aliases': 'messages.RoomAliasesEvent', // too complex
|
// 'm.room.aliases': 'messages.RoomAliasesEvent', // too complex
|
||||||
'm.room.canonical_alias': 'messages.TextualEvent',
|
'm.room.canonical_alias': 'messages.TextualEvent',
|
||||||
|
@ -55,7 +57,6 @@ const stateEventTileTypes = {
|
||||||
'm.room.avatar': 'messages.RoomAvatarEvent',
|
'm.room.avatar': 'messages.RoomAvatarEvent',
|
||||||
'm.room.third_party_invite': 'messages.TextualEvent',
|
'm.room.third_party_invite': 'messages.TextualEvent',
|
||||||
'm.room.history_visibility': 'messages.TextualEvent',
|
'm.room.history_visibility': 'messages.TextualEvent',
|
||||||
'm.room.encryption': 'messages.TextualEvent',
|
|
||||||
'm.room.topic': 'messages.TextualEvent',
|
'm.room.topic': 'messages.TextualEvent',
|
||||||
'm.room.power_levels': 'messages.TextualEvent',
|
'm.room.power_levels': 'messages.TextualEvent',
|
||||||
'm.room.pinned_events': 'messages.TextualEvent',
|
'm.room.pinned_events': 'messages.TextualEvent',
|
||||||
|
@ -600,7 +601,8 @@ export default createReactClass({
|
||||||
|
|
||||||
// Info messages are basically information about commands processed on a room
|
// Info messages are basically information about commands processed on a room
|
||||||
const isBubbleMessage = eventType.startsWith("m.key.verification") ||
|
const isBubbleMessage = eventType.startsWith("m.key.verification") ||
|
||||||
(eventType === "m.room.message" && msgtype && msgtype.startsWith("m.key.verification"));
|
(eventType === "m.room.message" && msgtype && msgtype.startsWith("m.key.verification")) ||
|
||||||
|
(eventType === "m.room.encryption");
|
||||||
let isInfoMessage = (
|
let isInfoMessage = (
|
||||||
!isBubbleMessage && eventType !== 'm.room.message' &&
|
!isBubbleMessage && eventType !== 'm.room.message' &&
|
||||||
eventType !== 'm.sticker' && eventType !== 'm.room.create'
|
eventType !== 'm.sticker' && eventType !== 'm.room.create'
|
||||||
|
|
|
@ -1194,6 +1194,10 @@
|
||||||
"Today": "Today",
|
"Today": "Today",
|
||||||
"Yesterday": "Yesterday",
|
"Yesterday": "Yesterday",
|
||||||
"View Source": "View Source",
|
"View Source": "View Source",
|
||||||
|
"Encryption enabled": "Encryption enabled",
|
||||||
|
"Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.": "Messages in this room are end-to-end encrypted. Learn more & verify this user in their user profile.",
|
||||||
|
"Encryption not enabled": "Encryption not enabled",
|
||||||
|
"The encryption used by this room isn't supported": "The encryption used by this room isn't supported",
|
||||||
"Error decrypting audio": "Error decrypting audio",
|
"Error decrypting audio": "Error decrypting audio",
|
||||||
"React": "React",
|
"React": "React",
|
||||||
"Reply": "Reply",
|
"Reply": "Reply",
|
||||||
|
|
Loading…
Reference in New Issue