Commit cfa65c40 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Convert UserMenu to TS

Refactor the computation of a couple of props set on MenuItem for
clarity and improved typing.
parent 38dfb915
import { ProfileIcon } from '@hypothesis/frontend-shared/lib/next'; import { ProfileIcon } from '@hypothesis/frontend-shared/lib/next';
import { useState } from 'preact/hooks'; import { useState } from 'preact/hooks';
import type { Service, SidebarSettings } from '../../types/config';
import { serviceConfig } from '../config/service-config'; import { serviceConfig } from '../config/service-config';
import { import {
isThirdPartyUser, isThirdPartyUser,
username as getUsername, username as getUsername,
} from '../helpers/account-id'; } from '../helpers/account-id';
import { withServices } from '../service-context'; import { withServices } from '../service-context';
import type { FrameSyncService } from '../services/frame-sync';
import { useSidebarStore } from '../store'; import { useSidebarStore } from '../store';
import Menu from './Menu'; import Menu from './Menu';
import MenuItem from './MenuItem'; import MenuItem from './MenuItem';
import MenuSection from './MenuSection'; import MenuSection from './MenuSection';
/** export type UserMenuProps = {
* @typedef {import('../../types/config').SidebarSettings} SidebarSettings onLogout: () => void;
* / frameSync: FrameSyncService;
settings: SidebarSettings;
/** };
* @typedef UserMenuProps
* @prop {() => void} onLogout - onClick callback for the "log out" button
* @prop {import('../services/frame-sync').FrameSyncService} frameSync
* @prop {SidebarSettings} settings
*/
/** /**
* A menu with user and account links. * A menu with user and account links.
* *
* This menu will contain different items depending on service configuration, * This menu will contain different items depending on service configuration,
* context and whether the user is first- or third-party. * context and whether the user is first- or third-party.
*
* @param {UserMenuProps} props
*/ */
function UserMenu({ frameSync, onLogout, settings }) { function UserMenu({ frameSync, onLogout, settings }: UserMenuProps) {
const store = useSidebarStore(); const store = useSidebarStore();
const defaultAuthority = store.defaultAuthority(); const defaultAuthority = store.defaultAuthority();
const profile = store.profile(); const profile = store.profile();
...@@ -43,8 +38,8 @@ function UserMenu({ frameSync, onLogout, settings }) { ...@@ -43,8 +38,8 @@ function UserMenu({ frameSync, onLogout, settings }) {
const displayName = profile.user_info?.display_name ?? username; const displayName = profile.user_info?.display_name ?? username;
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
/** @param {keyof import('../../types/config').Service} feature */ const serviceSupports = (feature: keyof Service) =>
const serviceSupports = feature => service && !!service[feature]; service && !!service[feature];
const isSelectableProfile = const isSelectableProfile =
!isThirdParty || serviceSupports('onProfileRequestProvided'); !isThirdParty || serviceSupports('onProfileRequestProvided');
...@@ -55,11 +50,9 @@ function UserMenu({ frameSync, onLogout, settings }) { ...@@ -55,11 +50,9 @@ function UserMenu({ frameSync, onLogout, settings }) {
frameSync.notifyHost('openNotebook', store.focusedGroupId()); frameSync.notifyHost('openNotebook', store.focusedGroupId());
}; };
// Temporary access to the Notebook without feature flag: // Access to the Notebook:
// type the key 'n' when user menu is focused/open // type the key 'n' when user menu is focused/open
const onKeyDown = (event: KeyboardEvent) => {
/** @param {KeyboardEvent} event */
const onKeyDown = event => {
if (event.key === 'n') { if (event.key === 'n') {
onSelectNotebook(); onSelectNotebook();
setOpen(false); setOpen(false);
...@@ -68,18 +61,10 @@ function UserMenu({ frameSync, onLogout, settings }) { ...@@ -68,18 +61,10 @@ function UserMenu({ frameSync, onLogout, settings }) {
const onProfileSelected = () => const onProfileSelected = () =>
isThirdParty && frameSync.notifyHost('profileRequested'); isThirdParty && frameSync.notifyHost('profileRequested');
const profileHref =
// Generate dynamic props for the profile <MenuItem> component isSelectableProfile && !isThirdParty
const profileItemProps = (() => { ? store.getLink('user', { user: username })
const props = {}; : undefined;
if (isSelectableProfile) {
if (!isThirdParty) {
props.href = store.getLink('user', { user: username });
}
props.onClick = onProfileSelected;
}
return props;
})();
const menuLabel = ( const menuLabel = (
<span className="p-1"> <span className="p-1">
...@@ -101,7 +86,8 @@ function UserMenu({ frameSync, onLogout, settings }) { ...@@ -101,7 +86,8 @@ function UserMenu({ frameSync, onLogout, settings }) {
<MenuItem <MenuItem
label={displayName} label={displayName}
isDisabled={!isSelectableProfile} isDisabled={!isSelectableProfile}
{...profileItemProps} href={profileHref}
onClick={isSelectableProfile ? onProfileSelected : undefined}
/> />
{!isThirdParty && ( {!isThirdParty && (
<MenuItem <MenuItem
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment