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

Update resize handle for new designs in new room list #4741

Merged
merged 2 commits into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions res/css/views/rooms/_RoomSublist2.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ limitations under the License.

// TODO: Rename to mx_RoomSublist during replacement of old component

// TODO: Just use the 3 selectors we need from this instead of importing it.
// We're going to end up with heavy modifications anyways.
@import "../../../../node_modules/react-resizable/css/styles.css";

.mx_RoomSublist2 {
// The sublist is a column of rows, essentially
display: flex;
Expand Down Expand Up @@ -63,18 +59,83 @@ limitations under the License.
}

.mx_RoomSublist2_resizeBox {
margin-bottom: 4px; // for the resize handle
position: relative;

// Create another flexbox column for the tiles
display: flex;
flex-direction: column;
overflow: hidden;

.mx_RoomSublist2_showMoreButton {
height: 44px; // 1 room tile high
cursor: pointer;
font-size: $font-13px;
line-height: $font-18px;
color: $roomtile2-preview-color;

// This is the same color as the left panel background because it needs
// to occlude the lastmost tile in the list.
background-color: $header-panel-bg-color;

// Update the render() function for RoomSublist2 if these change
// Update the ListLayout class for minVisibleTiles if these change.
//
// At 24px high and 8px padding on the top this equates to 0.65 of
// a tile due to how the padding calculations work.
height: 24px;
padding-top: 8px;

// 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: 4px; // the height of the resize handle
left: 0;
right: 0;

// We create a flexbox to cheat at alignment
display: flex;
align-items: center;

.mx_RoomSublist2_showMoreButtonChevron {
position: relative;
width: 16px;
height: 16px;
margin-left: 12px;
margin-right: 18px;
mask-image: url('$(res)/img/feather-customised/chevron-down.svg');
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
background: $roomtile2-preview-color;
}
}

// Class name comes from the ResizableBox component
// The hover state needs to use the whole sublist, not just the resizable box,
// so that selector is below and one level higher.
.react-resizable-handle {
cursor: ns-resize;
border-radius: 2px;

// This is positioned directly below the 'show more' button.
position: absolute;
bottom: 0;
left: 0;
right: 0;

// This is to visually align the bar in the list. Should be 12px from
// either side of the list. We define this after the positioning to
// trick the browser.
margin-left: 4px;
margin-right: 8px;
}
}

// The aforementioned selector for the hover state.
&:hover .react-resizable-handle {
opacity: 0.2;

// Update the render() function for RoomSublist2 if this changes
border: 2px solid $primary-fg-color;
}
}
76 changes: 46 additions & 30 deletions src/components/views/rooms/RoomSublist2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,46 +178,61 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {

let content = null;
if (tiles.length > 0) {
const layout = this.props.layout; // to shorten calls

// TODO: Lazy list rendering
// TODO: Whatever scrolling magic needs to happen here
const layout = this.props.layout; // to shorten calls
const minTilesPx = layout.tilesToPixels(Math.min(tiles.length, layout.minVisibleTiles));
const maxTilesPx = layout.tilesToPixels(tiles.length);
const tilesPx = layout.tilesToPixels(Math.min(tiles.length, layout.visibleTiles));
let handles = ['s'];
if (layout.visibleTiles >= tiles.length && tiles.length <= layout.minVisibleTiles) {
handles = []; // no handles, we're at a minimum
}

// TODO: This might need adjustment, however for now it is fine as a round.
const nVisible = Math.round(layout.visibleTiles);
const nVisible = Math.floor(layout.visibleTiles);
const visibleTiles = tiles.slice(0, nVisible);

// If we're hiding rooms, show a 'show more' button to the user. This button
// replaces the last visible tile, so will always show 2+ rooms. We do this
// because if it said "show 1 more room" we had might as well show that room
// instead. We also replace the last item so we don't have to adjust our math
// on pixel heights, etc. It's much easier to pretend the button is a tile.
// floats above the resize handle, if we have one present
let showMoreButton = null;
if (tiles.length > nVisible) {
// we have a cutoff condition - add the button to show all

// we +1 to account for the room we're about to hide with our 'show more' button
// this results in the button always being 1+, and not needing an i18n `count`.
const numMissing = (tiles.length - visibleTiles.length) + 1;

// TODO: CSS TBD
// TODO: Make this an actual tile
// TODO: This is likely to pop out of the list, consider that.
visibleTiles.splice(visibleTiles.length - 1, 1, (
<div
onClick={this.onShowAllClick}
className='mx_RoomSublist2_showMoreButton'
key='showall'
>
{_t("Show %(n)s more", {n: numMissing})}
const numMissing = tiles.length - visibleTiles.length;
showMoreButton = (
<div onClick={this.onShowAllClick} className='mx_RoomSublist2_showMoreButton'>
<span className='mx_RoomSublist2_showMoreButtonChevron'>
{/* set by CSS masking */}
</span>
<span className='mx_RoomSublist2_showMoreButtonText'>
{_t("Show %(count)s more", {count: numMissing})}
</span>
</div>
));
);
}

// Figure out if we need a handle
let handles = ['s'];
if (layout.visibleTiles >= tiles.length && tiles.length <= layout.minVisibleTiles) {
handles = []; // no handles, we're at a minimum
}

// We have to account for padding so we can accommodate a 'show more' button and
// the resize handle, which are pinned to the bottom of the container. This is the
// easiest way to have a resize handle below the button as otherwise we're writing
// our own resize handling and that doesn't sound fun.
//
// The layout class has some helpers for dealing with padding, as we don't want to
// apply it in all cases. If we apply it in all cases, the resizing feels like it
// goes backwards and can become wildly incorrect (visibleTiles says 18 when there's
// only mathematically 7 possible).

const showMoreHeight = 32; // As defined by CSS
const resizeHandleHeight = 4; // As defined by CSS

// The padding is variable though, so figure out what we need padding for.
let padding = 0;
if (showMoreButton) padding += showMoreHeight;
if (handles.length > 0) padding += resizeHandleHeight;

const minTilesPx = layout.calculateTilesToPixelsMin(tiles.length, layout.minVisibleTiles, padding);
const maxTilesPx = layout.tilesToPixelsWithPadding(tiles.length, padding);
const tilesWithoutPadding = Math.min(tiles.length, layout.visibleTiles);
const tilesPx = layout.calculateTilesToPixelsMin(tiles.length, tilesWithoutPadding, padding);

content = (
<ResizableBox
width={-1}
Expand All @@ -230,6 +245,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
className="mx_RoomSublist2_resizeBox"
>
{visibleTiles}
{showMoreButton}
</ResizableBox>
)
}
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,8 @@
"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",
"Show %(n)s more": "Show %(n)s more",
"Show %(count)s more|other": "Show %(count)s more",
"Show %(count)s more|one": "Show %(count)s more",
"Options": "Options",
"%(count)s unread messages including mentions.|other": "%(count)s unread messages including mentions.",
"%(count)s unread messages including mentions.|one": "1 unread mention.",
Expand Down
19 changes: 18 additions & 1 deletion src/stores/room-list/ListLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,24 @@ export class ListLayout {
}

public get minVisibleTiles(): number {
return 3;
// the .65 comes from the CSS where the show more button is
// mathematically 65% of a tile when floating.
return 4.65;
}

public calculateTilesToPixelsMin(maxTiles: number, n: number, possiblePadding: number): number {
// Only apply the padding if we're about to use maxTiles as we need to
// plan for the padding. If we're using n, the padding is already accounted
// for by the resizing stuff.
let padding = 0;
if (maxTiles < n) {
padding = possiblePadding;
}
return this.tilesToPixels(Math.min(maxTiles, n)) + padding;
}

public tilesToPixelsWithPadding(n: number, padding: number): number {
return this.tilesToPixels(n) + padding;
}

public tilesToPixels(n: number): number {
Expand Down