diff --git a/res/css/views/rooms/_InviteOnlyIcon.scss b/res/css/views/rooms/_InviteOnlyIcon.scss index e70586bb73..f4d9e4869f 100644 --- a/res/css/views/rooms/_InviteOnlyIcon.scss +++ b/res/css/views/rooms/_InviteOnlyIcon.scss @@ -20,7 +20,7 @@ limitations under the License. position: relative; display: block !important; // Align the padlock with unencrypted room names - margin-left: 6px; + margin: 0 4px; &::before { background-color: $roomtile-name-color; diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index fae9d0dfe3..a05b4c0c0e 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -76,8 +76,8 @@ limitations under the License. left: 60px; margin-right: 0; // Counteract the E2EIcon class margin-left: 3px; // Counteract the E2EIcon class - width: 12px; - height: 12px; + width: 15px; + height: 15px; } .mx_MessageComposer_noperm_error { diff --git a/res/css/views/rooms/_RoomHeader.scss b/res/css/views/rooms/_RoomHeader.scss index 6f0377b29c..47b8131ef0 100644 --- a/res/css/views/rooms/_RoomHeader.scss +++ b/res/css/views/rooms/_RoomHeader.scss @@ -21,10 +21,10 @@ limitations under the License. .mx_E2EIcon { margin: 0; position: absolute; - bottom: -1px; - right: -2px; - height: 10px; - width: 10px; + bottom: -2px; + right: -6px; + height: 15px; + width: 15px; } } diff --git a/res/css/views/rooms/_RoomTile.scss b/res/css/views/rooms/_RoomTile.scss index a24fdf2629..31d887cbbb 100644 --- a/res/css/views/rooms/_RoomTile.scss +++ b/res/css/views/rooms/_RoomTile.scss @@ -101,19 +101,19 @@ limitations under the License. // Note we match .mx_E2EIcon to make sure this matches more tightly than just // .mx_E2EIcon on its own .mx_RoomTile_e2eIcon.mx_E2EIcon { - height: 10px; - width: 10px; + height: 14px; + width: 14px; display: block; position: absolute; - bottom: -1px; - right: -2px; + bottom: -2px; + right: -5px; z-index: 1; margin: 0; } .mx_RoomTile_name { font-size: 14px; - padding: 0 6px; + padding: 0 4px; color: $roomtile-name-color; white-space: nowrap; overflow-x: hidden; @@ -214,8 +214,3 @@ limitations under the License. .mx_GroupInviteTile .mx_RoomTile_name { flex: 1; } - -.mx_InviteOnlyIcon + .mx_RoomTile_nameContainer .mx_RoomTile_name { - // Scoot the padding in a bit from 6px to make it look better - padding-left: 3px; -} diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index e708fad6a4..25526c3139 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -1171,28 +1171,40 @@ const TimelinePanel = createReactClass({ // get the user's membership at the last event by getting the timeline // that the event belongs to, and traversing the timeline looking for // that event, while keeping track of the user's membership - const lastEvent = events[events.length - 1]; - const timeline = room.getTimelineForEvent(lastEvent.getId()); - const userMembershipEvent = - timeline.getState(EventTimeline.FORWARDS).getMember(userId); - let userMembership = userMembershipEvent - ? userMembershipEvent.membership : "leave"; - const timelineEvents = timeline.getEvents(); - for (let i = timelineEvents.length - 1; i >= 0; i--) { - const event = timelineEvents[i]; - if (event.getId() === lastEvent.getId()) { - // found the last event, so we can stop looking through the timeline - break; - } else if (event.getStateKey() === userId - && event.getType() === "m.room.member") { - const prevContent = event.getPrevContent(); - userMembership = prevContent.membership || "leave"; + let i; + let userMembership = "leave"; + for (i = events.length - 1; i >= 0; i--) { + const timeline = room.getTimelineForEvent(events[i].getId()); + if (!timeline) { + // Somehow, it seems to be possible for live events to not have + // a timeline, even though that should not happen. :( + // https://github.com/vector-im/riot-web/issues/12120 + console.warn( + `Event ${events[i].getId()} in room ${room.roomId} is live, ` + + `but it does not have a timeline`, + ); + continue; } + const userMembershipEvent = + timeline.getState(EventTimeline.FORWARDS).getMember(userId); + userMembership = userMembershipEvent ? userMembershipEvent.membership : "leave"; + const timelineEvents = timeline.getEvents(); + for (let j = timelineEvents.length - 1; j >= 0; j--) { + const event = timelineEvents[j]; + if (event.getId() === events[i].getId()) { + break; + } else if (event.getStateKey() === userId + && event.getType() === "m.room.member") { + const prevContent = event.getPrevContent(); + userMembership = prevContent.membership || "leave"; + } + } + break; } - // now go through the events that we have and find the first undecryptable + // now go through the rest of the events and find the first undecryptable // one that was sent when the user wasn't in the room - for (let i = events.length - 1; i >= 0; i--) { + for (; i >= 0; i--) { const event = events[i]; if (event.getStateKey() === userId && event.getType() === "m.room.member") { diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js index 67e1649bb9..f2368ad795 100644 --- a/src/components/views/dialogs/DeviceVerifyDialog.js +++ b/src/components/views/dialogs/DeviceVerifyDialog.js @@ -194,10 +194,7 @@ export default class DeviceVerifyDialog extends React.Component { { _t("Verify by comparing a short text string.") }
- {_t( - "For maximum security, we recommend you do this in person or " + - "use another trusted means of communication.", - )} + {_t("To be secure, do this in person or use a trusted way to communicate.")}
{_t("For extra security, verify this user by checking a one-time code on both of your devices.")}
-{_t("For maximum security, do this in person.")}
+{_t("To be secure, do this in person or use a trusted way to communicate.")}
{ content }{sasCaption}
-{_t("For ultimate security, do this in person or use another way to communicate.")}
+{_t("To be secure, do this in person or use a trusted way to communicate.")}
{sasDisplay} {confirm}