-patreon: ajbura
+open_collective: cinny
liberapay: ajbura
\ No newline at end of file
}
}
}
- &:focus {
- outline: none;
+ &:focus-within {
background-color: var(--bg-surface-hover);
+ & button {
+ outline: none;
+ }
}
&:active {
background-color: var(--bg-surface-active);
const [, forceUpdate] = useState({});
- function selectorChanged(activeRoomID, prevActiveRoomId) {
+ function selectorChanged(selectedRoomId, prevSelectedRoomId) {
if (!drawerPostie.hasTopic('selector-change')) return;
const addresses = [];
- if (drawerPostie.hasSubscriber('selector-change', activeRoomID)) addresses.push(activeRoomID);
- if (drawerPostie.hasSubscriber('selector-change', prevActiveRoomId)) addresses.push(prevActiveRoomId);
+ if (drawerPostie.hasSubscriber('selector-change', selectedRoomId)) addresses.push(selectedRoomId);
+ if (drawerPostie.hasSubscriber('selector-change', prevSelectedRoomId)) addresses.push(prevSelectedRoomId);
if (addresses.length === 0) return;
- drawerPostie.post('selector-change', addresses, activeRoomID);
+ drawerPostie.post('selector-change', addresses, selectedRoomId);
}
function unreadChanged(roomId) {
function roomListUpdated() {
const { spaces, rooms, directs } = initMatrix.roomList;
if (!(
- spaces.has(navigation.getActiveRoomId())
- || rooms.has(navigation.getActiveRoomId())
- || directs.has(navigation.getActiveRoomId()))
+ spaces.has(navigation.selectedRoomId)
+ || rooms.has(navigation.selectedRoomId)
+ || directs.has(navigation.selectedRoomId))
) {
selectRoom(null);
}
key={id}
roomId={id}
drawerPostie={drawerPostie}
+ onClick={() => selectRoom(id)}
/>
));
}
import ScrollView from '../../atoms/scroll/ScrollView';
import DrawerHeader from './DrawerHeader';
+import DrawerBreadcrumb from './DrawerBreadcrumb';
import Home from './Home';
import Directs from './Directs';
-function DrawerBradcrumb() {
- return (
- <div className="breadcrumb__wrapper">
- <ScrollView horizontal vertical={false}>
- <div>
- {/* TODO: bradcrumb space paths when spaces become a thing */}
- </div>
- </ScrollView>
- </div>
- );
-}
-
function Drawer() {
- const [activeTab, setActiveTab] = useState('home');
+ const [selectedTab, setSelectedTab] = useState('home');
+ const [spaceId, setSpaceId] = useState(navigation.selectedSpaceId);
function onTabChanged(tabId) {
- setActiveTab(tabId);
+ setSelectedTab(tabId);
+ }
+ function onSpaceSelected(roomId) {
+ setSpaceId(roomId);
}
useEffect(() => {
navigation.on(cons.events.navigation.TAB_CHANGED, onTabChanged);
+ navigation.on(cons.events.navigation.SPACE_SELECTED, onSpaceSelected);
return () => {
navigation.removeListener(cons.events.navigation.TAB_CHANGED, onTabChanged);
+ navigation.removeListener(cons.events.navigation.SPACE_SELECTED, onSpaceSelected);
};
}, []);
return (
<div className="drawer">
- <DrawerHeader activeTab={activeTab} />
+ <DrawerHeader selectedTab={selectedTab} spaceId={spaceId} />
<div className="drawer__content-wrapper">
- <DrawerBradcrumb />
+ {selectedTab === 'home' && <DrawerBreadcrumb />}
<div className="rooms__wrapper">
<ScrollView autoHide>
<div className="rooms-container">
{
- activeTab === 'home'
- ? <Home />
+ selectedTab === 'home'
+ ? <Home spaceId={spaceId} />
: <Directs />
}
</div>
@extend .drawer-flexBox;
}
}
-
-.breadcrumb__wrapper {
- display: none;
- height: var(--header-height);
-}
.rooms__wrapper {
@extend .drawer-flexItem;
+ position: relative;
}
.rooms-container {
padding-bottom: var(--sp-extra-loose);
+ &::before {
+ position: absolute;
+ top: 0;
+
+ content: '';
+ display: inline-block;
+ width: 100%;
+ height: 8px;
+ background-image: linear-gradient(
+ to bottom,
+ var(--bg-surface-low),
+ var(--bg-surface-low-transparent));
+ }
+
& > .room-selector {
width: calc(100% - var(--sp-extra-tight));
margin-left: auto;
--- /dev/null
+import React, { useState, useEffect, useRef } from 'react';
+import './DrawerBreadcrumb.scss';
+
+import initMatrix from '../../../client/initMatrix';
+import cons from '../../../client/state/cons';
+import { selectSpace } from '../../../client/action/navigation';
+import navigation from '../../../client/state/navigation';
+
+import Text from '../../atoms/text/Text';
+import RawIcon from '../../atoms/system-icons/RawIcon';
+import Button from '../../atoms/button/Button';
+import ScrollView from '../../atoms/scroll/ScrollView';
+
+import ChevronRightIC from '../../../../public/res/ic/outlined/chevron-right.svg';
+
+function DrawerBreadcrumb() {
+ const [, forceUpdate] = useState({});
+ const scrollRef = useRef(null);
+ const mx = initMatrix.matrixClient;
+ const spacePath = navigation.selectedSpacePath;
+
+ function onSpaceSelected() {
+ forceUpdate({});
+ requestAnimationFrame(() => {
+ if (scrollRef?.current === null) return;
+ scrollRef.current.scrollLeft = scrollRef.current.scrollWidth;
+ });
+ }
+
+ useEffect(() => {
+ navigation.on(cons.events.navigation.SPACE_SELECTED, onSpaceSelected);
+ return () => {
+ navigation.removeListener(cons.events.navigation.SPACE_SELECTED, onSpaceSelected);
+ };
+ }, []);
+
+ if (spacePath.length === 0) return null;
+
+ return (
+ <div className="breadcrumb__wrapper">
+ <ScrollView ref={scrollRef} horizontal vertical={false} invisible>
+ <div className="breadcrumb">
+ <Button onClick={() => selectSpace(null)}>
+ <Text variant="b2">Home</Text>
+ </Button>
+ {
+ spacePath.map((spaceId, index) => (
+ <React.Fragment
+ key={spaceId}
+ >
+ <RawIcon size="extra-small" src={ChevronRightIC} />
+ <Button
+ className={index === spacePath.length - 1 ? 'breadcrumb__btn--selected' : ''}
+ onClick={() => selectSpace(spaceId)}
+ >
+ <Text variant="b2">{ mx.getRoom(spaceId).name }</Text>
+ </Button>
+ </React.Fragment>
+ ))
+ }
+ <div style={{ width: 'var(--sp-extra-tight)', height: '100%' }} />
+ </div>
+ </ScrollView>
+ </div>
+ );
+}
+
+export default DrawerBreadcrumb;
--- /dev/null
+.breadcrumb__wrapper {
+ height: var(--header-height);
+ position: relative;
+}
+
+.breadcrumb {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ margin: 0 var(--sp-extra-tight);
+
+ &::before,
+ &::after {
+ flex-shrink: 0;
+ position: absolute;
+ right: 0;
+ z-index: 99;
+
+ content: '';
+ display: inline-block;
+ min-width: 8px;
+ width: 8px;
+ height: 100%;
+ background-image: linear-gradient(
+ to right,
+ var(--bg-surface-low-transparent),
+ var(--bg-surface-low)
+ );
+ }
+ &::before {
+ left: 0;
+ right: unset;
+ background-image: linear-gradient(
+ to left,
+ var(--bg-surface-low-transparent),
+ var(--bg-surface-low)
+ );
+ }
+
+ & > * {
+ flex-shrink: 0;
+ }
+
+ & > .btn-surface {
+ min-width: 0;
+ padding: var(--sp-extra-tight) 10px;
+ white-space: nowrap;
+ box-shadow: none;
+ & p {
+ max-width: 86px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+
+ &__btn--selected {
+ box-shadow: var(--bs-surface-border) !important;
+ background-color: var(--bg-surface);
+ }
+}
\ No newline at end of file
import React from 'react';
import PropTypes from 'prop-types';
+import initMatrix from '../../../client/initMatrix';
import {
- openPublicRooms, openCreateRoom, openInviteUser,
+ selectSpace, openPublicRooms, openCreateRoom, openInviteUser,
} from '../../../client/action/navigation';
+import navigation from '../../../client/state/navigation';
import Text from '../../atoms/text/Text';
import Header, { TitleWrapper } from '../../atoms/header/Header';
import PlusIC from '../../../../public/res/ic/outlined/plus.svg';
import HashPlusIC from '../../../../public/res/ic/outlined/hash-plus.svg';
import HashSearchIC from '../../../../public/res/ic/outlined/hash-search.svg';
+import ChevronLeftIC from '../../../../public/res/ic/outlined/chevron-left.svg';
+
+function DrawerHeader({ selectedTab, spaceId }) {
+ const mx = initMatrix.matrixClient;
+ const tabName = selectedTab === 'home' ? 'Home' : 'Direct messages';
+
+ const room = mx.getRoom(spaceId);
+ const spaceName = selectedTab === 'dm' ? null : (room?.name || null);
+
+ function handleBackClick() {
+ const spacePath = navigation.selectedSpacePath;
+ if (spacePath.length === 1) {
+ selectSpace(null);
+ return;
+ }
+ selectSpace(spacePath[spacePath.length - 2]);
+ }
-function DrawerHeader({ activeTab }) {
return (
<Header>
<TitleWrapper>
- <Text variant="s1">{(activeTab === 'home' ? 'Home' : 'Direct messages')}</Text>
+ <Text variant="s1">{spaceName || tabName}</Text>
</TitleWrapper>
- {(activeTab === 'dm')
- ? <IconButton onClick={() => openInviteUser()} tooltip="Start DM" src={PlusIC} size="normal" />
- : (
+ { spaceName && <IconButton onClick={handleBackClick} tooltip="Back" src={ChevronLeftIC} size="normal" /> }
+ { selectedTab === 'dm' && <IconButton onClick={() => openInviteUser()} tooltip="Start DM" src={PlusIC} size="normal" /> }
+ { selectSpace !== 'dm' && !spaceName && (
+ <>
<ContextMenu
content={(hideMenu) => (
<>
)}
render={(toggleMenu) => (<IconButton onClick={toggleMenu} tooltip="Add room" src={PlusIC} size="normal" />)}
/>
- )}
+ </>
+ )}
{/* <IconButton onClick={() => ''} tooltip="Menu" src={VerticalMenuIC} size="normal" /> */}
</Header>
);
}
+
+DrawerHeader.defaultProps = {
+ spaceId: null,
+};
DrawerHeader.propTypes = {
- activeTab: PropTypes.string.isRequired,
+ selectedTab: PropTypes.string.isRequired,
+ spaceId: PropTypes.string,
};
export default DrawerHeader;
import React, { useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
import initMatrix from '../../../client/initMatrix';
import cons from '../../../client/state/cons';
import navigation from '../../../client/state/navigation';
-import { selectRoom } from '../../../client/action/navigation';
+import { selectSpace, selectRoom } from '../../../client/action/navigation';
import Postie from '../../../util/Postie';
import Text from '../../atoms/text/Text';
import { AtoZ } from './common';
const drawerPostie = new Postie();
-function Home() {
+function Home({ spaceId }) {
+ const [, forceUpdate] = useState({});
const { roomList } = initMatrix;
- const spaceIds = [...roomList.spaces].sort(AtoZ);
- const roomIds = [...roomList.rooms].sort(AtoZ);
+ let spaceIds = [];
+ let roomIds = [];
+ let directIds = [];
- const [, forceUpdate] = useState({});
+ const spaceChildIds = roomList.getSpaceChildren(spaceId);
+ if (spaceChildIds) {
+ spaceIds = spaceChildIds.filter((roomId) => roomList.spaces.has(roomId)).sort(AtoZ);
+ roomIds = spaceChildIds.filter((roomId) => roomList.rooms.has(roomId)).sort(AtoZ);
+ directIds = spaceChildIds.filter((roomId) => roomList.directs.has(roomId)).sort(AtoZ);
+ } else {
+ spaceIds = [...roomList.spaces]
+ .filter((roomId) => !roomList.roomIdToParents.has(roomId)).sort(AtoZ);
+ roomIds = [...roomList.rooms]
+ .filter((roomId) => !roomList.roomIdToParents.has(roomId)).sort(AtoZ);
+ }
- function selectorChanged(activeRoomID, prevActiveRoomId) {
+ function selectorChanged(selectedRoomId, prevSelectedRoomId) {
if (!drawerPostie.hasTopic('selector-change')) return;
const addresses = [];
- if (drawerPostie.hasSubscriber('selector-change', activeRoomID)) addresses.push(activeRoomID);
- if (drawerPostie.hasSubscriber('selector-change', prevActiveRoomId)) addresses.push(prevActiveRoomId);
+ if (drawerPostie.hasSubscriber('selector-change', selectedRoomId)) addresses.push(selectedRoomId);
+ if (drawerPostie.hasSubscriber('selector-change', prevSelectedRoomId)) addresses.push(prevSelectedRoomId);
if (addresses.length === 0) return;
- drawerPostie.post('selector-change', addresses, activeRoomID);
+ drawerPostie.post('selector-change', addresses, selectedRoomId);
}
function unreadChanged(roomId) {
if (!drawerPostie.hasTopic('unread-change')) return;
function roomListUpdated() {
const { spaces, rooms, directs } = initMatrix.roomList;
if (!(
- spaces.has(navigation.getActiveRoomId())
- || rooms.has(navigation.getActiveRoomId())
- || directs.has(navigation.getActiveRoomId()))
+ spaces.has(navigation.selectedRoomId)
+ || rooms.has(navigation.selectedRoomId)
+ || directs.has(navigation.selectedRoomId))
) {
selectRoom(null);
}
roomId={id}
isDM={false}
drawerPostie={drawerPostie}
+ onClick={() => selectSpace(id)}
/>
))}
roomId={id}
isDM={false}
drawerPostie={drawerPostie}
+ onClick={() => selectRoom(id)}
/>
)) }
+
+ { directIds.length !== 0 && <Text className="cat-header" variant="b3">People</Text> }
+ { directIds.map((id) => (
+ <Selector
+ key={id}
+ roomId={id}
+ drawerPostie={drawerPostie}
+ onClick={() => selectRoom(id)}
+ />
+ ))}
</>
);
}
+Home.defaultProps = {
+ spaceId: null,
+};
+Home.propTypes = {
+ spaceId: PropTypes.string,
+};
export default Home;
import initMatrix from '../../../client/initMatrix';
import { doesRoomHaveUnread } from '../../../util/matrixUtil';
-import { selectRoom } from '../../../client/action/navigation';
import navigation from '../../../client/state/navigation';
import RoomSelector from '../../molecules/room-selector/RoomSelector';
import SpaceIC from '../../../../public/res/ic/outlined/space.svg';
import SpaceLockIC from '../../../../public/res/ic/outlined/space-lock.svg';
-function Selector({ roomId, isDM, drawerPostie }) {
+function Selector({
+ roomId, isDM, drawerPostie, onClick,
+}) {
const mx = initMatrix.matrixClient;
const room = mx.getRoom(roomId);
const imageSrc = room.getAvatarFallbackMember()?.getAvatarUrl(mx.baseUrl, 24, 24, 'crop') || null;
- const [isSelected, setIsSelected] = useState(navigation.getActiveRoomId() === roomId);
+ const [isSelected, setIsSelected] = useState(navigation.selectedRoomId === roomId);
const [, forceUpdate] = useState({});
- function selectorChanged(activeRoomId) {
- setIsSelected(activeRoomId === roomId);
+ function selectorChanged(selectedRoomId) {
+ setIsSelected(selectedRoomId === roomId);
}
function changeNotificationBadge() {
forceUpdate({});
isUnread={doesRoomHaveUnread(room)}
notificationCount={room.getUnreadNotificationCount('total') || 0}
isAlert={room.getUnreadNotificationCount('highlight') !== 0}
- onClick={() => selectRoom(roomId)}
+ onClick={onClick}
/>
);
}
roomId: PropTypes.string.isRequired,
isDM: PropTypes.bool,
drawerPostie: PropTypes.shape({}).isRequired,
+ onClick: PropTypes.func.isRequired,
};
export default Selector;
+ initMatrix.roomList.inviteDirects.size;
const [totalInvites, updateTotalInvites] = useState(totalInviteCount());
- const [activeTab, setActiveTab] = useState('home');
+ const [selectedTab, setSelectedTab] = useState('home');
function onTabChanged(tabId) {
- setActiveTab(tabId);
+ setSelectedTab(tabId);
}
function onInviteListChange() {
updateTotalInvites(totalInviteCount());
<ScrollView invisible>
<div className="scrollable-content">
<div className="featured-container">
- <SidebarAvatar active={activeTab === 'home'} onClick={() => changeTab('home')} tooltip="Home" iconSrc={HomeIC} />
- <SidebarAvatar active={activeTab === 'dm'} onClick={() => changeTab('dm')} tooltip="People" iconSrc={UserIC} />
+ <SidebarAvatar active={selectedTab === 'home'} onClick={() => changeTab('home')} tooltip="Home" iconSrc={HomeIC} />
+ <SidebarAvatar active={selectedTab === 'dm'} onClick={() => changeTab('dm')} tooltip="People" iconSrc={UserIC} />
<SidebarAvatar onClick={() => openPublicRooms()} tooltip="Public rooms" iconSrc={HashSearchIC} />
</div>
<div className="sidebar-divider" />
height: 8px;
background: transparent;
- // background-image: linear-gradient(to top, var(--bg-surface-low), transparent);
- // It produce bug in safari
- // To fix it, we have to set the color as a fully transparent version of that exact color. like:
- // background-image: linear-gradient(to top, rgb(255, 255, 255), rgba(255, 255, 255, 0));
- // TODO: fix this bug while implementing spaces
+ background-image: linear-gradient(
+ to top,
+ var(--bg-surface-low),
+ var(--bg-surface-low-transparent));
position: sticky;
bottom: 0;
left: 0;
import CinnySvg from '../../../../public/res/svg/cinny.svg';
-// This regex validates historical usernames, which don't satisy today's username requirements.
+// This regex validates historical usernames, which don't satisfy today's username requirements.
// See https://matrix.org/docs/spec/appendices#id13 for more info.
const LOCALPART_LOGIN_REGEX = /.*/;
const LOCALPART_SIGNUP_REGEX = /^[a-z0-9_\-.=/]+$/;
});
}
+function selectSpace(roomId) {
+ appDispatcher.dispatch({
+ type: cons.actions.navigation.SELECT_SPACE,
+ roomId,
+ });
+}
+
function selectRoom(roomId) {
appDispatcher.dispatch({
type: cons.actions.navigation.SELECT_ROOM,
export {
changeTab,
+ selectSpace,
selectRoom,
togglePeopleDrawer,
openInviteList,
super();
this.matrixClient = matrixClient;
this.mDirects = this.getMDirects();
+ this.roomIdToParents = new Map();
this.inviteDirects = new Set();
this.inviteSpaces = new Set();
appDispatcher.register(this.roomActions.bind(this));
}
+ getSpaceChildren(roomId) {
+ const space = this.matrixClient.getRoom(roomId);
+ const mSpaceChild = space?.currentState.getStateEvents('m.space.child');
+ const children = mSpaceChild?.map((mEvent) => {
+ if (Object.keys(mEvent.event.content).length === 0) return null;
+ return mEvent.event.state_key;
+ });
+ return children?.filter((child) => child !== null);
+ }
+
+ addToRoomIdToParents(roomId, parentRoomId) {
+ if (!this.roomIdToParents.has(roomId)) {
+ this.roomIdToParents.set(roomId, new Set());
+ }
+ const parents = this.roomIdToParents.get(roomId);
+ parents.add(parentRoomId);
+ }
+
+ removeFromRoomIdToParents(roomId, parentRoomId) {
+ if (!this.roomIdToParents.has(roomId)) return;
+ const parents = this.roomIdToParents.get(roomId);
+ parents.delete(parentRoomId);
+ if (parents.size === 0) this.roomIdToParents.delete(roomId);
+ }
+
+ addToSpaces(roomId) {
+ this.spaces.add(roomId);
+ const spaceChildren = this.getSpaceChildren(roomId);
+ spaceChildren?.forEach((childRoomId) => {
+ this.addToRoomIdToParents(childRoomId, roomId);
+ });
+ }
+
+ deleteFromSpaces(roomId) {
+ this.spaces.delete(roomId);
+ const spaceChildren = this.getSpaceChildren(roomId);
+ spaceChildren?.forEach((childRoomId) => {
+ this.removeFromRoomIdToParents(childRoomId, roomId);
+ });
+ }
+
roomActions(action) {
const addRoom = (roomId, isDM) => {
const myRoom = this.matrixClient.getRoom(roomId);
if (myRoom === null) return false;
if (isDM) this.directs.add(roomId);
- else if (myRoom.isSpaceRoom()) this.spaces.add(roomId);
+ else if (myRoom.isSpaceRoom()) this.addToSpaces(roomId);
else this.rooms.add(roomId);
return true;
};
_populateRooms() {
this.directs.clear();
+ this.roomIdToParents.clear();
this.spaces.clear();
this.rooms.clear();
this.inviteDirects.clear();
if (room.getMyMembership() !== 'join') return;
if (this.mDirects.has(roomId)) this.directs.add(roomId);
- else if (room.isSpaceRoom()) this.spaces.add(roomId);
+ else if (room.isSpaceRoom()) this.addToSpaces(roomId);
else this.rooms.add(roomId);
});
}
}
});
- this.matrixClient.on('RoomState.events', (event) => {
- if (event.getType() !== 'm.room.join_rules') return;
+ this.matrixClient.on('RoomState.events', (mEvent) => {
+ if (mEvent.getType() === 'm.space.child') {
+ const { event } = mEvent;
+ const isRoomAdded = Object.keys(event.content).length > 0;
+ if (isRoomAdded) this.addToRoomIdToParents(event.state_key, event.room_id);
+ else this.removeFromRoomIdToParents(event.state_key, event.room_id);
+ this.emit(cons.events.roomList.ROOMLIST_UPDATED);
+ return;
+ }
+ if (mEvent.getType() !== 'm.room.join_rules') return;
this.emit(cons.events.roomList.ROOMLIST_UPDATED);
});
const procRoomInfo = this.processingRooms.get(roomId);
if (procRoomInfo.isDM) this.directs.add(roomId);
- else if (room.isSpaceRoom()) this.spaces.add(roomId);
+ else if (room.isSpaceRoom()) this.addToSpaces(roomId);
else this.rooms.add(roomId);
if (procRoomInfo.task === 'CREATE') this.emit(cons.events.roomList.ROOM_CREATED, roomId);
return;
}
if (room.isSpaceRoom()) {
- this.spaces.add(roomId);
+ this.addToSpaces(roomId);
this.emit(cons.events.roomList.ROOM_JOINED, roomId);
this.emit(cons.events.roomList.ROOMLIST_UPDATED);
}
// when room is not a DM add/remove it from rooms.
if (membership === 'leave' || membership === 'kick' || membership === 'ban') {
- if (room.isSpaceRoom()) this.spaces.delete(roomId);
+ if (room.isSpaceRoom()) this.deleteFromSpaces(roomId);
else this.rooms.delete(roomId);
this.emit(cons.events.roomList.ROOM_LEAVED, roomId);
}
if (membership === 'join') {
- if (room.isSpaceRoom()) this.spaces.add(roomId);
+ if (room.isSpaceRoom()) this.addToSpaces(roomId);
else this.rooms.add(roomId);
this.emit(cons.events.roomList.ROOM_JOINED, roomId);
}
actions: {
navigation: {
CHANGE_TAB: 'CHANGE_TAB',
+ SELECT_SPACE: 'SELECT_SPACE',
SELECT_ROOM: 'SELECT_ROOM',
TOGGLE_PEOPLE_DRAWER: 'TOGGLE_PEOPLE_DRAWER',
OPEN_INVITE_LIST: 'OPEN_INVITE_LIST',
events: {
navigation: {
TAB_CHANGED: 'TAB_CHANGED',
+ SPACE_SELECTED: 'SPACE_SELECTED',
ROOM_SELECTED: 'ROOM_SELECTED',
PEOPLE_DRAWER_TOGGLED: 'PEOPLE_DRAWER_TOGGLED',
INVITE_LIST_OPENED: 'INVITE_LIST_OPENED',
constructor() {
super();
- this.activeTab = 'home';
- this.activeRoomId = null;
+ this.selectedTab = 'home';
+ this.selectedSpaceId = null;
+ this.selectedSpacePath = [];
+ this.selectedRoomId = null;
this.isPeopleDrawerVisible = true;
- }
- getActiveTab() {
- return this.activeTab;
+ // TODO:
+ window.navigation = this;
}
- getActiveRoomId() {
- return this.activeRoomId;
+ _setSpacePath(roomId) {
+ if (roomId === null) {
+ this.selectedSpacePath = [];
+ return;
+ }
+ if (this.selectedSpacePath.includes(roomId)) {
+ const spIndex = this.selectedSpacePath.indexOf(roomId);
+ this.selectedSpacePath = this.selectedSpacePath.slice(0, spIndex + 1);
+ return;
+ }
+ this.selectedSpacePath.push(roomId);
}
navigate(action) {
const actions = {
[cons.actions.navigation.CHANGE_TAB]: () => {
- this.activeTab = action.tabId;
- this.emit(cons.events.navigation.TAB_CHANGED, this.activeTab);
+ this.selectedTab = action.tabId;
+ this.emit(cons.events.navigation.TAB_CHANGED, this.selectedTab);
+ },
+ [cons.actions.navigation.SELECT_SPACE]: () => {
+ this._setSpacePath(action.roomId);
+ this.selectedSpaceId = action.roomId;
+ this.emit(cons.events.navigation.SPACE_SELECTED, action.roomId);
},
[cons.actions.navigation.SELECT_ROOM]: () => {
- const prevActiveRoomId = this.activeRoomId;
- this.activeRoomId = action.roomId;
- this.emit(cons.events.navigation.ROOM_SELECTED, this.activeRoomId, prevActiveRoomId);
+ const prevSelectedRoomId = this.selectedRoomId;
+ this.selectedRoomId = action.roomId;
+ this.emit(cons.events.navigation.ROOM_SELECTED, this.selectedRoomId, prevSelectedRoomId);
},
[cons.actions.navigation.TOGGLE_PEOPLE_DRAWER]: () => {
this.isPeopleDrawerVisible = !this.isPeopleDrawerVisible;
/* background color | --bg-[background type]: value */
--bg-surface: #FFFFFF;
+ --bg-surface-transparent: #FFFFFF00;
--bg-surface-low: #F6F6F6;
+ --bg-surface-low-transparent: #F6F6F600;
--bg-surface-hover: rgba(0, 0, 0, 3%);
--bg-surface-active: rgba(0, 0, 0, 5%);
--bg-surface-border: rgba(0, 0, 0, 6%);
.silver-theme {
/* background color | --bg-[background type]: value */
--bg-surface: hsl(0, 0%, 95%);
+ --bg-surface-transparent: hsla(0, 0%, 95%, 0);
--bg-surface-low: hsl(0, 0%, 91%);
+ --bg-surface-low-transparent: hsla(0, 0%, 91%, 0);
}
.dark-theme,
.butter-theme {
/* background color | --bg-[background type]: value */
--bg-surface: hsl(208, 8%, 20%);
+ --bg-surface-transparent: hsla(208, 8%, 20%, 0);
--bg-surface-low: hsl(208, 8%, 16%);
+ --bg-surface-low-transparent: hsla(208, 8%, 16%, 0);
--bg-surface-hover: rgba(255, 255, 255, 3%);
--bg-surface-active: rgba(255, 255, 255, 5%);
--bg-surface-border: rgba(0, 0, 0, 20%);
.butter-theme {
/* background color | --bg-[background type]: value */
--bg-surface: hsl(64, 6%, 14%);
+ --bg-surface-transparent: hsla(64, 6%, 14%, 0);
--bg-surface-low: hsl(64, 6%, 10%);
+ --bg-surface-low-transparent: hsla(64, 6%, 14%, 0);
/* text color | --tc-[background type]-[priority]: value */