Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Show room intro at beginning of visible history
Browse files Browse the repository at this point in the history
When the user has reached the beginning of visible history in a room,
show them a room intro to explain why messages before that point are
unavailable and reassure them that the timeline has loaded.

Signed-off-by: Robin Townsend <robin@robin.town>
  • Loading branch information
robintown committed Apr 25, 2021
1 parent 6430168 commit 0063fd2
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 5 deletions.
12 changes: 9 additions & 3 deletions src/components/structures/MessagePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {textForEvent} from "../../TextForEvent";
import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResizer";
import DMRoomMap from "../../utils/DMRoomMap";
import NewRoomIntro from "../views/rooms/NewRoomIntro";
import RoomHistoryIntro from "../views/rooms/RoomHistoryIntro";
import {replaceableComponent} from "../../utils/replaceableComponent";

const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
Expand Down Expand Up @@ -106,8 +107,8 @@ export default class MessagePanel extends React.Component {
// for pending messages.
ourUserId: PropTypes.string,

// true to suppress the date at the start of the timeline
suppressFirstDateSeparator: PropTypes.bool,
// whether the timeline can visually go back any further
canBackPaginate: PropTypes.bool,

// whether to show read receipts
showReadReceipts: PropTypes.bool,
Expand Down Expand Up @@ -672,7 +673,7 @@ export default class MessagePanel extends React.Component {
if (prevEvent == null) {
// first event in the panel: depends if we could back-paginate from
// here.
return !this.props.suppressFirstDateSeparator;
return !this.props.canBackPaginate;
}
return wantsDateSeparator(prevEvent.getDate(), nextEventDate);
}
Expand Down Expand Up @@ -1220,6 +1221,11 @@ class MemberGrouper {
eventTiles = null;
}

// If a membership event is the start of visible history, show a room intro
if (!this.panel.props.canBackPaginate && !this.prevEvent) {
ret.push(<RoomHistoryIntro key="roomhistoryintro" />);
}

ret.push(
<MemberEventListSummary key={key}
events={this.events}
Expand Down
2 changes: 1 addition & 1 deletion src/components/structures/TimelinePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,7 @@ class TimelinePanel extends React.Component {
highlightedEventId={this.props.highlightedEventId}
readMarkerEventId={this.state.readMarkerEventId}
readMarkerVisible={this.state.readMarkerVisible}
suppressFirstDateSeparator={this.state.canBackPaginate && this.state.firstVisibleEventIndex === 0}
canBackPaginate={this.state.canBackPaginate && this.state.firstVisibleEventIndex === 0}
showUrlPreview={this.props.showUrlPreview}
showReadReceipts={this.props.showReadReceipts}
ourUserId={MatrixClientPeg.get().credentials.userId}
Expand Down
136 changes: 136 additions & 0 deletions src/components/views/rooms/RoomHistoryIntro.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import React, {useContext} from "react";
import {EventType} from "matrix-js-sdk/src/@types/event";
import {EventTimeline} from "matrix-js-sdk/src/models/event-timeline";

import RoomIntro from "./RoomIntro";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import RoomContext from "../../../contexts/RoomContext";
import DMRoomMap from "../../../utils/DMRoomMap";
import {_t} from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
import dis from "../../../dispatcher/dispatcher";

const RoomHistoryIntro = () => {
const cli = useContext(MatrixClientContext);
const {room, roomId} = useContext(RoomContext);

const oldState = room.getLiveTimeline().getState(EventTimeline.BACKWARDS);
const encryptionState = oldState.getStateEvents("m.room.encryption")[0];
let historyState = oldState.getStateEvents("m.room.history_visibility")[0];
historyState = historyState && historyState.getContent().history_visibility;

const dmPartner = DMRoomMap.shared().getUserIdForRoomId(roomId);
if (dmPartner) {
const member = room?.getMember(dmPartner);
const displayName = member?.rawDisplayName || dmPartner;

let caption1;
if (encryptionState) {
caption1 = _t("This is the beginning of your visible history with <displayName/>, "
+ "as encrypted messages before this point are unavailable.", {}, {
displayName: () => <b>{ displayName }</b>,
});
} else if (historyState == "invited") {
caption1 = _t("This is the beginning of your visible history with <displayName/>, "
+ "as the room's admins have restricted your ability to view messages "
+ "from before you were invited.", {}, {
displayName: () => <b>{ displayName }</b>,
});
} else if (historyState == "joined") {
caption1 = _t("This is the beginning of your visible history with <displayName/>, "
+ "as the room's admins have restricted your ability to view messages "
+ "from before you joined.", {}, {
displayName: () => <b>{ displayName }</b>,
});
} else {
caption1 = _t("This is the beginning of your visible history with <displayName/>.", {}, {
displayName: () => <b>{ displayName }</b>,
});
}

let caption2;
if ((room.getJoinedMemberCount() + room.getInvitedMemberCount()) === 2) {
caption2 = _t("Only the two of you are in this conversation, unless either of you invites anyone to join.");
}

return <RoomIntro>
<p>{ caption1 }</p>
{ caption2 && <p>{ caption2 }</p> }
</RoomIntro>;
} else {
const inRoom = room && room.getMyMembership() === "join";
const topic = room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic;
const canAddTopic = inRoom && room.currentState.maySendStateEvent(EventType.RoomTopic, cli.getUserId());

const onTopicClick = () => {
dis.dispatch({
action: "open_room_settings",
room_id: roomId,
}, true);
// focus the topic field to help the user find it as it'll gain an outline
setImmediate(() => {
window.document.getElementById("profileTopic").focus();
});
};

let topicText;
if (canAddTopic && topic) {
topicText = _t("Topic: %(topic)s (<a>edit</a>)", { topic }, {
a: sub => <AccessibleButton kind="link" onClick={onTopicClick}>{ sub }</AccessibleButton>,
});
} else if (topic) {
topicText = _t("Topic: %(topic)s ", { topic });
} else if (canAddTopic) {
topicText = _t("<a>Add a topic</a> to help people know what it is about.", {}, {
a: sub => <AccessibleButton kind="link" onClick={onTopicClick}>{ sub }</AccessibleButton>,
});
}

let caption;
if (encryptionState) {
caption = _t("This is the beginning of your visible history in <roomName/>, "
+ "as encrypted messages before this point are unavailable.", {}, {
roomName: () => <b>{ room.name }</b>,
});
} else if (historyState == "invited") {
caption = _t("This is the beginning of your visible history in <roomName/>, "
+ "as the room's admins have restricted your ability to view messages "
+ "from before you were invited.", {}, {
roomName: () => <b>{ room.name }</b>,
});
} else if (historyState == "joined") {
caption = _t("This is the beginning of your visible history in <roomName/>, "
+ "as the room's admins have restricted your ability to view messages "
+ "from before you joined.", {}, {
roomName: () => <b>{ room.name }</b>,
});
} else {
caption = _t("This is the beginning of your visible history in <roomName/>.", {}, {
roomName: () => <b>{ room.name }</b>,
});
}

return <RoomIntro>
<p>{ caption }</p>
{ topicText && <p>{ topicText }</p> }
</RoomIntro>;
}
};

export default RoomHistoryIntro;
10 changes: 9 additions & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1487,7 +1487,6 @@
"You created this room.": "You created this room.",
"%(displayName)s created this room.": "%(displayName)s created this room.",
"Invite to just this room": "Invite to just this room",
"Add a photo, so people can easily spot your room.": "Add a photo, so people can easily spot your room.",
"This is the start of <roomName/>.": "This is the start of <roomName/>.",
"No pinned messages.": "No pinned messages.",
"Loading...": "Loading...",
Expand Down Expand Up @@ -1525,6 +1524,15 @@
"Search": "Search",
"Voice call": "Voice call",
"Video call": "Video call",
"This is the beginning of your visible history with <displayName/>, as encrypted messages before this point are unavailable.": "This is the beginning of your visible history with <displayName/>, as encrypted messages before this point are unavailable.",
"This is the beginning of your visible history with <displayName/>, as the room's admins have restricted your ability to view messages from before you were invited.": "This is the beginning of your visible history with <displayName/>, as the room's admins have restricted your ability to view messages from before you were invited.",
"This is the beginning of your visible history with <displayName/>, as the room's admins have restricted your ability to view messages from before you joined.": "This is the beginning of your visible history with <displayName/>, as the room's admins have restricted your ability to view messages from before you joined.",
"This is the beginning of your visible history with <displayName/>.": "This is the beginning of your visible history with <displayName/>.",
"This is the beginning of your visible history in <roomName/>, as encrypted messages before this point are unavailable.": "This is the beginning of your visible history in <roomName/>, as encrypted messages before this point are unavailable.",
"This is the beginning of your visible history in <roomName/>, as the room's admins have restricted your ability to view messages from before you were invited.": "This is the beginning of your visible history in <roomName/>, as the room's admins have restricted your ability to view messages from before you were invited.",
"This is the beginning of your visible history in <roomName/>, as the room's admins have restricted your ability to view messages from before you joined.": "This is the beginning of your visible history in <roomName/>, as the room's admins have restricted your ability to view messages from before you joined.",
"This is the beginning of your visible history in <roomName/>.": "This is the beginning of your visible history in <roomName/>.",
"Add a photo, so people can easily spot your room.": "Add a photo, so people can easily spot your room.",
"Start a Conversation": "Start a Conversation",
"Open dial pad": "Open dial pad",
"Invites": "Invites",
Expand Down

0 comments on commit 0063fd2

Please sign in to comment.