Merge branch 'develop' into travis/room-list/enable
						commit
						bdb641279a
					
				| 
						 | 
				
			
			@ -181,7 +181,6 @@ limitations under the License.
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    .mx_RoomSublist2_resizeBox {
 | 
			
		||||
        margin-bottom: 4px; // for the resize handle
 | 
			
		||||
        position: relative;
 | 
			
		||||
 | 
			
		||||
        // Create another flexbox column for the tiles
 | 
			
		||||
| 
						 | 
				
			
			@ -189,55 +188,22 @@ limitations under the License.
 | 
			
		|||
        flex-direction: column;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
 | 
			
		||||
        .mx_RoomSublist2_placeholder {
 | 
			
		||||
            height: 44px; // Height of a room tile plus margins
 | 
			
		||||
        .mx_RoomSublist2_tiles {
 | 
			
		||||
            flex: 1 0 0;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            // need this to be flex otherwise the overflow hidden from above
 | 
			
		||||
            // sometimes vertically centers the clipped list ... no idea why it would do this
 | 
			
		||||
            // as the box model should be top aligned. Happens in both FF and Chromium
 | 
			
		||||
            display: flex;
 | 
			
		||||
            flex-direction: column;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .mx_RoomSublist2_showNButton {
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
            font-size: $font-13px;
 | 
			
		||||
            line-height: $font-18px;
 | 
			
		||||
            color: $roomtile2-preview-color;
 | 
			
		||||
        .mx_RoomSublist2_resizerHandles_showNButton {
 | 
			
		||||
            flex: 0 0 32px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            // Update the render() function for RoomSublist2 if these change
 | 
			
		||||
            // Update the ListLayout class for minVisibleTiles if these change.
 | 
			
		||||
            //
 | 
			
		||||
            // At 24px high, 8px padding on the top and 4px padding on the bottom  this equates to 0.73 of
 | 
			
		||||
            // a tile due to how the padding calculations work.
 | 
			
		||||
            height: 24px;
 | 
			
		||||
            padding-top: 8px;
 | 
			
		||||
            padding-bottom: 4px;
 | 
			
		||||
 | 
			
		||||
            // We force this to the bottom so it will overlap rooms as needed.
 | 
			
		||||
            // We account for the space it takes up (24px) in the code through padding.
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            bottom: 0;
 | 
			
		||||
            left: 0;
 | 
			
		||||
            right: 0;
 | 
			
		||||
 | 
			
		||||
            // We create a flexbox to cheat at alignment
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
 | 
			
		||||
            .mx_RoomSublist2_showNButtonChevron {
 | 
			
		||||
                position: relative;
 | 
			
		||||
                width: 16px;
 | 
			
		||||
                height: 16px;
 | 
			
		||||
                margin-left: 12px;
 | 
			
		||||
                margin-right: 18px;
 | 
			
		||||
                mask-position: center;
 | 
			
		||||
                mask-size: contain;
 | 
			
		||||
                mask-repeat: no-repeat;
 | 
			
		||||
                background: $roomtile2-preview-color;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .mx_RoomSublist2_showMoreButtonChevron {
 | 
			
		||||
                mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .mx_RoomSublist2_showLessButtonChevron {
 | 
			
		||||
                mask-image: url('$(res)/img/feather-customised/chevron-up.svg');
 | 
			
		||||
            }
 | 
			
		||||
        .mx_RoomSublist2_resizerHandles {
 | 
			
		||||
            flex: 0 0 4px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Class name comes from the ResizableBox component
 | 
			
		||||
| 
						 | 
				
			
			@ -269,6 +235,42 @@ limitations under the License.
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .mx_RoomSublist2_showNButton {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        font-size: $font-13px;
 | 
			
		||||
        line-height: $font-18px;
 | 
			
		||||
        color: $roomtile2-preview-color;
 | 
			
		||||
 | 
			
		||||
        // Update the render() function for RoomSublist2 if these change
 | 
			
		||||
        // Update the ListLayout class for minVisibleTiles if these change.
 | 
			
		||||
        height: 24px;
 | 
			
		||||
        padding-bottom: 4px;
 | 
			
		||||
 | 
			
		||||
        // We create a flexbox to cheat at alignment
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
 | 
			
		||||
        .mx_RoomSublist2_showNButtonChevron {
 | 
			
		||||
            position: relative;
 | 
			
		||||
            width: 16px;
 | 
			
		||||
            height: 16px;
 | 
			
		||||
            margin-left: 12px;
 | 
			
		||||
            margin-right: 18px;
 | 
			
		||||
            mask-position: center;
 | 
			
		||||
            mask-size: contain;
 | 
			
		||||
            mask-repeat: no-repeat;
 | 
			
		||||
            background: $roomtile2-preview-color;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .mx_RoomSublist2_showMoreButtonChevron {
 | 
			
		||||
            mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .mx_RoomSublist2_showLessButtonChevron {
 | 
			
		||||
            mask-image: url('$(res)/img/feather-customised/chevron-up.svg');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.mx_RoomSublist2_hasMenuOpen,
 | 
			
		||||
    &:not(.mx_RoomSublist2_minimized) > .mx_RoomSublist2_headerContainer:focus-within,
 | 
			
		||||
    &:not(.mx_RoomSublist2_minimized) > .mx_RoomSublist2_headerContainer:hover {
 | 
			
		||||
| 
						 | 
				
			
			@ -314,13 +316,13 @@ limitations under the License.
 | 
			
		|||
 | 
			
		||||
        .mx_RoomSublist2_resizeBox {
 | 
			
		||||
            align-items: center;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            .mx_RoomSublist2_showNButton {
 | 
			
		||||
                flex-direction: column;
 | 
			
		||||
        .mx_RoomSublist2_showNButton {
 | 
			
		||||
            flex-direction: column;
 | 
			
		||||
 | 
			
		||||
                .mx_RoomSublist2_showNButtonChevron {
 | 
			
		||||
                    margin-right: 12px; // to center
 | 
			
		||||
                }
 | 
			
		||||
            .mx_RoomSublist2_showNButtonChevron {
 | 
			
		||||
                margin-right: 12px; // to center
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
 | 
			
		|||
 * warning disappears.                                             *
 | 
			
		||||
 *******************************************************************/
 | 
			
		||||
 | 
			
		||||
const SHOW_N_BUTTON_HEIGHT = 32; // As defined by CSS
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -87,6 +87,12 @@ interface IProps {
 | 
			
		|||
    // TODO: Account for https://github.com/vector-im/riot-web/issues/14179
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Use re-resizer's NumberSize when it is exposed as the type
 | 
			
		||||
interface ResizeDelta {
 | 
			
		||||
    width: number;
 | 
			
		||||
    height: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PartialDOMRect = Pick<DOMRect, "left" | "top" | "height">;
 | 
			
		||||
 | 
			
		||||
interface IState {
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +100,7 @@ interface IState {
 | 
			
		|||
    contextMenuPosition: PartialDOMRect;
 | 
			
		||||
    isResizing: boolean;
 | 
			
		||||
    isExpanded: boolean; // used for the for expand of the sublist when the room list is being filtered
 | 
			
		||||
    height: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		||||
| 
						 | 
				
			
			@ -101,28 +108,54 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
    private sublistRef = createRef<HTMLDivElement>();
 | 
			
		||||
    private dispatcherRef: string;
 | 
			
		||||
    private layout: ListLayout;
 | 
			
		||||
    private heightAtStart: number;
 | 
			
		||||
 | 
			
		||||
    constructor(props: IProps) {
 | 
			
		||||
        super(props);
 | 
			
		||||
 | 
			
		||||
        this.layout = RoomListLayoutStore.instance.getLayoutFor(this.props.tagId);
 | 
			
		||||
 | 
			
		||||
        this.heightAtStart = 0;
 | 
			
		||||
        const height = this.calculateInitialHeight();
 | 
			
		||||
        this.state = {
 | 
			
		||||
            notificationState: RoomNotificationStateStore.instance.getListState(this.props.tagId),
 | 
			
		||||
            contextMenuPosition: null,
 | 
			
		||||
            isResizing: false,
 | 
			
		||||
            isExpanded: this.props.isFiltered ? this.props.isFiltered : !this.layout.isCollapsed
 | 
			
		||||
            isExpanded: this.props.isFiltered ? this.props.isFiltered : !this.layout.isCollapsed,
 | 
			
		||||
            height,
 | 
			
		||||
        };
 | 
			
		||||
        this.state.notificationState.setRooms(this.props.rooms);
 | 
			
		||||
        this.dispatcherRef = defaultDispatcher.register(this.onAction);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private calculateInitialHeight() {
 | 
			
		||||
        const requestedVisibleTiles = Math.max(Math.floor(this.layout.visibleTiles), this.layout.minVisibleTiles);
 | 
			
		||||
        const tileCount = Math.min(this.numTiles, requestedVisibleTiles);
 | 
			
		||||
        const height = this.layout.tilesToPixelsWithPadding(tileCount, this.padding);
 | 
			
		||||
        return height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private get padding() {
 | 
			
		||||
        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) {
 | 
			
		||||
            padding += SHOW_N_BUTTON_HEIGHT;
 | 
			
		||||
        }
 | 
			
		||||
        return padding;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private get numTiles(): number {
 | 
			
		||||
        return (this.props.rooms || []).length + (this.props.extraBadTilesThatShouldntExist || []).length;
 | 
			
		||||
        return RoomSublist2.calcNumTiles(this.props);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static calcNumTiles(props) {
 | 
			
		||||
        return (props.rooms || []).length + (props.extraBadTilesThatShouldntExist || []).length;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private get numVisibleTiles(): number {
 | 
			
		||||
        const nVisible = Math.floor(this.layout.visibleTiles);
 | 
			
		||||
        const nVisible = Math.ceil(this.layout.visibleTiles);
 | 
			
		||||
        return Math.min(nVisible, this.numTiles);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +168,11 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
                this.setState({isExpanded: !this.layout.isCollapsed});
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // as the rooms can come in one by one we need to reevaluate
 | 
			
		||||
        // the amount of available rooms to cap the amount of requested visible rooms by the layout
 | 
			
		||||
        if (RoomSublist2.calcNumTiles(prevProps) !== this.numTiles) {
 | 
			
		||||
            this.setState({height: this.calculateInitialHeight()});
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public componentWillUnmount() {
 | 
			
		||||
| 
						 | 
				
			
			@ -166,47 +204,50 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
        if (this.props.onAddRoom) this.props.onAddRoom();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private applyHeightChange(newHeight: number) {
 | 
			
		||||
        const heightInTiles = Math.ceil(this.layout.pixelsToTiles(newHeight - this.padding));
 | 
			
		||||
        this.layout.visibleTiles = Math.min(this.numTiles, heightInTiles);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private onResize = (
 | 
			
		||||
        e: MouseEvent | TouchEvent,
 | 
			
		||||
        travelDirection: Direction,
 | 
			
		||||
        refToElement: HTMLDivElement,
 | 
			
		||||
        delta: { width: number, height: number }, // TODO: Use re-resizer's NumberSize when it is exposed as the type
 | 
			
		||||
        delta: ResizeDelta,
 | 
			
		||||
    ) => {
 | 
			
		||||
        // Do some sanity checks, but in reality we shouldn't need these.
 | 
			
		||||
        if (travelDirection !== "bottom") return;
 | 
			
		||||
        if (delta.height === 0) return; // something went wrong, so just ignore it.
 | 
			
		||||
 | 
			
		||||
        // NOTE: the movement in the MouseEvent (not present on a TouchEvent) is inaccurate
 | 
			
		||||
        // for our purposes. The delta provided by the library is also a change *from when
 | 
			
		||||
        // resizing started*, meaning it is fairly useless for us. This is why we just use
 | 
			
		||||
        // the client height and run with it.
 | 
			
		||||
 | 
			
		||||
        const heightBefore = this.layout.visibleTiles;
 | 
			
		||||
        const heightInTiles = this.layout.pixelsToTiles(refToElement.clientHeight);
 | 
			
		||||
        this.layout.setVisibleTilesWithin(heightInTiles, this.numTiles);
 | 
			
		||||
        if (heightBefore === this.layout.visibleTiles) return; // no-op
 | 
			
		||||
        this.forceUpdate(); // because the layout doesn't trigger a re-render
 | 
			
		||||
        const newHeight = this.heightAtStart + delta.height;
 | 
			
		||||
        this.applyHeightChange(newHeight);
 | 
			
		||||
        this.setState({height: newHeight});
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onResizeStart = () => {
 | 
			
		||||
        this.heightAtStart = this.state.height;
 | 
			
		||||
        this.setState({isResizing: true});
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onResizeStop = () => {
 | 
			
		||||
        this.setState({isResizing: false});
 | 
			
		||||
    private onResizeStop = (
 | 
			
		||||
        e: MouseEvent | TouchEvent,
 | 
			
		||||
        travelDirection: Direction,
 | 
			
		||||
        refToElement: HTMLDivElement,
 | 
			
		||||
        delta: ResizeDelta,
 | 
			
		||||
    ) => {
 | 
			
		||||
        const newHeight = this.heightAtStart + delta.height;
 | 
			
		||||
        this.applyHeightChange(newHeight);
 | 
			
		||||
        this.setState({isResizing: false, height: newHeight});
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onShowAllClick = () => {
 | 
			
		||||
        const numVisibleTiles = this.numVisibleTiles;
 | 
			
		||||
        this.layout.visibleTiles = this.layout.tilesWithPadding(this.numTiles, MAX_PADDING_HEIGHT);
 | 
			
		||||
        this.forceUpdate(); // because the layout doesn't trigger a re-render
 | 
			
		||||
        setImmediate(this.focusRoomTile, numVisibleTiles); // focus the tile after the current bottom one
 | 
			
		||||
        const newHeight = this.layout.tilesToPixelsWithPadding(this.numTiles, this.padding);
 | 
			
		||||
        this.applyHeightChange(newHeight);
 | 
			
		||||
        this.setState({height: newHeight}, () => {
 | 
			
		||||
            this.focusRoomTile(this.numTiles - 1);
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onShowLessClick = () => {
 | 
			
		||||
        this.layout.visibleTiles = this.layout.defaultVisibleTiles;
 | 
			
		||||
        this.forceUpdate(); // because the layout doesn't trigger a re-render
 | 
			
		||||
        // focus will flow to the show more button here
 | 
			
		||||
        const newHeight = this.layout.tilesToPixelsWithPadding(this.layout.defaultVisibleTiles, this.padding);
 | 
			
		||||
        this.applyHeightChange(newHeight);
 | 
			
		||||
        this.setState({height: newHeight});
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private focusRoomTile = (index: number) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -559,7 +600,6 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
        // TODO: Error boundary: https://github.com/vector-im/riot-web/issues/14185
 | 
			
		||||
 | 
			
		||||
        const visibleTiles = this.renderVisibleTiles();
 | 
			
		||||
 | 
			
		||||
        const classes = classNames({
 | 
			
		||||
            'mx_RoomSublist2': true,
 | 
			
		||||
            'mx_RoomSublist2_hasMenuOpen': !!this.state.contextMenuPosition,
 | 
			
		||||
| 
						 | 
				
			
			@ -570,6 +610,11 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
        if (visibleTiles.length > 0) {
 | 
			
		||||
            const layout = this.layout; // to shorten calls
 | 
			
		||||
 | 
			
		||||
            const minTiles = Math.min(layout.minVisibleTiles, this.numTiles);
 | 
			
		||||
            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);
 | 
			
		||||
            const showMoreBtnClasses = classNames({
 | 
			
		||||
                'mx_RoomSublist2_showNButton': true,
 | 
			
		||||
            });
 | 
			
		||||
| 
						 | 
				
			
			@ -578,9 +623,11 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
            // floats above the resize handle, if we have one present. If the user has all
 | 
			
		||||
            // tiles visible, it becomes 'show less'.
 | 
			
		||||
            let showNButton = null;
 | 
			
		||||
            if (this.numTiles > visibleTiles.length) {
 | 
			
		||||
                // we have a cutoff condition - add the button to show all
 | 
			
		||||
                const numMissing = this.numTiles - visibleTiles.length;
 | 
			
		||||
 | 
			
		||||
            if (maxTilesPx > this.state.height) {
 | 
			
		||||
                const nonPaddedHeight = this.state.height - RESIZE_HANDLE_HEIGHT - SHOW_N_BUTTON_HEIGHT;
 | 
			
		||||
                const amountFullyShown = Math.floor(nonPaddedHeight / this.layout.tileHeight);
 | 
			
		||||
                const numMissing = this.numTiles - amountFullyShown;
 | 
			
		||||
                let showMoreText = (
 | 
			
		||||
                    <span className='mx_RoomSublist2_showNButtonText'>
 | 
			
		||||
                        {_t("Show %(count)s more", {count: numMissing})}
 | 
			
		||||
| 
						 | 
				
			
			@ -595,7 +642,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
                        {showMoreText}
 | 
			
		||||
                    </RovingAccessibleButton>
 | 
			
		||||
                );
 | 
			
		||||
            } else if (this.numTiles <= visibleTiles.length && this.numTiles > this.layout.defaultVisibleTiles) {
 | 
			
		||||
            } else if (this.numTiles > this.layout.defaultVisibleTiles) {
 | 
			
		||||
                // we have all tiles visible - add a button to show less
 | 
			
		||||
                let showLessText = (
 | 
			
		||||
                    <span className='mx_RoomSublist2_showNButtonText'>
 | 
			
		||||
| 
						 | 
				
			
			@ -639,44 +686,31 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
 | 
			
		|||
            // goes backwards and can become wildly incorrect (visibleTiles says 18 when there's
 | 
			
		||||
            // only mathematically 7 possible).
 | 
			
		||||
 | 
			
		||||
            // The padding is variable though, so figure out what we need padding for.
 | 
			
		||||
            let padding = 0;
 | 
			
		||||
            if (showNButton) padding += SHOW_N_BUTTON_HEIGHT;
 | 
			
		||||
            padding += RESIZE_HANDLE_HEIGHT; // always append the handle height
 | 
			
		||||
            const handleWrapperClasses = classNames({
 | 
			
		||||
                'mx_RoomSublist2_resizerHandles': true,
 | 
			
		||||
                'mx_RoomSublist2_resizerHandles_showNButton': !!showNButton,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            const relativeTiles = layout.tilesWithPadding(this.numTiles, padding);
 | 
			
		||||
            const minTilesPx = layout.calculateTilesToPixelsMin(relativeTiles, layout.minVisibleTiles, padding);
 | 
			
		||||
            const maxTilesPx = layout.tilesToPixelsWithPadding(this.numTiles, padding);
 | 
			
		||||
            const tilesWithoutPadding = Math.min(relativeTiles, layout.visibleTiles);
 | 
			
		||||
            const tilesPx = layout.calculateTilesToPixelsMin(relativeTiles, tilesWithoutPadding, padding);
 | 
			
		||||
 | 
			
		||||
            // Now that we know our padding constraints, let's find out if we need to chop off the
 | 
			
		||||
            // last rendered visible tile so it doesn't collide with the 'show more' button
 | 
			
		||||
            let visibleUnpaddedTiles = Math.round(layout.visibleTiles - layout.pixelsToTiles(padding));
 | 
			
		||||
            if (visibleUnpaddedTiles === visibleTiles.length - 1) {
 | 
			
		||||
                const placeholder = <div className="mx_RoomSublist2_placeholder" key='placeholder' />;
 | 
			
		||||
                visibleTiles.splice(visibleUnpaddedTiles, 1, placeholder);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const dimensions = {
 | 
			
		||||
                height: tilesPx,
 | 
			
		||||
            };
 | 
			
		||||
            content = (
 | 
			
		||||
                <Resizable
 | 
			
		||||
                    size={dimensions as any}
 | 
			
		||||
                    minHeight={minTilesPx}
 | 
			
		||||
                    maxHeight={maxTilesPx}
 | 
			
		||||
                    onResizeStart={this.onResizeStart}
 | 
			
		||||
                    onResizeStop={this.onResizeStop}
 | 
			
		||||
                    onResize={this.onResize}
 | 
			
		||||
                    handleWrapperClass="mx_RoomSublist2_resizerHandles"
 | 
			
		||||
                    handleClasses={{bottom: "mx_RoomSublist2_resizerHandle"}}
 | 
			
		||||
                    className="mx_RoomSublist2_resizeBox"
 | 
			
		||||
                    enable={handles}
 | 
			
		||||
                >
 | 
			
		||||
                    {visibleTiles}
 | 
			
		||||
                    {showNButton}
 | 
			
		||||
                </Resizable>
 | 
			
		||||
                <React.Fragment>
 | 
			
		||||
                    <Resizable
 | 
			
		||||
                        size={{height: this.state.height} as any}
 | 
			
		||||
                        minHeight={minTilesPx}
 | 
			
		||||
                        maxHeight={maxTilesPx}
 | 
			
		||||
                        onResizeStart={this.onResizeStart}
 | 
			
		||||
                        onResizeStop={this.onResizeStop}
 | 
			
		||||
                        onResize={this.onResize}
 | 
			
		||||
                        handleWrapperClass={handleWrapperClasses}
 | 
			
		||||
                        handleClasses={{bottom: "mx_RoomSublist2_resizerHandle"}}
 | 
			
		||||
                        className="mx_RoomSublist2_resizeBox"
 | 
			
		||||
                        enable={handles}
 | 
			
		||||
                    >
 | 
			
		||||
                        <div className="mx_RoomSublist2_tiles">
 | 
			
		||||
                            {visibleTiles}
 | 
			
		||||
                        </div>
 | 
			
		||||
                        {showNButton}
 | 
			
		||||
                    </Resizable>
 | 
			
		||||
                </React.Fragment>
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,8 @@ const TILE_HEIGHT_PX = 44;
 | 
			
		|||
 | 
			
		||||
// this comes from the CSS where the show more button is
 | 
			
		||||
// mathematically this percent of a tile when floating.
 | 
			
		||||
const RESIZER_BOX_FACTOR = 0.78;
 | 
			
		||||
//const RESIZER_BOX_FACTOR = 0.78;
 | 
			
		||||
const RESIZER_BOX_FACTOR = 0;
 | 
			
		||||
 | 
			
		||||
interface ISerializedListLayout {
 | 
			
		||||
    numTiles: number;
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +110,10 @@ export class ListLayout {
 | 
			
		|||
        return this.tilesToPixels(Math.min(maxTiles, n)) + padding;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public tilesWithResizerBoxFactor(n: number): number {
 | 
			
		||||
        return n + RESIZER_BOX_FACTOR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public tilesWithPadding(n: number, paddingPx: number): number {
 | 
			
		||||
        return this.pixelsToTiles(this.tilesToPixelsWithPadding(n, paddingPx));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ import { IListOrderingMap, ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm
 | 
			
		|||
import { ActionPayload } from "../../dispatcher/payloads";
 | 
			
		||||
import defaultDispatcher from "../../dispatcher/dispatcher";
 | 
			
		||||
import { readReceiptChangeIsFor } from "../../utils/read-receipts";
 | 
			
		||||
import { IFilterCondition } from "./filters/IFilterCondition";
 | 
			
		||||
import { FILTER_CHANGED, IFilterCondition } from "./filters/IFilterCondition";
 | 
			
		||||
import { TagWatcher } from "./TagWatcher";
 | 
			
		||||
import RoomViewStore from "../RoomViewStore";
 | 
			
		||||
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm";
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +71,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
 | 
			
		|||
        for (const settingName of this.watchedSettings) SettingsStore.monitorSetting(settingName, null);
 | 
			
		||||
        RoomViewStore.addListener(() => this.handleRVSUpdate({}));
 | 
			
		||||
        this.algorithm.on(LIST_UPDATED_EVENT, this.onAlgorithmListUpdated);
 | 
			
		||||
        this.algorithm.on(FILTER_CHANGED, this.onAlgorithmFilterUpdated);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public get orderedLists(): ITagMap {
 | 
			
		||||
| 
						 | 
				
			
			@ -512,6 +513,11 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
 | 
			
		|||
        this.updateFn.mark();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private onAlgorithmFilterUpdated = () => {
 | 
			
		||||
        // The filter can happen off-cycle, so trigger an update if we need to.
 | 
			
		||||
        this.updateFn.triggerIfWillMark();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Regenerates the room whole room list, discarding any previous results.
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,11 +153,11 @@ export class Algorithm extends EventEmitter {
 | 
			
		|||
        // Populate the cache of the new filter
 | 
			
		||||
        this.allowedByFilter.set(filterCondition, this.rooms.filter(r => filterCondition.isVisible(r)));
 | 
			
		||||
        this.recalculateFilteredRooms();
 | 
			
		||||
        filterCondition.on(FILTER_CHANGED, this.recalculateFilteredRooms.bind(this));
 | 
			
		||||
        filterCondition.on(FILTER_CHANGED, this.handleFilterChange.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public removeFilterCondition(filterCondition: IFilterCondition): void {
 | 
			
		||||
        filterCondition.off(FILTER_CHANGED, this.recalculateFilteredRooms.bind(this));
 | 
			
		||||
        filterCondition.off(FILTER_CHANGED, this.handleFilterChange.bind(this));
 | 
			
		||||
        if (this.allowedByFilter.has(filterCondition)) {
 | 
			
		||||
            this.allowedByFilter.delete(filterCondition);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +169,13 @@ export class Algorithm extends EventEmitter {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async handleFilterChange() {
 | 
			
		||||
        await this.recalculateFilteredRooms();
 | 
			
		||||
 | 
			
		||||
        // re-emit the update so the list store can fire an off-cycle update if needed
 | 
			
		||||
        this.emit(FILTER_CHANGED);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async updateStickyRoom(val: Room) {
 | 
			
		||||
        try {
 | 
			
		||||
            return await this.doUpdateStickyRoom(val);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue