Merge branch 'develop' into travis/room-list/enable
commit
0908e813fb
|
@ -20,7 +20,7 @@ import * as React from "react";
|
||||||
import { createRef } from "react";
|
import { createRef } from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import {RovingAccessibleButton, RovingTabIndexWrapper} from "../../../accessibility/RovingTabIndex";
|
import { RovingAccessibleButton, RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import AccessibleButton from "../../views/elements/AccessibleButton";
|
import AccessibleButton from "../../views/elements/AccessibleButton";
|
||||||
import RoomTile2 from "./RoomTile2";
|
import RoomTile2 from "./RoomTile2";
|
||||||
|
@ -36,12 +36,12 @@ import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
||||||
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
import { ListAlgorithm, SortAlgorithm } from "../../../stores/room-list/algorithms/models";
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
import NotificationBadge from "./NotificationBadge";
|
import NotificationBadge from "./NotificationBadge";
|
||||||
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
import { ListNotificationState } from "../../../stores/notifications/ListNotificationState";
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
import { Key } from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
import { ActionPayload } from "../../../dispatcher/payloads";
|
||||||
import {ActionPayload} from "../../../dispatcher/payloads";
|
|
||||||
import { Enable, Resizable } from "re-resizable";
|
import { Enable, Resizable } from "re-resizable";
|
||||||
import { Direction } from "re-resizable/lib/resizer";
|
import { Direction } from "re-resizable/lib/resizer";
|
||||||
import { polyfillTouchEvent } from "../../../@types/polyfill";
|
import { polyfillTouchEvent } from "../../../@types/polyfill";
|
||||||
|
@ -130,8 +130,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
private calculateInitialHeight() {
|
private calculateInitialHeight() {
|
||||||
const requestedVisibleTiles = Math.max(Math.floor(this.layout.visibleTiles), this.layout.minVisibleTiles);
|
const requestedVisibleTiles = Math.max(Math.floor(this.layout.visibleTiles), this.layout.minVisibleTiles);
|
||||||
const tileCount = Math.min(this.numTiles, requestedVisibleTiles);
|
const tileCount = Math.min(this.numTiles, requestedVisibleTiles);
|
||||||
const height = this.layout.tilesToPixelsWithPadding(tileCount, this.padding);
|
return this.layout.tilesToPixelsWithPadding(tileCount, this.padding);
|
||||||
return height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private get padding() {
|
private get padding() {
|
||||||
|
|
|
@ -18,11 +18,6 @@ import { TagID } from "./models";
|
||||||
|
|
||||||
const TILE_HEIGHT_PX = 44;
|
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;
|
|
||||||
|
|
||||||
interface ISerializedListLayout {
|
interface ISerializedListLayout {
|
||||||
numTiles: number;
|
numTiles: number;
|
||||||
showPreviews: boolean;
|
showPreviews: boolean;
|
||||||
|
@ -82,36 +77,12 @@ export class ListLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get minVisibleTiles(): number {
|
public get minVisibleTiles(): number {
|
||||||
return 1 + RESIZER_BOX_FACTOR;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get defaultVisibleTiles(): number {
|
public get defaultVisibleTiles(): number {
|
||||||
// This number is what "feels right", and mostly subject to design's opinion.
|
// This number is what "feels right", and mostly subject to design's opinion.
|
||||||
return 5 + RESIZER_BOX_FACTOR;
|
return 5;
|
||||||
}
|
|
||||||
|
|
||||||
public setVisibleTilesWithin(newVal: number, maxPossible: number) {
|
|
||||||
maxPossible = maxPossible + RESIZER_BOX_FACTOR;
|
|
||||||
if (newVal > maxPossible) {
|
|
||||||
this.visibleTiles = maxPossible;
|
|
||||||
} else {
|
|
||||||
this.visibleTiles = newVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 tilesWithResizerBoxFactor(n: number): number {
|
|
||||||
return n + RESIZER_BOX_FACTOR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public tilesWithPadding(n: number, paddingPx: number): number {
|
public tilesWithPadding(n: number, paddingPx: number): number {
|
||||||
|
|
|
@ -403,10 +403,14 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setTagSorting(tagId: TagID, sort: SortAlgorithm) {
|
public async setTagSorting(tagId: TagID, sort: SortAlgorithm) {
|
||||||
|
await this.setAndPersistTagSorting(tagId, sort);
|
||||||
|
this.updateFn.trigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async setAndPersistTagSorting(tagId: TagID, sort: SortAlgorithm) {
|
||||||
await this.algorithm.setTagSorting(tagId, sort);
|
await this.algorithm.setTagSorting(tagId, sort);
|
||||||
// TODO: Per-account? https://github.com/vector-im/riot-web/issues/14114
|
// TODO: Per-account? https://github.com/vector-im/riot-web/issues/14114
|
||||||
localStorage.setItem(`mx_tagSort_${tagId}`, sort);
|
localStorage.setItem(`mx_tagSort_${tagId}`, sort);
|
||||||
this.updateFn.triggerIfWillMark();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTagSorting(tagId: TagID): SortAlgorithm {
|
public getTagSorting(tagId: TagID): SortAlgorithm {
|
||||||
|
@ -442,10 +446,14 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setListOrder(tagId: TagID, order: ListAlgorithm) {
|
public async setListOrder(tagId: TagID, order: ListAlgorithm) {
|
||||||
|
await this.setAndPersistListOrder(tagId, order);
|
||||||
|
this.updateFn.trigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async setAndPersistListOrder(tagId: TagID, order: ListAlgorithm) {
|
||||||
await this.algorithm.setListOrdering(tagId, order);
|
await this.algorithm.setListOrdering(tagId, order);
|
||||||
// TODO: Per-account? https://github.com/vector-im/riot-web/issues/14114
|
// TODO: Per-account? https://github.com/vector-im/riot-web/issues/14114
|
||||||
localStorage.setItem(`mx_listOrder_${tagId}`, order);
|
localStorage.setItem(`mx_listOrder_${tagId}`, order);
|
||||||
this.updateFn.triggerIfWillMark();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getListOrder(tagId: TagID): ListAlgorithm {
|
public getListOrder(tagId: TagID): ListAlgorithm {
|
||||||
|
@ -493,10 +501,10 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
const listOrder = this.calculateListOrder(tag);
|
const listOrder = this.calculateListOrder(tag);
|
||||||
|
|
||||||
if (tagSort !== definedSort) {
|
if (tagSort !== definedSort) {
|
||||||
await this.setTagSorting(tag, tagSort);
|
await this.setAndPersistTagSorting(tag, tagSort);
|
||||||
}
|
}
|
||||||
if (listOrder !== definedOrder) {
|
if (listOrder !== definedOrder) {
|
||||||
await this.setListOrder(tag, listOrder);
|
await this.setAndPersistListOrder(tag, listOrder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,47 +19,29 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { RoomUpdateCause, TagID } from "../../models";
|
import { RoomUpdateCause, TagID } from "../../models";
|
||||||
import { SortAlgorithm } from "../models";
|
import { SortAlgorithm } from "../models";
|
||||||
import { sortRoomsWithAlgorithm } from "../tag-sorting";
|
import { sortRoomsWithAlgorithm } from "../tag-sorting";
|
||||||
import * as Unread from '../../../../Unread';
|
|
||||||
import { OrderingAlgorithm } from "./OrderingAlgorithm";
|
import { OrderingAlgorithm } from "./OrderingAlgorithm";
|
||||||
|
import { NotificationColor } from "../../../notifications/NotificationColor";
|
||||||
/**
|
import { RoomNotificationStateStore } from "../../../notifications/RoomNotificationStateStore";
|
||||||
* The determined category of a room.
|
|
||||||
*/
|
|
||||||
export enum Category {
|
|
||||||
/**
|
|
||||||
* The room has unread mentions within.
|
|
||||||
*/
|
|
||||||
Red = "RED",
|
|
||||||
/**
|
|
||||||
* The room has unread notifications within. Note that these are not unread
|
|
||||||
* mentions - they are simply messages which the user has asked to cause a
|
|
||||||
* badge count update or push notification.
|
|
||||||
*/
|
|
||||||
Grey = "GREY",
|
|
||||||
/**
|
|
||||||
* The room has unread messages within (grey without the badge).
|
|
||||||
*/
|
|
||||||
Bold = "BOLD",
|
|
||||||
/**
|
|
||||||
* The room has no relevant unread messages within.
|
|
||||||
*/
|
|
||||||
Idle = "IDLE",
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICategorizedRoomMap {
|
interface ICategorizedRoomMap {
|
||||||
// @ts-ignore - TS wants this to be a string, but we know better
|
// @ts-ignore - TS wants this to be a string, but we know better
|
||||||
[category: Category]: Room[];
|
[category: NotificationColor]: Room[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICategoryIndex {
|
interface ICategoryIndex {
|
||||||
// @ts-ignore - TS wants this to be a string, but we know better
|
// @ts-ignore - TS wants this to be a string, but we know better
|
||||||
[category: Category]: number; // integer
|
[category: NotificationColor]: number; // integer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caution: changing this means you'll need to update a bunch of assumptions and
|
// Caution: changing this means you'll need to update a bunch of assumptions and
|
||||||
// comments! Check the usage of Category carefully to figure out what needs changing
|
// comments! Check the usage of Category carefully to figure out what needs changing
|
||||||
// if you're going to change this array's order.
|
// if you're going to change this array's order.
|
||||||
const CATEGORY_ORDER = [Category.Red, Category.Grey, Category.Bold, Category.Idle];
|
const CATEGORY_ORDER = [
|
||||||
|
NotificationColor.Red,
|
||||||
|
NotificationColor.Grey,
|
||||||
|
NotificationColor.Bold,
|
||||||
|
NotificationColor.None, // idle
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the "importance" algorithm for room list sorting. Where
|
* An implementation of the "importance" algorithm for room list sorting. Where
|
||||||
|
@ -92,10 +74,10 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
// noinspection JSMethodCanBeStatic
|
// noinspection JSMethodCanBeStatic
|
||||||
private categorizeRooms(rooms: Room[]): ICategorizedRoomMap {
|
private categorizeRooms(rooms: Room[]): ICategorizedRoomMap {
|
||||||
const map: ICategorizedRoomMap = {
|
const map: ICategorizedRoomMap = {
|
||||||
[Category.Red]: [],
|
[NotificationColor.Red]: [],
|
||||||
[Category.Grey]: [],
|
[NotificationColor.Grey]: [],
|
||||||
[Category.Bold]: [],
|
[NotificationColor.Bold]: [],
|
||||||
[Category.Idle]: [],
|
[NotificationColor.None]: [],
|
||||||
};
|
};
|
||||||
for (const room of rooms) {
|
for (const room of rooms) {
|
||||||
const category = this.getRoomCategory(room);
|
const category = this.getRoomCategory(room);
|
||||||
|
@ -105,25 +87,11 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSMethodCanBeStatic
|
// noinspection JSMethodCanBeStatic
|
||||||
private getRoomCategory(room: Room): Category {
|
private getRoomCategory(room: Room): NotificationColor {
|
||||||
// Function implementation borrowed from old RoomListStore
|
// It's fine for us to call this a lot because it's cached, and we shouldn't be
|
||||||
|
// wasting anything by doing so as the store holds single references
|
||||||
const mentions = room.getUnreadNotificationCount('highlight') > 0;
|
const state = RoomNotificationStateStore.instance.getRoomState(room, this.tagId);
|
||||||
if (mentions) {
|
return state.color;
|
||||||
return Category.Red;
|
|
||||||
}
|
|
||||||
|
|
||||||
let unread = room.getUnreadNotificationCount() > 0;
|
|
||||||
if (unread) {
|
|
||||||
return Category.Grey;
|
|
||||||
}
|
|
||||||
|
|
||||||
unread = Unread.doesRoomHaveUnreadMessages(room);
|
|
||||||
if (unread) {
|
|
||||||
return Category.Bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Category.Idle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setRooms(rooms: Room[]): Promise<any> {
|
public async setRooms(rooms: Room[]): Promise<any> {
|
||||||
|
@ -217,7 +185,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async sortCategory(category: Category) {
|
private async sortCategory(category: NotificationColor) {
|
||||||
// This should be relatively quick because the room is usually inserted at the top of the
|
// This should be relatively quick because the room is usually inserted at the top of the
|
||||||
// category, and most popular sorting algorithms will deal with trying to keep the active
|
// category, and most popular sorting algorithms will deal with trying to keep the active
|
||||||
// room at the top/start of the category. For the few algorithms that will have to move the
|
// room at the top/start of the category. For the few algorithms that will have to move the
|
||||||
|
@ -234,7 +202,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSMethodCanBeStatic
|
// noinspection JSMethodCanBeStatic
|
||||||
private getCategoryFromIndices(index: number, indices: ICategoryIndex): Category {
|
private getCategoryFromIndices(index: number, indices: ICategoryIndex): NotificationColor {
|
||||||
for (let i = 0; i < CATEGORY_ORDER.length; i++) {
|
for (let i = 0; i < CATEGORY_ORDER.length; i++) {
|
||||||
const category = CATEGORY_ORDER[i];
|
const category = CATEGORY_ORDER[i];
|
||||||
const isLast = i === (CATEGORY_ORDER.length - 1);
|
const isLast = i === (CATEGORY_ORDER.length - 1);
|
||||||
|
@ -250,7 +218,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSMethodCanBeStatic
|
// noinspection JSMethodCanBeStatic
|
||||||
private moveRoomIndexes(nRooms: number, fromCategory: Category, toCategory: Category, indices: ICategoryIndex) {
|
private moveRoomIndexes(nRooms: number, fromCategory: NotificationColor, toCategory: NotificationColor, indices: ICategoryIndex) {
|
||||||
// We have to update the index of the category *after* the from/toCategory variables
|
// We have to update the index of the category *after* the from/toCategory variables
|
||||||
// in order to update the indices correctly. Because the room is moving from/to those
|
// in order to update the indices correctly. Because the room is moving from/to those
|
||||||
// categories, the next category's index will change - not the category we're modifying.
|
// categories, the next category's index will change - not the category we're modifying.
|
||||||
|
@ -261,7 +229,7 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
this.alterCategoryPositionBy(toCategory, +nRooms, indices);
|
this.alterCategoryPositionBy(toCategory, +nRooms, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private alterCategoryPositionBy(category: Category, n: number, indices: ICategoryIndex) {
|
private alterCategoryPositionBy(category: NotificationColor, n: number, indices: ICategoryIndex) {
|
||||||
// Note: when we alter a category's index, we actually have to modify the ones following
|
// Note: when we alter a category's index, we actually have to modify the ones following
|
||||||
// the target and not the target itself.
|
// the target and not the target itself.
|
||||||
|
|
||||||
|
|
|
@ -53,15 +53,4 @@ export class MarkedExecution {
|
||||||
this.reset(); // reset first just in case the fn() causes a trigger()
|
this.reset(); // reset first just in case the fn() causes a trigger()
|
||||||
this.fn();
|
this.fn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Triggers the function if a mark() call would mark it. If the function
|
|
||||||
* has already been marked this will do nothing.
|
|
||||||
*/
|
|
||||||
public triggerIfWillMark() {
|
|
||||||
if (!this.marked) {
|
|
||||||
this.mark();
|
|
||||||
this.trigger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue