mirror of https://github.com/vector-im/riot-web
				
				
				
			Merge branch 'develop' into joriks/delabs-font-scaling
						commit
						76fbb7c1b0
					
				|  | @ -47,12 +47,6 @@ limitations under the License. | |||
|         padding-bottom: 8px; | ||||
|         height: 24px; | ||||
| 
 | ||||
|         // Hide the header container if the contained element is stickied. | ||||
|         // We don't use display:none as that causes the header to go away too. | ||||
|         &.mx_RoomSublist2_headerContainer_hasSticky { | ||||
|             height: 0; | ||||
|         } | ||||
| 
 | ||||
|         .mx_RoomSublist2_stickable { | ||||
|             flex: 1; | ||||
|             max-width: 100%; | ||||
|  | @ -180,6 +174,15 @@ limitations under the License. | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // In the general case, we leave height of headers alone even if sticky, so | ||||
|     // that the sublists below them do not jump. However, that leaves a gap | ||||
|     // when scrolled to the top above the first sublist (whose header can only | ||||
|     // ever stick to top), so we force height to 0 for only that first header. | ||||
|     // See also https://github.com/vector-im/riot-web/issues/14429. | ||||
|     &:first-child .mx_RoomSublist2_headerContainer { | ||||
|         height: 0; | ||||
|     } | ||||
| 
 | ||||
|     .mx_RoomSublist2_resizeBox { | ||||
|         position: relative; | ||||
| 
 | ||||
|  | @ -196,6 +199,8 @@ limitations under the License. | |||
|             // as the box model should be top aligned. Happens in both FF and Chromium | ||||
|             display: flex; | ||||
|             flex-direction: column; | ||||
| 
 | ||||
|             mask-image: linear-gradient(0deg, transparent, black 3px); | ||||
|         } | ||||
| 
 | ||||
|         .mx_RoomSublist2_resizerHandles_showNButton { | ||||
|  |  | |||
|  | @ -37,9 +37,6 @@ declare global { | |||
|         mx_RoomListStore2: RoomListStore2; | ||||
|         mx_RoomListLayoutStore: RoomListLayoutStore; | ||||
|         mxPlatformPeg: PlatformPeg; | ||||
| 
 | ||||
|         // TODO: Remove flag before launch: https://github.com/vector-im/riot-web/issues/14231
 | ||||
|         mx_QuietRoomListLogging: boolean; | ||||
|     } | ||||
| 
 | ||||
|     // workaround for https://github.com/microsoft/TypeScript/issues/30933
 | ||||
|  |  | |||
|  | @ -35,17 +35,8 @@ import RoomListStore, { LISTS_UPDATE_EVENT } from "../../stores/room-list/RoomLi | |||
| import {Key} from "../../Keyboard"; | ||||
| import IndicatorScrollbar from "../structures/IndicatorScrollbar"; | ||||
| 
 | ||||
| // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| // TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| 
 | ||||
| /******************************************************************* | ||||
|  *   CAUTION                                                       * | ||||
|  ******************************************************************* | ||||
|  * This is a work in progress implementation and isn't complete or * | ||||
|  * even useful as a component. Please avoid using it until this    * | ||||
|  * warning disappears.                                             * | ||||
|  *******************************************************************/ | ||||
| 
 | ||||
| interface IProps { | ||||
|     isMinimized: boolean; | ||||
|     resizeNotifier: ResizeNotifier; | ||||
|  | @ -111,6 +102,10 @@ export default class LeftPanel2 extends React.Component<IProps, IState> { | |||
|         const newVal = BreadcrumbsStore.instance.visible; | ||||
|         if (newVal !== this.state.showBreadcrumbs) { | ||||
|             this.setState({showBreadcrumbs: newVal}); | ||||
| 
 | ||||
|             // Update the sticky headers too as the breadcrumbs will be popping in or out.
 | ||||
|             if (!this.listContainerRef.current) return; // ignore: no headers to sticky
 | ||||
|             this.handleStickyHeaders(this.listContainerRef.current); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|  | @ -170,7 +165,6 @@ export default class LeftPanel2 extends React.Component<IProps, IState> { | |||
|         // layout updates.
 | ||||
|         for (const header of targetStyles.keys()) { | ||||
|             const style = targetStyles.get(header); | ||||
|             const headerContainer = header.parentElement; // .mx_RoomSublist2_headerContainer
 | ||||
| 
 | ||||
|             if (style.makeInvisible) { | ||||
|                 // we will have already removed the 'display: none', so add it back.
 | ||||
|  | @ -187,19 +181,29 @@ export default class LeftPanel2 extends React.Component<IProps, IState> { | |||
|                 if (header.style.top !== newTop) { | ||||
|                     header.style.top = newTop; | ||||
|                 } | ||||
|             } else if (style.stickyBottom) { | ||||
|             } else { | ||||
|                 if (header.classList.contains("mx_RoomSublist2_headerContainer_stickyTop")) { | ||||
|                     header.classList.remove("mx_RoomSublist2_headerContainer_stickyTop"); | ||||
|                 } | ||||
|                 if (header.style.top) { | ||||
|                     header.style.removeProperty('top'); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (style.stickyBottom) { | ||||
|                 if (!header.classList.contains("mx_RoomSublist2_headerContainer_stickyBottom")) { | ||||
|                     header.classList.add("mx_RoomSublist2_headerContainer_stickyBottom"); | ||||
|                 } | ||||
|             } else { | ||||
|                 if (header.classList.contains("mx_RoomSublist2_headerContainer_stickyBottom")) { | ||||
|                     header.classList.remove("mx_RoomSublist2_headerContainer_stickyBottom"); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (style.stickyTop || style.stickyBottom) { | ||||
|                 if (!header.classList.contains("mx_RoomSublist2_headerContainer_sticky")) { | ||||
|                     header.classList.add("mx_RoomSublist2_headerContainer_sticky"); | ||||
|                 } | ||||
|                 if (!headerContainer.classList.contains("mx_RoomSublist2_headerContainer_hasSticky")) { | ||||
|                     headerContainer.classList.add("mx_RoomSublist2_headerContainer_hasSticky"); | ||||
|                 } | ||||
| 
 | ||||
|                 const newWidth = `${headerStickyWidth}px`; | ||||
|                 if (header.style.width !== newWidth) { | ||||
|  | @ -209,21 +213,9 @@ export default class LeftPanel2 extends React.Component<IProps, IState> { | |||
|                 if (header.classList.contains("mx_RoomSublist2_headerContainer_sticky")) { | ||||
|                     header.classList.remove("mx_RoomSublist2_headerContainer_sticky"); | ||||
|                 } | ||||
|                 if (header.classList.contains("mx_RoomSublist2_headerContainer_stickyTop")) { | ||||
|                     header.classList.remove("mx_RoomSublist2_headerContainer_stickyTop"); | ||||
|                 } | ||||
|                 if (header.classList.contains("mx_RoomSublist2_headerContainer_stickyBottom")) { | ||||
|                     header.classList.remove("mx_RoomSublist2_headerContainer_stickyBottom"); | ||||
|                 } | ||||
|                 if (headerContainer.classList.contains("mx_RoomSublist2_headerContainer_hasSticky")) { | ||||
|                     headerContainer.classList.remove("mx_RoomSublist2_headerContainer_hasSticky"); | ||||
|                 } | ||||
|                 if (header.style.width) { | ||||
|                     header.style.removeProperty('width'); | ||||
|                 } | ||||
|                 if (header.style.top) { | ||||
|                     header.style.removeProperty('top'); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -242,7 +234,6 @@ export default class LeftPanel2 extends React.Component<IProps, IState> { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // TODO: Improve header reliability: https://github.com/vector-im/riot-web/issues/14232
 | ||||
|     private onScroll = (ev: React.MouseEvent<HTMLDivElement>) => { | ||||
|         const list = ev.target as HTMLDivElement; | ||||
|         this.handleStickyHeaders(list); | ||||
|  | @ -383,8 +374,6 @@ export default class LeftPanel2 extends React.Component<IProps, IState> { | |||
|             onResize={this.onResize} | ||||
|         />; | ||||
| 
 | ||||
|         // TODO: Conference handling / calls: https://github.com/vector-im/riot-web/issues/14177
 | ||||
| 
 | ||||
|         const containerClasses = classNames({ | ||||
|             "mx_LeftPanel2": true, | ||||
|             "mx_LeftPanel2_hasTagPanel": !!tagPanel, | ||||
|  |  | |||
|  | @ -25,16 +25,6 @@ import { Key } from "../../Keyboard"; | |||
| import AccessibleButton from "../views/elements/AccessibleButton"; | ||||
| import { Action } from "../../dispatcher/actions"; | ||||
| 
 | ||||
| // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| 
 | ||||
| /******************************************************************* | ||||
|  *   CAUTION                                                       * | ||||
|  ******************************************************************* | ||||
|  * This is a work in progress implementation and isn't complete or * | ||||
|  * even useful as a component. Please avoid using it until this    * | ||||
|  * warning disappears.                                             * | ||||
|  *******************************************************************/ | ||||
| 
 | ||||
| interface IProps { | ||||
|     onQueryUpdate: (newQuery: string) => void; | ||||
|     isMinimized: boolean; | ||||
|  |  | |||
|  | @ -170,6 +170,7 @@ export default class UserMenu extends React.Component<IProps, IState> { | |||
|         ev.stopPropagation(); | ||||
| 
 | ||||
|         // TODO: Archived room view: https://github.com/vector-im/riot-web/issues/14038
 | ||||
|         // Note: You'll need to uncomment the button too.
 | ||||
|         console.log("TODO: Show archived rooms"); | ||||
|     }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,8 +18,6 @@ import React from "react"; | |||
| import classNames from "classnames"; | ||||
| import { formatMinimalBadgeCount } from "../../../utils/FormattingUtils"; | ||||
| import SettingsStore from "../../../settings/SettingsStore"; | ||||
| import { DefaultTagID, TagID } from "../../../stores/room-list/models"; | ||||
| import { readReceiptChangeIsFor } from "../../../utils/read-receipts"; | ||||
| import AccessibleButton from "../elements/AccessibleButton"; | ||||
| import { XOR } from "../../../@types/common"; | ||||
| import { NOTIFICATION_STATE_UPDATE, NotificationState } from "../../../stores/notifications/NotificationState"; | ||||
|  |  | |||
|  | @ -27,17 +27,8 @@ import RoomListStore from "../../../stores/room-list/RoomListStore2"; | |||
| import { DefaultTagID } from "../../../stores/room-list/models"; | ||||
| import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; | ||||
| 
 | ||||
| // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| // TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| 
 | ||||
| /******************************************************************* | ||||
|  *   CAUTION                                                       * | ||||
|  ******************************************************************* | ||||
|  * This is a work in progress implementation and isn't complete or * | ||||
|  * even useful as a component. Please avoid using it until this    * | ||||
|  * warning disappears.                                             * | ||||
|  *******************************************************************/ | ||||
| 
 | ||||
| interface IProps { | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,17 +41,8 @@ import { Action } from "../../../dispatcher/actions"; | |||
| import { ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload"; | ||||
| import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; | ||||
| 
 | ||||
| // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| // TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| 
 | ||||
| /******************************************************************* | ||||
|  *   CAUTION                                                       * | ||||
|  ******************************************************************* | ||||
|  * This is a work in progress implementation and isn't complete or * | ||||
|  * even useful as a component. Please avoid using it until this    * | ||||
|  * warning disappears.                                             * | ||||
|  *******************************************************************/ | ||||
| 
 | ||||
| interface IProps { | ||||
|     onKeyDown: (ev: React.KeyboardEvent) => void; | ||||
|     onFocus: (ev: React.FocusEvent) => void; | ||||
|  | @ -218,19 +209,14 @@ export default class RoomList2 extends React.Component<IProps, IState> { | |||
|     }; | ||||
| 
 | ||||
|     private updateLists = () => { | ||||
|         const newLists = RoomListStore.instance.orderedLists; | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log("new lists", newLists); | ||||
|         } | ||||
| 
 | ||||
|         this.setState({sublists: newLists}, () => { | ||||
|         this.setState({sublists: RoomListStore.instance.orderedLists}, () => { | ||||
|             this.props.onResize(); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     private renderCommunityInvites(): React.ReactElement[] { | ||||
|         // TODO: Put community invites in a more sensible place (not in the room list)
 | ||||
|         // See https://github.com/vector-im/riot-web/issues/14456
 | ||||
|         return MatrixClientPeg.get().getGroups().filter(g => { | ||||
|            if (g.myMembership !== 'invite') return false; | ||||
|            return !this.searchFilter || this.searchFilter.matches(g.name || ""); | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ limitations under the License. | |||
| */ | ||||
| 
 | ||||
| import * as React from "react"; | ||||
| import {createRef, UIEventHandler} from "react"; | ||||
| import {createRef} from "react"; | ||||
| import { Room } from "matrix-js-sdk/src/models/room"; | ||||
| import classNames from 'classnames'; | ||||
| import { RovingAccessibleButton, RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex"; | ||||
|  | @ -48,17 +48,8 @@ import { polyfillTouchEvent } from "../../../@types/polyfill"; | |||
| import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; | ||||
| import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore"; | ||||
| 
 | ||||
| // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| // TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| 
 | ||||
| /******************************************************************* | ||||
|  *   CAUTION                                                       * | ||||
|  ******************************************************************* | ||||
|  * This is a work in progress implementation and isn't complete or * | ||||
|  * even useful as a component. Please avoid using it until this    * | ||||
|  * warning disappears.                                             * | ||||
|  *******************************************************************/ | ||||
| 
 | ||||
| const SHOW_N_BUTTON_HEIGHT = 28; // As defined by CSS
 | ||||
| const RESIZE_HANDLE_HEIGHT = 4; // As defined by CSS
 | ||||
| export const HEADER_HEIGHT = 32; // As defined by CSS
 | ||||
|  | @ -137,9 +128,10 @@ export default class RoomSublist2 extends React.Component<IProps, IState> { | |||
|         let padding = RESIZE_HANDLE_HEIGHT; | ||||
|         // this is used for calculating the max height of the whole container,
 | ||||
|         // and takes into account whether there should be room reserved for the show less button
 | ||||
|         // when fully expanded. Note that the show more button might still be shown when not fully expanded,
 | ||||
|         // but in this case it will take the space of a tile and we don't need to reserve space for it.
 | ||||
|         if (this.numTiles > this.layout.defaultVisibleTiles) { | ||||
|         // when fully expanded. We cannot check against the layout's defaultVisible tile count
 | ||||
|         // because there are conditions in which we need to know that the 'show more' button
 | ||||
|         // is present while well under the default tile limit.
 | ||||
|         if (this.numTiles > this.numVisibleTiles) { | ||||
|             padding += SHOW_N_BUTTON_HEIGHT; | ||||
|         } | ||||
|         return padding; | ||||
|  | @ -236,10 +228,13 @@ export default class RoomSublist2 extends React.Component<IProps, IState> { | |||
|     }; | ||||
| 
 | ||||
|     private onShowAllClick = () => { | ||||
|         // read number of visible tiles before we mutate it
 | ||||
|         const numVisibleTiles = this.numVisibleTiles; | ||||
|         const newHeight = this.layout.tilesToPixelsWithPadding(this.numTiles, this.padding); | ||||
|         this.applyHeightChange(newHeight); | ||||
|         this.setState({height: newHeight}, () => { | ||||
|             this.focusRoomTile(this.numTiles - 1); | ||||
|             // focus the top-most new room
 | ||||
|             this.focusRoomTile(numVisibleTiles); | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -606,8 +601,6 @@ export default class RoomSublist2 extends React.Component<IProps, IState> { | |||
|     } | ||||
| 
 | ||||
|     public render(): React.ReactElement { | ||||
|         // TODO: Error boundary: https://github.com/vector-im/riot-web/issues/14185
 | ||||
| 
 | ||||
|         const visibleTiles = this.renderVisibleTiles(); | ||||
|         const classes = classNames({ | ||||
|             'mx_RoomSublist2': true, | ||||
|  | @ -623,11 +616,15 @@ export default class RoomSublist2 extends React.Component<IProps, IState> { | |||
|             const showMoreAtMinHeight = minTiles < this.numTiles; | ||||
|             const minHeightPadding = RESIZE_HANDLE_HEIGHT + (showMoreAtMinHeight ? SHOW_N_BUTTON_HEIGHT : 0); | ||||
|             const minTilesPx = layout.tilesToPixelsWithPadding(minTiles, minHeightPadding); | ||||
|             const maxTilesPx = layout.tilesToPixelsWithPadding(this.numTiles, this.padding); | ||||
|             let maxTilesPx = layout.tilesToPixelsWithPadding(this.numTiles, this.padding); | ||||
|             const showMoreBtnClasses = classNames({ | ||||
|                 'mx_RoomSublist2_showNButton': true, | ||||
|             }); | ||||
| 
 | ||||
|             if (this.numTiles > this.layout.defaultVisibleTiles) { | ||||
|                 maxTilesPx += SHOW_N_BUTTON_HEIGHT; | ||||
|             } | ||||
| 
 | ||||
|             // If we're hiding rooms, show a 'show more' button to the user. This button
 | ||||
|             // floats above the resize handle, if we have one present. If the user has all
 | ||||
|             // tiles visible, it becomes 'show less'.
 | ||||
|  |  | |||
|  | @ -55,17 +55,8 @@ import {ActionPayload} from "../../../dispatcher/payloads"; | |||
| import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; | ||||
| import { NotificationState } from "../../../stores/notifications/NotificationState"; | ||||
| 
 | ||||
| // TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| // TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
 | ||||
| 
 | ||||
| /******************************************************************* | ||||
|  *   CAUTION                                                       * | ||||
|  ******************************************************************* | ||||
|  * This is a work in progress implementation and isn't complete or * | ||||
|  * even useful as a component. Please avoid using it until this    * | ||||
|  * warning disappears.                                             * | ||||
|  *******************************************************************/ | ||||
| 
 | ||||
| interface IProps { | ||||
|     room: Room; | ||||
|     showMessagePreview: boolean; | ||||
|  | @ -124,7 +115,6 @@ const NotifOption: React.FC<INotifOptionProps> = ({active, onClick, iconClassNam | |||
| export default class RoomTile2 extends React.Component<IProps, IState> { | ||||
|     private dispatcherRef: string; | ||||
|     private roomTileRef = createRef<HTMLDivElement>(); | ||||
|     // TODO: a11y: https://github.com/vector-im/riot-web/issues/14180
 | ||||
| 
 | ||||
|     constructor(props: IProps) { | ||||
|         super(props); | ||||
|  | @ -310,7 +300,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> { | |||
|             await setRoomNotifsState(this.props.room.roomId, newState); | ||||
|         } catch (error) { | ||||
|             // TODO: some form of error notification to the user to inform them that their state change failed.
 | ||||
|             // https://github.com/vector-im/riot-web/issues/14281
 | ||||
|             // See https://github.com/vector-im/riot-web/issues/14281
 | ||||
|             console.error(error); | ||||
|         } | ||||
| 
 | ||||
|  | @ -398,8 +388,6 @@ export default class RoomTile2 extends React.Component<IProps, IState> { | |||
|     private renderGeneralMenu(): React.ReactElement { | ||||
|         if (!this.showContextMenu) return null; // no menu to show
 | ||||
| 
 | ||||
|         // TODO: We could do with a proper invite context menu, unlike what showContextMenu suggests
 | ||||
| 
 | ||||
|         const roomTags = RoomListStore.instance.getTagsForRoom(this.props.room); | ||||
| 
 | ||||
|         const isFavorite = roomTags.includes(DefaultTagID.Favourite); | ||||
|  | @ -465,8 +453,6 @@ export default class RoomTile2 extends React.Component<IProps, IState> { | |||
|     } | ||||
| 
 | ||||
|     public render(): React.ReactElement { | ||||
|         // TODO: Invites: https://github.com/vector-im/riot-web/issues/14198
 | ||||
| 
 | ||||
|         const classes = classNames({ | ||||
|             'mx_RoomTile2': true, | ||||
|             'mx_RoomTile2_selected': this.state.selected, | ||||
|  | @ -495,7 +481,6 @@ export default class RoomTile2 extends React.Component<IProps, IState> { | |||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         // TODO: the original RoomTile uses state for the room name. Do we need to?
 | ||||
|         let name = this.props.room.name; | ||||
|         if (typeof name !== 'string') name = ''; | ||||
|         name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
 | ||||
|  |  | |||
|  | @ -34,6 +34,7 @@ interface IState { | |||
|     hover: boolean; | ||||
| } | ||||
| 
 | ||||
| // TODO: Remove with community invites in the room list: https://github.com/vector-im/riot-web/issues/14456
 | ||||
| export default class TemporaryTile extends React.Component<IProps, IState> { | ||||
|     constructor(props: IProps) { | ||||
|         super(props); | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ import { AsyncStoreWithClient } from "./AsyncStoreWithClient"; | |||
| import defaultDispatcher from "../dispatcher/dispatcher"; | ||||
| import { arrayHasDiff } from "../utils/arrays"; | ||||
| import { RoomListStoreTempProxy } from "./room-list/RoomListStoreTempProxy"; | ||||
| import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; | ||||
| 
 | ||||
| const MAX_ROOMS = 20; // arbitrary
 | ||||
| const AUTOJOIN_WAIT_THRESHOLD_MS = 90000; // 90s, the time we wait for an autojoined room to show up
 | ||||
|  | @ -51,7 +52,11 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> { | |||
|     } | ||||
| 
 | ||||
|     public get visible(): boolean { | ||||
|         return this.state.enabled && this.matrixClient.getVisibleRooms().length >= 20; | ||||
|         return this.state.enabled && this.meetsRoomRequirement; | ||||
|     } | ||||
| 
 | ||||
|     private get meetsRoomRequirement(): boolean { | ||||
|         return this.matrixClient.getVisibleRooms().length >= 20; | ||||
|     } | ||||
| 
 | ||||
|     protected async onAction(payload: ActionPayload) { | ||||
|  | @ -99,8 +104,9 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> { | |||
|     } | ||||
| 
 | ||||
|     private onMyMembership = async (room: Room) => { | ||||
|         // We turn on breadcrumbs by default once the user has at least 1 room to show.
 | ||||
|         if (!this.state.enabled) { | ||||
|         // Only turn on breadcrumbs is the user hasn't explicitly turned it off again.
 | ||||
|         const settingValueRaw = SettingsStore.getValue("breadcrumbs", null, /*excludeDefault=*/true); | ||||
|         if (this.meetsRoomRequirement && isNullOrUndefined(settingValueRaw)) { | ||||
|             await SettingsStore.setValue("breadcrumbs", null, SettingLevel.ACCOUNT, true); | ||||
|         } | ||||
|     }; | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ limitations under the License. | |||
| import { NotificationColor } from "./NotificationColor"; | ||||
| import { IDestroyable } from "../../utils/IDestroyable"; | ||||
| import { MatrixClientPeg } from "../../MatrixClientPeg"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../room-list/membership"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership"; | ||||
| import { readReceiptChangeIsFor } from "../../utils/read-receipts"; | ||||
| import { MatrixEvent } from "matrix-js-sdk/src/models/event"; | ||||
| import { Room } from "matrix-js-sdk/src/models/room"; | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ import { MatrixClient } from "matrix-js-sdk/src/client"; | |||
| import SettingsStore from "../../settings/SettingsStore"; | ||||
| import { DefaultTagID, OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models"; | ||||
| import TagOrderStore from "../TagOrderStore"; | ||||
| import { AsyncStore } from "../AsyncStore"; | ||||
| import { Room } from "matrix-js-sdk/src/models/room"; | ||||
| import { IListOrderingMap, ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models"; | ||||
| import { ActionPayload } from "../../dispatcher/payloads"; | ||||
|  | @ -29,10 +28,11 @@ import { FILTER_CHANGED, IFilterCondition } from "./filters/IFilterCondition"; | |||
| import { TagWatcher } from "./TagWatcher"; | ||||
| import RoomViewStore from "../RoomViewStore"; | ||||
| import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "./membership"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership"; | ||||
| import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; | ||||
| import RoomListLayoutStore from "./RoomListLayoutStore"; | ||||
| import { MarkedExecution } from "../../utils/MarkedExecution"; | ||||
| import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; | ||||
| 
 | ||||
| interface IState { | ||||
|     tagsEnabled?: boolean; | ||||
|  | @ -44,14 +44,13 @@ interface IState { | |||
|  */ | ||||
| export const LISTS_UPDATE_EVENT = "lists_update"; | ||||
| 
 | ||||
| export class RoomListStore2 extends AsyncStore<ActionPayload> { | ||||
| export class RoomListStore2 extends AsyncStoreWithClient<ActionPayload> { | ||||
|     /** | ||||
|      * Set to true if you're running tests on the store. Should not be touched in | ||||
|      * any other environment. | ||||
|      */ | ||||
|     public static TEST_MODE = false; | ||||
| 
 | ||||
|     private _matrixClient: MatrixClient; | ||||
|     private initialListsGenerated = false; | ||||
|     private enabled = false; | ||||
|     private algorithm = new Algorithm(); | ||||
|  | @ -79,7 +78,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|     } | ||||
| 
 | ||||
|     public get matrixClient(): MatrixClient { | ||||
|         return this._matrixClient; | ||||
|         return super.matrixClient; | ||||
|     } | ||||
| 
 | ||||
|     // Intended for test usage
 | ||||
|  | @ -88,23 +87,28 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|         this.tagWatcher = new TagWatcher(this); | ||||
|         this.filterConditions = []; | ||||
|         this.initialListsGenerated = false; | ||||
|         this._matrixClient = null; | ||||
| 
 | ||||
|         this.algorithm.off(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated); | ||||
|         this.algorithm.off(FILTER_CHANGED, this.onAlgorithmListUpdated); | ||||
|         this.algorithm = new Algorithm(); | ||||
|         this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated); | ||||
|         this.algorithm.on(FILTER_CHANGED, this.onAlgorithmListUpdated); | ||||
| 
 | ||||
|         // Reset state without causing updates as the client will have been destroyed
 | ||||
|         // and downstream code will throw NPE errors.
 | ||||
|         await this.reset(null, true); | ||||
|     } | ||||
| 
 | ||||
|     // Public for test usage. Do not call this.
 | ||||
|     public async makeReady(client: MatrixClient) { | ||||
|     public async makeReady(forcedClient?: MatrixClient) { | ||||
|         if (forcedClient) { | ||||
|             super.matrixClient = forcedClient; | ||||
|         } | ||||
| 
 | ||||
|         // TODO: Remove with https://github.com/vector-im/riot-web/issues/14367
 | ||||
|         this.checkEnabled(); | ||||
|         if (!this.enabled) return; | ||||
| 
 | ||||
|         this._matrixClient = client; | ||||
| 
 | ||||
|         // Update any settings here, as some may have happened before we were logically ready.
 | ||||
|         // Update any settings here, as some may have happened before we were logically ready.
 | ||||
|         console.log("Regenerating room lists: Startup"); | ||||
|  | @ -150,10 +154,6 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|                 console.warn(`${activeRoomId} is current in RVS but missing from client - clearing sticky room`); | ||||
|                 await this.algorithm.setStickyRoom(null); | ||||
|             } else if (activeRoom !== this.algorithm.stickyRoom) { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`Changing sticky room to ${activeRoomId}`); | ||||
|                 } | ||||
|                 await this.algorithm.setStickyRoom(activeRoom); | ||||
|             } | ||||
|         } | ||||
|  | @ -161,7 +161,15 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|         if (trigger) this.updateFn.trigger(); | ||||
|     } | ||||
| 
 | ||||
|     protected async onDispatch(payload: ActionPayload) { | ||||
|     protected async onReady(): Promise<any> { | ||||
|         await this.makeReady(); | ||||
|     } | ||||
| 
 | ||||
|     protected async onNotReady(): Promise<any> { | ||||
|         await this.resetStore(); | ||||
|     } | ||||
| 
 | ||||
|     protected async onAction(payload: ActionPayload) { | ||||
|         // When we're running tests we can't reliably use setImmediate out of timing concerns.
 | ||||
|         // As such, we use a more synchronous model.
 | ||||
|         if (RoomListStore2.TEST_MODE) { | ||||
|  | @ -175,29 +183,10 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|     } | ||||
| 
 | ||||
|     protected async onDispatchAsync(payload: ActionPayload) { | ||||
|         if (payload.action === 'MatrixActions.sync') { | ||||
|             // Filter out anything that isn't the first PREPARED sync.
 | ||||
|             if (!(payload.prevState === 'PREPARED' && payload.state !== 'PREPARED')) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             await this.makeReady(payload.matrixClient); | ||||
| 
 | ||||
|             return; // no point in running the next conditions - they won't match
 | ||||
|         } | ||||
| 
 | ||||
|         // TODO: Remove this once the RoomListStore becomes default
 | ||||
|         if (!this.enabled) return; | ||||
| 
 | ||||
|         if (payload.action === 'on_client_not_viable' || payload.action === 'on_logged_out') { | ||||
|             // Reset state without causing updates as the client will have been destroyed
 | ||||
|             // and downstream code will throw NPE errors.
 | ||||
|             await this.reset(null, true); | ||||
|             this._matrixClient = null; | ||||
|             this.initialListsGenerated = false; // we'll want to regenerate them
 | ||||
|         } | ||||
| 
 | ||||
|         // Everything below here requires a MatrixClient or some sort of logical readiness.
 | ||||
|         // Everything here requires a MatrixClient or some sort of logical readiness.
 | ||||
|         const logicallyReady = this.matrixClient && this.initialListsGenerated; | ||||
|         if (!logicallyReady) return; | ||||
| 
 | ||||
|  | @ -225,20 +214,12 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|                     console.warn(`Own read receipt was in unknown room ${room.roomId}`); | ||||
|                     return; | ||||
|                 } | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`[RoomListDebug] Got own read receipt in ${room.roomId}`); | ||||
|                 } | ||||
|                 await this.handleRoomUpdate(room, RoomUpdateCause.ReadReceipt); | ||||
|                 this.updateFn.trigger(); | ||||
|                 return; | ||||
|             } | ||||
|         } else if (payload.action === 'MatrixActions.Room.tags') { | ||||
|             const roomPayload = (<any>payload); // TODO: Type out the dispatcher types
 | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`[RoomListDebug] Got tag change in ${roomPayload.room.roomId}`); | ||||
|             } | ||||
|             await this.handleRoomUpdate(roomPayload.room, RoomUpdateCause.PossibleTagChange); | ||||
|             this.updateFn.trigger(); | ||||
|         } else if (payload.action === 'MatrixActions.Room.timeline') { | ||||
|  | @ -250,16 +231,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|             const roomId = eventPayload.event.getRoomId(); | ||||
|             const room = this.matrixClient.getRoom(roomId); | ||||
|             const tryUpdate = async (updatedRoom: Room) => { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`[RoomListDebug] Live timeline event ${eventPayload.event.getId()}` + | ||||
|                         ` in ${updatedRoom.roomId}`); | ||||
|                 } | ||||
|                 if (eventPayload.event.getType() === 'm.room.tombstone' && eventPayload.event.getStateKey() === '') { | ||||
|                     if (!window.mx_QuietRoomListLogging) { | ||||
|                         // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                         console.log(`[RoomListDebug] Got tombstone event - trying to remove now-dead room`); | ||||
|                     } | ||||
|                     const newRoom = this.matrixClient.getRoom(eventPayload.event.getContent()['replacement_room']); | ||||
|                     if (newRoom) { | ||||
|                         // If we have the new room, then the new room check will have seen the predecessor
 | ||||
|  | @ -289,18 +261,10 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|                 console.warn(`Event ${eventPayload.event.getId()} was decrypted in an unknown room ${roomId}`); | ||||
|                 return; | ||||
|             } | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`[RoomListDebug] Decrypted timeline event ${eventPayload.event.getId()} in ${roomId}`); | ||||
|             } | ||||
|             await this.handleRoomUpdate(room, RoomUpdateCause.Timeline); | ||||
|             this.updateFn.trigger(); | ||||
|         } else if (payload.action === 'MatrixActions.accountData' && payload.event_type === 'm.direct') { | ||||
|             const eventPayload = (<any>payload); // TODO: Type out the dispatcher types
 | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`[RoomListDebug] Received updated DM map`); | ||||
|             } | ||||
|             const dmMap = eventPayload.event.getContent(); | ||||
|             for (const userId of Object.keys(dmMap)) { | ||||
|                 const roomIds = dmMap[userId]; | ||||
|  | @ -324,54 +288,29 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|             const oldMembership = getEffectiveMembership(membershipPayload.oldMembership); | ||||
|             const newMembership = getEffectiveMembership(membershipPayload.membership); | ||||
|             if (oldMembership !== EffectiveMembership.Join && newMembership === EffectiveMembership.Join) { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`[RoomListDebug] Handling new room ${membershipPayload.room.roomId}`); | ||||
|                 } | ||||
| 
 | ||||
|                 // If we're joining an upgraded room, we'll want to make sure we don't proliferate
 | ||||
|                 // the dead room in the list.
 | ||||
|                 const createEvent = membershipPayload.room.currentState.getStateEvents("m.room.create", ""); | ||||
|                 if (createEvent && createEvent.getContent()['predecessor']) { | ||||
|                     if (!window.mx_QuietRoomListLogging) { | ||||
|                         // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                         console.log(`[RoomListDebug] Room has a predecessor`); | ||||
|                     } | ||||
|                     const prevRoom = this.matrixClient.getRoom(createEvent.getContent()['predecessor']['room_id']); | ||||
|                     if (prevRoom) { | ||||
|                         const isSticky = this.algorithm.stickyRoom === prevRoom; | ||||
|                         if (isSticky) { | ||||
|                             if (!window.mx_QuietRoomListLogging) { | ||||
|                                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                                 console.log(`[RoomListDebug] Clearing sticky room due to room upgrade`); | ||||
|                             } | ||||
|                             await this.algorithm.setStickyRoom(null); | ||||
|                         } | ||||
| 
 | ||||
|                         // Note: we hit the algorithm instead of our handleRoomUpdate() function to
 | ||||
|                         // avoid redundant updates.
 | ||||
|                         if (!window.mx_QuietRoomListLogging) { | ||||
|                             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                             console.log(`[RoomListDebug] Removing previous room from room list`); | ||||
|                         } | ||||
|                         await this.algorithm.handleRoomUpdate(prevRoom, RoomUpdateCause.RoomRemoved); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`[RoomListDebug] Adding new room to room list`); | ||||
|                 } | ||||
|                 await this.handleRoomUpdate(membershipPayload.room, RoomUpdateCause.NewRoom); | ||||
|                 this.updateFn.trigger(); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (oldMembership !== EffectiveMembership.Invite && newMembership === EffectiveMembership.Invite) { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`[RoomListDebug] Handling invite to ${membershipPayload.room.roomId}`); | ||||
|                 } | ||||
|                 await this.handleRoomUpdate(membershipPayload.room, RoomUpdateCause.NewRoom); | ||||
|                 this.updateFn.trigger(); | ||||
|                 return; | ||||
|  | @ -379,10 +318,6 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
| 
 | ||||
|             // If it's not a join, it's transitioning into a different list (possibly historical)
 | ||||
|             if (oldMembership !== newMembership) { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`[RoomListDebug] Handling membership change in ${membershipPayload.room.roomId}`); | ||||
|                 } | ||||
|                 await this.handleRoomUpdate(membershipPayload.room, RoomUpdateCause.PossibleTagChange); | ||||
|                 this.updateFn.trigger(); | ||||
|                 return; | ||||
|  | @ -393,10 +328,6 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|     private async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise<any> { | ||||
|         const shouldUpdate = await this.algorithm.handleRoomUpdate(room, cause); | ||||
|         if (shouldUpdate) { | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`[DEBUG] Room "${room.name}" (${room.roomId}) triggered by ${cause} requires list update`); | ||||
|             } | ||||
|             this.updateFn.mark(); | ||||
|         } | ||||
|     } | ||||
|  | @ -516,10 +447,6 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|     } | ||||
| 
 | ||||
|     private onAlgorithmListUpdated = () => { | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log("Underlying algorithm has triggered a list update - marking"); | ||||
|         } | ||||
|         this.updateFn.mark(); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -566,10 +493,6 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|     } | ||||
| 
 | ||||
|     public addFilter(filter: IFilterCondition): void { | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log("Adding filter condition:", filter); | ||||
|         } | ||||
|         this.filterConditions.push(filter); | ||||
|         if (this.algorithm) { | ||||
|             this.algorithm.addFilterCondition(filter); | ||||
|  | @ -578,10 +501,6 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> { | |||
|     } | ||||
| 
 | ||||
|     public removeFilter(filter: IFilterCondition): void { | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log("Removing filter condition:", filter); | ||||
|         } | ||||
|         const idx = this.filterConditions.indexOf(filter); | ||||
|         if (idx >= 0) { | ||||
|             this.filterConditions.splice(idx, 1); | ||||
|  |  | |||
|  | @ -30,12 +30,10 @@ import { | |||
|     SortAlgorithm | ||||
| } from "./models"; | ||||
| import { FILTER_CHANGED, FilterPriority, IFilterCondition } from "../filters/IFilterCondition"; | ||||
| import { EffectiveMembership, getEffectiveMembership, splitRoomsByMembership } from "../membership"; | ||||
| import { EffectiveMembership, getEffectiveMembership, splitRoomsByMembership } from "../../../utils/membership"; | ||||
| import { OrderingAlgorithm } from "./list-ordering/OrderingAlgorithm"; | ||||
| import { getListAlgorithmInstance } from "./list-ordering"; | ||||
| 
 | ||||
| // TODO: Add locking support to avoid concurrent writes? https://github.com/vector-im/riot-web/issues/14235
 | ||||
| 
 | ||||
| /** | ||||
|  * Fired when the Algorithm has determined a list has been updated. | ||||
|  */ | ||||
|  | @ -321,11 +319,6 @@ export class Algorithm extends EventEmitter { | |||
|                 } | ||||
|             } | ||||
|             newMap[tagId] = allowedRoomsInThisTag; | ||||
| 
 | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`[DEBUG] ${newMap[tagId].length}/${rooms.length} rooms filtered into ${tagId}`); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const allowedRooms = Object.values(newMap).reduce((rv, v) => { rv.push(...v); return rv; }, <Room[]>[]); | ||||
|  | @ -337,10 +330,6 @@ export class Algorithm extends EventEmitter { | |||
|     protected recalculateFilteredRoomsForTag(tagId: TagID): void { | ||||
|         if (!this.hasFilters) return; // don't bother doing work if there's nothing to do
 | ||||
| 
 | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log(`Recalculating filtered rooms for ${tagId}`); | ||||
|         } | ||||
|         delete this.filteredRooms[tagId]; | ||||
|         const rooms = this.cachedRooms[tagId].map(r => r); // cheap clone
 | ||||
|         this.tryInsertStickyRoomToFilterSet(rooms, tagId); | ||||
|  | @ -348,11 +337,6 @@ export class Algorithm extends EventEmitter { | |||
|         if (filteredRooms.length > 0) { | ||||
|             this.filteredRooms[tagId] = filteredRooms; | ||||
|         } | ||||
| 
 | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log(`[DEBUG] ${filteredRooms.length}/${rooms.length} rooms filtered into ${tagId}`); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected tryInsertStickyRoomToFilterSet(rooms: Room[], tagId: TagID) { | ||||
|  | @ -391,10 +375,6 @@ export class Algorithm extends EventEmitter { | |||
|         } | ||||
| 
 | ||||
|         if (!this._cachedStickyRooms || !updatedTag) { | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`Generating clone of cached rooms for sticky room handling`); | ||||
|             } | ||||
|             const stickiedTagMap: ITagMap = {}; | ||||
|             for (const tagId of Object.keys(this.cachedRooms)) { | ||||
|                 stickiedTagMap[tagId] = this.cachedRooms[tagId].map(r => r); // shallow clone
 | ||||
|  | @ -405,10 +385,6 @@ export class Algorithm extends EventEmitter { | |||
|         if (updatedTag) { | ||||
|             // Update the tag indicated by the caller, if possible. This is mostly to ensure
 | ||||
|             // our cache is up to date.
 | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`Replacing cached sticky rooms for ${updatedTag}`); | ||||
|             } | ||||
|             this._cachedStickyRooms[updatedTag] = this.cachedRooms[updatedTag].map(r => r); // shallow clone
 | ||||
|         } | ||||
| 
 | ||||
|  | @ -417,10 +393,6 @@ export class Algorithm extends EventEmitter { | |||
|         // we might have updated from the cache is also our sticky room.
 | ||||
|         const sticky = this._stickyRoom; | ||||
|         if (!updatedTag || updatedTag === sticky.tag) { | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`Inserting sticky room ${sticky.room.roomId} at position ${sticky.position} in ${sticky.tag}`); | ||||
|             } | ||||
|             this._cachedStickyRooms[sticky.tag].splice(sticky.position, 0, sticky.room); | ||||
|         } | ||||
| 
 | ||||
|  | @ -645,10 +617,6 @@ export class Algorithm extends EventEmitter { | |||
|      * processing. | ||||
|      */ | ||||
|     public async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise<boolean> { | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log(`Handle room update for ${room.roomId} called with cause ${cause}`); | ||||
|         } | ||||
|         if (!this.algorithms) throw new Error("Not ready: no algorithms to determine tags from"); | ||||
| 
 | ||||
|         // Note: check the isSticky against the room ID just in case the reference is wrong
 | ||||
|  | @ -698,27 +666,24 @@ export class Algorithm extends EventEmitter { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let didTagChange = false; | ||||
|         if (cause === RoomUpdateCause.PossibleTagChange) { | ||||
|             let didTagChange = false; | ||||
|             const oldTags = this.roomIdsToTags[room.roomId] || []; | ||||
|             const newTags = this.getTagsForRoom(room); | ||||
|             const diff = arrayDiff(oldTags, newTags); | ||||
|             if (diff.removed.length > 0 || diff.added.length > 0) { | ||||
|                 for (const rmTag of diff.removed) { | ||||
|                     if (!window.mx_QuietRoomListLogging) { | ||||
|                         // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                         console.log(`Removing ${room.roomId} from ${rmTag}`); | ||||
|                     } | ||||
|                     const algorithm: OrderingAlgorithm = this.algorithms[rmTag]; | ||||
|                     if (!algorithm) throw new Error(`No algorithm for ${rmTag}`); | ||||
|                     await algorithm.handleRoomUpdate(room, RoomUpdateCause.RoomRemoved); | ||||
|                     this.cachedRooms[rmTag] = algorithm.orderedRooms; | ||||
| 
 | ||||
|                     // Later on we won't update the filtered rooms or sticky room for removed
 | ||||
|                     // tags, so do so now.
 | ||||
|                     this.recalculateFilteredRoomsForTag(rmTag); | ||||
|                     this.recalculateStickyRoom(rmTag); | ||||
|                 } | ||||
|                 for (const addTag of diff.added) { | ||||
|                     if (!window.mx_QuietRoomListLogging) { | ||||
|                         // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                         console.log(`Adding ${room.roomId} to ${addTag}`); | ||||
|                     } | ||||
|                     const algorithm: OrderingAlgorithm = this.algorithms[addTag]; | ||||
|                     if (!algorithm) throw new Error(`No algorithm for ${addTag}`); | ||||
|                     await algorithm.handleRoomUpdate(room, RoomUpdateCause.NewRoom); | ||||
|  | @ -728,17 +693,9 @@ export class Algorithm extends EventEmitter { | |||
|                 // Update the tag map so we don't regen it in a moment
 | ||||
|                 this.roomIdsToTags[room.roomId] = newTags; | ||||
| 
 | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`Changing update cause for ${room.roomId} to Timeline to sort rooms`); | ||||
|                 } | ||||
|                 cause = RoomUpdateCause.Timeline; | ||||
|                 didTagChange = true; | ||||
|             } else { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.log(`Received no-op update for ${room.roomId} - changing to Timeline update`); | ||||
|                 } | ||||
|                 cause = RoomUpdateCause.Timeline; | ||||
|             } | ||||
| 
 | ||||
|  | @ -764,28 +721,15 @@ export class Algorithm extends EventEmitter { | |||
|         // as the sticky room relies on this.
 | ||||
|         if (cause !== RoomUpdateCause.NewRoom && cause !== RoomUpdateCause.RoomRemoved) { | ||||
|             if (this.stickyRoom === room) { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.warn(`[RoomListDebug] Received ${cause} update for sticky room ${room.roomId} - ignoring`); | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (!this.roomIdsToTags[room.roomId]) { | ||||
|             if (CAUSES_REQUIRING_ROOM.includes(cause)) { | ||||
|                 if (!window.mx_QuietRoomListLogging) { | ||||
|                     // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                     console.warn(`Skipping tag update for ${room.roomId} because we don't know about the room`); | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`[RoomListDebug] Updating tags for room ${room.roomId} (${room.name})`); | ||||
|             } | ||||
| 
 | ||||
|             // Get the tags for the room and populate the cache
 | ||||
|             const roomTags = this.getTagsForRoom(room).filter(t => !isNullOrUndefined(this.cachedRooms[t])); | ||||
| 
 | ||||
|  | @ -794,16 +738,6 @@ export class Algorithm extends EventEmitter { | |||
|             if (!roomTags.length) throw new Error(`Tags cannot be determined for ${room.roomId}`); | ||||
| 
 | ||||
|             this.roomIdsToTags[room.roomId] = roomTags; | ||||
| 
 | ||||
|             if (!window.mx_QuietRoomListLogging) { | ||||
|                 // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|                 console.log(`[RoomListDebug] Updated tags for ${room.roomId}:`, roomTags); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log(`[RoomListDebug] Reached algorithmic handling for ${room.roomId} and cause ${cause}`); | ||||
|         } | ||||
| 
 | ||||
|         const tags = this.roomIdsToTags[room.roomId]; | ||||
|  | @ -812,7 +746,7 @@ export class Algorithm extends EventEmitter { | |||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         let changed = false; | ||||
|         let changed = didTagChange; | ||||
|         for (const tag of tags) { | ||||
|             const algorithm: OrderingAlgorithm = this.algorithms[tag]; | ||||
|             if (!algorithm) throw new Error(`No algorithm for ${tag}`); | ||||
|  | @ -826,10 +760,6 @@ export class Algorithm extends EventEmitter { | |||
|             changed = true; | ||||
|         } | ||||
| 
 | ||||
|         if (!window.mx_QuietRoomListLogging) { | ||||
|             // TODO: Remove debug: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             console.log(`[RoomListDebug] Finished handling ${room.roomId} with cause ${cause} (changed=${changed})`); | ||||
|         } | ||||
|         return changed; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ export class NaturalAlgorithm extends OrderingAlgorithm { | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // TODO: Optimize this to avoid useless operations: https://github.com/vector-im/riot-web/issues/14035
 | ||||
|             // TODO: Optimize this to avoid useless operations: https://github.com/vector-im/riot-web/issues/14457
 | ||||
|             // For example, we can skip updates to alphabetic (sometimes) and manually ordered tags
 | ||||
|             this.cachedOrderedRooms = await sortRoomsWithAlgorithm(this.cachedOrderedRooms, this.tagId, this.sortingAlgorithm); | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,8 +17,6 @@ limitations under the License. | |||
| import { Room } from "matrix-js-sdk/src/models/room"; | ||||
| import { TagID } from "../../models"; | ||||
| import { IAlgorithm } from "./IAlgorithm"; | ||||
| import { MatrixClientPeg } from "../../../../MatrixClientPeg"; | ||||
| import * as Unread from "../../../../Unread"; | ||||
| 
 | ||||
| /** | ||||
|  * Sorts rooms according to the browser's determination of alphabetic. | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ import { TagID } from "../../models"; | |||
| import { IAlgorithm } from "./IAlgorithm"; | ||||
| import { MatrixClientPeg } from "../../../../MatrixClientPeg"; | ||||
| import * as Unread from "../../../../Unread"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../../membership"; | ||||
| import { EffectiveMembership, getEffectiveMembership } from "../../../../utils/membership"; | ||||
| 
 | ||||
| /** | ||||
|  * Sorts rooms according to the last event's timestamp in each room that seems | ||||
|  | @ -33,12 +33,13 @@ export class RecentAlgorithm implements IAlgorithm { | |||
|         // of the rooms to each other.
 | ||||
| 
 | ||||
|         // TODO: We could probably improve the sorting algorithm here by finding changes.
 | ||||
|         // See https://github.com/vector-im/riot-web/issues/14035
 | ||||
|         // See https://github.com/vector-im/riot-web/issues/14459
 | ||||
|         // For example, if we spent a little bit of time to determine which elements have
 | ||||
|         // actually changed (probably needs to be done higher up?) then we could do an
 | ||||
|         // insertion sort or similar on the limited set of changes.
 | ||||
| 
 | ||||
|         // TODO: Don't assume we're using the same client as the peg
 | ||||
|         // See https://github.com/vector-im/riot-web/issues/14458
 | ||||
|         let myUserId = ''; | ||||
|         if (MatrixClientPeg.get()) { | ||||
|             myUserId = MatrixClientPeg.get().getUserId(); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Travis Ralston
						Travis Ralston