Page MenuHomePhabricator

D3341.diff
No OneTemporary

D3341.diff

diff --git a/web/sidebar/app-switcher.react.js b/web/sidebar/app-switcher.react.js
--- a/web/sidebar/app-switcher.react.js
+++ b/web/sidebar/app-switcher.react.js
@@ -1,11 +1,139 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
+import { useDispatch } from 'react-redux';
+import {
+ mostRecentReadThreadSelector,
+ unreadCount,
+} from 'lib/selectors/thread-selectors';
+
+import { useSelector } from '../redux/redux-utils';
+import SWMansionIcon from '../SWMansionIcon.react';
+import { updateNavInfoActionType } from '../types/nav-types';
+import css from './left-layout-aside.css';
import NavigationPanel from './navigation-panel.react';
function AppSwitcher(): React.Node {
- return <NavigationPanel />;
+ const activeChatThreadID = useSelector(
+ state => state.navInfo.activeChatThreadID,
+ );
+ const mostRecentReadThread = useSelector(mostRecentReadThreadSelector);
+ const activeThreadCurrentlyUnread = useSelector(
+ state =>
+ !activeChatThreadID ||
+ !!state.threadStore.threadInfos[activeChatThreadID]?.currentUser.unread,
+ );
+
+ const dispatch = useDispatch();
+
+ const onClickChat = React.useCallback(
+ (event: SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ dispatch({
+ type: updateNavInfoActionType,
+ payload: {
+ tab: 'chat',
+ activeChatThreadID: activeThreadCurrentlyUnread
+ ? mostRecentReadThread
+ : activeChatThreadID,
+ },
+ });
+ },
+ [
+ dispatch,
+ activeThreadCurrentlyUnread,
+ mostRecentReadThread,
+ activeChatThreadID,
+ ],
+ );
+
+ const viewerID = useSelector(
+ state => state.currentUserInfo && state.currentUserInfo.id,
+ );
+
+ const boundUnreadCount = useSelector(unreadCount);
+
+ invariant(viewerID, 'should be set');
+ let chatBadge = null;
+ if (boundUnreadCount > 0) {
+ chatBadge = <span className={css.chatBadge}>{boundUnreadCount}</span>;
+ }
+
+ const chatNavigationItem = React.useMemo(
+ () => (
+ <NavigationPanel.Item tab="chat">
+ <p>
+ <span className={css.chatIconWrapper}>
+ <SWMansionIcon icon="message-square" size={24} />
+ {chatBadge}
+ </span>
+ <a onClick={onClickChat}>Chat</a>
+ </p>
+ </NavigationPanel.Item>
+ ),
+ [chatBadge, onClickChat],
+ );
+
+ const onClickCalendar = React.useCallback(
+ (event: SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ dispatch({
+ type: updateNavInfoActionType,
+ payload: { tab: 'calendar' },
+ });
+ },
+ [dispatch],
+ );
+
+ const isCalendarEnabled = useSelector(state => state.enabledApps.calendar);
+ const calendarNavigationItem = React.useMemo(() => {
+ if (!isCalendarEnabled) {
+ return null;
+ }
+ return (
+ <NavigationPanel.Item tab="calendar">
+ <p>
+ <SWMansionIcon icon="calendar" size={24} />
+ <a onClick={onClickCalendar}>Calendar</a>
+ </p>
+ </NavigationPanel.Item>
+ );
+ }, [isCalendarEnabled, onClickCalendar]);
+
+ const onClickApps = React.useCallback(
+ (event: SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ dispatch({
+ type: updateNavInfoActionType,
+ payload: {
+ tab: 'apps',
+ },
+ });
+ },
+ [dispatch],
+ );
+
+ const appNavigationItem = React.useMemo(
+ () => (
+ <NavigationPanel.Item tab="apps">
+ <p>
+ <SWMansionIcon icon="wrench" size={24} />
+ <a onClick={onClickApps}>Apps</a>
+ </p>
+ </NavigationPanel.Item>
+ ),
+ [onClickApps],
+ );
+
+ return (
+ <NavigationPanel.Container>
+ {chatNavigationItem}
+ {calendarNavigationItem}
+ {appNavigationItem}
+ </NavigationPanel.Container>
+ );
}
export default AppSwitcher;
diff --git a/web/sidebar/left-layout-aside.css b/web/sidebar/left-layout-aside.css
--- a/web/sidebar/left-layout-aside.css
+++ b/web/sidebar/left-layout-aside.css
@@ -57,12 +57,12 @@
line-height: 1.25;
}
-p.current-tab svg {
+li.current-tab svg {
color: var(--fg);
}
-p.current-tab a,
-p.current-tab svg {
+li.current-tab a,
+li.current-tab svg {
fill: var(--fg);
color: var(--fg);
}
diff --git a/web/sidebar/navigation-panel.react.js b/web/sidebar/navigation-panel.react.js
--- a/web/sidebar/navigation-panel.react.js
+++ b/web/sidebar/navigation-panel.react.js
@@ -1,138 +1,62 @@
// @flow
import classNames from 'classnames';
-import invariant from 'invariant';
import * as React from 'react';
-import { useDispatch } from 'react-redux';
-
-import {
- mostRecentReadThreadSelector,
- unreadCount,
-} from 'lib/selectors/thread-selectors';
import { useSelector } from '../redux/redux-utils';
-import SWMansionIcon from '../SWMansionIcon.react';
-import { updateNavInfoActionType } from '../types/nav-types';
+import type { NavigationTab } from '../types/nav-types';
import css from './left-layout-aside.css';
-function NavigationPanel(): React.Node {
- const activeChatThreadID = useSelector(
- state => state.navInfo.activeChatThreadID,
- );
- const navInfo = useSelector(state => state.navInfo);
- const mostRecentReadThread = useSelector(mostRecentReadThreadSelector);
- const activeThreadCurrentlyUnread = useSelector(
- state =>
- !activeChatThreadID ||
- !!state.threadStore.threadInfos[activeChatThreadID]?.currentUser.unread,
- );
- const viewerID = useSelector(
- state => state.currentUserInfo && state.currentUserInfo.id,
- );
-
- const isCalendarEnabled = useSelector(state => state.enabledApps.calendar);
+type NavigationPanelItemProps = {
+ +tab: NavigationTab,
+ +children: React.Node,
+};
- const dispatch = useDispatch();
+function NavigationPanelItem(props: NavigationPanelItemProps): React.Node {
+ const { children } = props;
+ return children;
+}
- const onClickCalendar = React.useCallback(
- (event: SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- dispatch({
- type: updateNavInfoActionType,
- payload: { tab: 'calendar' },
- });
- },
- [dispatch],
- );
+type NavigationPanelContainerProps = {
+ +children: React.ChildrenArray<?React.Element<typeof NavigationPanelItem>>,
+};
- const onClickChat = React.useCallback(
- (event: SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- dispatch({
- type: updateNavInfoActionType,
- payload: {
- tab: 'chat',
- activeChatThreadID: activeThreadCurrentlyUnread
- ? mostRecentReadThread
- : activeChatThreadID,
- },
- });
- },
- [
- dispatch,
- activeThreadCurrentlyUnread,
- mostRecentReadThread,
- activeChatThreadID,
- ],
- );
+function NavigationPanelContainer(
+ props: NavigationPanelContainerProps,
+): React.Node {
+ const { children } = props;
+ const navInfo = useSelector(state => state.navInfo);
- const onClickApps = React.useCallback(
- (event: SyntheticEvent<HTMLAnchorElement>) => {
- event.preventDefault();
- dispatch({
- type: updateNavInfoActionType,
- payload: {
- tab: 'apps',
- },
- });
- },
- [dispatch],
+ const items = React.useMemo(
+ () =>
+ React.Children.map(children, child => {
+ if (!child) {
+ return null;
+ }
+ return (
+ <li
+ key={child.props.tab}
+ className={classNames({
+ [css['current-tab']]: navInfo.tab === child.props.tab,
+ })}
+ >
+ {child}
+ </li>
+ );
+ }),
+ [children, navInfo.tab],
);
- const boundUnreadCount = useSelector(unreadCount);
-
- invariant(viewerID, 'should be set');
- let chatBadge = null;
- if (boundUnreadCount > 0) {
- chatBadge = <span className={css.chatBadge}>{boundUnreadCount}</span>;
- }
-
- const chatNavClasses = classNames({
- [css['current-tab']]: navInfo.tab === 'chat',
- });
- const appsNavClasses = classNames({
- [css['current-tab']]: navInfo.tab === 'apps',
- });
-
- const calendarLink = React.useMemo(() => {
- if (!isCalendarEnabled) {
- return null;
- }
- const calendarNavClasses = classNames({
- [css['current-tab']]: navInfo.tab === 'calendar',
- });
- return (
- <li>
- <p className={calendarNavClasses}>
- <SWMansionIcon icon="calendar" size={24} />
- <a onClick={onClickCalendar}>Calendar</a>
- </p>
- </li>
- );
- }, [isCalendarEnabled, navInfo.tab, onClickCalendar]);
-
return (
<div className={css.navigationPanelContainer}>
- <ul>
- <li>
- <p className={chatNavClasses}>
- <span className={css.chatIconWrapper}>
- <SWMansionIcon icon="message-square" size={24} />
- {chatBadge}
- </span>
- <a onClick={onClickChat}>Chat</a>
- </p>
- </li>
- {calendarLink}
- <li>
- <p className={appsNavClasses}>
- <SWMansionIcon icon="wrench" size={24} />
- <a onClick={onClickApps}>Apps</a>
- </p>
- </li>
- </ul>
+ <ul>{items}</ul>
</div>
);
}
+const NavigationPanel = {
+ Item: NavigationPanelItem,
+ Container: NavigationPanelContainer,
+};
+
export default NavigationPanel;

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 9:00 PM (20 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2531815
Default Alt Text
D3341.diff (9 KB)

Event Timeline