Merge pull request #4906 from matrix-org/travis/room-list/invites-list
Fix a number of issues with the new room list's invitespull/21833/head
						commit
						b3b404f121
					
				|  | @ -64,8 +64,6 @@ interface IState { | |||
| } | ||||
| 
 | ||||
| const TAG_ORDER: TagID[] = [ | ||||
|     // -- Community Invites Placeholder --
 | ||||
| 
 | ||||
|     DefaultTagID.Invite, | ||||
|     DefaultTagID.Favourite, | ||||
|     DefaultTagID.DM, | ||||
|  | @ -77,7 +75,6 @@ const TAG_ORDER: TagID[] = [ | |||
|     DefaultTagID.ServerNotice, | ||||
|     DefaultTagID.Archived, | ||||
| ]; | ||||
| const COMMUNITY_TAGS_BEFORE_TAG = DefaultTagID.Invite; | ||||
| const CUSTOM_TAGS_BEFORE_TAG = DefaultTagID.LowPriority; | ||||
| const ALWAYS_VISIBLE_TAGS: TagID[] = [ | ||||
|     DefaultTagID.DM, | ||||
|  | @ -227,17 +224,15 @@ export default class RoomList2 extends React.Component<IProps, IState> { | |||
|         const components: React.ReactElement[] = []; | ||||
| 
 | ||||
|         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) { | ||||
|                 // Populate custom tags if needed
 | ||||
|                 // TODO: Custom tags: https://github.com/vector-im/riot-web/issues/14091
 | ||||
|             } | ||||
| 
 | ||||
|             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
 | ||||
|             } | ||||
| 
 | ||||
|  | @ -245,7 +240,6 @@ export default class RoomList2 extends React.Component<IProps, IState> { | |||
|             if (!aesthetics) throw new Error(`Tag ${orderedTagId} does not have aesthetics`); | ||||
| 
 | ||||
|             const onAddRoomFn = aesthetics.onAddRoom ? () => aesthetics.onAddRoom(dis) : null; | ||||
|             const extraTiles = orderedTagId === DefaultTagID.Invite ? this.renderCommunityInvites() : null; | ||||
|             components.push( | ||||
|                 <RoomSublist2 | ||||
|                     key={`sublist-${orderedTagId}`} | ||||
|  |  | |||
|  | @ -27,7 +27,6 @@ import RoomTile2 from "./RoomTile2"; | |||
| import { ResizableBox, ResizeCallbackData } from "react-resizable"; | ||||
| import { ListLayout } from "../../../stores/room-list/ListLayout"; | ||||
| import { ContextMenu, ContextMenuButton } from "../../structures/ContextMenu"; | ||||
| import StyledCheckbox from "../elements/StyledCheckbox"; | ||||
| import StyledRadioButton from "../elements/StyledRadioButton"; | ||||
| import RoomListStore from "../../../stores/room-list/RoomListStore2"; | ||||
| 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 NotificationBadge from "./NotificationBadge"; | ||||
| import { ListNotificationState } from "../../../stores/notifications/ListNotificationState"; | ||||
| import Tooltip from "../elements/Tooltip"; | ||||
| import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; | ||||
| import { Key } from "../../../Keyboard"; | ||||
| import StyledCheckbox from "../elements/StyledCheckbox"; | ||||
| 
 | ||||
| // 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
 | ||||
|  | @ -280,10 +279,6 @@ export default class RoomSublist2 extends React.Component<IProps, IState> { | |||
| 
 | ||||
|         const tiles: React.ReactElement[] = []; | ||||
| 
 | ||||
|         if (this.props.extraBadTilesThatShouldntExist) { | ||||
|             tiles.push(...this.props.extraBadTilesThatShouldntExist); | ||||
|         } | ||||
| 
 | ||||
|         if (this.props.rooms) { | ||||
|             const visibleRooms = this.props.rooms.slice(0, this.numVisibleTiles); | ||||
|             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
 | ||||
|         // 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
 | ||||
|  | @ -311,15 +310,40 @@ export default class RoomSublist2 extends React.Component<IProps, IState> { | |||
|     } | ||||
| 
 | ||||
|     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; | ||||
|         if (this.state.contextMenuPosition) { | ||||
|             const isAlphabetical = RoomListStore.instance.getTagSorting(this.props.tagId) === SortAlgorithm.Alphabetic; | ||||
|             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 | ||||
|                     chevronFace="none" | ||||
|  | @ -345,26 +369,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> { | |||
|                                 {_t("A-Z")} | ||||
|                             </StyledRadioButton> | ||||
|                         </div> | ||||
|                         <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> | ||||
|                         {otherSections} | ||||
|                     </div> | ||||
|                 </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>", | ||||
|     "Not now": "Not now", | ||||
|     "Don't ask me again": "Don't ask me again", | ||||
|     "Sort by": "Sort by", | ||||
|     "Activity": "Activity", | ||||
|     "A-Z": "A-Z", | ||||
|     "Unread rooms": "Unread rooms", | ||||
|     "Always show first": "Always show first", | ||||
|     "Show": "Show", | ||||
|     "Message preview": "Message preview", | ||||
|     "Sort by": "Sort by", | ||||
|     "Activity": "Activity", | ||||
|     "A-Z": "A-Z", | ||||
|     "List options": "List options", | ||||
|     "Add room": "Add room", | ||||
|     "Show %(count)s more|other": "Show %(count)s more", | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ import { TagID } from "../../models"; | |||
| import { IAlgorithm } from "./IAlgorithm"; | ||||
| import { MatrixClientPeg } from "../../../../MatrixClientPeg"; | ||||
| import * as Unread from "../../../../Unread"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../../membership"; | ||||
| 
 | ||||
| /** | ||||
|  * 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
 | ||||
|         // insertion sort or similar on the limited set of changes.
 | ||||
| 
 | ||||
|         const myUserId = MatrixClientPeg.get().getUserId(); | ||||
| 
 | ||||
|         const tsCache: { [roomId: string]: number } = {}; | ||||
|         const getLastTs = (r: Room) => { | ||||
|             if (tsCache[r.roomId]) { | ||||
|  | @ -50,13 +53,23 @@ export class RecentAlgorithm implements IAlgorithm { | |||
|                     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) { | ||||
|                     const ev = r.timeline[i]; | ||||
|                     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
 | ||||
|                     if (ev.getSender() === MatrixClientPeg.get().getUserId() | ||||
|                         || Unread.eventTriggersUnreadCount(ev)) { | ||||
|                     if (ev.getSender() === myUserId || Unread.eventTriggersUnreadCount(ev)) { | ||||
|                         return ev.getTs(); | ||||
|                     } | ||||
|                 } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Travis Ralston
						Travis Ralston