Merge pull request #4906 from matrix-org/travis/room-list/invites-list
Fix a number of issues with the new room list's invites
This commit is contained in:
commit
b3b404f121
4 changed files with 57 additions and 45 deletions
|
@ -64,8 +64,6 @@ interface IState {
|
||||||
}
|
}
|
||||||
|
|
||||||
const TAG_ORDER: TagID[] = [
|
const TAG_ORDER: TagID[] = [
|
||||||
// -- Community Invites Placeholder --
|
|
||||||
|
|
||||||
DefaultTagID.Invite,
|
DefaultTagID.Invite,
|
||||||
DefaultTagID.Favourite,
|
DefaultTagID.Favourite,
|
||||||
DefaultTagID.DM,
|
DefaultTagID.DM,
|
||||||
|
@ -77,7 +75,6 @@ const TAG_ORDER: TagID[] = [
|
||||||
DefaultTagID.ServerNotice,
|
DefaultTagID.ServerNotice,
|
||||||
DefaultTagID.Archived,
|
DefaultTagID.Archived,
|
||||||
];
|
];
|
||||||
const COMMUNITY_TAGS_BEFORE_TAG = DefaultTagID.Invite;
|
|
||||||
const CUSTOM_TAGS_BEFORE_TAG = DefaultTagID.LowPriority;
|
const CUSTOM_TAGS_BEFORE_TAG = DefaultTagID.LowPriority;
|
||||||
const ALWAYS_VISIBLE_TAGS: TagID[] = [
|
const ALWAYS_VISIBLE_TAGS: TagID[] = [
|
||||||
DefaultTagID.DM,
|
DefaultTagID.DM,
|
||||||
|
@ -227,17 +224,15 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
const components: React.ReactElement[] = [];
|
const components: React.ReactElement[] = [];
|
||||||
|
|
||||||
for (const orderedTagId of TAG_ORDER) {
|
for (const orderedTagId of TAG_ORDER) {
|
||||||
if (COMMUNITY_TAGS_BEFORE_TAG === orderedTagId) {
|
|
||||||
// Populate community invites if we have the chance
|
|
||||||
// TODO: Community invites: https://github.com/vector-im/riot-web/issues/14179
|
|
||||||
}
|
|
||||||
if (CUSTOM_TAGS_BEFORE_TAG === orderedTagId) {
|
if (CUSTOM_TAGS_BEFORE_TAG === orderedTagId) {
|
||||||
// Populate custom tags if needed
|
// Populate custom tags if needed
|
||||||
// TODO: Custom tags: https://github.com/vector-im/riot-web/issues/14091
|
// TODO: Custom tags: https://github.com/vector-im/riot-web/issues/14091
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderedRooms = this.state.sublists[orderedTagId] || [];
|
const orderedRooms = this.state.sublists[orderedTagId] || [];
|
||||||
if (orderedRooms.length === 0 && !ALWAYS_VISIBLE_TAGS.includes(orderedTagId)) {
|
const extraTiles = orderedTagId === DefaultTagID.Invite ? this.renderCommunityInvites() : null;
|
||||||
|
const totalTiles = orderedRooms.length + (extraTiles ? extraTiles.length : 0);
|
||||||
|
if (totalTiles === 0 && !ALWAYS_VISIBLE_TAGS.includes(orderedTagId)) {
|
||||||
continue; // skip tag - not needed
|
continue; // skip tag - not needed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +240,6 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
if (!aesthetics) throw new Error(`Tag ${orderedTagId} does not have aesthetics`);
|
if (!aesthetics) throw new Error(`Tag ${orderedTagId} does not have aesthetics`);
|
||||||
|
|
||||||
const onAddRoomFn = aesthetics.onAddRoom ? () => aesthetics.onAddRoom(dis) : null;
|
const onAddRoomFn = aesthetics.onAddRoom ? () => aesthetics.onAddRoom(dis) : null;
|
||||||
const extraTiles = orderedTagId === DefaultTagID.Invite ? this.renderCommunityInvites() : null;
|
|
||||||
components.push(
|
components.push(
|
||||||
<RoomSublist2
|
<RoomSublist2
|
||||||
key={`sublist-${orderedTagId}`}
|
key={`sublist-${orderedTagId}`}
|
||||||
|
|
|
@ -27,7 +27,6 @@ import RoomTile2 from "./RoomTile2";
|
||||||
import { ResizableBox, ResizeCallbackData } from "react-resizable";
|
import { ResizableBox, ResizeCallbackData } from "react-resizable";
|
||||||
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
import { ListLayout } from "../../../stores/room-list/ListLayout";
|
||||||
import { ContextMenu, ContextMenuButton } from "../../structures/ContextMenu";
|
import { ContextMenu, ContextMenuButton } from "../../structures/ContextMenu";
|
||||||
import StyledCheckbox from "../elements/StyledCheckbox";
|
|
||||||
import StyledRadioButton from "../elements/StyledRadioButton";
|
import StyledRadioButton from "../elements/StyledRadioButton";
|
||||||
import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
||||||
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
||||||
|
@ -35,9 +34,9 @@ import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
import NotificationBadge from "./NotificationBadge";
|
import NotificationBadge from "./NotificationBadge";
|
||||||
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
||||||
import Tooltip from "../elements/Tooltip";
|
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import { Key } from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
|
import StyledCheckbox from "../elements/StyledCheckbox";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
||||||
|
@ -280,10 +279,6 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
const tiles: React.ReactElement[] = [];
|
const tiles: React.ReactElement[] = [];
|
||||||
|
|
||||||
if (this.props.extraBadTilesThatShouldntExist) {
|
|
||||||
tiles.push(...this.props.extraBadTilesThatShouldntExist);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.rooms) {
|
if (this.props.rooms) {
|
||||||
const visibleRooms = this.props.rooms.slice(0, this.numVisibleTiles);
|
const visibleRooms = this.props.rooms.slice(0, this.numVisibleTiles);
|
||||||
for (const room of visibleRooms) {
|
for (const room of visibleRooms) {
|
||||||
|
@ -299,6 +294,10 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.props.extraBadTilesThatShouldntExist) {
|
||||||
|
tiles.push(...this.props.extraBadTilesThatShouldntExist);
|
||||||
|
}
|
||||||
|
|
||||||
// We only have to do this because of the extra tiles. We do it conditionally
|
// We only have to do this because of the extra tiles. We do it conditionally
|
||||||
// to avoid spending cycles on slicing. It's generally fine to do this though
|
// to avoid spending cycles on slicing. It's generally fine to do this though
|
||||||
// as users are unlikely to have more than a handful of tiles when the extra
|
// as users are unlikely to have more than a handful of tiles when the extra
|
||||||
|
@ -311,15 +310,40 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderMenu(): React.ReactElement {
|
private renderMenu(): React.ReactElement {
|
||||||
// TODO: Get a proper invite context menu, or take invites out of the room list.
|
|
||||||
if (this.props.tagId === DefaultTagID.Invite) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let contextMenu = null;
|
let contextMenu = null;
|
||||||
if (this.state.contextMenuPosition) {
|
if (this.state.contextMenuPosition) {
|
||||||
const isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic;
|
const isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic;
|
||||||
const isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance;
|
const isUnreadFirst = RoomListStore.instance.getListOrder(this.props.tagId) === ListAlgorithm.Importance;
|
||||||
|
|
||||||
|
// Invites don't get some nonsense options, so only add them if we have to.
|
||||||
|
let otherSections = null;
|
||||||
|
if (this.props.tagId !== DefaultTagID.Invite) {
|
||||||
|
otherSections = (
|
||||||
|
<React.Fragment>
|
||||||
|
<hr />
|
||||||
|
<div>
|
||||||
|
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Unread rooms")}</div>
|
||||||
|
<StyledCheckbox
|
||||||
|
onChange={this.onUnreadFirstChanged}
|
||||||
|
checked={isUnreadFirst}
|
||||||
|
>
|
||||||
|
{_t("Always show first")}
|
||||||
|
</StyledCheckbox>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<div>
|
||||||
|
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Show")}</div>
|
||||||
|
<StyledCheckbox
|
||||||
|
onChange={this.onMessagePreviewChanged}
|
||||||
|
checked={this.props.layout.showPreviews}
|
||||||
|
>
|
||||||
|
{_t("Message preview")}
|
||||||
|
</StyledCheckbox>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
contextMenu = (
|
contextMenu = (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
chevronFace="none"
|
chevronFace="none"
|
||||||
|
@ -345,26 +369,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
{_t("A-Z")}
|
{_t("A-Z")}
|
||||||
</StyledRadioButton>
|
</StyledRadioButton>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
{otherSections}
|
||||||
<div>
|
|
||||||
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Unread rooms")}</div>
|
|
||||||
<StyledCheckbox
|
|
||||||
onChange={this.onUnreadFirstChanged}
|
|
||||||
checked={isUnreadFirst}
|
|
||||||
>
|
|
||||||
{_t("Always show first")}
|
|
||||||
</StyledCheckbox>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
<div>
|
|
||||||
<div className='mx_RoomSublist2_contextMenu_title'>{_t("Show")}</div>
|
|
||||||
<StyledCheckbox
|
|
||||||
onChange={this.onMessagePreviewChanged}
|
|
||||||
checked={this.props.layout.showPreviews}
|
|
||||||
>
|
|
||||||
{_t("Message preview")}
|
|
||||||
</StyledCheckbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1200,13 +1200,13 @@
|
||||||
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Securely back up your keys to avoid losing them. <a>Learn more.</a>",
|
"Securely back up your keys to avoid losing them. <a>Learn more.</a>": "Securely back up your keys to avoid losing them. <a>Learn more.</a>",
|
||||||
"Not now": "Not now",
|
"Not now": "Not now",
|
||||||
"Don't ask me again": "Don't ask me again",
|
"Don't ask me again": "Don't ask me again",
|
||||||
"Sort by": "Sort by",
|
|
||||||
"Activity": "Activity",
|
|
||||||
"A-Z": "A-Z",
|
|
||||||
"Unread rooms": "Unread rooms",
|
"Unread rooms": "Unread rooms",
|
||||||
"Always show first": "Always show first",
|
"Always show first": "Always show first",
|
||||||
"Show": "Show",
|
"Show": "Show",
|
||||||
"Message preview": "Message preview",
|
"Message preview": "Message preview",
|
||||||
|
"Sort by": "Sort by",
|
||||||
|
"Activity": "Activity",
|
||||||
|
"A-Z": "A-Z",
|
||||||
"List options": "List options",
|
"List options": "List options",
|
||||||
"Add room": "Add room",
|
"Add room": "Add room",
|
||||||
"Show %(count)s more|other": "Show %(count)s more",
|
"Show %(count)s more|other": "Show %(count)s more",
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { TagID } from "../../models";
|
||||||
import { IAlgorithm } from "./IAlgorithm";
|
import { IAlgorithm } from "./IAlgorithm";
|
||||||
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../MatrixClientPeg";
|
||||||
import * as Unread from "../../../../Unread";
|
import * as Unread from "../../../../Unread";
|
||||||
|
import { EffectiveMembership, getEffectiveMembership } from "../../membership";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts rooms according to the last event's timestamp in each room that seems
|
* Sorts rooms according to the last event's timestamp in each room that seems
|
||||||
|
@ -37,6 +38,8 @@ export class RecentAlgorithm implements IAlgorithm {
|
||||||
// actually changed (probably needs to be done higher up?) then we could do an
|
// actually changed (probably needs to be done higher up?) then we could do an
|
||||||
// insertion sort or similar on the limited set of changes.
|
// insertion sort or similar on the limited set of changes.
|
||||||
|
|
||||||
|
const myUserId = MatrixClientPeg.get().getUserId();
|
||||||
|
|
||||||
const tsCache: { [roomId: string]: number } = {};
|
const tsCache: { [roomId: string]: number } = {};
|
||||||
const getLastTs = (r: Room) => {
|
const getLastTs = (r: Room) => {
|
||||||
if (tsCache[r.roomId]) {
|
if (tsCache[r.roomId]) {
|
||||||
|
@ -50,13 +53,23 @@ export class RecentAlgorithm implements IAlgorithm {
|
||||||
return Number.MAX_SAFE_INTEGER;
|
return Number.MAX_SAFE_INTEGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the room hasn't been joined yet, it probably won't have a timeline to
|
||||||
|
// parse. We'll still fall back to the timeline if this fails, but chances
|
||||||
|
// are we'll at least have our own membership event to go off of.
|
||||||
|
const effectiveMembership = getEffectiveMembership(r.getMyMembership());
|
||||||
|
if (effectiveMembership !== EffectiveMembership.Join) {
|
||||||
|
const membershipEvent = r.currentState.getStateEvents("m.room.member", myUserId);
|
||||||
|
if (membershipEvent && !Array.isArray(membershipEvent)) {
|
||||||
|
return membershipEvent.getTs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = r.timeline.length - 1; i >= 0; --i) {
|
for (let i = r.timeline.length - 1; i >= 0; --i) {
|
||||||
const ev = r.timeline[i];
|
const ev = r.timeline[i];
|
||||||
if (!ev.getTs()) continue; // skip events that don't have timestamps (tests only?)
|
if (!ev.getTs()) continue; // skip events that don't have timestamps (tests only?)
|
||||||
|
|
||||||
// TODO: Don't assume we're using the same client as the peg
|
// TODO: Don't assume we're using the same client as the peg
|
||||||
if (ev.getSender() === MatrixClientPeg.get().getUserId()
|
if (ev.getSender() === myUserId || Unread.eventTriggersUnreadCount(ev)) {
|
||||||
|| Unread.eventTriggersUnreadCount(ev)) {
|
|
||||||
return ev.getTs();
|
return ev.getTs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue