diff --git a/lib/utils/url-utils.js b/lib/utils/url-utils.js --- a/lib/utils/url-utils.js +++ b/lib/utils/url-utils.js @@ -8,6 +8,7 @@ verify?: string, calendar?: boolean, chat?: boolean, + apps?: boolean, thread?: string, ... }; @@ -18,6 +19,7 @@ const verifyRegex = new RegExp('(/|^)verify/([a-f0-9]+)(/|$)', 'i'); const calendarRegex = new RegExp('(/|^)calendar(/|$)', 'i'); const chatRegex = new RegExp('(/|^)chat(/|$)', 'i'); +const appsRegex = new RegExp('(/|^)apps(/|$)', 'i'); function infoFromURL(url: string): URLInfo { const yearMatches = yearRegex.exec(url); @@ -26,6 +28,7 @@ const verifyMatches = verifyRegex.exec(url); const calendarTest = calendarRegex.test(url); const chatTest = chatRegex.test(url); + const appsTest = appsRegex.test(url); const returnObj = {}; if (yearMatches) { returnObj.year = parseInt(yearMatches[2], 10); @@ -47,6 +50,8 @@ returnObj.calendar = true; } else if (chatTest) { returnObj.chat = true; + } else if (appsTest) { + returnObj.apps = true; } return returnObj; } diff --git a/web/app.react.js b/web/app.react.js --- a/web/app.react.js +++ b/web/app.react.js @@ -31,6 +31,7 @@ import type { Dispatch } from 'lib/types/redux-types'; import { registerConfig } from 'lib/utils/config'; +import AppsDirectory from './apps/apps-directory.react'; import Calendar from './calendar/calendar.react'; import Chat from './chat/chat.react'; import InputStateContainer from './input/input-state-container.react'; @@ -149,6 +150,8 @@ mainContent = <Calendar url={this.props.location.pathname} />; } else if (this.props.navInfo.tab === 'chat') { mainContent = <Chat />; + } else if (this.props.navInfo.tab === 'apps') { + mainContent = <AppsDirectory />; } return ( diff --git a/web/apps/apps-directory.react.js b/web/apps/apps-directory.react.js new file mode 100644 --- /dev/null +++ b/web/apps/apps-directory.react.js @@ -0,0 +1,9 @@ +// @flow + +import * as React from 'react'; + +function AppsDirectory(): React.Node { + return <div style={{ color: 'white' }}>Apps directory</div>; +} + +export default AppsDirectory; 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 @@ -71,6 +71,19 @@ ], ); + const onClickApps = React.useCallback( + (event: SyntheticEvent<HTMLAnchorElement>) => { + event.preventDefault(); + dispatch({ + type: updateNavInfoActionType, + payload: { + tab: 'apps', + }, + }); + }, + [dispatch], + ); + invariant(viewerID, 'should be set'); let chatBadge = null; if (boundUnreadCount > 0) { @@ -83,6 +96,9 @@ const chatNavClasses = classNames({ [css['current-tab']]: navInfo.tab === 'chat', }); + const appsNavClasses = classNames({ + [css['current-tab']]: navInfo.tab === 'apps', + }); return ( <div className={css.appSwitcherContainer}> @@ -102,6 +118,12 @@ <a onClick={onClickCalendar}>Calendar</a> </p> </li> + <li> + <p className={appsNavClasses}> + <SWMansionIcon icon="wrench" size={24} /> + <a onClick={onClickApps}>Apps</a> + </p> + </li> </ul> </div> ); diff --git a/web/types/nav-types.js b/web/types/nav-types.js --- a/web/types/nav-types.js +++ b/web/types/nav-types.js @@ -5,7 +5,7 @@ export type NavInfo = { ...$Exact<BaseNavInfo>, - +tab: 'calendar' | 'chat', + +tab: 'calendar' | 'chat' | 'apps', +activeChatThreadID: ?string, +pendingThread?: ThreadInfo, }; diff --git a/web/url-utils.js b/web/url-utils.js --- a/web/url-utils.js +++ b/web/url-utils.js @@ -97,8 +97,15 @@ activeChatThreadID = navInfo.activeChatThreadID; } + let tab = 'chat'; + if (urlInfo.calendar) { + tab = 'calendar'; + } else if (urlInfo.apps) { + tab = 'apps'; + } + return { - tab: urlInfo.chat ? 'chat' : 'calendar', + tab, startDate: startDateForYearAndMonth(year, month), endDate: endDateForYearAndMonth(year, month), activeChatThreadID,