Selected state, cleanup, and profile display
parent
ea6b0a60ab
commit
1d8833e9f8
|
@ -14,6 +14,9 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_LeftPanel during replacement of old component
|
||||||
|
|
||||||
|
// TODO: Put these variables in the right place, or namespace them.
|
||||||
$tagPanelWidth: 70px;
|
$tagPanelWidth: 70px;
|
||||||
$roomListMinimizedWidth: 50px;
|
$roomListMinimizedWidth: 50px;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_RoomList during replacement of old component
|
||||||
|
|
||||||
.mx_RoomList2 {
|
.mx_RoomList2 {
|
||||||
// Create a column-based flexbox for the sublists. That's pretty much all we have to
|
// Create a column-based flexbox for the sublists. That's pretty much all we have to
|
||||||
// worry about in this stylesheet.
|
// worry about in this stylesheet.
|
||||||
|
|
|
@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_RoomSublist during replacement of old component
|
||||||
|
|
||||||
@import "../../../../node_modules/react-resizable/css/styles.css";
|
@import "../../../../node_modules/react-resizable/css/styles.css";
|
||||||
|
|
||||||
.mx_RoomSublist2 {
|
.mx_RoomSublist2 {
|
||||||
|
|
|
@ -14,15 +14,24 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: Rename to mx_RoomTile during replacement of old component
|
||||||
|
|
||||||
// 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 {
|
||||||
width: 100%;
|
width: calc(100% - 11px); // 8px for padding (4px on either side), 3px for margin
|
||||||
padding-bottom: 12px;
|
margin-bottom: 4px;
|
||||||
|
margin-right: 3px;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
// The tile is also a flexbox row itself
|
// The tile is also a flexbox row itself
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
&.mx_RoomTile2_selected {
|
||||||
|
background-color: $roomtile2-selected-bg-color;
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_RoomTile2_avatarContainer {
|
.mx_RoomTile2_avatarContainer {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,7 @@ $header-divider-color: #91A1C0;
|
||||||
// TODO: Dark theme
|
// TODO: Dark theme
|
||||||
$roomtile2-preview-color: #9e9e9e;
|
$roomtile2-preview-color: #9e9e9e;
|
||||||
$roomtile2-badge-color: #61708b;
|
$roomtile2-badge-color: #61708b;
|
||||||
|
$roomtile2-selected-bg-color: #FFF;
|
||||||
|
|
||||||
$roomtile-name-color: #61708b;
|
$roomtile-name-color: #61708b;
|
||||||
$roomtile-badge-fg-color: $accent-fg-color;
|
$roomtile-badge-fg-color: $accent-fg-color;
|
||||||
|
|
|
@ -27,7 +27,7 @@ import RoomViewStore from './stores/RoomViewStore';
|
||||||
*/
|
*/
|
||||||
class ActiveRoomObserver {
|
class ActiveRoomObserver {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._listeners = {};
|
this._listeners = {}; // key=roomId, value=function(isActive:boolean)
|
||||||
|
|
||||||
this._activeRoomId = RoomViewStore.getRoomId();
|
this._activeRoomId = RoomViewStore.getRoomId();
|
||||||
// TODO: We could self-destruct when the last listener goes away, or at least
|
// TODO: We could self-destruct when the last listener goes away, or at least
|
||||||
|
@ -35,6 +35,10 @@ class ActiveRoomObserver {
|
||||||
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate.bind(this));
|
this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get activeRoomId(): string {
|
||||||
|
return this._activeRoomId;
|
||||||
|
}
|
||||||
|
|
||||||
addListener(roomId, listener) {
|
addListener(roomId, listener) {
|
||||||
if (!this._listeners[roomId]) this._listeners[roomId] = [];
|
if (!this._listeners[roomId]) this._listeners[roomId] = [];
|
||||||
this._listeners[roomId].push(listener);
|
this._listeners[roomId].push(listener);
|
||||||
|
@ -51,23 +55,23 @@ class ActiveRoomObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_emit(roomId) {
|
_emit(roomId, isActive: boolean) {
|
||||||
if (!this._listeners[roomId]) return;
|
if (!this._listeners[roomId]) return;
|
||||||
|
|
||||||
for (const l of this._listeners[roomId]) {
|
for (const l of this._listeners[roomId]) {
|
||||||
l.call();
|
l.call(null, isActive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRoomViewStoreUpdate() {
|
_onRoomViewStoreUpdate() {
|
||||||
// emit for the old room ID
|
// emit for the old room ID
|
||||||
if (this._activeRoomId) this._emit(this._activeRoomId);
|
if (this._activeRoomId) this._emit(this._activeRoomId, false);
|
||||||
|
|
||||||
// update our cache
|
// update our cache
|
||||||
this._activeRoomId = RoomViewStore.getRoomId();
|
this._activeRoomId = RoomViewStore.getRoomId();
|
||||||
|
|
||||||
// and emit for the new one
|
// and emit for the new one
|
||||||
if (this._activeRoomId) this._emit(this._activeRoomId);
|
if (this._activeRoomId) this._emit(this._activeRoomId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,26 +86,35 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderHeader(): React.ReactNode {
|
private renderHeader(): React.ReactNode {
|
||||||
// TODO: Use real profile info
|
// TODO: Update when profile info changes
|
||||||
// TODO: Presence
|
// TODO: Presence
|
||||||
// TODO: Breadcrumbs toggle
|
// TODO: Breadcrumbs toggle
|
||||||
// TODO: Menu button
|
// TODO: Menu button
|
||||||
const avatarSize = 32;
|
const avatarSize = 32;
|
||||||
|
// TODO: Don't do this profile lookup in render()
|
||||||
|
const client = MatrixClientPeg.get();
|
||||||
|
let displayName = client.getUserId();
|
||||||
|
let avatarUrl: string = null;
|
||||||
|
const myUser = client.getUser(client.getUserId());
|
||||||
|
if (myUser) {
|
||||||
|
displayName = myUser.rawDisplayName;
|
||||||
|
avatarUrl = myUser.avatarUrl;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className="mx_LeftPanel2_userHeader">
|
<div className="mx_LeftPanel2_userHeader">
|
||||||
<div className="mx_LeftPanel2_headerRow">
|
<div className="mx_LeftPanel2_headerRow">
|
||||||
<span className="mx_LeftPanel2_userAvatarContainer">
|
<span className="mx_LeftPanel2_userAvatarContainer">
|
||||||
<BaseAvatar
|
<BaseAvatar
|
||||||
idName={MatrixClientPeg.get().getUserId()}
|
idName={MatrixClientPeg.get().getUserId()}
|
||||||
name={"TODO: Display Name"}
|
name={displayName}
|
||||||
url={null}
|
url={avatarUrl}
|
||||||
width={avatarSize}
|
width={avatarSize}
|
||||||
height={avatarSize}
|
height={avatarSize}
|
||||||
resizeMethod="crop"
|
resizeMethod="crop"
|
||||||
className="mx_LeftPanel2_userAvatar"
|
className="mx_LeftPanel2_userAvatar"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span className="mx_LeftPanel2_userName">Irene</span>
|
<span className="mx_LeftPanel2_userName">{displayName}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_LeftPanel2_headerRow mx_LeftPanel2_breadcrumbsContainer">
|
<div className="mx_LeftPanel2_headerRow mx_LeftPanel2_breadcrumbsContainer">
|
||||||
<RoomBreadcrumbs />
|
<RoomBreadcrumbs />
|
||||||
|
|
|
@ -23,7 +23,6 @@ import classNames from "classnames";
|
||||||
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
import { RovingTabIndexWrapper } from "../../../accessibility/RovingTabIndex";
|
||||||
import AccessibleButton from "../../views/elements/AccessibleButton";
|
import AccessibleButton from "../../views/elements/AccessibleButton";
|
||||||
import RoomAvatar from "../../views/avatars/RoomAvatar";
|
import RoomAvatar from "../../views/avatars/RoomAvatar";
|
||||||
import Tooltip from "../../views/elements/Tooltip";
|
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import { Key } from "../../../Keyboard";
|
import { Key } from "../../../Keyboard";
|
||||||
import * as RoomNotifs from '../../../RoomNotifs';
|
import * as RoomNotifs from '../../../RoomNotifs';
|
||||||
|
@ -32,6 +31,7 @@ import * as Unread from '../../../Unread';
|
||||||
import * as FormattingUtils from "../../../utils/FormattingUtils";
|
import * as FormattingUtils from "../../../utils/FormattingUtils";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import ActiveRoomObserver from "../../../ActiveRoomObserver";
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
* CAUTION *
|
* CAUTION *
|
||||||
|
@ -66,6 +66,7 @@ interface INotificationState {
|
||||||
interface IState {
|
interface IState {
|
||||||
hover: boolean;
|
hover: boolean;
|
||||||
notificationState: INotificationState;
|
notificationState: INotificationState;
|
||||||
|
selected: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RoomTile2 extends React.Component<IProps, IState> {
|
export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
|
@ -88,12 +89,14 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
this.state = {
|
this.state = {
|
||||||
hover: false,
|
hover: false,
|
||||||
notificationState: this.getNotificationState(),
|
notificationState: this.getNotificationState(),
|
||||||
|
selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.props.room.on("Room.receipt", this.handleRoomEventUpdate);
|
this.props.room.on("Room.receipt", this.handleRoomEventUpdate);
|
||||||
this.props.room.on("Room.timeline", this.handleRoomEventUpdate);
|
this.props.room.on("Room.timeline", this.handleRoomEventUpdate);
|
||||||
this.props.room.on("Room.redaction", this.handleRoomEventUpdate);
|
this.props.room.on("Room.redaction", this.handleRoomEventUpdate);
|
||||||
MatrixClientPeg.get().on("Event.decrypted", this.handleRoomEventUpdate);
|
MatrixClientPeg.get().on("Event.decrypted", this.handleRoomEventUpdate);
|
||||||
|
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillUnmount() {
|
public componentWillUnmount() {
|
||||||
|
@ -101,6 +104,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
this.props.room.removeListener("Room.receipt", this.handleRoomEventUpdate);
|
this.props.room.removeListener("Room.receipt", this.handleRoomEventUpdate);
|
||||||
this.props.room.removeListener("Room.timeline", this.handleRoomEventUpdate);
|
this.props.room.removeListener("Room.timeline", this.handleRoomEventUpdate);
|
||||||
this.props.room.removeListener("Room.redaction", this.handleRoomEventUpdate);
|
this.props.room.removeListener("Room.redaction", this.handleRoomEventUpdate);
|
||||||
|
ActiveRoomObserver.removeListener(this.props.room.roomId, this.onActiveRoomUpdate);
|
||||||
}
|
}
|
||||||
if (MatrixClientPeg.get()) {
|
if (MatrixClientPeg.get()) {
|
||||||
MatrixClientPeg.get().removeListener("Event.decrypted", this.handleRoomEventUpdate);
|
MatrixClientPeg.get().removeListener("Event.decrypted", this.handleRoomEventUpdate);
|
||||||
|
@ -187,6 +191,10 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onActiveRoomUpdate = (isActive: boolean) => {
|
||||||
|
this.setState({selected: isActive});
|
||||||
|
};
|
||||||
|
|
||||||
public render(): React.ReactElement {
|
public render(): React.ReactElement {
|
||||||
// TODO: Collapsed state
|
// TODO: Collapsed state
|
||||||
// TODO: Invites
|
// TODO: Invites
|
||||||
|
@ -195,6 +203,7 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
'mx_RoomTile2': true,
|
'mx_RoomTile2': true,
|
||||||
|
'mx_RoomTile2_selected': this.state.selected,
|
||||||
});
|
});
|
||||||
|
|
||||||
let badge;
|
let badge;
|
||||||
|
|
Loading…
Reference in New Issue