Merge pull request #4919 from matrix-org/travis/room-list/enable
Enable the new room list by default
This commit is contained in:
commit
a70e575b96
21 changed files with 146 additions and 97 deletions
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
$tagPanelWidth: 70px; // only applies in this file, used for calculations
|
$tagPanelWidth: 70px; // only applies in this file, used for calculations
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
.mx_RoomBreadcrumbs2 {
|
.mx_RoomBreadcrumbs2 {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
.mx_RoomSublist2 {
|
.mx_RoomSublist2 {
|
||||||
// The sublist is a column of rows, essentially
|
// The sublist is a column of rows, essentially
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
// Note: the room tile expects to be in a flexbox column container
|
// Note: the room tile expects to be in a flexbox column container
|
||||||
.mx_RoomTile2 {
|
.mx_RoomTile2 {
|
||||||
|
|
|
@ -35,8 +35,8 @@ import RoomListStore, { LISTS_UPDATE_EVENT } from "../../stores/room-list/RoomLi
|
||||||
import {Key} from "../../Keyboard";
|
import {Key} from "../../Keyboard";
|
||||||
import IndicatorScrollbar from "../structures/IndicatorScrollbar";
|
import IndicatorScrollbar from "../structures/IndicatorScrollbar";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// 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/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
|
|
@ -668,8 +668,7 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
disabled={this.props.leftDisabled}
|
disabled={this.props.leftDisabled}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
if (SettingsStore.isFeatureEnabled("feature_new_room_list")) {
|
if (SettingsStore.getValue("feature_new_room_list")) {
|
||||||
// TODO: Supply props like collapsed and disabled to LeftPanel2
|
|
||||||
leftPanel = (
|
leftPanel = (
|
||||||
<LeftPanel2
|
<LeftPanel2
|
||||||
isMinimized={this.props.collapseLhs || false}
|
isMinimized={this.props.collapseLhs || false}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { Key } from "../../Keyboard";
|
||||||
import AccessibleButton from "../views/elements/AccessibleButton";
|
import AccessibleButton from "../views/elements/AccessibleButton";
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
|
|
@ -27,8 +27,8 @@ import RoomListStore from "../../../stores/room-list/RoomListStore2";
|
||||||
import { DefaultTagID } from "../../../stores/room-list/models";
|
import { DefaultTagID } from "../../../stores/room-list/models";
|
||||||
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// 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/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
|
|
@ -41,8 +41,8 @@ import { Action } from "../../../dispatcher/actions";
|
||||||
import { ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload";
|
import { ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload";
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// 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/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
|
|
@ -48,8 +48,8 @@ import { polyfillTouchEvent } from "../../../@types/polyfill";
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||||
import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
|
import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// 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/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
|
|
@ -55,8 +55,8 @@ import {ActionPayload} from "../../../dispatcher/payloads";
|
||||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||||
import { NotificationState } from "../../../stores/notifications/NotificationState";
|
import { NotificationState } from "../../../stores/notifications/NotificationState";
|
||||||
|
|
||||||
// TODO: Remove banner on launch: https://github.com/vector-im/riot-web/issues/14231
|
// 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/14231
|
// TODO: Rename on launch: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
|
|
@ -32,12 +32,12 @@ export default class PreferencesUserSettingsTab extends React.Component {
|
||||||
'breadcrumbs',
|
'breadcrumbs',
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: Remove temp structures: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove temp structures: https://github.com/vector-im/riot-web/issues/14367
|
||||||
static ROOM_LIST_2_SETTINGS = [
|
static ROOM_LIST_2_SETTINGS = [
|
||||||
'breadcrumbs',
|
'breadcrumbs',
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: Remove temp structures: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove temp structures: https://github.com/vector-im/riot-web/issues/14367
|
||||||
static eligibleRoomListSettings = () => {
|
static eligibleRoomListSettings = () => {
|
||||||
if (RoomListStoreTempProxy.isUsingNewStore()) {
|
if (RoomListStoreTempProxy.isUsingNewStore()) {
|
||||||
return PreferencesUserSettingsTab.ROOM_LIST_2_SETTINGS;
|
return PreferencesUserSettingsTab.ROOM_LIST_2_SETTINGS;
|
||||||
|
|
|
@ -147,7 +147,8 @@ export const SETTINGS = {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
"feature_new_room_list": {
|
"feature_new_room_list": {
|
||||||
isFeature: true,
|
// TODO: Remove setting: https://github.com/vector-im/riot-web/issues/14367
|
||||||
|
// XXX: We shouldn't have non-features appear like features.
|
||||||
displayName: _td("Use the improved room list (will refresh to apply changes)"),
|
displayName: _td("Use the improved room list (will refresh to apply changes)"),
|
||||||
supportedLevels: LEVELS_FEATURE,
|
supportedLevels: LEVELS_FEATURE,
|
||||||
default: true,
|
default: true,
|
||||||
|
|
|
@ -57,7 +57,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
protected async onAction(payload: ActionPayload) {
|
protected async onAction(payload: ActionPayload) {
|
||||||
if (!this.matrixClient) return;
|
if (!this.matrixClient) return;
|
||||||
|
|
||||||
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14367
|
||||||
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
||||||
|
|
||||||
if (payload.action === 'setting_updated') {
|
if (payload.action === 'setting_updated') {
|
||||||
|
@ -80,7 +80,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onReady() {
|
protected async onReady() {
|
||||||
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14367
|
||||||
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
||||||
|
|
||||||
await this.updateRooms();
|
await this.updateRooms();
|
||||||
|
@ -91,7 +91,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient<IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onNotReady() {
|
protected async onNotReady() {
|
||||||
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14367
|
||||||
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
||||||
|
|
||||||
this.matrixClient.removeListener("Room.myMembership", this.onMyMembership);
|
this.matrixClient.removeListener("Room.myMembership", this.onMyMembership);
|
||||||
|
|
|
@ -99,7 +99,7 @@ class RoomListStore extends Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
_checkDisabled() {
|
_checkDisabled() {
|
||||||
this.disabled = SettingsStore.isFeatureEnabled("feature_new_room_list");
|
this.disabled = SettingsStore.getValue("feature_new_room_list");
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
console.warn("👋 legacy room list store has been disabled");
|
console.warn("👋 legacy room list store has been disabled");
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,7 @@ export class MessagePreviewStore extends AsyncStoreWithClient<IState> {
|
||||||
protected async onAction(payload: ActionPayload) {
|
protected async onAction(payload: ActionPayload) {
|
||||||
if (!this.matrixClient) return;
|
if (!this.matrixClient) return;
|
||||||
|
|
||||||
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14231
|
// TODO: Remove when new room list is made the default: https://github.com/vector-im/riot-web/issues/14367
|
||||||
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
if (!RoomListStoreTempProxy.isUsingNewStore()) return;
|
||||||
|
|
||||||
if (payload.action === 'MatrixActions.Room.timeline' || payload.action === 'MatrixActions.Event.decrypted') {
|
if (payload.action === 'MatrixActions.Room.timeline' || payload.action === 'MatrixActions.Event.decrypted') {
|
||||||
|
|
|
@ -46,6 +46,12 @@ interface IState {
|
||||||
export const LISTS_UPDATE_EVENT = "lists_update";
|
export const LISTS_UPDATE_EVENT = "lists_update";
|
||||||
|
|
||||||
export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
export class RoomListStore2 extends AsyncStore<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 _matrixClient: MatrixClient;
|
||||||
private initialListsGenerated = false;
|
private initialListsGenerated = false;
|
||||||
private enabled = false;
|
private enabled = false;
|
||||||
|
@ -77,9 +83,43 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
return this._matrixClient;
|
return this._matrixClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove enabled flag with the old RoomListStore: https://github.com/vector-im/riot-web/issues/14231
|
// Intended for test usage
|
||||||
|
public async resetStore() {
|
||||||
|
await this.reset();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public for test usage. Do not call this.
|
||||||
|
public async makeReady(client: MatrixClient) {
|
||||||
|
// 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");
|
||||||
|
await this.readAndCacheSettingsFromStore();
|
||||||
|
await this.regenerateAllLists({trigger: false});
|
||||||
|
await this.handleRVSUpdate({trigger: false}); // fake an RVS update to adjust sticky room, if needed
|
||||||
|
|
||||||
|
this.updateFn.mark(); // we almost certainly want to trigger an update.
|
||||||
|
this.updateFn.trigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Remove enabled flag with the old RoomListStore: https://github.com/vector-im/riot-web/issues/14367
|
||||||
private checkEnabled() {
|
private checkEnabled() {
|
||||||
this.enabled = SettingsStore.isFeatureEnabled("feature_new_room_list");
|
this.enabled = SettingsStore.getValue("feature_new_room_list");
|
||||||
if (this.enabled) {
|
if (this.enabled) {
|
||||||
console.log("⚡ new room list store engaged");
|
console.log("⚡ new room list store engaged");
|
||||||
}
|
}
|
||||||
|
@ -99,7 +139,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
* be used if the calling code will manually trigger the update.
|
* be used if the calling code will manually trigger the update.
|
||||||
*/
|
*/
|
||||||
private async handleRVSUpdate({trigger = true}) {
|
private async handleRVSUpdate({trigger = true}) {
|
||||||
if (!this.enabled) return; // TODO: Remove with https://github.com/vector-im/riot-web/issues/14231
|
if (!this.enabled) return; // TODO: Remove with https://github.com/vector-im/riot-web/issues/14367
|
||||||
if (!this.matrixClient) return; // We assume there won't be RVS updates without a client
|
if (!this.matrixClient) return; // We assume there won't be RVS updates without a client
|
||||||
|
|
||||||
const activeRoomId = RoomViewStore.getRoomId();
|
const activeRoomId = RoomViewStore.getRoomId();
|
||||||
|
@ -122,7 +162,14 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
if (trigger) this.updateFn.trigger();
|
if (trigger) this.updateFn.trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onDispatch(payload: ActionPayload) {
|
protected async onDispatch(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) {
|
||||||
|
await this.onDispatchAsync(payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We do this to intentionally break out of the current event loop task, allowing
|
// We do this to intentionally break out of the current event loop task, allowing
|
||||||
// us to instead wait for a more convenient time to run our updates.
|
// us to instead wait for a more convenient time to run our updates.
|
||||||
setImmediate(() => this.onDispatchAsync(payload));
|
setImmediate(() => this.onDispatchAsync(payload));
|
||||||
|
@ -135,19 +182,7 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove with https://github.com/vector-im/riot-web/issues/14231
|
await this.makeReady(payload.matrixClient);
|
||||||
this.checkEnabled();
|
|
||||||
if (!this.enabled) return;
|
|
||||||
|
|
||||||
this._matrixClient = payload.matrixClient;
|
|
||||||
|
|
||||||
// Update any settings here, as some may have happened before we were logically ready.
|
|
||||||
console.log("Regenerating room lists: Startup");
|
|
||||||
await this.readAndCacheSettingsFromStore();
|
|
||||||
await this.regenerateAllLists({trigger: false});
|
|
||||||
await this.handleRVSUpdate({trigger: false}); // fake an RVS update to adjust sticky room, if needed
|
|
||||||
|
|
||||||
this.updateFn.trigger();
|
|
||||||
|
|
||||||
return; // no point in running the next conditions - they won't match
|
return; // no point in running the next conditions - they won't match
|
||||||
}
|
}
|
||||||
|
@ -496,10 +531,13 @@ export class RoomListStore2 extends AsyncStore<ActionPayload> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regenerates the room whole room list, discarding any previous results.
|
* Regenerates the room whole room list, discarding any previous results.
|
||||||
|
*
|
||||||
|
* Note: This is only exposed externally for the tests. Do not call this from within
|
||||||
|
* the app.
|
||||||
* @param trigger Set to false to prevent a list update from being sent. Should only
|
* @param trigger Set to false to prevent a list update from being sent. Should only
|
||||||
* be used if the calling code will manually trigger the update.
|
* be used if the calling code will manually trigger the update.
|
||||||
*/
|
*/
|
||||||
private async regenerateAllLists({trigger = true}) {
|
public async regenerateAllLists({trigger = true}) {
|
||||||
console.warn("Regenerating all room lists");
|
console.warn("Regenerating all room lists");
|
||||||
|
|
||||||
const sorts: ITagSortingMap = {};
|
const sorts: ITagSortingMap = {};
|
||||||
|
|
|
@ -24,11 +24,11 @@ import { ITagMap } from "./algorithms/models";
|
||||||
* Temporary RoomListStore proxy. Should be replaced with RoomListStore2 when
|
* Temporary RoomListStore proxy. Should be replaced with RoomListStore2 when
|
||||||
* it is available to everyone.
|
* it is available to everyone.
|
||||||
*
|
*
|
||||||
* TODO: Delete this: https://github.com/vector-im/riot-web/issues/14231
|
* TODO: Delete this: https://github.com/vector-im/riot-web/issues/14367
|
||||||
*/
|
*/
|
||||||
export class RoomListStoreTempProxy {
|
export class RoomListStoreTempProxy {
|
||||||
public static isUsingNewStore(): boolean {
|
public static isUsingNewStore(): boolean {
|
||||||
return SettingsStore.isFeatureEnabled("feature_new_room_list");
|
return SettingsStore.getValue("feature_new_room_list");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static addListener(handler: () => void): RoomListStoreTempToken {
|
public static addListener(handler: () => void): RoomListStoreTempToken {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTestUtils from 'react-dom/test-utils';
|
import ReactTestUtils from 'react-dom/test-utils';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import lolex from 'lolex';
|
|
||||||
|
|
||||||
import * as TestUtils from '../../../test-utils';
|
import * as TestUtils from '../../../test-utils';
|
||||||
|
|
||||||
|
@ -15,11 +14,18 @@ import GroupStore from '../../../../src/stores/GroupStore.js';
|
||||||
|
|
||||||
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
|
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
|
||||||
import {DefaultTagID} from "../../../../src/stores/room-list/models";
|
import {DefaultTagID} from "../../../../src/stores/room-list/models";
|
||||||
|
import RoomListStore, {LISTS_UPDATE_EVENT, RoomListStore2} from "../../../../src/stores/room-list/RoomListStore2";
|
||||||
|
import RoomListLayoutStore from "../../../../src/stores/room-list/RoomListLayoutStore";
|
||||||
|
|
||||||
function generateRoomId() {
|
function generateRoomId() {
|
||||||
return '!' + Math.random().toString().slice(2, 10) + ':domain';
|
return '!' + Math.random().toString().slice(2, 10) + ':domain';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function waitForRoomListStoreUpdate() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
RoomListStore.instance.once(LISTS_UPDATE_EVENT, () => resolve());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
describe('RoomList', () => {
|
describe('RoomList', () => {
|
||||||
function createRoom(opts) {
|
function createRoom(opts) {
|
||||||
|
@ -34,7 +40,6 @@ describe('RoomList', () => {
|
||||||
let client = null;
|
let client = null;
|
||||||
let root = null;
|
let root = null;
|
||||||
const myUserId = '@me:domain';
|
const myUserId = '@me:domain';
|
||||||
let clock = null;
|
|
||||||
|
|
||||||
const movingRoomId = '!someroomid';
|
const movingRoomId = '!someroomid';
|
||||||
let movingRoom;
|
let movingRoom;
|
||||||
|
@ -43,25 +48,25 @@ describe('RoomList', () => {
|
||||||
let myMember;
|
let myMember;
|
||||||
let myOtherMember;
|
let myOtherMember;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(async function(done) {
|
||||||
|
RoomListStore2.TEST_MODE = true;
|
||||||
|
|
||||||
TestUtils.stubClient();
|
TestUtils.stubClient();
|
||||||
client = MatrixClientPeg.get();
|
client = MatrixClientPeg.get();
|
||||||
client.credentials = {userId: myUserId};
|
client.credentials = {userId: myUserId};
|
||||||
//revert this to prototype method as the test-utils monkey-patches this to return a hardcoded value
|
//revert this to prototype method as the test-utils monkey-patches this to return a hardcoded value
|
||||||
client.getUserId = MatrixClient.prototype.getUserId;
|
client.getUserId = MatrixClient.prototype.getUserId;
|
||||||
|
|
||||||
clock = lolex.install();
|
|
||||||
|
|
||||||
DMRoomMap.makeShared();
|
DMRoomMap.makeShared();
|
||||||
|
|
||||||
parentDiv = document.createElement('div');
|
parentDiv = document.createElement('div');
|
||||||
document.body.appendChild(parentDiv);
|
document.body.appendChild(parentDiv);
|
||||||
|
|
||||||
const RoomList = sdk.getComponent('views.rooms.RoomList');
|
const RoomList = sdk.getComponent('views.rooms.RoomList2');
|
||||||
const WrappedRoomList = TestUtils.wrapInMatrixClientContext(RoomList);
|
const WrappedRoomList = TestUtils.wrapInMatrixClientContext(RoomList);
|
||||||
root = ReactDOM.render(
|
root = ReactDOM.render(
|
||||||
<DragDropContext>
|
<DragDropContext>
|
||||||
<WrappedRoomList searchFilter="" />
|
<WrappedRoomList searchFilter="" onResize={() => {}} />
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
, parentDiv);
|
, parentDiv);
|
||||||
ReactTestUtils.findRenderedComponentWithType(root, RoomList);
|
ReactTestUtils.findRenderedComponentWithType(root, RoomList);
|
||||||
|
@ -102,23 +107,29 @@ describe('RoomList', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
client.getRoom = (roomId) => roomMap[roomId];
|
client.getRoom = (roomId) => roomMap[roomId];
|
||||||
|
|
||||||
|
// Now that everything has been set up, prepare and update the store
|
||||||
|
await RoomListStore.instance.makeReady(client);
|
||||||
|
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach((done) => {
|
afterEach(async (done) => {
|
||||||
if (parentDiv) {
|
if (parentDiv) {
|
||||||
ReactDOM.unmountComponentAtNode(parentDiv);
|
ReactDOM.unmountComponentAtNode(parentDiv);
|
||||||
parentDiv.remove();
|
parentDiv.remove();
|
||||||
parentDiv = null;
|
parentDiv = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
clock.uninstall();
|
await RoomListLayoutStore.instance.resetLayouts();
|
||||||
|
await RoomListStore.instance.resetStore();
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
function expectRoomInSubList(room, subListTest) {
|
function expectRoomInSubList(room, subListTest) {
|
||||||
const RoomSubList = sdk.getComponent('structures.RoomSubList');
|
const RoomSubList = sdk.getComponent('views.rooms.RoomSublist2');
|
||||||
const RoomTile = sdk.getComponent('views.rooms.RoomTile');
|
const RoomTile = sdk.getComponent('views.rooms.RoomTile2');
|
||||||
|
|
||||||
const subLists = ReactTestUtils.scryRenderedComponentsWithType(root, RoomSubList);
|
const subLists = ReactTestUtils.scryRenderedComponentsWithType(root, RoomSubList);
|
||||||
const containingSubList = subLists.find(subListTest);
|
const containingSubList = subLists.find(subListTest);
|
||||||
|
@ -140,20 +151,20 @@ describe('RoomList', () => {
|
||||||
expect(expectedRoomTile.props.room).toBe(room);
|
expect(expectedRoomTile.props.room).toBe(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectCorrectMove(oldTag, newTag) {
|
function expectCorrectMove(oldTagId, newTagId) {
|
||||||
const getTagSubListTest = (tag) => {
|
const getTagSubListTest = (tagId) => {
|
||||||
if (tag === undefined) return (s) => s.props.label.endsWith('Rooms');
|
return (s) => s.props.tagId === tagId;
|
||||||
return (s) => s.props.tagName === tag;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Default to finding the destination sublist with newTag
|
// Default to finding the destination sublist with newTag
|
||||||
const destSubListTest = getTagSubListTest(newTag);
|
const destSubListTest = getTagSubListTest(newTagId);
|
||||||
const srcSubListTest = getTagSubListTest(oldTag);
|
const srcSubListTest = getTagSubListTest(oldTagId);
|
||||||
|
|
||||||
// Set up the room that will be moved such that it has the correct state for a room in
|
// Set up the room that will be moved such that it has the correct state for a room in
|
||||||
// the section for oldTag
|
// the section for oldTagId
|
||||||
if (['m.favourite', 'm.lowpriority'].includes(oldTag)) movingRoom.tags = {[oldTag]: {}};
|
if (oldTagId === DefaultTagID.Favourite || oldTagId === DefaultTagID.LowPriority) {
|
||||||
if (oldTag === DefaultTagID.DM) {
|
movingRoom.tags = {[oldTagId]: {}};
|
||||||
|
} else if (oldTagId === DefaultTagID.DM) {
|
||||||
// Mock inverse m.direct
|
// Mock inverse m.direct
|
||||||
DMRoomMap.shared().roomToUser = {
|
DMRoomMap.shared().roomToUser = {
|
||||||
[movingRoom.roomId]: '@someotheruser:domain',
|
[movingRoom.roomId]: '@someotheruser:domain',
|
||||||
|
@ -162,17 +173,12 @@ describe('RoomList', () => {
|
||||||
|
|
||||||
dis.dispatch({action: 'MatrixActions.sync', prevState: null, state: 'PREPARED', matrixClient: client});
|
dis.dispatch({action: 'MatrixActions.sync', prevState: null, state: 'PREPARED', matrixClient: client});
|
||||||
|
|
||||||
clock.runAll();
|
|
||||||
|
|
||||||
expectRoomInSubList(movingRoom, srcSubListTest);
|
expectRoomInSubList(movingRoom, srcSubListTest);
|
||||||
|
|
||||||
dis.dispatch({action: 'RoomListActions.tagRoom.pending', request: {
|
dis.dispatch({action: 'RoomListActions.tagRoom.pending', request: {
|
||||||
oldTag, newTag, room: movingRoom,
|
oldTagId, newTagId, room: movingRoom,
|
||||||
}});
|
}});
|
||||||
|
|
||||||
// Run all setTimeouts for dispatches and room list rate limiting
|
|
||||||
clock.runAll();
|
|
||||||
|
|
||||||
expectRoomInSubList(movingRoom, destSubListTest);
|
expectRoomInSubList(movingRoom, destSubListTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +275,12 @@ describe('RoomList', () => {
|
||||||
};
|
};
|
||||||
GroupStore._notifyListeners();
|
GroupStore._notifyListeners();
|
||||||
|
|
||||||
|
// We also have to mock the client's getGroup function for the room list to filter it.
|
||||||
|
// It's not smart enough to tell the difference between a real group and a template though.
|
||||||
|
client.getGroup = (groupId) => {
|
||||||
|
return {groupId};
|
||||||
|
};
|
||||||
|
|
||||||
// Select tag
|
// Select tag
|
||||||
dis.dispatch({action: 'select_tag', tag: '+group:domain'}, true);
|
dis.dispatch({action: 'select_tag', tag: '+group:domain'}, true);
|
||||||
}
|
}
|
||||||
|
@ -277,17 +289,14 @@ describe('RoomList', () => {
|
||||||
setupSelectedTag();
|
setupSelectedTag();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('displays the correct rooms when the groups rooms are changed', () => {
|
it('displays the correct rooms when the groups rooms are changed', async () => {
|
||||||
GroupStore.getGroupRooms = (groupId) => {
|
GroupStore.getGroupRooms = (groupId) => {
|
||||||
return [movingRoom, otherRoom];
|
return [movingRoom, otherRoom];
|
||||||
};
|
};
|
||||||
GroupStore._notifyListeners();
|
GroupStore._notifyListeners();
|
||||||
|
|
||||||
// Run through RoomList debouncing
|
await waitForRoomListStoreUpdate();
|
||||||
clock.runAll();
|
expectRoomInSubList(otherRoom, (s) => s.props.tagId === DefaultTagID.Untagged);
|
||||||
|
|
||||||
// By default, the test will
|
|
||||||
expectRoomInSubList(otherRoom, (s) => s.props.label.endsWith('Rooms'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
itDoesCorrectOptimisticUpdatesForDraggedRoomTiles();
|
itDoesCorrectOptimisticUpdatesForDraggedRoomTiles();
|
||||||
|
|
|
@ -15,10 +15,12 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const {findSublist} = require("./create-room");
|
||||||
|
|
||||||
module.exports = async function acceptInvite(session, name) {
|
module.exports = async function acceptInvite(session, name) {
|
||||||
session.log.step(`accepts "${name}" invite`);
|
session.log.step(`accepts "${name}" invite`);
|
||||||
//TODO: brittle selector
|
const inviteSublist = await findSublist(session, "invites");
|
||||||
const invitesHandles = await session.queryAll('.mx_RoomTile_name.mx_RoomTile_invite');
|
const invitesHandles = await inviteSublist.$$(".mx_RoomTile2_name");
|
||||||
const invitesWithText = await Promise.all(invitesHandles.map(async (inviteHandle) => {
|
const invitesWithText = await Promise.all(invitesHandles.map(async (inviteHandle) => {
|
||||||
const text = await session.innerText(inviteHandle);
|
const text = await session.innerText(inviteHandle);
|
||||||
return {inviteHandle, text};
|
return {inviteHandle, text};
|
||||||
|
|
|
@ -16,21 +16,27 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function openRoomDirectory(session) {
|
async function openRoomDirectory(session) {
|
||||||
const roomDirectoryButton = await session.query('.mx_LeftPanel_explore .mx_AccessibleButton');
|
const roomDirectoryButton = await session.query('.mx_LeftPanel2_exploreButton');
|
||||||
await roomDirectoryButton.click();
|
await roomDirectoryButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function findSublist(session, name) {
|
||||||
|
const sublists = await session.queryAll('.mx_RoomSublist2');
|
||||||
|
for (const sublist of sublists) {
|
||||||
|
const header = await sublist.$('.mx_RoomSublist2_headerText');
|
||||||
|
const headerText = await session.innerText(header);
|
||||||
|
if (headerText.toLowerCase().includes(name.toLowerCase())) {
|
||||||
|
return sublist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`could not find room list section that contains '${name}' in header`);
|
||||||
|
}
|
||||||
|
|
||||||
async function createRoom(session, roomName, encrypted=false) {
|
async function createRoom(session, roomName, encrypted=false) {
|
||||||
session.log.step(`creates room "${roomName}"`);
|
session.log.step(`creates room "${roomName}"`);
|
||||||
|
|
||||||
const roomListHeaders = await session.queryAll('.mx_RoomSubList_labelContainer');
|
const roomsSublist = await findSublist(session, "rooms");
|
||||||
const roomListHeaderLabels = await Promise.all(roomListHeaders.map(h => session.innerText(h)));
|
const addRoomButton = await roomsSublist.$(".mx_RoomSublist2_auxButton");
|
||||||
const roomsIndex = roomListHeaderLabels.findIndex(l => l.toLowerCase().includes("rooms"));
|
|
||||||
if (roomsIndex === -1) {
|
|
||||||
throw new Error("could not find room list section that contains 'rooms' in header");
|
|
||||||
}
|
|
||||||
const roomsHeader = roomListHeaders[roomsIndex];
|
|
||||||
const addRoomButton = await roomsHeader.$(".mx_RoomSubList_addRoom");
|
|
||||||
await addRoomButton.click();
|
await addRoomButton.click();
|
||||||
|
|
||||||
const roomNameInput = await session.query('.mx_CreateRoomDialog_name input');
|
const roomNameInput = await session.query('.mx_CreateRoomDialog_name input');
|
||||||
|
@ -51,14 +57,8 @@ async function createRoom(session, roomName, encrypted=false) {
|
||||||
async function createDm(session, invitees) {
|
async function createDm(session, invitees) {
|
||||||
session.log.step(`creates DM with ${JSON.stringify(invitees)}`);
|
session.log.step(`creates DM with ${JSON.stringify(invitees)}`);
|
||||||
|
|
||||||
const roomListHeaders = await session.queryAll('.mx_RoomSubList_labelContainer');
|
const dmsSublist = await findSublist(session, "people");
|
||||||
const roomListHeaderLabels = await Promise.all(roomListHeaders.map(h => session.innerText(h)));
|
const startChatButton = await dmsSublist.$(".mx_RoomSublist2_auxButton");
|
||||||
const dmsIndex = roomListHeaderLabels.findIndex(l => l.toLowerCase().includes('direct messages'));
|
|
||||||
if (dmsIndex === -1) {
|
|
||||||
throw new Error("could not find room list section that contains 'direct messages' in header");
|
|
||||||
}
|
|
||||||
const dmsHeader = roomListHeaders[dmsIndex];
|
|
||||||
const startChatButton = await dmsHeader.$(".mx_RoomSubList_addRoom");
|
|
||||||
await startChatButton.click();
|
await startChatButton.click();
|
||||||
|
|
||||||
const inviteesEditor = await session.query('.mx_InviteDialog_editor textarea');
|
const inviteesEditor = await session.query('.mx_InviteDialog_editor textarea');
|
||||||
|
@ -83,4 +83,4 @@ async function createDm(session, invitees) {
|
||||||
session.log.done();
|
session.log.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {openRoomDirectory, createRoom, createDm};
|
module.exports = {openRoomDirectory, findSublist, createRoom, createDm};
|
||||||
|
|
Loading…
Reference in a new issue