mirror of
https://github.com/element-hq/element-web
synced 2024-11-24 18:25:49 +03:00
Merge branch 'develop' into joriks/room-list-voip
This commit is contained in:
commit
dad3dce364
6 changed files with 94 additions and 39 deletions
|
@ -19,7 +19,6 @@ limitations under the License.
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as PropTypes from 'prop-types';
|
import * as PropTypes from 'prop-types';
|
||||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||||
import { MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
|
||||||
import { DragDropContext } from 'react-beautiful-dnd';
|
import { DragDropContext } from 'react-beautiful-dnd';
|
||||||
|
|
||||||
import {Key, isOnlyCtrlOrCmdKeyEvent, isOnlyCtrlOrCmdIgnoreShiftKeyEvent} from '../../Keyboard';
|
import {Key, isOnlyCtrlOrCmdKeyEvent, isOnlyCtrlOrCmdIgnoreShiftKeyEvent} from '../../Keyboard';
|
||||||
|
@ -54,6 +53,7 @@ import {
|
||||||
import { Action } from "../../dispatcher/actions";
|
import { Action } from "../../dispatcher/actions";
|
||||||
import LeftPanel2 from "./LeftPanel2";
|
import LeftPanel2 from "./LeftPanel2";
|
||||||
import CallContainer from '../views/voip/CallContainer';
|
import CallContainer from '../views/voip/CallContainer';
|
||||||
|
import { ViewRoomDeltaPayload } from "../../dispatcher/payloads/ViewRoomDeltaPayload";
|
||||||
|
|
||||||
// We need to fetch each pinned message individually (if we don't already have it)
|
// We need to fetch each pinned message individually (if we don't already have it)
|
||||||
// so each pinned message may trigger a request. Limit the number per room for sanity.
|
// so each pinned message may trigger a request. Limit the number per room for sanity.
|
||||||
|
@ -410,20 +410,6 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
};
|
};
|
||||||
|
|
||||||
_onKeyDown = (ev) => {
|
_onKeyDown = (ev) => {
|
||||||
/*
|
|
||||||
// Remove this for now as ctrl+alt = alt-gr so this breaks keyboards which rely on alt-gr for numbers
|
|
||||||
// Will need to find a better meta key if anyone actually cares about using this.
|
|
||||||
if (ev.altKey && ev.ctrlKey && ev.keyCode > 48 && ev.keyCode < 58) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'view_indexed_room',
|
|
||||||
roomIndex: ev.keyCode - 49,
|
|
||||||
});
|
|
||||||
ev.stopPropagation();
|
|
||||||
ev.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
let handled = false;
|
let handled = false;
|
||||||
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
const ctrlCmdOnly = isOnlyCtrlOrCmdKeyEvent(ev);
|
||||||
const hasModifier = ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey;
|
const hasModifier = ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey;
|
||||||
|
@ -475,8 +461,8 @@ class LoggedInView extends React.Component<IProps, IState> {
|
||||||
case Key.ARROW_UP:
|
case Key.ARROW_UP:
|
||||||
case Key.ARROW_DOWN:
|
case Key.ARROW_DOWN:
|
||||||
if (ev.altKey && !ev.ctrlKey && !ev.metaKey) {
|
if (ev.altKey && !ev.ctrlKey && !ev.metaKey) {
|
||||||
dis.dispatch({
|
dis.dispatch<ViewRoomDeltaPayload>({
|
||||||
action: 'view_room_delta',
|
action: Action.ViewRoomDelta,
|
||||||
delta: ev.key === Key.ARROW_UP ? -1 : 1,
|
delta: ev.key === Key.ARROW_UP ? -1 : 1,
|
||||||
unread: ev.shiftKey,
|
unread: ev.shiftKey,
|
||||||
});
|
});
|
||||||
|
|
|
@ -596,15 +596,9 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'view_prev_room':
|
|
||||||
this.viewNextRoom(-1);
|
|
||||||
break;
|
|
||||||
case 'view_next_room':
|
case 'view_next_room':
|
||||||
this.viewNextRoom(1);
|
this.viewNextRoom(1);
|
||||||
break;
|
break;
|
||||||
case 'view_indexed_room':
|
|
||||||
this.viewIndexedRoom(payload.roomIndex);
|
|
||||||
break;
|
|
||||||
case Action.ViewUserSettings: {
|
case Action.ViewUserSettings: {
|
||||||
const tabPayload = payload as OpenToTabPayload;
|
const tabPayload = payload as OpenToTabPayload;
|
||||||
const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
|
const UserSettingsDialog = sdk.getComponent("dialogs.UserSettingsDialog");
|
||||||
|
@ -812,19 +806,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move to RoomViewStore
|
|
||||||
private viewIndexedRoom(roomIndex: number) {
|
|
||||||
const allRooms = RoomListSorter.mostRecentActivityFirst(
|
|
||||||
MatrixClientPeg.get().getRooms(),
|
|
||||||
);
|
|
||||||
if (allRooms[roomIndex]) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'view_room',
|
|
||||||
room_id: allRooms[roomIndex].roomId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch view to the given room
|
// switch view to the given room
|
||||||
//
|
//
|
||||||
// @param {Object} roomInfo Object containing data about the room to be joined
|
// @param {Object} roomInfo Object containing data about the room to be joined
|
||||||
|
|
|
@ -17,13 +17,16 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { Dispatcher } from "flux";
|
||||||
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
|
||||||
import { _t, _td } from "../../../languageHandler";
|
import { _t, _td } from "../../../languageHandler";
|
||||||
import { RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
import { RovingTabIndexProvider } from "../../../accessibility/RovingTabIndex";
|
||||||
import { ResizeNotifier } from "../../../utils/ResizeNotifier";
|
import { ResizeNotifier } from "../../../utils/ResizeNotifier";
|
||||||
import RoomListStore, { LISTS_UPDATE_EVENT, RoomListStore2 } from "../../../stores/room-list/RoomListStore2";
|
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore2";
|
||||||
|
import RoomViewStore from "../../../stores/RoomViewStore";
|
||||||
import { ITagMap } from "../../../stores/room-list/algorithms/models";
|
import { ITagMap } from "../../../stores/room-list/algorithms/models";
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import { Dispatcher } from "flux";
|
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||||
import RoomSublist2 from "./RoomSublist2";
|
import RoomSublist2 from "./RoomSublist2";
|
||||||
|
@ -35,6 +38,9 @@ import GroupAvatar from "../avatars/GroupAvatar";
|
||||||
import TemporaryTile from "./TemporaryTile";
|
import TemporaryTile from "./TemporaryTile";
|
||||||
import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState";
|
import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState";
|
||||||
import { NotificationColor } from "../../../stores/notifications/NotificationColor";
|
import { NotificationColor } from "../../../stores/notifications/NotificationColor";
|
||||||
|
import { TagSpecificNotificationState } from "../../../stores/notifications/TagSpecificNotificationState";
|
||||||
|
import { Action } from "../../../dispatcher/actions";
|
||||||
|
import { ViewRoomDeltaPayload } from "../../../dispatcher/payloads/ViewRoomDeltaPayload";
|
||||||
|
|
||||||
// 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/14231
|
||||||
// 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/14231
|
||||||
|
@ -138,6 +144,7 @@ const TAG_AESTHETICS: {
|
||||||
|
|
||||||
export default class RoomList2 extends React.Component<IProps, IState> {
|
export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
private searchFilter: NameFilterCondition = new NameFilterCondition();
|
private searchFilter: NameFilterCondition = new NameFilterCondition();
|
||||||
|
private dispatcherRef;
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -146,6 +153,8 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
sublists: {},
|
sublists: {},
|
||||||
layouts: new Map<TagID, ListLayout>(),
|
layouts: new Map<TagID, ListLayout>(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.dispatcherRef = defaultDispatcher.register(this.onAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidUpdate(prevProps: Readonly<IProps>): void {
|
public componentDidUpdate(prevProps: Readonly<IProps>): void {
|
||||||
|
@ -170,8 +179,50 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.updateLists);
|
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.updateLists);
|
||||||
|
defaultDispatcher.unregister(this.dispatcherRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onAction = (payload: ActionPayload) => {
|
||||||
|
if (payload.action === Action.ViewRoomDelta) {
|
||||||
|
const viewRoomDeltaPayload = payload as ViewRoomDeltaPayload;
|
||||||
|
const currentRoomId = RoomViewStore.getRoomId();
|
||||||
|
const room = this.getRoomDelta(currentRoomId, viewRoomDeltaPayload.delta, viewRoomDeltaPayload.unread);
|
||||||
|
if (room) {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'view_room',
|
||||||
|
room_id: room.roomId,
|
||||||
|
show_room_tile: true, // to make sure the room gets scrolled into view
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private getRoomDelta = (roomId: string, delta: number, unread = false) => {
|
||||||
|
const lists = RoomListStore.instance.orderedLists;
|
||||||
|
let rooms: Room = [];
|
||||||
|
TAG_ORDER.forEach(t => {
|
||||||
|
let listRooms = lists[t];
|
||||||
|
|
||||||
|
if (unread) {
|
||||||
|
// TODO Be smarter and not spin up a bunch of wasted listeners just to kill them 4 lines later
|
||||||
|
// https://github.com/vector-im/riot-web/issues/14035
|
||||||
|
const notificationStates = rooms.map(r => new TagSpecificNotificationState(r, t));
|
||||||
|
// filter to only notification rooms (and our current active room so we can index properly)
|
||||||
|
listRooms = notificationStates.filter(state => {
|
||||||
|
return state.room.roomId === roomId || state.color >= NotificationColor.Bold;
|
||||||
|
});
|
||||||
|
notificationStates.forEach(state => state.destroy());
|
||||||
|
}
|
||||||
|
|
||||||
|
rooms.push(...listRooms);
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentIndex = rooms.findIndex(r => r.roomId === roomId);
|
||||||
|
// use slice to account for looping around the start
|
||||||
|
const [room] = rooms.slice((currentIndex + delta) % rooms.length);
|
||||||
|
return room;
|
||||||
|
};
|
||||||
|
|
||||||
private updateLists = () => {
|
private updateLists = () => {
|
||||||
const newLists = RoomListStore.instance.orderedLists;
|
const newLists = RoomListStore.instance.orderedLists;
|
||||||
console.log("new lists", newLists);
|
console.log("new lists", newLists);
|
||||||
|
|
|
@ -79,4 +79,9 @@ export enum Action {
|
||||||
* Sets a system font. Should be used with UpdateSystemFontPayload
|
* Sets a system font. Should be used with UpdateSystemFontPayload
|
||||||
*/
|
*/
|
||||||
UpdateSystemFont = "update_system_font",
|
UpdateSystemFont = "update_system_font",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes room based on room list order and payload parameters. Should be used with ViewRoomDeltaPayload.
|
||||||
|
*/
|
||||||
|
ViewRoomDelta = "view_room_delta",
|
||||||
}
|
}
|
||||||
|
|
32
src/dispatcher/payloads/ViewRoomDeltaPayload.ts
Normal file
32
src/dispatcher/payloads/ViewRoomDeltaPayload.ts
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ActionPayload } from "../payloads";
|
||||||
|
import { Action } from "../actions";
|
||||||
|
|
||||||
|
export interface ViewRoomDeltaPayload extends ActionPayload {
|
||||||
|
action: Action.ViewRoomDelta;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The delta index of the room to view.
|
||||||
|
*/
|
||||||
|
delta: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optionally, whether or not to filter to unread (Bold/Grey/Red) rooms only. (Default: false)
|
||||||
|
*/
|
||||||
|
unread?: boolean;
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ export class RoomNotificationState extends EventEmitter implements IDestroyable,
|
||||||
private _count: number;
|
private _count: number;
|
||||||
private _color: NotificationColor;
|
private _color: NotificationColor;
|
||||||
|
|
||||||
constructor(private room: Room) {
|
constructor(public readonly room: Room) {
|
||||||
super();
|
super();
|
||||||
this.room.on("Room.receipt", this.handleReadReceipt);
|
this.room.on("Room.receipt", this.handleReadReceipt);
|
||||||
this.room.on("Room.timeline", this.handleRoomEventUpdate);
|
this.room.on("Room.timeline", this.handleRoomEventUpdate);
|
||||||
|
|
Loading…
Reference in a new issue